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';
|
import browser from 'webextension-polyfill';
|
||||||
|
|
||||||
let awaitingResponse = false
|
interface State {
|
||||||
|
awaitingResponse: boolean
|
||||||
const onFeedDownloaded = (req: XMLHttpRequest) => {
|
feedUrl: string | null
|
||||||
return async () => {
|
}
|
||||||
awaitingResponse = false
|
|
||||||
if (req.status >= 400) {
|
const state: State = {
|
||||||
console.error(
|
awaitingResponse: false,
|
||||||
`Could not load URL feed: ${req.responseURL}: ` +
|
feedUrl: null,
|
||||||
`${req.status}: ${req.statusText}`
|
}
|
||||||
)
|
|
||||||
|
const getActiveTab = async () => {
|
||||||
return
|
const [tab] = await browser.tabs.query({
|
||||||
}
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
const [tab] = await browser.tabs.query({
|
})
|
||||||
active: true,
|
|
||||||
currentWindow: true
|
return tab
|
||||||
})
|
}
|
||||||
|
|
||||||
if (!tab || tab.id === -1)
|
const onFeedDownloaded = (req: XMLHttpRequest) => {
|
||||||
return
|
return async () => {
|
||||||
|
state.awaitingResponse = false
|
||||||
await browser.tabs.sendMessage(
|
if (req.status >= 400) {
|
||||||
tab.id, {
|
console.error(
|
||||||
type: 'renderFeed',
|
`Could not load URL feed: ${req.responseURL}: ` +
|
||||||
document: req.responseText
|
`${req.status}: ${req.statusText}`
|
||||||
}
|
)
|
||||||
)
|
|
||||||
}
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderFeed = (url: string) => {
|
const tab = await getActiveTab()
|
||||||
awaitingResponse = true
|
if (!tab || tab.id === -1)
|
||||||
const req = new XMLHttpRequest()
|
return
|
||||||
req.onload = onFeedDownloaded(req)
|
|
||||||
req.open('GET', url)
|
await browser.tabs.sendMessage(
|
||||||
req.responseType = 'text'
|
tab.id, {
|
||||||
req.send()
|
type: 'renderFeed',
|
||||||
}
|
document: req.responseText
|
||||||
|
}
|
||||||
browser.webNavigation.onCompleted.addListener(
|
)
|
||||||
async (event: {tabId: Number}) => {
|
}
|
||||||
const { tabId } = event
|
}
|
||||||
await browser.tabs.sendMessage(tabId, {type: 'renderFeed'})
|
|
||||||
}
|
const renderFeed = (url: string) => {
|
||||||
)
|
state.awaitingResponse = true
|
||||||
|
const req = new XMLHttpRequest()
|
||||||
browser.webRequest.onHeadersReceived.addListener(
|
req.onload = onFeedDownloaded(req)
|
||||||
async (event: {
|
req.open('GET', url)
|
||||||
url: string,
|
req.responseType = 'text'
|
||||||
responseHeaders: Array<{name: string, value: string}>
|
req.send()
|
||||||
}) => {
|
}
|
||||||
if (awaitingResponse)
|
|
||||||
return
|
const updateFeedUrl = (tabId: number, feedUrl: string | null) => {
|
||||||
|
if (!feedUrl?.length) {
|
||||||
const {url, responseHeaders} = event
|
browser.pageAction.hide()
|
||||||
const contentType = responseHeaders.find(
|
state.feedUrl = null
|
||||||
h => h.name.toLowerCase() === 'content-type'
|
} else {
|
||||||
)?.value || ''
|
browser.pageAction.show(tabId)
|
||||||
|
state.feedUrl = feedUrl
|
||||||
if (contentType.startsWith('application/rss+xml'))
|
}
|
||||||
renderFeed(url)
|
}
|
||||||
},
|
|
||||||
{urls: ['<all_urls>']},
|
browser.pageAction.onClicked.addListener(
|
||||||
['blocking', 'responseHeaders']
|
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(
|
browser.runtime.onMessage.addListener(
|
||||||
async (
|
async (
|
||||||
message: {
|
message: {
|
||||||
type: Object,
|
type: string,
|
||||||
url: string,
|
url: string,
|
||||||
document: string,
|
document: string,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,13 @@
|
||||||
"description": "An easy way to render RSS feeds directly in your browser",
|
"description": "An easy way to render RSS feeds directly in your browser",
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"browser_action": {
|
"page_action": {
|
||||||
"default_title": "Feed Viewer",
|
"default_icon": {
|
||||||
"default_popup": "popup/index.html"
|
"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": {
|
"icons": {
|
||||||
"16": "assets/icon16.png",
|
"16": "assets/icon16.png",
|
||||||
|
|
|
@ -3,14 +3,13 @@
|
||||||
"description": "An easy way to render RSS feeds directly in your browser",
|
"description": "An easy way to render RSS feeds directly in your browser",
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"action": {
|
"page_action": {
|
||||||
"default_title": "Feed Viewer",
|
|
||||||
"default_popup": "popup/index.html",
|
|
||||||
"default_icon": {
|
"default_icon": {
|
||||||
"16": "assets/icon16.png",
|
"16": "assets/icon-gray-16.png",
|
||||||
"48": "assets/icon48.png",
|
"48": "assets/icon-gray-48.png",
|
||||||
"128": "assets/icon128.png"
|
"128": "assets/icon-gray-128.png"
|
||||||
}
|
},
|
||||||
|
"default_title": "Detected an RSS/Atom feed"
|
||||||
},
|
},
|
||||||
"background": {
|
"background": {
|
||||||
"service_worker": "background.ts",
|
"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