Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 0.9.1 #152

Merged
merged 2 commits into from
Dec 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fluent-reader",
"version": "0.9.0",
"version": "0.9.1",
"description": "Modern desktop RSS reader",
"main": "./dist/electron.js",
"scripts": {
Expand Down Expand Up @@ -68,6 +68,7 @@
"category": "public.app-category.news",
"electronLanguages": [
"zh_CN",
"zh_TW",
"en",
"fr",
"es",
Expand Down
1 change: 1 addition & 0 deletions src/components/settings/services/greader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class GReaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReaderC
endpoint: this.state.endpoint,
fetchLimit: this.state.fetchLimit
} as GReaderConfigs
if (this.state.password) configs.password = this.state.password
} else {
configs = {
type: SyncService.GReader,
Expand Down
63 changes: 52 additions & 11 deletions src/components/settings/services/inoreader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ import { ServiceConfigsTabProps } from "../service"
import { GReaderConfigs } from "../../../scripts/models/services/greader"
import { SyncService } from "../../../schema-types"
import { Stack, Label, TextField, PrimaryButton, DefaultButton, Checkbox,
MessageBar, MessageBarType, Dropdown, IDropdownOption, MessageBarButton } from "@fluentui/react"
MessageBar, MessageBarType, Dropdown, IDropdownOption, MessageBarButton, Link } from "@fluentui/react"
import DangerButton from "../../utils/danger-button"

type GReaderConfigsTabState = {
existing: boolean
endpoint: string
username: string
password: string
apiId: string
apiKey: string
removeAd: boolean
fetchLimit: number
importGroups: boolean
}

const endpointOptions: IDropdownOption[] = [
Expand All @@ -33,8 +35,10 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
endpoint: configs.endpoint || "https://www.inoreader.com",
username: configs.username || "",
password: "",
apiId: configs.inoreaderId || "",
apiKey: configs.inoreaderKey || "",
removeAd: configs.removeInoreaderAd === undefined ? true : configs.removeInoreaderAd,
fetchLimit: configs.fetchLimit || 250,
importGroups: true,
}
}

Expand Down Expand Up @@ -62,7 +66,8 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
}

validateForm = () => {
return this.state.existing || (this.state.username && this.state.password)
return (this.state.existing || (this.state.username && this.state.password))
&& this.state.apiId && this.state.apiKey
}

save = async () => {
Expand All @@ -71,18 +76,25 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
configs = {
...this.props.configs,
endpoint: this.state.endpoint,
fetchLimit: this.state.fetchLimit
fetchLimit: this.state.fetchLimit,
inoreaderId: this.state.apiId,
inoreaderKey: this.state.apiKey,
removeInoreaderAd: this.state.removeAd,
} as GReaderConfigs
if (this.state.password) configs.password = this.state.password
} else {
configs = {
type: SyncService.Inoreader,
endpoint: this.state.endpoint,
username: this.state.username,
password: this.state.password,
inoreaderId: this.state.apiId,
inoreaderKey: this.state.apiKey,
removeInoreaderAd: this.state.removeAd,
fetchLimit: this.state.fetchLimit,
importGroups: true,
useInt64: true
}
if (this.state.importGroups) configs.importGroups = true
}
this.props.blockActions()
configs = await this.props.reauthenticate(configs) as GReaderConfigs
Expand All @@ -97,6 +109,8 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
}
}

createKey = () => window.utils.openExternal(this.state.endpoint + "/all_articles#preferences-developer")

