Replaced browser_action with a page_action
This commit is contained in:
parent
9ff4ea8564
commit
55397b10d7
10 changed files with 115 additions and 130 deletions
BIN
src/assets/icon-gray-128.png
Normal file
BIN
src/assets/icon-gray-128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
BIN
src/assets/icon-gray-16.png
Normal file
BIN
src/assets/icon-gray-16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
src/assets/icon-gray-48.png
Normal file
BIN
src/assets/icon-gray-48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
|
@ -1,69 +1,101 @@
|
|||
import browser from 'webextension-polyfill';
|
||||
|
||||
let awaitingResponse = false
|
||||
|
||||
const onFeedDownloaded = (req: XMLHttpRequest) => {
|
||||
return async () => {
|
||||
awaitingResponse = false
|
||||
if (req.status >= 400) {
|
||||
console.error(
|
||||
`Could not load URL feed: ${req.responseURL}: ` +
|
||||
`${req.status}: ${req.statusText}`
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const [tab] = await browser.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true
|
||||
})
|
||||
|
||||
if (!tab || tab.id === -1)
|
||||
return
|
||||
|
||||
await browser.tabs.sendMessage(
|
||||
tab.id, {
|
||||
type: 'renderFeed',
|
||||
document: req.responseText
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const renderFeed = (url: string) => {
|
||||
awaitingResponse = true
|
||||
const req = new XMLHttpRequest()
|
||||
req.onload = onFeedDownloaded(req)
|
||||
req.open('GET', url)
|
||||
req.responseType = 'text'
|
||||
req.send()
|
||||
}
|
||||
|
||||
browser.webNavigation.onCompleted.addListener(
|
||||
async (event: {tabId: Number}) => {
|
||||
const { tabId } = event
|
||||
await browser.tabs.sendMessage(tabId, {type: 'renderFeed'})
|
||||
}
|
||||
)
|
||||
|
||||
browser.webRequest.onHeadersReceived.addListener(
|
||||
async (event: {
|
||||
url: string,
|
||||
responseHeaders: Array<{name: string, value: string}>
|
||||
}) => {
|
||||
if (awaitingResponse)
|
||||
return
|
||||
|
||||
const {url, responseHeaders} = event
|
||||
const contentType = responseHeaders.find(
|
||||
h => h.name.toLowerCase() === 'content-type'
|
||||
)?.value || ''
|
||||
|
||||
if (contentType.startsWith('application/rss+xml'))
|
||||
renderFeed(url)
|
||||
},
|
||||
{urls: ['<all_urls>']},
|
||||
['blocking', 'responseHeaders']
|
||||
)
|
||||
|
||||
import browser from 'webextension-polyfill';
|
||||
|
||||
interface State {
|
||||
awaitingResponse: boolean
|
||||
feedUrl: string | null
|
||||
}
|
||||
|
||||
const state: State = {
|
||||
awaitingResponse: false,
|
||||
feedUrl: null,
|
||||
}
|
||||
|
||||
const getActiveTab = async () => {
|
||||
const [tab] = await browser.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true
|
||||
})
|
||||
|
||||
return tab
|
||||
}
|
||||
|
||||
const onFeedDownloaded = (req: XMLHttpRequest) => {
|
||||
return async () => {
|
||||
state.awaitingResponse = false
|
||||
if (req.status >= 400) {
|
||||
console.error(
|
||||
`Could not load URL feed: ${req.responseURL}: ` +
|
||||
`${req.status}: ${req.statusText}`
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const tab = await getActiveTab()
|
||||
if (!tab || tab.id === -1)
|
||||
return
|
||||
|
||||
await browser.tabs.sendMessage(
|
||||
tab.id, {
|
||||
type: 'renderFeed',
|
||||
document: req.responseText
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const renderFeed = (url: string) => {
|
||||
state.awaitingResponse = true
|
||||
const req = new XMLHttpRequest()
|
||||
req.onload = onFeedDownloaded(req)
|
||||
req.open('GET', url)
|
||||
req.responseType = 'text'
|
||||
req.send()
|
||||
}
|
||||
|
||||
const updateFeedUrl = (tabId: number, feedUrl: string | null) => {
|
||||
if (!feedUrl?.length) {
|
||||
browser.pageAction.hide()
|
||||
state.feedUrl = null
|
||||
} else {
|
||||
browser.pageAction.show(tabId)
|
||||
state.feedUrl = feedUrl
|
||||
}
|
||||
}
|
||||
|
||||
browser.pageAction.onClicked.addListener(
|
||||
async () => {
|
||||
if (state.feedUrl?.length)
|
||||
renderFeed(state.feedUrl)
|
||||
}
|
||||
)
|
||||
|
||||
browser.webNavigation.onCompleted.addListener(
|
||||
async (event: {tabId: number}) => {
|
||||
const { tabId } = event
|
||||
const feedUrl = await browser.tabs.sendMessage(tabId, {type: 'extractFeedUrl'})
|
||||
updateFeedUrl(tabId, feedUrl)
|
||||
await browser.tabs.sendMessage(tabId, {type: 'renderFeed'})
|
||||
}
|
||||
)
|
||||
|
||||
browser.webRequest.onHeadersReceived.addListener(
|
||||
async (event: {
|
||||
url: string,
|
||||
responseHeaders: Array<{name: string, value: string}>
|
||||
}) => {
|
||||
if (state.awaitingResponse)
|
||||
return
|
||||
|
||||
const {url, responseHeaders} = event
|
||||
const contentType = responseHeaders.find(
|
||||
h => h.name.toLowerCase() === 'content-type'
|
||||
)?.value || ''
|
||||
|
||||
if (contentType.startsWith('application/rss+xml'))
|
||||
renderFeed(url)
|
||||
},
|
||||
{urls: ['<all_urls>']},
|
||||
['blocking', 'responseHeaders']
|
||||
)
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ const extractFeedUrl = () => {
|
|||
browser.runtime.onMessage.addListener(
|
||||
async (
|
||||
message: {
|
||||
type: Object,
|
||||
type: string,
|
||||
url: string,
|
||||
document: string,
|
||||
}
|
||||
|
|
|
@ -3,9 +3,13 @@
|
|||
"description": "An easy way to render RSS feeds directly in your browser",
|
||||
"version": "0.1.2",
|
||||
"manifest_version": 2,
|
||||
"browser_action": {
|
||||
"default_title": "Feed Viewer",
|
||||
"default_popup": "popup/index.html"
|
||||
"page_action": {
|
||||
"default_icon": {
|
||||
"16": "assets/icon-gray-16.png",
|
||||
"48": "assets/icon-gray-48.png",
|
||||
"128": "assets/icon-gray-128.png"
|
||||
},
|
||||
"default_title": "Detected an RSS/Atom feed"
|
||||
},
|
||||
"icons": {
|
||||
"16": "assets/icon16.png",
|
||||
|
|
|
@ -3,14 +3,13 @@
|
|||
"description": "An easy way to render RSS feeds directly in your browser",
|
||||
"version": "0.1.2",
|
||||
"manifest_version": 3,
|
||||
"action": {
|
||||
"default_title": "Feed Viewer",
|
||||
"default_popup": "popup/index.html",
|
||||
"page_action": {
|
||||
"default_icon": {
|
||||
"16": "assets/icon16.png",
|
||||
"48": "assets/icon48.png",
|
||||
"128": "assets/icon128.png"
|
||||
}
|
||||
"16": "assets/icon-gray-16.png",
|
||||
"48": "assets/icon-gray-48.png",
|
||||
"128": "assets/icon-gray-128.png"
|
||||
},
|
||||
"default_title": "Detected an RSS/Atom feed"
|
||||
},
|
||||
"background": {
|
||||
"service_worker": "background.ts",
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
<template>
|
||||
<div class="popup">
|
||||
<div v-if="feedUrl">
|
||||
<a :href="feedUrl" target="_blank">Found a feed URL</a>
|
||||
</div>
|
||||
<div v-else>
|
||||
No feed URLs found on this page
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import browser from 'webextension-polyfill';
|
||||
|
||||
export default {
|
||||
name: 'Popup',
|
||||
data() {
|
||||
return {
|
||||
feedUrl: null,
|
||||
}
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
const [tab] = await browser.tabs.query({ active: true, currentWindow: true })
|
||||
this.feedUrl = await browser.tabs.sendMessage(tab.id, {type: 'extractFeedUrl'})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.popup {
|
||||
padding: 1em;
|
||||
}
|
||||
</style>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>RSS Viewer Popup</title>
|
||||
</head>
|
||||
<body style="min-width: 200px;">
|
||||
<div id="app"></div>
|
||||
<script type="module" src="./main.ts"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +0,0 @@
|
|||
import { createApp } from "vue";
|
||||
import App from "./Popup.vue";
|
||||
|
||||
const app = createApp(App)
|
||||
app.mount('#app')
|
Loading…
Reference in a new issue