add exporting to mobile app
This commit is contained in:
parent
09bb6cbd07
commit
b336260d0c
|
@ -32,7 +32,7 @@ jobs:
|
|||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Fluent Reader v${{ steps.package-version.outputs.current-version }} Beta
|
||||
release_name: Fluent Reader v${{ steps.package-version.outputs.current-version }}
|
||||
draft: true
|
||||
prerelease: false
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "fluent-reader",
|
||||
"version": "0.9.1",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "fluent-reader",
|
||||
"version": "0.9.1",
|
||||
"version": "1.0.0",
|
||||
"description": "Modern desktop RSS reader",
|
||||
"main": "./dist/electron.js",
|
||||
"scripts": {
|
||||
|
|
|
@ -40,7 +40,7 @@ export const shareSubmenu = (item: RSSItem): IContextualMenuItem[] => [
|
|||
{ key: "qr", url: item.link, onRender: renderShareQR }
|
||||
]
|
||||
|
||||
const renderShareQR = (item: IContextualMenuItem) => (
|
||||
export const renderShareQR = (item: IContextualMenuItem) => (
|
||||
<div className="qr-container">
|
||||
<QRCode
|
||||
value={item.url}
|
||||
|
|
|
@ -7,6 +7,7 @@ import { Stack, Icon, Label, TextField, PrimaryButton, DefaultButton, Checkbox,
|
|||
MessageBar, MessageBarType, Dropdown, IDropdownOption } from "@fluentui/react"
|
||||
import DangerButton from "../../utils/danger-button"
|
||||
import { urlTest } from "../../../scripts/utils"
|
||||
import LiteExporter from "./lite-exporter"
|
||||
|
||||
type FeedbinConfigsTabState = {
|
||||
existing: boolean
|
||||
|
@ -173,6 +174,7 @@ class FeedbinConfigsTab extends React.Component<ServiceConfigsTabProps, FeedbinC
|
|||
}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
{ this.state.existing && <LiteExporter serviceConfigs={this.props.configs} /> }
|
||||
</Stack>
|
||||
</>
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import { SyncService } from "../../../schema-types"
|
|||
import { Stack, Icon, Label, TextField, PrimaryButton, DefaultButton, Checkbox, MessageBar, MessageBarType, Dropdown, IDropdownOption } from "@fluentui/react"
|
||||
import DangerButton from "../../utils/danger-button"
|
||||
import { urlTest } from "../../../scripts/utils"
|
||||
import LiteExporter from "./lite-exporter"
|
||||
|
||||
type FeverConfigsTabState = {
|
||||
existing: boolean
|
||||
|
@ -173,6 +174,7 @@ class FeverConfigsTab extends React.Component<ServiceConfigsTabProps, FeverConfi
|
|||
}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
{ this.state.existing && <LiteExporter serviceConfigs={this.props.configs} /> }
|
||||
</Stack>
|
||||
</>
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import { SyncService } from "../../../schema-types"
|
|||
import { Stack, Icon, Label, TextField, PrimaryButton, DefaultButton, Checkbox, MessageBar, MessageBarType, Dropdown, IDropdownOption } from "@fluentui/react"
|
||||
import DangerButton from "../../utils/danger-button"
|
||||
import { urlTest } from "../../../scripts/utils"
|
||||
import LiteExporter from "./lite-exporter"
|
||||
|
||||
type GReaderConfigsTabState = {
|
||||
existing: boolean
|
||||
|
@ -173,6 +174,7 @@ class GReaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReaderC
|
|||
}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
{ this.state.existing && <LiteExporter serviceConfigs={this.props.configs} /> }
|
||||
</Stack>
|
||||
</>
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import { SyncService } from "../../../schema-types"
|
|||
import { Stack, Label, TextField, PrimaryButton, DefaultButton, Checkbox,
|
||||
MessageBar, MessageBarType, Dropdown, IDropdownOption, MessageBarButton, Link } from "@fluentui/react"
|
||||
import DangerButton from "../../utils/danger-button"
|
||||
import LiteExporter from "./lite-exporter"
|
||||
|
||||
type GReaderConfigsTabState = {
|
||||
existing: boolean
|
||||
|
@ -225,6 +226,7 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
|
|||
}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
{ this.state.existing && <LiteExporter serviceConfigs={this.props.configs} /> }
|
||||
</Stack>
|
||||
</>
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
import * as React from "react"
|
||||
import intl from "react-intl-universal"
|
||||
import { Stack, ContextualMenuItemType, DefaultButton, IContextualMenuProps, DirectionalHint } from "@fluentui/react"
|
||||
import { ServiceConfigs, SyncService } from "../../../schema-types"
|
||||
import { renderShareQR } from "../../context-menu"
|
||||
import { platformCtrl } from "../../../scripts/utils"
|
||||
import { FeverConfigs } from "../../../scripts/models/services/fever"
|
||||
import { GReaderConfigs } from "../../../scripts/models/services/greader"
|
||||
import { FeedbinConfigs } from "../../../scripts/models/services/feedbin"
|
||||
|
||||
type LiteExporterProps = {
|
||||
serviceConfigs: ServiceConfigs
|
||||
}
|
||||
|
||||
const LEARN_MORE_URL = "https://github.com/yang991178/fluent-reader/wiki/Support#mobile-app"
|
||||
|
||||
const LiteExporter: React.FunctionComponent<LiteExporterProps> = (props) => {
|
||||
let url = "https://hyliu.me/fr2l/?"
|
||||
const params = new URLSearchParams()
|
||||
switch (props.serviceConfigs.type) {
|
||||
case SyncService.Fever: {
|
||||
const configs = props.serviceConfigs as FeverConfigs
|
||||
params.set("t", "f")
|
||||
params.set("e", configs.endpoint)
|
||||
params.set("u", configs.username)
|
||||
params.set("k", configs.apiKey)
|
||||
break
|
||||
}
|
||||
case SyncService.GReader:
|
||||
case SyncService.Inoreader: {
|
||||
const configs = props.serviceConfigs as GReaderConfigs
|
||||
params.set("t", configs.type == SyncService.GReader ? "g" : "i")
|
||||
params.set("e", configs.endpoint)
|
||||
params.set("u", configs.username)
|
||||
params.set("p", btoa(configs.password))
|
||||
if (configs.inoreaderId) {
|
||||
params.set("i", configs.inoreaderId)
|
||||
params.set("k", configs.inoreaderKey)
|
||||
}
|
||||
break
|
||||
}
|
||||
case SyncService.Feedbin: {
|
||||
const configs = props.serviceConfigs as FeedbinConfigs
|
||||
params.set("t", "fb")
|
||||
params.set("e", configs.endpoint)
|
||||
params.set("u", configs.username)
|
||||
params.set("p", btoa(configs.password))
|
||||
break
|
||||
}
|
||||
}
|
||||
url += params.toString()
|
||||
const menuProps: IContextualMenuProps = {
|
||||
directionalHint: DirectionalHint.bottomCenter,
|
||||
items: [
|
||||
{ key: "qr", url: url, onRender: renderShareQR },
|
||||
{ key: "divider_1", itemType: ContextualMenuItemType.Divider },
|
||||
{
|
||||
key: "openInBrowser",
|
||||
text: intl.get("rules.help"),
|
||||
iconProps: { iconName: "NavigateExternalInline" },
|
||||
onClick: e => { window.utils.openExternal(LEARN_MORE_URL, platformCtrl(e)) }
|
||||
},
|
||||
]
|
||||
}
|
||||
return <Stack style={{marginTop: 32}}>
|
||||
<DefaultButton
|
||||
text={intl.get("service.exportToLite")}
|
||||
onRenderMenuIcon={() => <></>}
|
||||
menuProps={menuProps} />
|
||||
</Stack>
|
||||
}
|
||||
|
||||
export default LiteExporter
|
|
@ -202,7 +202,8 @@
|
|||
"importGroups": "Import groups",
|
||||
"failure": "Cannot connect to service",
|
||||
"failureHint": "Please check the service configuration or network status.",
|
||||
"fetchUnlimited": "Unlimited (not recommended)"
|
||||
"fetchUnlimited": "Unlimited (not recommended)",
|
||||
"exportToLite": "Export to Fluent Reader Lite"
|
||||
},
|
||||
"app": {
|
||||
"cleanup": "Clean up",
|
||||
|
|
|
@ -200,7 +200,8 @@
|
|||
"importGroups": "导入分组",
|
||||
"failure": "连接到服务时出错",
|
||||
"failureHint": "请检查服务配置或网络连接",
|
||||
"fetchUnlimited": "无限制(不建议)"
|
||||
"fetchUnlimited": "无限制(不建议)",
|
||||
"exportToLite": "导出至 Fluent Reader Lite"
|
||||
},
|
||||
"app": {
|
||||
"cleanup": "清理",
|
||||
|
|
|
@ -200,7 +200,8 @@
|
|||
"importGroups": "匯入分組",
|
||||
"failure": "連線到服務時出錯",
|
||||
"failureHint": "請檢查服務配置或網路連線",
|
||||
"fetchUnlimited": "無限制(不建議)"
|
||||
"fetchUnlimited": "無限制(不建議)",
|
||||
"exportToLite": "匯出至 Fluent Reader Lite"
|
||||
},
|
||||
"app": {
|
||||
"cleanup": "清理",
|
||||
|
|
|
@ -94,7 +94,7 @@ export async function importAll() {
|
|||
let requests = Object.entries(configs.nedb).map(([key, value]) => {
|
||||
return objectStore.put(value, key)
|
||||
})
|
||||
let promises = requests.map(req => new Promise((resolve, reject) => {
|
||||
let promises = requests.map(req => new Promise<void>((resolve, reject) => {
|
||||
req.onsuccess = () => resolve()
|
||||
req.onerror = () => reject()
|
||||
}))
|
||||
|
|
Loading…
Reference in New Issue