Skip to content

Commit 48b69e7

Browse files
committed
Feature: Use icon url of browser (#11)
1 parent 19bd856 commit 48b69e7

File tree

7 files changed

+95
-10
lines changed

7 files changed

+95
-10
lines changed

src/app/components/report/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ const queryWhiteList = async () => {
125125
return await Promise.resolve()
126126
}
127127

128-
const host2ElLink = (host: string) => {
128+
const host2ElLink = (host: string, iconUrl: string) => {
129129
const link = h(ElLink,
130130
{ href: `https://${host}`, target: '_blank' },
131131
() => host
@@ -134,7 +134,7 @@ const host2ElLink = (host: string) => {
134134
{ style: 'height:23px;line-height:23px;padding-left:2px;' },
135135
h('img',
136136
{
137-
src: FAVICON(host),
137+
src: iconUrl || FAVICON(host),
138138
width: 12,
139139
height: 12
140140
}
@@ -306,7 +306,7 @@ export default defineComponent(() => {
306306
}, {
307307
default: ({ row }: { row: SiteInfo }) => {
308308
if (!mergeDomainRef.value) {
309-
return host2ElLink(row.host)
309+
return host2ElLink(row.host, row.iconUrl)
310310
} else {
311311
return h(ElTooltip,
312312
{
@@ -320,7 +320,7 @@ export default defineComponent(() => {
320320
{ class: 'el-link el-link--default is-underline' },
321321
h('span', { class: 'el-link--inner' }, row.host)
322322
),
323-
content: () => h('div', { style: 'margin: 10px' }, row.mergedHosts.map(host => h('p', host2ElLink(host))))
323+
content: () => h('div', { style: 'margin: 10px' }, row.mergedHosts.map(origin => h('p', host2ElLink(origin.host, origin.iconUrl))))
324324
})
325325
}
326326
}

src/background/index.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { openLog } from '../common/logger'
2+
import iconUrlDatabase from '../database/icon-url-database'
23
import timerService from '../service/timer-service'
34
import { extractHostname, isBrowserUrl } from '../util/pattern'
45
import versionManager from './version-manager'
@@ -54,4 +55,17 @@ setInterval(() => {
5455
timeMap = {}
5556
}, 2048)
5657

57-
chrome.runtime.onInstalled.addListener(detail => versionManager.onChromeInstalled(detail.reason))
58+
chrome.runtime.onInstalled.addListener(detail => versionManager.onChromeInstalled(detail.reason))
59+
60+
chrome.webNavigation.onCompleted.addListener((detail) => {
61+
if (detail.frameId > 0) {
62+
// we don't care about activity occurring within a subframe of a tab
63+
return
64+
}
65+
chrome.tabs.get(detail.tabId, tab => {
66+
const domain = extractHostname(tab.url)
67+
const iconUrl = tab.favIconUrl
68+
if (!domain || !iconUrl) return
69+
iconUrlDatabase.put(domain, iconUrl)
70+
})
71+
})

src/database/icon-url-database.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { REMAIN_WORD_PREFIX } from "./constant"
2+
3+
const DB_KEY_PREFIX = REMAIN_WORD_PREFIX + "ICON_URL"
4+
5+
const generateKey = (host: string) => DB_KEY_PREFIX + host
6+
7+
const urlOf = (key: string) => key.substring(DB_KEY_PREFIX.length)
8+
9+
/**
10+
* The icon url of hosts
11+
*
12+
* @since 0.1.7
13+
*/
14+
class IconUrlDatabase {
15+
private localStorage = chrome.storage.local
16+
17+
/**
18+
* Replace or insert
19+
*
20+
* @param host host
21+
* @param iconUrl icon url
22+
*/
23+
put(host: string, iconUrl: string): Promise<void> {
24+
const toUpdate = {}
25+
toUpdate[generateKey(host)] = iconUrl
26+
return new Promise(resolve => this.localStorage.set(toUpdate, resolve))
27+
}
28+
29+
/**
30+
* @param hosts hosts
31+
*/
32+
get(...hosts: string[]): Promise<{ [host: string]: string }> {
33+
const keys = hosts.map(generateKey)
34+
return new Promise(resolve =>
35+
this.localStorage.get(keys,
36+
items => {
37+
const result = {}
38+
for (const [key, iconUrl] of Object.entries(items)) {
39+
result[urlOf(key)] = iconUrl
40+
}
41+
resolve(result)
42+
}
43+
)
44+
)
45+
}
46+
}
47+
48+
export default new IconUrlDatabase()

src/entity/dto/site-info.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@ export default class SiteInfo {
1515
*
1616
* @since 0.1.5
1717
*/
18-
mergedHosts: string[]
18+
mergedHosts: SiteInfo[]
19+
/**
20+
* Icon url
21+
*
22+
* Must be undefined if merged
23+
*/
24+
iconUrl?: string
1925

2026
constructor(host: string, date?: string) {
2127
this.host = host

src/manifest.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module.exports = {
3737
permissions: [
3838
'storage',
3939
'tabs',
40+
'webNavigation'
4041
],
4142
browser_action: {
4243
default_popup: "static/popup.html",

src/popup/app.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const queryDataAndUpdate = () => {
4949
sortOrder: SortDirect.DESC
5050
}
5151
timerService
52-
.select(param)
52+
.select(param, true)
5353
.then(rows => {
5454
const result = []
5555
const other: SiteInfo = { host: t('popup.otherLabel'), focus: 0, total: 0, date: '0000-00-00', time: 0, mergedHosts: [] }
@@ -138,7 +138,7 @@ const pieOptions: () => any = () => {
138138
height: LABEL_ICON_SIZE,
139139
width: LABEL_ICON_SIZE,
140140
fontSize: LABEL_ICON_SIZE,
141-
backgroundColor: { image: FAVICON(host) }
141+
backgroundColor: { image: d.iconUrl || FAVICON(host) }
142142
}
143143
})
144144
options.legend.data = legendData

src/service/timer-service.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import CustomizedDOmainMergeRuler from './domain-merge-ruler'
77
import DomainMergeRuleItem from '../entity/dto/domain-merge-rule-item'
88
import mergeRuleDatabase from '../database/merge-rule-database'
99
import WastePerDay from '../entity/dao/waste-per-day'
10+
import iconUrlDatabase from '../database/icon-url-database'
1011

1112
declare type PageParam = {
1213
pageNum?: number
@@ -88,8 +89,18 @@ class TimeService {
8889
return timerDatabase.delete(rows)
8990
}
9091

91-
async select(param?: TimerQueryParam): Promise<SiteInfo[]> {
92+
private async fillIconUrl(siteInfos: SiteInfo[]): Promise<void> {
93+
const hosts = siteInfos.map(o => o.host)
94+
const iconUrlMap = await iconUrlDatabase.get(...hosts)
95+
siteInfos.forEach(siteInfo => {
96+
siteInfo.iconUrl = iconUrlMap[siteInfo.host]
97+
})
98+
return Promise.resolve()
99+
}
100+
101+
async select(param?: TimerQueryParam, needIconUrl?: boolean): Promise<SiteInfo[]> {
92102
log("service: select:{param}", param)
103+
param = param || {}
93104
let origin = await timerDatabase.select(param as TimerCondition)
94105
// Process after select
95106
// 1st merge
@@ -112,6 +123,10 @@ class TimeService {
112123
return order * (aa > bb ? 1 : -1)
113124
})
114125
}
126+
// 3rd get icon url if need
127+
if (!param.mergeDomain && needIconUrl) {
128+
await this.fillIconUrl(origin)
129+
}
115130
return Promise.resolve(origin)
116131
}
117132

@@ -128,6 +143,7 @@ class TimeService {
128143
const endIndex = (pageNum) * pageSize
129144
const total = origin.length
130145
const list: SiteInfo[] = startIndex >= total ? [] : origin.slice(startIndex, Math.min(endIndex, total))
146+
await this.fillIconUrl(list)
131147
return Promise.resolve({ total, list })
132148
}
133149

@@ -151,7 +167,7 @@ class TimeService {
151167
const merged = this.merge(map, o, domain + date)
152168
merged.host = domain
153169
const mergedHosts = merged.mergedHosts || (merged.mergedHosts = [])
154-
mergedHosts.push(host)
170+
mergedHosts.push(o)
155171
})
156172
for (let key in map) {
157173
newSiteInfos.push(map[key])

0 commit comments

Comments
 (0)