Skip to content

Commit 1526345

Browse files
undead-voronrr-denis-inozemtsevatinuxDen
authored
feat: add option to display framework icon (#21)
* save tabs data to storage handle service worker for manifest v3 * refactor background. Split background into modules * add branded icons * update tabs manager * add cache controller * implement user local settings * add settings controller UI * change UI color * Update src/components/Settings.vue * use framework icon by default #21 (comment) * remove on-click-outside * remove checkbox icons * chore: update vta --------- Co-authored-by: Den <[email protected]> Co-authored-by: Sébastien Chopin <[email protected]> Co-authored-by: Den <[email protected]> Co-authored-by: Sébastien Chopin <[email protected]>
1 parent 742cbc8 commit 1526345

File tree

15 files changed

+106
-50
lines changed

15 files changed

+106
-50
lines changed

chrome/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"background": {
2929
"service_worker": "background.js"
3030
},
31-
"permissions": ["scripting"],
31+
"permissions": ["scripting", "storage"],
3232
"host_permissions": [
3333
"<all_urls>"
3434
],

firefox/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"background": {
2828
"scripts": ["background.js"]
2929
},
30-
"permissions": ["https://*/*"],
30+
"permissions": ["https://*/*", "storage"],
3131
"content_security_policy": "script-src 'self'; object-src 'self'",
3232
"web_accessible_resources": ["injected.js"]
3333
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"postcss-loader": "^3.0.0",
3232
"tailwindcss": "^1.3.5",
3333
"vue": "^2.6.12",
34-
"vue-telescope-analyzer": "^0.9.19",
34+
"vue-telescope-analyzer": "^0.9.21",
3535
"vuex": "^3.1.3",
3636
"webextension-polyfill": "^0.3.1"
3737
},

src/background/TabsStateService.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import CacheService from '../shared/CacheService'
2+
3+
// persistent state storage
4+
export default class TabsStorage extends CacheService {
5+
get key () {
6+
return 'tabs'
7+
}
8+
9+
async get () {
10+
const cache = await super.get()
11+
return cache || {}
12+
}
13+
14+
async updateData (tabId, state) {
15+
const cache = await this.get()
16+
return this.set({ ...cache, [tabId]: state })
17+
}
18+
}
Lines changed: 60 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { IS_CHROME, IS_FIREFOX, isSupportExecutionVersion } from './utils'
2-
const browser = require('webextension-polyfill')
1+
import { IS_CHROME, IS_FIREFOX, isSupportExecutionVersion } from '../utils'
2+
import browser from 'webextension-polyfill'
3+
import TabsStateService from './TabsStateService'
34

4-
const tabsStorage = {}
5+
const tabsState = new TabsStateService()
56

