mirror of
https://github.com/yang991178/fluent-reader.git
synced 2025-04-13 09:52:42 +02:00
add service warnings
This commit is contained in:
parent
fc0183a80d
commit
c35efa04ba
4
dist/styles/global.css
vendored
4
dist/styles/global.css
vendored
@ -109,6 +109,10 @@ i.ms-Nav-chevron {
|
||||
.ms-ActivityItem-timeStamp {
|
||||
color: var(--neutralSecondaryAlt);
|
||||
}
|
||||
.ms-MessageBar {
|
||||
user-select: none;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#root > nav {
|
||||
height: var(--navHeight);
|
||||
|
@ -3,12 +3,13 @@ import intl from "react-intl-universal"
|
||||
import { SourceGroup } from "../../schema-types"
|
||||
import { SourceState, RSSSource } from "../../scripts/models/source"
|
||||
import { IColumn, Selection, SelectionMode, DetailsList, Label, Stack,
|
||||
TextField, PrimaryButton, DefaultButton, Dropdown, IDropdownOption, CommandBarButton, MarqueeSelection, IDragDropEvents } from "@fluentui/react"
|
||||
TextField, PrimaryButton, DefaultButton, Dropdown, IDropdownOption, CommandBarButton, MarqueeSelection, IDragDropEvents, MessageBar, MessageBarType } from "@fluentui/react"
|
||||
import DangerButton from "../utils/danger-button"
|
||||
|
||||
type GroupsTabProps = {
|
||||
sources: SourceState,
|
||||
groups: SourceGroup[],
|
||||
serviceOn: boolean,
|
||||
createGroup: (name: string) => void,
|
||||
updateGroup: (group: SourceGroup) => void,
|
||||
addToGroup: (groupIndex: number, sid: number) => void,
|
||||
@ -263,6 +264,9 @@ class GroupsTab extends React.Component<GroupsTabProps, GroupsTabState> {
|
||||
|
||||
render = () => (
|
||||
<div className="tab-body">
|
||||
{this.props.serviceOn && (
|
||||
<MessageBar messageBarType={MessageBarType.info}>{intl.get("service.groupsWarning")}</MessageBar>
|
||||
)}
|
||||
{this.state.manageGroup && this.state.selectedGroup &&
|
||||
<>
|
||||
<Stack horizontal horizontalAlign="space-between" style={{height: 40}}>
|
||||
|
@ -95,14 +95,12 @@ class FeverConfigsTab extends React.Component<ServiceConfigsTabProps, FeverConfi
|
||||
|
||||
render() {
|
||||
return <>
|
||||
<Stack tokens={{childrenGap: 8}}>
|
||||
{!this.state.existing && (
|
||||
<MessageBar messageBarType={MessageBarType.warning}>{intl.get("service.overwriteWarning")}</MessageBar>
|
||||
)}
|
||||
{!this.state.existing && this.state.importGroups && (
|
||||
<MessageBar messageBarType={MessageBarType.info}>{intl.get("service.groupsWarning")}</MessageBar>
|
||||
)}
|
||||
</Stack>
|
||||
{!this.state.existing && (
|
||||
<MessageBar messageBarType={MessageBarType.warning}>{intl.get("service.overwriteWarning")}</MessageBar>
|
||||
)}
|
||||
{!this.state.existing && this.state.importGroups && (
|
||||
<MessageBar messageBarType={MessageBarType.info}>{intl.get("service.groupsWarning")}</MessageBar>
|
||||
)}
|
||||
<Stack horizontalAlign="center" style={{marginTop: 48}}>
|
||||
<Icon iconName="Calories" style={{fontSize: 32, userSelect: "none"}} />
|
||||
<Label style={{margin: "8px 0 36px"}}>Fever API</Label>
|
||||
|
@ -1,13 +1,15 @@
|
||||
import * as React from "react"
|
||||
import intl from "react-intl-universal"
|
||||
import { Label, DefaultButton, TextField, Stack, PrimaryButton, DetailsList,
|
||||
IColumn, SelectionMode, Selection, IChoiceGroupOption, ChoiceGroup, IDropdownOption, Dropdown } from "@fluentui/react"
|
||||
IColumn, SelectionMode, Selection, IChoiceGroupOption, ChoiceGroup, IDropdownOption,
|
||||
Dropdown, MessageBar, MessageBarType } from "@fluentui/react"
|
||||
import { SourceState, RSSSource, SourceOpenTarget } from "../../scripts/models/source"
|
||||
import { urlTest } from "../../scripts/utils"
|
||||
import DangerButton from "../utils/danger-button"
|
||||
|
||||
type SourcesTabProps = {
|
||||
sources: SourceState
|
||||
serviceOn: boolean
|
||||
addSource: (url: string) => void
|
||||
updateSourceName: (source: RSSSource, name: string) => void
|
||||
updateSourceIcon: (source: RSSSource, iconUrl: string) => Promise<void>
|
||||
@ -154,6 +156,9 @@ class SourcesTab extends React.Component<SourcesTabProps, SourcesTabState> {
|
||||
|
||||
render = () => (
|
||||
<div className="tab-body">
|
||||
{this.props.serviceOn && (
|
||||
<MessageBar messageBarType={MessageBarType.info}>{intl.get("sources.serviceWarning")}</MessageBar>
|
||||
)}
|
||||
<Label>{intl.get("sources.opmlFile")}</Label>
|
||||
<Stack horizontal>
|
||||
<Stack.Item>
|
||||
@ -196,6 +201,9 @@ class SourcesTab extends React.Component<SourcesTabProps, SourcesTabState> {
|
||||
selectionMode={SelectionMode.multiple} />
|
||||
|
||||
{this.state.selectedSource && <>
|
||||
{this.state.selectedSource.serviceRef && (
|
||||
<MessageBar messageBarType={MessageBarType.info}>{intl.get("sources.serviceManaged")}</MessageBar>
|
||||
)}
|
||||
<Label>{intl.get("sources.selected")}</Label>
|
||||
<Stack horizontal>
|
||||
<Stack.Item>
|
||||
@ -251,34 +259,39 @@ class SourcesTab extends React.Component<SourcesTabProps, SourcesTabState> {
|
||||
</>}
|
||||
|
||||
</Stack>
|
||||
<Label>{intl.get("sources.fetchFrequency")}</Label>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Dropdown
|
||||
options={this.fetchFrequencyOptions()}
|
||||
selectedKey={this.state.selectedSource.fetchFrequency ? String(this.state.selectedSource.fetchFrequency) : "0"}
|
||||
onChange={this.onFetchFrequencyChange}
|
||||
style={{width: 200}} />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
{!this.state.selectedSource.serviceRef && <>
|
||||
<Label>{intl.get("sources.fetchFrequency")}</Label>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Dropdown
|
||||
options={this.fetchFrequencyOptions()}
|
||||
selectedKey={this.state.selectedSource.fetchFrequency ? String(this.state.selectedSource.fetchFrequency) : "0"}
|
||||
onChange={this.onFetchFrequencyChange}
|
||||
style={{width: 200}} />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</>}
|
||||
<ChoiceGroup
|
||||
label={intl.get("sources.openTarget")}
|
||||
options={this.sourceOpenTargetChoices()}
|
||||
selectedKey={String(this.state.selectedSource.openTarget)}
|
||||
onChange={this.onOpenTargetChange} />
|
||||
<Stack horizontal>
|
||||
<Stack.Item>
|
||||
<DangerButton
|
||||
onClick={() => this.props.deleteSource(this.state.selectedSource)}
|
||||
key={this.state.selectedSource.sid}
|
||||
text={intl.get("sources.delete")} />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<span className="settings-hint">{intl.get("sources.deleteWarning")}</span>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
{!this.state.selectedSource.serviceRef && (
|
||||
<Stack horizontal>
|
||||
<Stack.Item>
|
||||
<DangerButton
|
||||
onClick={() => this.props.deleteSource(this.state.selectedSource)}
|
||||
key={this.state.selectedSource.sid}
|
||||
text={intl.get("sources.delete")} />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<span className="settings-hint">{intl.get("sources.deleteWarning")}</span>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
)}
|
||||
</>}
|
||||
{this.state.selectedSources && <>
|
||||
{this.state.selectedSources && (this.state.selectedSources.filter(s => s.serviceRef).length === 0
|
||||
? <>
|
||||
<Label>{intl.get("sources.selectedMulti")}</Label>
|
||||
<Stack horizontal>
|
||||
<Stack.Item>
|
||||
@ -290,7 +303,10 @@ class SourcesTab extends React.Component<SourcesTabProps, SourcesTabState> {
|
||||
<span className="settings-hint">{intl.get("sources.deleteWarning")}</span>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</>}
|
||||
</>
|
||||
: (
|
||||
<MessageBar messageBarType={MessageBarType.info}>{intl.get("sources.serviceManaged")}</MessageBar>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -4,16 +4,18 @@ import { RootState } from "../../scripts/reducer"
|
||||
import GroupsTab from "../../components/settings/groups"
|
||||
import { createSourceGroup, updateSourceGroup, addSourceToGroup,
|
||||
deleteSourceGroup, removeSourceFromGroup, reorderSourceGroups } from "../../scripts/models/group"
|
||||
import { SourceGroup } from "../../schema-types"
|
||||
import { SourceGroup, SyncService } from "../../schema-types"
|
||||
|
||||
const getSources = (state: RootState) => state.sources
|
||||
const getGroups = (state: RootState) => state.groups
|
||||
const getServiceOn = (state: RootState) => state.service.type !== SyncService.None
|
||||
|
||||
const mapStateToProps = createSelector(
|
||||
[getSources, getGroups],
|
||||
(sources, groups) => ({
|
||||
[getSources, getGroups, getServiceOn],
|
||||
(sources, groups, serviceOn) => ({
|
||||
sources: sources,
|
||||
groups: groups.map((g, i) => ({ ...g, index: i })),
|
||||
serviceOn: serviceOn,
|
||||
key: groups.length
|
||||
})
|
||||
)
|
||||
|
@ -7,13 +7,16 @@ import { addSource, RSSSource, updateSource, deleteSource, SourceOpenTarget, del
|
||||
import { importOPML, exportOPML } from "../../scripts/models/group"
|
||||
import { AppDispatch, validateFavicon } from "../../scripts/utils"
|
||||
import { saveSettings } from "../../scripts/models/app"
|
||||
import { SyncService } from "../../schema-types"
|
||||
|
||||
const getSources = (state: RootState) => state.sources
|
||||
const getServiceOn = (state: RootState) => state.service.type !== SyncService.None
|
||||
|
||||
const mapStateToProps = createSelector(
|
||||
[getSources],
|
||||
(sources) => ({
|
||||
sources: sources
|
||||
[getSources, getServiceOn],
|
||||
(sources, serviceOn) => ({
|
||||
sources: sources,
|
||||
serviceOn: serviceOn
|
||||
})
|
||||
)
|
||||
|
||||
|
@ -32,7 +32,8 @@
|
||||
"fetchFailure": "Failed to load source \"{name}\".",
|
||||
"fetchSuccess": "Successfully fetched {count, plural, =1 {# article} other {# articles}}.",
|
||||
"networkError": "A network error has occurred.",
|
||||
"parseError": "An error has occurred when parsing the XML feed."
|
||||
"parseError": "An error has occurred when parsing the XML feed.",
|
||||
"syncFailure": "Failed to sync with service"
|
||||
},
|
||||
"nav": {
|
||||
"menu": "Menu",
|
||||
@ -112,6 +113,8 @@
|
||||
"feedback": "Feedback"
|
||||
},
|
||||
"sources": {
|
||||
"serviceWarning": "Sources imported or added here will not be synced with your service.",
|
||||
"serviceManaged": "This source is managed by your service.",
|
||||
"untitled": "Source",
|
||||
"errorAdd": "An error has occured when adding the source.",
|
||||
"errorParse": "An error has occurred when parsing the OPML file.",
|
||||
|
@ -32,7 +32,8 @@
|
||||
"fetchFailure": "无法加载订阅源“{name}”",
|
||||
"fetchSuccess": "成功加载 {count} 篇文章",
|
||||
"networkError": "连接订阅源时出错",
|
||||
"parseError": "解析XML信息流时出错"
|
||||
"parseError": "解析XML信息流时出错",
|
||||
"syncFailure": "无法与服务同步"
|
||||
},
|
||||
"nav": {
|
||||
"menu": "菜单",
|
||||
@ -110,6 +111,8 @@
|
||||
"feedback": "反馈"
|
||||
},
|
||||
"sources": {
|
||||
"serviceWarning": "此处导入或添加的订阅源将不会与服务端同步",
|
||||
"serviceManaged": "该订阅源由服务端管理",
|
||||
"untitled": "订阅源",
|
||||
"errorAdd": "添加订阅源时出错",
|
||||
"errorParse": "解析OPML文件时出错",
|
||||
@ -187,7 +190,7 @@
|
||||
"fetchLimit": "同步数量",
|
||||
"fetchLimitNum": "最近 {count} 篇文章",
|
||||
"importGroups": "导入分组",
|
||||
"failure": "无法连接到服务",
|
||||
"failure": "连接到服务时出错",
|
||||
"failureHint": "请检查服务配置或网络连接"
|
||||
},
|
||||
"app": {
|
||||
|
@ -356,6 +356,19 @@ export function appReducer(
|
||||
...state,
|
||||
syncing: true
|
||||
}
|
||||
case ActionStatus.Failure: return {
|
||||
...state,
|
||||
syncing: false,
|
||||
logMenu: {
|
||||
...state.logMenu,
|
||||
notify: true,
|
||||
logs: [...state.logMenu.logs, new AppLog(
|
||||
AppLogType.Failure,
|
||||
intl.get("log.syncFailure"),
|
||||
String(action.err)
|
||||
)]
|
||||
}
|
||||
}
|
||||
default: return {
|
||||
...state,
|
||||
syncing: false
|
||||
@ -467,6 +480,7 @@ export function appReducer(
|
||||
settings: {
|
||||
...state.settings,
|
||||
display: true,
|
||||
changed: true,
|
||||
saving: !state.settings.saving
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user