store filter type & xml charset detection

This commit is contained in:
刘浩远 2020-08-11 18:09:08 +08:00
parent c6420d1ec8
commit e0f1b4e6e5
7 changed files with 38 additions and 13 deletions

View File

@ -89,6 +89,13 @@ const settingsBridge = {
ipcRenderer.invoke("set-service-configs", configs)
},
getFilterType: (): number => {
return ipcRenderer.sendSync("get-filter-type")
},
setFilterType: (filterType: number) => {
ipcRenderer.invoke("set-filter-type", filterType)
},
getAll: () => {
return ipcRenderer.sendSync("get-all-settings") as Object
},

View File

@ -145,3 +145,11 @@ ipcMain.on("get-service-configs", (event) => {
ipcMain.handle("set-service-configs", (_, configs: ServiceConfigs) => {
store.set(SERVICE_CONFIGS_STORE_KEY, configs)
})
const FILTER_TYPE_STORE_KEY = "filterType"
ipcMain.on("get-filter-type", (event) => {
event.returnValue = store.get(FILTER_TYPE_STORE_KEY, null)
})
ipcMain.handle("set-filter-type", (_, filterType: number) => {
store.set(FILTER_TYPE_STORE_KEY, filterType)
})

View File

@ -65,4 +65,5 @@ export type SchemaTypes = {
fetchInterval: number
searchEngine: SearchEngines
serviceConfigs: ServiceConfigs
filterType: number
}

View File

@ -12,16 +12,19 @@ export enum FilterType {
FullSearch = 1 << 3,
CaseInsensitive = 1 << 4,
Default = ShowRead | ShowNotStarred | CaseInsensitive,
Default = ShowRead | ShowNotStarred,
UnreadOnly = ShowNotStarred,
StarredOnly = ShowRead,
Toggles = ShowHidden | FullSearch
Toggles = ShowHidden | FullSearch | CaseInsensitive,
}
export class FeedFilter {
type: FilterType
search: string
constructor(type=FilterType.Default, search="") {
constructor(type: FilterType = null, search="") {
if (type === null && (type = window.settings.getFilterType()) === null) {
type = FilterType.Default | FilterType.CaseInsensitive
}
this.type = type
this.search = search
}

View File

@ -174,7 +174,9 @@ const applyFilterDone = (filter: FeedFilter): PageActionTypes => ({
})
function applyFilter(filter: FeedFilter): AppThunk {
return (dispatch) => {
return (dispatch, getState) => {
const oldFilterType = getState().page.filter.type
if (filter.type !== oldFilterType) window.settings.setFilterType(filter.type)
dispatch(applyFilterDone(filter))
dispatch(initFeeds(true))
}

View File

@ -68,7 +68,7 @@ export class SourceRule {
constructor(regex: string, actions: string[], fullSearch: boolean, caseSensitive: boolean, match: boolean) {
this.filter = new FeedFilter(FilterType.Default | FilterType.ShowHidden, regex)
if (fullSearch) this.filter.type |= FilterType.FullSearch
if (caseSensitive) this.filter.type &= ~FilterType.CaseInsensitive
if (!caseSensitive) this.filter.type |= FilterType.CaseInsensitive
this.match = match
this.actions = RuleActions.fromKeys(actions)
}

View File

@ -29,17 +29,21 @@ const rssParser = new Parser({
})
const CHARSET_RE = /charset=([^()<>@,;:\"/[\]?.=\s]*)/i
const XML_ENCODING_RE = /^<\?xml.+encoding="(.+)".*\?>\s*\n/i
export async function decodeFetchResponse(response: Response, isHTML = false) {
const buffer = await response.arrayBuffer()
const ctype = response.headers.has("content-type") && response.headers.get("content-type")
const charset = (ctype && CHARSET_RE.test(ctype)) ? CHARSET_RE.exec(ctype)[1] : undefined
const decoder = new TextDecoder(charset)
let content = decoder.decode(buffer)
if (charset === undefined && isHTML) {
const dom = domParser.parseFromString(content, "text/html")
const meta = dom.querySelector("meta[charset]")
if (meta) {
content = (new TextDecoder(meta.getAttribute("charset"))).decode(buffer)
let charset = (ctype && CHARSET_RE.test(ctype)) ? CHARSET_RE.exec(ctype)[1] : undefined
let content = (new TextDecoder(charset)).decode(buffer)
if (charset === undefined) {
if (isHTML) {
const dom = domParser.parseFromString(content, "text/html")
charset = dom.querySelector("meta[charset]")?.getAttribute("charset")?.toLowerCase()
} else {
charset = (XML_ENCODING_RE.test(content) && XML_ENCODING_RE.exec(content)[1])?.toLowerCase()
}
if (charset && charset !== "utf-8" && charset !== "utf8") {
content = (new TextDecoder(charset)).decode(buffer)
}
}
return content