67
if (IS_CHROME && isSupportExecutionVersion) {
78
/**
@@ -30,39 +31,75 @@ if (IS_CHROME && isSupportExecutionVersion) {
3031
)
3132
}
3233

33-
browser.tabs.onActivated.addListener(handleActivated)
3434
browser.tabs.onUpdated.addListener(handleUpdated)
35+
browser.runtime.onStartup.addListener(() => {
36+
// clear state on startup.
37+
// note: chrome allows to use 'browser.storage.session' but it is available in chrome only.
38+
// for firefox a 'window.session' can be considered as alternative.
39+
// TODO: create polyfill for session store.
40+
tabsState.clear()
41+
})
3542

36-
function setIcon (details) {
43+
async function setIcon (details) {
3744
// because manifest version is different
3845
if (IS_FIREFOX) {
39-
browser.browserAction.setIcon(details)
46+
await browser.browserAction.setIcon(details)
4047
} else {
41-
browser.action.setIcon(details)
48+
await browser.action.setIcon(details)
4249
}
4350
}
4451

52+
const setIconForTab = async (tabId) => {
53+
const tabs = await tabsState.get()
54+
const tab = tabs[tabId];
55+
if (tab?.framework?.slug) {
56+
const slug = tab.framework.slug
57+
const iconPath = `icons/${slug}.png`
58+
try {
59+
await setIcon({tabId, path: iconPath});
60+
} catch(e) {
61+
await setIcon({
62+
tabId,
63+
path: 'icons/icon-128.png'
64+
})
65+
}
66+
} else {
67+
await setIcon({
68+
tabId,
69+
path: tab?.hasVue ? 'icons/icon-128.png' : 'icons/icon-grey-128.png'
70+
})
71+
}
72+
}
73+
74+
browser.storage.local.onChanged.addListener(async (payload) => {
75+
if (payload.settings) {
76+
const tabs = await browser.tabs.query({});
77+
tabs.forEach(tab => {
78+
if (tab.id) {
79+
setIconForTab(tab.id)
80+
}
81+
})
82+
}
83+
})
84+
4585
browser.runtime.onMessage.addListener(
4686
async function (message, sender, sendResponse) {
4787
if (message.action === 'analyze') {
4888
// when sending message from popup.js there's no sender.tab, so need to pass tabId
4989
const tabId = (sender.tab && sender.tab.id) || message.payload.tabId
50-
setIcon({
51-
tabId: tabId,
52-
path: message.payload.hasVue ? 'icons/icon-128.png' : 'icons/icon-grey-128.png'
53-
})
5490

55-
if (!tabsStorage[tabId]) {
56-
tabsStorage[tabId] = message.payload
91+
const tabs = await tabsState.get()
92+
if (!tabs[tabId]) {
93+
tabs[tabId] = message.payload
5794
} else {
5895
// temporary fix when hit CSP
5996
if (!message.payload.modules.length) delete message.payload.modules
6097
if (!message.payload.plugins.length) delete message.payload.plugins
6198

62-
tabsStorage[tabId] = { ...tabsStorage[tabId], ...message.payload }
99+
tabs[tabId] = { ...tabs[tabId], ...message.payload }
63100
}
64101

65-
const showcase = tabsStorage[tabId]
102+
const showcase = tabs[tabId]
66103
if (showcase.hasVue && !showcase.slug) {
67104
try {
68105
if (typeof EventSource === 'undefined') {
@@ -72,7 +109,7 @@ browser.runtime.onMessage.addListener(
72109
const sse = new EventSource(
73110
`https://service.vuetelescope.com?url=${message.payload.url}`
74111
)
75-
sse.addEventListener('message', (event) => {
112+
sse.addEventListener('message', async (event) => {
76113
try {
77114
const res = JSON.parse(event.data)
78115
if (!res.error && !res.isAdultContent) {
@@ -87,6 +124,7 @@ browser.runtime.onMessage.addListener(
87124
if (!showcase.plugins.length && res.plugins.length) {
88125
showcase.plugins = res.plugins
89126
}
127+
await tabsState.updateData(tabId, tabs[tabId])
90128
} else {
91129
throw new Error('API call to VT failed')
92130
}
@@ -96,48 +134,28 @@ browser.runtime.onMessage.addListener(
96134
})
97135
} catch (err) {}
98136
}
99-
// tabsStorage[tabId] = message.payload
137+
await tabsState.updateData(tabId, tabs[tabId])
138+
await setIconForTab(tabId);
100139
} else if (!sender.tab) {
101140
if (message.action === 'getShowcase') {
102-
// this is likely popup requesting
103-
// sendResponse doesn't work in Firefox 👀
104-
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage#Sending_a_synchronous_response
105-
return Promise.resolve({ payload: tabsStorage[message.payload.tabId] })
106-
// sendResponse({ payload: tabsStorage[message.payload.tabId] })
141+
const tabs = await tabsState.get()
142+
return { payload: tabs[message.payload.tabId] }
107143
}
108144
}
109145
}
110146
)
111147

112-
// when tab clicked
113-
async function handleActivated ({ tabId, windowId }) {
114-
setIcon({
115-
tabId,
116-
path: tabsStorage[tabId] && tabsStorage[tabId] && tabsStorage[tabId].hasVue ? 'icons/icon-128.png' : 'icons/icon-grey-128.png'
117-
})
118-
// chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
119-
// const { id, url, status } = tabs[0]
120-
// if (status === 'complete') {
121-
// // tabsStorage[id].url = url
122-
// }
123-
// })
124-
}
125-
126148
// when tab updated
127149
async function handleUpdated (tabId, changeInfo, tabInfo) {
128150
if (changeInfo.status === 'complete') {
129-
if (!tabsStorage[tabId]) return
151+
const tabs = await tabsState.get()
152+
if (!tabs[tabId]) return
130153
// tabsStorage[tabId].url = tabInfo.url
131154
browser.tabs.sendMessage(tabId, {
132155
from: 'background',
133156
to: 'injected',
134157
action: 'analyze',
135158
payload: {}
136159
})
137-
// chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
138-
// // send message to content script
139-
// chrome.tabs.sendMessage(tabs[0].id, { from: 'background', to: 'injected', payload: { message: 'hello from background with sendMessage' } })
140-
// })
141-
// console.log('tabsStorage', tabsStorage)
142160
}
143161
}

src/icons/gridsome.png

2.79 KB
Loading

src/icons/iles.png

6.34 KB
Loading

src/icons/nuxtjs.png

2.34 KB
Loading

src/icons/quasar.png

3.98 KB
Loading

src/icons/vitepress.png

6.35 KB
Loading

0 commit comments

Comments
 (0)