diff --git a/dist/styles.css b/dist/styles.css index fafe682..e90d109 100644 --- a/dist/styles.css +++ b/dist/styles.css @@ -53,6 +53,21 @@ i.ms-Nav-chevron { user-select: none; overflow: hidden; } +nav .progress { + position: fixed; + top: 0; + left: 0; + z-index: 10; + width: 100%; + height: 2px; + overflow: hidden; +} +.ms-ProgressIndicator-itemProgress { + padding: 0; +} +.ms-ProgressIndicator-progressTrack { + background: none; +} #root > nav span.title { font-size: 12px; line-height: 32px; @@ -240,7 +255,7 @@ img.favicon { z-index: 1; } -@media (min-width: 1721px) { +@media (min-width: 1441px) { #root > nav.menu-on { padding-left: 296px; } @@ -256,6 +271,17 @@ img.favicon { .menu-container .menu { background-color: #edebe9; } + .menu-container .menu::after { + content: ""; + display: block; + pointer-events: none; + position: absolute; + top: -10%; + right: 0; + width: 120%; + height: 120%; + box-shadow: inset 5px 0 20px #0004; + } .main.menu-on { padding-left: 280px; } diff --git a/src/components/nav.tsx b/src/components/nav.tsx index ccd7666..52a6c7d 100644 --- a/src/components/nav.tsx +++ b/src/components/nav.tsx @@ -1,7 +1,8 @@ import * as React from "react" -import { ipcRenderer, remote } from "electron" +import { remote } from "electron" import { Icon } from "@fluentui/react/lib/Icon" import { AppState } from "../scripts/models/app" +import { ProgressIndicator } from "@fluentui/react" type NavProps = { state: AppState, @@ -56,6 +57,12 @@ class Nav extends React.Component { if (this.canFetch()) this.props.fetch() } + getProgress = () => { + return this.props.state.fetchingTotal > 0 + ? this.props.state.fetchingProgress / this.props.state.fetchingTotal + : null + } + render() { return ( ) } diff --git a/src/components/settings/proxy.tsx b/src/components/settings/proxy.tsx index 7d4de7f..cd5e37a 100644 --- a/src/components/settings/proxy.tsx +++ b/src/components/settings/proxy.tsx @@ -28,7 +28,7 @@ class ProxyTab extends React.Component { render = () => (
- + diff --git a/src/scripts/models/app.ts b/src/scripts/models/app.ts index 87c3530..61ee9a6 100644 --- a/src/scripts/models/app.ts +++ b/src/scripts/models/app.ts @@ -30,6 +30,8 @@ export class AppState { sourceInit = false feedInit = false fetchingItems = false + fetchingProgress = 0 + fetchingTotal = 0 menu = getWindowBreakpoint() menuKey = ALL title = "全部文章" @@ -182,7 +184,9 @@ export function appReducer( switch (action.status) { case ActionStatus.Request: return { ...state, - fetchingItems: true + fetchingItems: true, + fetchingProgress: 0, + fetchingTotal: action.fetchCount } case ActionStatus.Failure: return { ...state, @@ -199,6 +203,7 @@ export function appReducer( case ActionStatus.Success: return { ...state, fetchingItems: false, + fetchingTotal: 0, logMenu: action.items.length == 0 ? state.logMenu : { ...state.logMenu, logs: [...state.logMenu.logs, new AppLog( @@ -207,6 +212,11 @@ export function appReducer( )] } } + case ActionStatus.Intermediate: return { + ...state, + fetchingProgress: state.fetchingProgress + 1 + } + default: return state } case SELECT_PAGE: switch (action.pageType) { diff --git a/src/scripts/models/feed.ts b/src/scripts/models/feed.ts index 9fa7cb4..7a30b2c 100644 --- a/src/scripts/models/feed.ts +++ b/src/scripts/models/feed.ts @@ -251,6 +251,7 @@ export function feedReducer( loading: false } } + default: return state } case SELECT_PAGE: switch (action.pageType) { diff --git a/src/scripts/models/item.ts b/src/scripts/models/item.ts index 39093ec..702760a 100644 --- a/src/scripts/models/item.ts +++ b/src/scripts/models/item.ts @@ -55,6 +55,7 @@ export const MARK_UNREAD = "MARK_UNREAD" interface FetchItemsAction { type: typeof FETCH_ITEMS status: ActionStatus + fetchCount?: number items?: RSSItem[] errSource?: RSSSource err? @@ -72,10 +73,11 @@ interface MarkUnreadAction { export type ItemActionTypes = FetchItemsAction | MarkReadAction | MarkUnreadAction -export function fetchItemsRequest(): ItemActionTypes { +export function fetchItemsRequest(fetchCount = 0): ItemActionTypes { return { type: FETCH_ITEMS, - status: ActionStatus.Request + status: ActionStatus.Request, + fetchCount: fetchCount } } @@ -96,6 +98,13 @@ export function fetchItemsFailure(source: RSSSource, err): ItemActionTypes { } } +export function fetchItemsIntermediate(): ItemActionTypes { + return { + type: FETCH_ITEMS, + status: ActionStatus.Intermediate + } +} + export function insertItems(items: RSSItem[]): Promise { return new Promise((resolve, reject) => { db.idb.find({}).projection({ id: 1 }).sort({ id: -1 }).limit(1).exec((err, docs) => { @@ -118,13 +127,15 @@ export function insertItems(items: RSSItem[]): Promise { export function fetchItems(): AppThunk> { return (dispatch, getState) => { - let p = new Array>() + let promises = new Array>() if (!getState().app.fetchingItems) { for (let source of Object.values(getState().sources)) { - p.push(RSSSource.fetchItems(source, rssParser, db.idb)) + let promise = RSSSource.fetchItems(source, rssParser, db.idb) + promise.finally(() => dispatch(fetchItemsIntermediate())) + promises.push(promise) } - dispatch(fetchItemsRequest()) - return Promise.allSettled(p).then(results => new Promise((resolve, reject) => { + dispatch(fetchItemsRequest(promises.length)) + return Promise.allSettled(promises).then(results => new Promise((resolve, reject) => { let items = new Array() results.map((r, i) => { if (r.status === "fulfilled") items.push(...r.value) diff --git a/src/scripts/utils.ts b/src/scripts/utils.ts index 08983d3..ce89d52 100644 --- a/src/scripts/utils.ts +++ b/src/scripts/utils.ts @@ -4,7 +4,7 @@ import { AnyAction } from "redux" import { RootState } from "./reducer" export enum ActionStatus { - Request, Success, Failure + Request, Success, Failure, Intermediate } export type AppThunk = ThunkAction< @@ -82,4 +82,4 @@ 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 \ No newline at end of file +export const getWindowBreakpoint = () => remote.getCurrentWindow().getSize()[0] >= 1441 \ No newline at end of file