pin menu
This commit is contained in:
parent
8debcfe7e4
commit
9bdcf4ea34
Binary file not shown.
|
@ -1,11 +1,6 @@
|
|||
@font-face {
|
||||
font-family: "Source Han Sans";
|
||||
src: url("SourceHanSansSC-Regular.otf");
|
||||
}
|
||||
|
||||
html, body {
|
||||
background-color: #faf9f8;
|
||||
font-family: "Source Han Sans", sans-serif;
|
||||
font-family: "Source Han Sans SC Regular", "Microsoft YaHei", sans-serif;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
|
@ -101,12 +96,15 @@ i.ms-Nav-chevron {
|
|||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
nav.hide-btns .btn-group .btn {
|
||||
nav.menu-on .btn-group .btn, nav.hide-btns .btn-group .btn {
|
||||
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;
|
||||
}
|
||||
.btn-group .btn.system.menu-on {
|
||||
color: #fff;
|
||||
}
|
||||
.btn-group .btn:hover {
|
||||
background-color: #0001;
|
||||
}
|
||||
|
@ -132,8 +130,8 @@ nav.hide-btns .btn-group .btn.system {
|
|||
background-color: #f1707a;
|
||||
color: #fff;
|
||||
}
|
||||
.btn-group .btn.system.on {
|
||||
color: #fff;
|
||||
.btn-group .btn.inline-block-wide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.menu-container {
|
||||
|
@ -242,6 +240,34 @@ img.favicon {
|
|||
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 {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
import * as React from "react"
|
||||
import { Icon } from "@fluentui/react/lib/Icon"
|
||||
import { Nav, INavLink, INavLinkGroup } from "office-ui-fabric-react/lib/Nav"
|
||||
import { MenuStatus } from "../scripts/models/app"
|
||||
import { SourceGroup } from "../scripts/models/page"
|
||||
import { SourceState, RSSSource } from "../scripts/models/source"
|
||||
import { ALL } from "../scripts/models/feed"
|
||||
import { AnimationClassNames } from "@fluentui/react"
|
||||
|
||||
export type MenuProps = {
|
||||
status: MenuStatus,
|
||||
status: boolean,
|
||||
selected: string,
|
||||
sources: SourceState,
|
||||
groups: SourceGroup[],
|
||||
closeMenu: () => void,
|
||||
toggleMenu: () => void,
|
||||
allArticles: () => void,
|
||||
selectSourceGroup: (group: SourceGroup, menuKey: string) => void,
|
||||
selectSource: (source: RSSSource) => void
|
||||
|
@ -74,11 +73,12 @@ export class Menu extends React.Component<MenuProps> {
|
|||
})
|
||||
|
||||
render() {
|
||||
return this.props.status == MenuStatus.Hidden ? null : (
|
||||
<div className="menu-container" onClick={this.props.closeMenu}>
|
||||
return this.props.status ? (
|
||||
<div className="menu-container" onClick={this.props.toggleMenu}>
|
||||
<div className="menu" onClick={(e) => e.stopPropagation()}>
|
||||
<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 className="nav-wrapper">
|
||||
<Nav
|
||||
|
@ -91,6 +91,6 @@ export class Menu extends React.Component<MenuProps> {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
) : null
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from "react"
|
||||
import { ipcRenderer, remote } from "electron"
|
||||
import { Icon } from "@fluentui/react/lib/Icon"
|
||||
import { AppState, MenuStatus } from "../scripts/models/app"
|
||||
import { AppState } from "../scripts/models/app"
|
||||
|
||||
type NavProps = {
|
||||
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
|
||||
fetching = () => !this.canFetch() ? " fetching" : ""
|
||||
menuOn = () => this.props.state.menu == MenuStatus.Open ? " on" : ""
|
||||
hideButtons = () => (this.props.state.menu == MenuStatus.Open || this.props.state.settings.display) ? "hide-btns" : ""
|
||||
menuOn = () => this.props.state.menu ? " menu-on" : ""
|
||||
hideButtons = () => this.props.state.settings.display ? "hide-btns" : ""
|
||||
|
||||
fetch = () => {
|
||||
if (this.canFetch()) this.props.fetch()
|
||||
|
@ -58,9 +58,9 @@ class Nav extends React.Component<NavProps, NavState> {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<nav className={this.hideButtons()}>
|
||||
<nav className={this.hideButtons() + this.menuOn()}>
|
||||
<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>
|
||||
<span className="title">{this.props.state.title}</span>
|
||||
<div className="btn-group" style={{float:"right"}}>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { FeedIdType } from "../scripts/models/feed"
|
|||
import { FeedContainer } from "../containers/feed-container"
|
||||
|
||||
type PageProps = {
|
||||
menuOn: boolean
|
||||
settingsOn: boolean
|
||||
feeds: FeedIdType[]
|
||||
}
|
||||
|
@ -11,7 +12,7 @@ class Page extends React.Component<PageProps> {
|
|||
render = () => (
|
||||
<>
|
||||
{this.props.settingsOn ? null :
|
||||
<div className="main">
|
||||
<div className={"main" + (this.props.menuOn ? " menu-on" : "")}>
|
||||
{this.props.feeds.map(fid => (
|
||||
<FeedContainer feedId={fid} key={fid} />
|
||||
))}
|
||||
|
|
|
@ -2,12 +2,12 @@ import { connect } from "react-redux"
|
|||
import { createSelector } from "reselect"
|
||||
import { RootState } from "../scripts/reducer"
|
||||
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 { initFeeds } from "../scripts/models/feed"
|
||||
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 getSources = (state: RootState) => state.sources
|
||||
const getGroups = (state: RootState) => state.page.sourceGroups
|
||||
|
@ -23,7 +23,7 @@ const mapStateToProps = createSelector(
|
|||
)
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
closeMenu: () => dispatch(closeMenu()),
|
||||
toggleMenu: () => dispatch(toggleMenu()),
|
||||
allArticles: () => {
|
||||
dispatch(selectAllArticles()),
|
||||
dispatch(initFeeds())
|
||||
|
|
|
@ -2,7 +2,7 @@ import { connect } from "react-redux"
|
|||
import { createSelector } from "reselect"
|
||||
import { RootState } from "../scripts/reducer"
|
||||
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"
|
||||
|
||||
const getState = (state: RootState) => state.app
|
||||
|
@ -13,7 +13,7 @@ const mapStateToProps = createSelector(getState, (state) => ({
|
|||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
fetch: () => dispatch(fetchItems()),
|
||||
menu: () => dispatch(openMenu()),
|
||||
menu: () => dispatch(toggleMenu()),
|
||||
logs: () => dispatch(toggleLogMenu()),
|
||||
settings: () => dispatch(toggleSettings())
|
||||
})
|
||||
|
|
|
@ -5,12 +5,14 @@ import Page from "../components/page"
|
|||
|
||||
const getFeeds = (state: RootState) => state.page.feedId
|
||||
const getSettings = (state: RootState) => state.app.settings.display
|
||||
const getMenu = (state: RootState) => state.app.menu
|
||||
|
||||
const mapStateToProps = createSelector(
|
||||
[getFeeds, getSettings],
|
||||
(feeds, settingsOn) => ({
|
||||
[getFeeds, getSettings, getMenu],
|
||||
(feeds, settingsOn, menuOn) => ({
|
||||
feeds: [feeds],
|
||||
settingsOn: settingsOn
|
||||
settingsOn: settingsOn,
|
||||
menuOn: menuOn
|
||||
})
|
||||
)
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import { AppDispatch, setProxy } from "./scripts/utils"
|
|||
|
||||
setProxy()
|
||||
|
||||
loadTheme({ defaultFontStyle: { fontFamily: '"Source Han Sans", sans-serif' } })
|
||||
loadTheme({ defaultFontStyle: { fontFamily: '"Source Han Sans SC Regular", "Microsoft YaHei", sans-serif' } })
|
||||
initializeIcons("icons/")
|
||||
|
||||
const store = createStore(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { RSSSource, INIT_SOURCES, SourceActionTypes, ADD_SOURCE, UPDATE_SOURCE, DELETE_SOURCE } from "./source"
|
||||
import { RSSItem, ItemActionTypes, FETCH_ITEMS, fetchItems } from "./item"
|
||||
import { ActionStatus, AppThunk } from "../utils"
|
||||
import { RSSItem, ItemActionTypes, FETCH_ITEMS } from "./item"
|
||||
import { ActionStatus, AppThunk, getWindowBreakpoint } from "../utils"
|
||||
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"
|
||||
|
||||
|
@ -8,10 +8,6 @@ export enum ContextMenuType {
|
|||
Hidden, Item
|
||||
}
|
||||
|
||||
export enum MenuStatus {
|
||||
Hidden, Open, Pinned
|
||||
}
|
||||
|
||||
export enum AppLogType {
|
||||
Info, Warning, Failure
|
||||
}
|
||||
|
@ -34,7 +30,7 @@ export class AppState {
|
|||
sourceInit = false
|
||||
feedInit = false
|
||||
fetchingItems = false
|
||||
menu = MenuStatus.Hidden
|
||||
menu = getWindowBreakpoint()
|
||||
menuKey = ALL
|
||||
title = "全部文章"
|
||||
settings = {
|
||||
|
@ -79,11 +75,10 @@ export type ContextMenuActionTypes = CloseContextMenuAction | OpenItemMenuAction
|
|||
export const TOGGLE_LOGS = "TOGGLE_LOGS"
|
||||
export interface LogMenuActionType { type: typeof TOGGLE_LOGS }
|
||||
|
||||
export const OPEN_MENU = "OPEN_MENU"
|
||||
export const CLOSE_MENU = "CLOSE_MENU"
|
||||
export const TOGGLE_MENU = "TOGGLE_MENU"
|
||||
|
||||
export interface MenuActionTypes {
|
||||
type: typeof OPEN_MENU | typeof CLOSE_MENU
|
||||
type: typeof TOGGLE_MENU
|
||||
}
|
||||
|
||||
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 closeMenu = () => ({ type: CLOSE_MENU })
|
||||
export const toggleMenu = () => ({ type: TOGGLE_MENU })
|
||||
export const toggleLogMenu = () => ({ type: TOGGLE_LOGS })
|
||||
export const toggleSettings = () => ({ type: TOGGLE_SETTINGS })
|
||||
export const saveSettings = () => ({ type: SAVE_SETTINGS })
|
||||
|
@ -218,13 +212,13 @@ export function appReducer(
|
|||
switch (action.pageType) {
|
||||
case PageType.AllArticles: return {
|
||||
...state,
|
||||
menu: MenuStatus.Hidden,
|
||||
menu: state.menu && action.keepMenu,
|
||||
menuKey: ALL,
|
||||
title: "全部文章"
|
||||
}
|
||||
case PageType.Sources: return {
|
||||
...state,
|
||||
menu: MenuStatus.Hidden,
|
||||
menu: state.menu && action.keepMenu,
|
||||
menuKey: action.menuKey,
|
||||
title: action.title
|
||||
}
|
||||
|
@ -243,13 +237,9 @@ export function appReducer(
|
|||
target: action.item
|
||||
}
|
||||
}
|
||||
case OPEN_MENU: return {
|
||||
case TOGGLE_MENU: return {
|
||||
...state,
|
||||
menu: MenuStatus.Open
|
||||
}
|
||||
case CLOSE_MENU: return {
|
||||
...state,
|
||||
menu: MenuStatus.Hidden
|
||||
menu: !state.menu
|
||||
}
|
||||
case SAVE_SETTINGS: return {
|
||||
...state,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import fs = require("fs")
|
||||
import { SourceActionTypes, ADD_SOURCE, DELETE_SOURCE, addSource } from "./source"
|
||||
import { ALL, SOURCE } from "./feed"
|
||||
import { ActionStatus, AppThunk, domParser, AppDispatch } from "../utils"
|
||||
import { ActionStatus, AppThunk, domParser, AppDispatch, getWindowBreakpoint } from "../utils"
|
||||
import { saveSettings } from "./app"
|
||||
|
||||
const GROUPS_STORE_KEY = "sourceGroups"
|
||||
|
@ -43,6 +43,7 @@ interface SelectPageAction {
|
|||
type: typeof SELECT_PAGE
|
||||
pageType: PageType
|
||||
init: boolean
|
||||
keepMenu: boolean
|
||||
sids?: number[]
|
||||
menuKey?: string
|
||||
title?: string
|
||||
|
@ -53,6 +54,7 @@ export type PageActionTypes = SelectPageAction
|
|||
export function selectAllArticles(init = false): SelectPageAction {
|
||||
return {
|
||||
type: SELECT_PAGE,
|
||||
keepMenu: getWindowBreakpoint(),
|
||||
pageType: PageType.AllArticles,
|
||||
init: init
|
||||
}
|
||||
|
@ -62,6 +64,7 @@ export function selectSources(sids: number[], menuKey: string, title: string) {
|
|||
return {
|
||||
type: SELECT_PAGE,
|
||||
pageType: PageType.Sources,
|
||||
keepMenu: getWindowBreakpoint(),
|
||||
sids: sids,
|
||||
menuKey: menuKey,
|
||||
title: title,
|
||||
|
|
|
@ -81,3 +81,5 @@ export function openExternal(url: 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)
|
||||
|
||||
export const getWindowBreakpoint = () => remote.getCurrentWindow().getSize()[0] >= 1721
|
Loading…
Reference in New Issue