remove = async () => {
this.props.exit()
await this.props.remove()
Expand All @@ -106,8 +120,9 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
return <>
<MessageBar messageBarType={MessageBarType.severeWarning}
isMultiline={false}
actions={<MessageBarButton text={intl.get("rules.help")} onClick={openSupport} />}>
actions={<MessageBarButton text={intl.get("create")} onClick={this.createKey} />}>
{intl.get("service.rateLimitWarning")}
<Link onClick={openSupport} style={{marginLeft: 6}}>{intl.get("rules.help")}</Link>
</MessageBar>
{!this.state.existing && (
<MessageBar messageBarType={MessageBarType.warning}>{intl.get("service.overwriteWarning")}</MessageBar>
Expand Down Expand Up @@ -155,6 +170,32 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
onChange={this.handleInputChange} />
</Stack.Item>
</Stack>
<Stack className="login-form" horizontal>
<Stack.Item>
<Label>API ID</Label>
</Stack.Item>
<Stack.Item grow>
<TextField
onGetErrorMessage={this.checkNotEmpty}
validateOnLoad={false}
name="apiId"
value={this.state.apiId}
onChange={this.handleInputChange} />
</Stack.Item>
</Stack>
<Stack className="login-form" horizontal>
<Stack.Item>
<Label>API Key</Label>
</Stack.Item>
<Stack.Item grow>
<TextField
onGetErrorMessage={this.checkNotEmpty}
validateOnLoad={false}
name="apiKey"
value={this.state.apiKey}
onChange={this.handleInputChange} />
</Stack.Item>
</Stack>
<Stack className="login-form" horizontal>
<Stack.Item>
<Label>{intl.get("service.fetchLimit")}</Label>
Expand All @@ -166,10 +207,10 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
onChange={this.onFetchLimitOptionChange} />
</Stack.Item>
</Stack>
{!this.state.existing && <Checkbox
label={intl.get("service.importGroups")}
checked={this.state.importGroups}
onChange={(_, c) => this.setState({importGroups: c})} />}
<Checkbox
label={intl.get("service.removeAd")}
checked={this.state.removeAd}
onChange={(_, c) => this.setState({removeAd: c})} />
<Stack horizontal style={{marginTop: 32}}>
<Stack.Item>
<PrimaryButton
Expand Down
3 changes: 2 additions & 1 deletion src/scripts/i18n/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@
"suggest": "Suggest a new service",
"overwriteWarning": "Local sources will be deleted if they exist in the service.",
"groupsWarning": "Groups aren't automatically synced with the service.",
"rateLimitWarning": "If connection errors persist, the app may have been rate limited by the service.",
"rateLimitWarning": "To avoid rate limiting, you need to create your own API Key.",
"removeAd": "Remove Ad",
"endpoint": "Endpoint",
"username": "Username",
"password": "Password",
Expand Down
3 changes: 2 additions & 1 deletion src/scripts/i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@
"suggest": "建议一项新服务",
"overwriteWarning": "若本地与服务端存在URL相同的订阅源,则本地订阅源将被删除",
"groupsWarning": "分组不会自动与服务端保持同步",
"rateLimitWarning": "若反复出现错误,则原因可能是应用被服务限流",
"rateLimitWarning": "为避免限流,您需要新建自己的 API Key",
"removeAd": "移除广告",
"endpoint": "端点",
"username": "用户名",
"password": "密码",
Expand Down
3 changes: 2 additions & 1 deletion src/scripts/i18n/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@
"suggest": "建議一項新服務",
"overwriteWarning": "若本地與服務端存在URL相同的訂閱源,則本地訂閱源將被刪除",
"groupsWarning": "分組不會自動與服務端保持同步",
"rateLimitWarning": "若反覆出現錯誤,則原因可能是應用被服務限流",
"rateLimitWarning": "為避免限流,您需要新建自己的 API Key",
"removeAd": "移除廣告",
"endpoint": "端點",
"username": "使用者名稱",
"password": "密碼",
Expand Down
19 changes: 16 additions & 3 deletions src/scripts/models/services/greader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,22 @@ export interface GReaderConfigs extends ServiceConfigs {
lastId?: string
auth?: string
useInt64: boolean // The Old Reader uses ids longer than 64 bits
inoreaderId?: string
inoreaderKey?: string
removeInoreaderAd?: boolean
}

async function fetchAPI(configs: GReaderConfigs, params: string, method="GET", body:BodyInit=null) {
const headers = new Headers()
if (configs.auth !== null) headers.set("Authorization", configs.auth)
if (configs.type == SyncService.Inoreader) {
headers.set("AppId", "999999298")
headers.set("AppKey", "KPbKYXTfgrKbwmroOeYC7mcW21ZRwF5Y")
if (configs.inoreaderId) {
headers.set("AppId", configs.inoreaderId)
headers.set("AppKey", configs.inoreaderKey)
} else {
headers.set("AppId", "999999298")
headers.set("AppKey", "KPbKYXTfgrKbwmroOeYC7mcW21ZRwF5Y")
}
}
return await fetch(configs.endpoint + params, {
method: method,
Expand Down Expand Up @@ -189,13 +197,18 @@ export const gReaderServiceHooks: ServiceHooks = {
const source = fidMap.get(i.origin.streamId)
if (source === undefined) return
const dom = domParser.parseFromString(i.summary.content, "text/html")
if (configs.type == SyncService.Inoreader && configs.removeInoreaderAd !== false) {
if (dom.documentElement.textContent.trim().startsWith("Ads from Inoreader")) {
dom.body.firstChild.remove()
}
}
const item = {
source: source.sid,
title: i.title,
link: i.canonical[0].href,
date: new Date(i.published * 1000),
fetchedDate: new Date(parseInt(i.crawlTimeMsec)),
content: i.summary.content,
content: dom.body.innerHTML,
snippet: dom.documentElement.textContent.trim(),
creator: i.author,
hasRead: false,
Expand Down