From 47220ccdee46c6dc47120c7386c24adc8b5181db Mon Sep 17 00:00:00 2001 From: NejcZdovc Date: Fri, 19 Apr 2019 12:58:25 +0200 Subject: [PATCH] Adds different logo for verified publishers Resolves https://github.com/brave/brave-browser/issues/4043 --- .../extension/brave_rewards/BUILD.gn | 4 +- .../actions/rewards_panel_actions.ts | 5 + .../extension/brave_rewards/background.ts | 25 ++-- .../brave_rewards/background/browserAction.ts | 41 ++++++ .../reducers/rewards_panel_reducer.ts | 55 +++++--- .../constants/rewards_panel_types.ts | 3 +- .../brave_rewards/img/rewards-off.png | Bin 627 -> 0 bytes .../brave_rewards/img/rewards-off@2x.png | Bin 1293 -> 0 bytes .../brave_rewards/img/rewards-off@3x.png | Bin 1956 -> 0 bytes components/definitions/rewardsExtensions.d.ts | 1 + .../background/browserAction_test.ts | 121 ++++++++++++++++++ .../reducers/rewards_panel_reducer_test.ts | 43 +++++++ 12 files changed, 266 insertions(+), 32 deletions(-) create mode 100644 components/brave_rewards/resources/extension/brave_rewards/background/browserAction.ts delete mode 100644 components/brave_rewards/resources/extension/brave_rewards/img/rewards-off.png delete mode 100644 components/brave_rewards/resources/extension/brave_rewards/img/rewards-off@2x.png delete mode 100644 components/brave_rewards/resources/extension/brave_rewards/img/rewards-off@3x.png create mode 100644 components/test/brave_rewards/extension/brave_rewards/background/browserAction_test.ts diff --git a/components/brave_rewards/resources/extension/brave_rewards/BUILD.gn b/components/brave_rewards/resources/extension/brave_rewards/BUILD.gn index 10706565251b8..c2cf7ffd81af4 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/BUILD.gn +++ b/components/brave_rewards/resources/extension/brave_rewards/BUILD.gn @@ -18,6 +18,7 @@ transpile_web_ui("brave_rewards_panel") { "background/reducers/grant_panel_reducer.ts", "background/reducers/index.ts", "background/reducers/rewards_panel_reducer.ts", + "background/browserAction.ts", "background/storage.ts", "background/store.ts", "brave_rewards_panel.html", @@ -25,9 +26,6 @@ transpile_web_ui("brave_rewards_panel") { "components/app.tsx", "components/panel.tsx", "constants/rewards_panel_types.ts", - "img/rewards-off.png", - "img/rewards-off@2x.png", - "img/rewards-off@3x.png", "img/rewards-on.png", "img/rewards-on@2x.png", "img/rewards-on@3x.png", diff --git a/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts b/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts index c402128dbefec..373fdf4ac64c3 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts @@ -137,6 +137,11 @@ export const refreshPublisher = (verified: boolean, publisherKey: string) => act verified, publisherKey }) + export const onAllNotifications = (list: RewardsExtension.Notification[]) => action(types.ON_ALL_NOTIFICATIONS, { list }) + +export const init = (tabs: chrome.tabs.Tab[]) => action(types.ON_INIT, { + tabs +}) diff --git a/components/brave_rewards/resources/extension/brave_rewards/background.ts b/components/brave_rewards/resources/extension/brave_rewards/background.ts index c31e0865aa601..5cb4bfda7deaf 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/background.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/background.ts @@ -2,16 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +import rewardsPanelActions from './background/actions/rewardsPanelActions' + import './background/store' import './background/events/rewardsEvents' import './background/events/tabEvents' import batIconOn18Url from './img/rewards-on.png' import batIconOn36Url from './img/rewards-on@2x.png' import batIconOn54Url from './img/rewards-on@3x.png' -// TODO: display 'off' icon at appropriate time -// import batIconOff18Url from './img/rewards-off.png' -// import batIconOff36Url from './img/rewards-off@2x.png' -// import batIconOff54Url from './img/rewards-off@3x.png' const iconOn = { path: { @@ -21,17 +19,20 @@ const iconOn = { } } -// const iconOff = { -// path: { -// 18: batIconOff18Url, -// 36: batIconOff36Url, -// 54: batIconOff54Url -// } -// } - chrome.browserAction.setBadgeBackgroundColor({ color: '#FB542B' }) chrome.browserAction.setIcon(iconOn) +// We need to set initial state for all active tabs in all windows +chrome.tabs.query({ + highlighted: true +}, (tabs) => { + if (!tabs || !tabs.length) { + return + } + + rewardsPanelActions.init(tabs) +}) + chrome.runtime.onInstalled.addListener(function (details) { if (details.reason === 'install') { const initialNotificationDismissed = 'false' diff --git a/components/brave_rewards/resources/extension/brave_rewards/background/browserAction.ts b/components/brave_rewards/resources/extension/brave_rewards/background/browserAction.ts new file mode 100644 index 0000000000000..1191eb8e209df --- /dev/null +++ b/components/brave_rewards/resources/extension/brave_rewards/background/browserAction.ts @@ -0,0 +1,41 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +export const setBadgeText = (state?: RewardsExtension.State, verified: boolean = false, tabId: number = -1) => { + let text = '' + + if (!state) { + return + } + + if (state.notifications && !verified) { + const count = Object.keys(state.notifications).length + if (count > 0) { + text = count.toString() + } + } + + let data: chrome.browserAction.BadgeTextDetails = { + text + } + + if (tabId !== -1) { + data.tabId = tabId + chrome.browserAction.setBadgeBackgroundColor({ + color: verified ? '#4C54D2' : '#FB542B', + tabId + }) + + if (verified) { + data.text = '✓️' + } + } else { + chrome.browserAction.setBadgeBackgroundColor({ + color: '#FB542B' + }) + } + + chrome.browserAction.setBadgeText(data) +} diff --git a/components/brave_rewards/resources/extension/brave_rewards/background/reducers/rewards_panel_reducer.ts b/components/brave_rewards/resources/extension/brave_rewards/background/reducers/rewards_panel_reducer.ts index bd5657c58eeb5..c716defab81a8 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/background/reducers/rewards_panel_reducer.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/background/reducers/rewards_panel_reducer.ts @@ -5,21 +5,7 @@ import { types } from '../../constants/rewards_panel_types' import * as storage from '../storage' import { getTabData } from '../api/tabs_api' - -function setBadgeText (state: RewardsExtension.State): void { - let text = '' - - if (state && state.notifications) { - const count = Object.keys(state.notifications).length - if (count > 0) { - text = count.toString() - } - } - - chrome.browserAction.setBadgeText({ - text - }) -} +import { setBadgeText } from '../browserAction' const getWindowId = (id: number) => { return `id_${id}` @@ -102,9 +88,18 @@ export const rewardsPanelReducer = (state: RewardsExtension.State | undefined, a } publishers[id] = { - tabUrl: tab.url + tabUrl: tab.url, + tabId: tab.id } + } else if (publisher && + publisher.tabUrl === tab.url && + publisher.tabId !== tab.id && + validKey) { + // if we switch between tabs that have the same url, we need to update as well + setBadgeText(state, publisher.verified, tab.id) + publishers[id].tabId = tab.id } + state = { ...state, publishers @@ -120,6 +115,11 @@ export const rewardsPanelReducer = (state: RewardsExtension.State | undefined, a delete publishers[id] } else { publishers[id] = { ...publishers[id], ...publisher } + const newPublisher = publishers[id] + + if (newPublisher.tabId) { + setBadgeText(state, newPublisher.verified, newPublisher.tabId) + } } state = { @@ -407,6 +407,29 @@ export const rewardsPanelReducer = (state: RewardsExtension.State | undefined, a setBadgeText(state) break } + + case types.ON_INIT: { + const tabs: chrome.tabs.Tab[] = payload.tabs + + if (!tabs) { + break + } + + const publishers: Record = state.publishers + + tabs.forEach((tab) => { + const id = getWindowId(tab.windowId) + const publisher = publishers[id] + + if (!publisher || publisher.tabId !== tab.id) { + return + } + + setBadgeText(state, publisher.verified, publisher.tabId) + }) + + break + } } return state } diff --git a/components/brave_rewards/resources/extension/brave_rewards/constants/rewards_panel_types.ts b/components/brave_rewards/resources/extension/brave_rewards/constants/rewards_panel_types.ts index 55a9b9d601d98..31cda69b68a49 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/constants/rewards_panel_types.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/constants/rewards_panel_types.ts @@ -35,7 +35,8 @@ export const enum types { ON_RECURRING_TIPS = '@@rewards_panel/ON_RECURRING_TIPS', ON_PUBLISHER_BANNER = '@@rewards_panel/ON_PUBLISHER_BANNER', ON_PUBLISHER_STATUS_REFRESHED = '@@rewards_panel/ON_PUBLISHER_STATUS_REFRESHED', - ON_ALL_NOTIFICATIONS = '@@rewards_panel/ON_ALL_NOTIFICATIONS' + ON_ALL_NOTIFICATIONS = '@@rewards_panel/ON_ALL_NOTIFICATIONS', + ON_INIT = '@@rewards_panel/ON_INIT' } // Note: This declaration must match the RewardsNotificationType enum in diff --git a/components/brave_rewards/resources/extension/brave_rewards/img/rewards-off.png b/components/brave_rewards/resources/extension/brave_rewards/img/rewards-off.png deleted file mode 100644 index 6ef1990ae4407b8185c3b40bb32aec15872a4cd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 627 zcmV-(0*w8MP)Ku@H<$hYzkfY2#YRTD_vGYcA3^y4nf^2WnE;bRrZHUf=*j0oplg&sihu$A zucADMV?uxXGq|Sz47L{5&f#!Al!0PUXlQ~2(2#1FqKNQ-qwMVLno?2{77h-!=V9Uu z{}{V0Ekilsd>{kGpkKck+JOPg15&`n#q}vP)JFrRxUr#zL*JuM%GEXp&4!%vU5N zWf?iSczRfF+&IJW?%kVLKs6wI15GVnF3@6zXHOsgQ N002ovPDHLkV1hvTE3p6o diff --git a/components/brave_rewards/resources/extension/brave_rewards/img/rewards-off@2x.png b/components/brave_rewards/resources/extension/brave_rewards/img/rewards-off@2x.png deleted file mode 100644 index e017d3077ea6701a2e9a6a92f665ec25679fea0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1293 zcmV+o1@iidP)=5lO&(ub3Y`|7N*uE-L3aDmWQZBL@gVZNecp z8I1bt>gv=9?V=2l7Q_%d1ThjW2kfr`ua}&SnlIrnDM5$rZEr!nsZJPm(|{o6jK%V5 zkyv}yPP8D0<5W5(=<{TPLza{b2_)qsTF`oMsRK?*~^zloir{QODL$N$TY7@bv z7rq9v1o=%Ot{}GBh8e^jb80(z!g*C9kr+6#sK{V3SD7ZcG5-m%au=6_J$#JTk1NR5 z;%tMHa)9QTlau|Y)mmkW=6ZX3Q5s!%k-=@{@0Y&7fKI z_jONdG+8m1t6VP6fx0;|{__N_{z&1XE1sX9`I;7!#RM~imzXYiQ60^3-~NhUjK%^B zjbkyV^PO_FTIHqjkntvqrM8a7u^3g5&GtblBIJ~S6X`sAg1tHfuMgN)xu1R7bwj`( z!RPM4!GkUtji(A?P~alGiGt?fc%yMtrBYVVI6h`JSDK59jcz{1>p!)&HgcRdj&x%L z!EIgx*=deg@H*+~N?&X1>t#GBUN>#viwg^a1{k^ELrxpbZxQ5hd?SV9F&J&cjZc4k z>?er?Q}-2T!+%1dtbF;9b)1iJeJBH328GUZWA3>{P$2OAhp<$8Ig>+|MJrf1B2 zOicgWxz0?fR2rt)VuX*uJ-21~BO9}|_4uxT{Qf&2C_CDDVZl8%J2PDfn^kmn_%Sd> zw{^Ngg(6M0hmW&;jPaGLV^?Z9JW_{BN}leAE8-AGuurddWomNb$KMw{e?JGqEJ(8? zl^??p-RkOcw%_j?QLD35@M8Qg$&w;t>CL&h`%~IB_{ZS16J{zG>edqB! zxN-N+q=sP_vB!ExbjoD1>-qYkJP@WOD)nxu!BBeX)~#!v2Y=0**rT{3vm_A&5>Vh> zT~F$Q?sZK?PSsQ-$uF+T zhdf&_nmK7U6TwrFbJB?sMEwkmrjM{>5JGVX^=xo43kdmL&kyv+j~H2xw{a6IbgLC zA?|SA*!@n7AZmjV#weQ{5Q-+rzFpoF?#{>W#2i%bXOJ|`U1H7-(|>J7#ybg|?60R^ zi4_-D$07#*+>_$q=NL%Q=&&a~O0a$w*@hXIYtnK-!|obAqIqS8ZpPcCB^zdj0GKCeKo$s;QRW8SW%I!0xC=42ll3o z7_`r7Eu7_zuh7S5Vg#`<1YziaFtC?$I7vRM_tMwJ&1Yf`$H*>t`J-K;`XIpczX|q{ zNj`)abM=W>Nl8@#yACNS!VqR4mEfS0G_b%oD#6NOd?H3sG^{@;P%Z&yYi!)-C@Rcr z;bgfdOeAYkEvs|oFz#$#6N3pO6Gp4ZT>{p=a)tT#@GwKlwr!tA&zLbo(a2#8bF`+W zCO}DiF^pI120@%uQ}mrv5YQ+Vl&@2%)YRcab);IYHmFppS&@<9=gywJVB%vW+Tq<# z`ujRN+ZBznFostn=5+p4!>&8RU}Exy>eBN80ReM3TV7uF(ujz#Zcdha!Y^X)^5r=Z zau_L_$HWQ?D`&wjVV_h$zCJWm-iPb@hl?Nl9fAgU}|oQ2~&c zn9!D#G}j`5#Sb3bM@!fQYNVoQ+T-n-N5q^I#;z|KL1t00Zugd9Fi1{LdVR=(b?b=p zqRs*(yw59P_rF%4mK7Bf%P+3TgEec7Y_#XbHQB3LLPKXRc8A^gQFVM^V9SkNY;@-<3HtG-%4R57@zp?P=8CkKm}o_RR3HZ1VX>@M)M;*s5ri!QN7x=E zqzr~vx>v2TELDQ#VS*cvHaz6XGEJnT81$tKVBF-E80lp8!^;~w?jh6IQ&-ytX1xqV z)HHi`T)H`J*>zE)P>E1kT1Hl?P%V^YiNSGyA&%kILMJi#%{S(^#>dA=P48kZF1m(> z-2phRVqBEs0*+DcZ;@q*vG))#TCx}}_s*T0*>%b5D{HM*`}+Fz<;tdi45eBuS!G;q zv8QCw1;w_tK*}oSB-9lb<(}8+w2JnQLSMdIWm}g7ah~yYQf=t;FS4?-bW(OvVwIJ! zUNGp8loMYc7#KKGR<<^Quk*GIyZ?xW{dJd>_``wp)xkk#hZI(nSldHJ46@UbJ;4t$F!1zRclTrZ z^y!~};p=^E&q;_KZf}2}hY>W$#ez`_qA`-aMJ9x}2`_s=Vdd8_TIE6@Uv`kAf3>z= zeqgr`r}OpxZR7o+p@u)gBO)zuZ8>28__@?7^~wtu&Yb1zT!40e6kYm_e;><`PLi9KV*6ow2mOzJ7eU7~g$Eq4`*Q&?y#gDLbI&cHn(VB4R!u8ugJjzygAMLprrN(Kk(n0iY2aw1A2&X7VZ|lv=mpVG`ErcV3qK)Si5Y{-Iq^ZCE zX%9>+*MowzuR%_3aCA-w7SP#w{|sBl7_s>H`Fr841?Me5;fTI}zwOty+t;HUj?pAg zi7p8&_62_QFmc5V4D{Xz4%YU-QHi_oNr_FEd!p-MdoK=`GbRRMw}4nsPjC0tyKUD) z7=}rFfkk_o8o^=pTvSwCl3JsQfS=@#EzM2u;`xOY-;LVs=3A|ox<*Gw(>#qjjqro8 zJX|q^87;U*lLwmyb$NSxYcfSqrfF29H>CuUq}?>o-}6YV);z$C#$+9i4|2azZvsv$ qAC<~McXf4jPOG9`7W04Zfqwy;nQTY-xd>qZ0000 { + describe('setBadgeText', () => { + let spyText: jest.SpyInstance + let spyColor: jest.SpyInstance + + beforeEach(() => { + spyText = jest.spyOn(chrome.browserAction, 'setBadgeText') + spyColor = jest.spyOn(chrome.browserAction, 'setBadgeBackgroundColor') + }) + + afterEach(() => { + spyText.mockRestore() + spyColor.mockRestore() + }) + + it('publisher is not verified, no pending notifications', () => { + const state: RewardsExtension.State = { + notifications: {} + } + + setBadgeText(state) + + expect(spyText).toHaveBeenCalled() + expect(spyText.mock.calls[0][0]).toEqual({ + text: '' + }) + }) + + it('publisher is not verified, pending notifications', () => { + const state: RewardsExtension.State = { + notifications: { + '1': { + id: 'test' + } + } + } + + setBadgeText(state) + + expect(spyText).toHaveBeenCalled() + expect(spyText.mock.calls[0][0]).toEqual({ + text: '1' + }) + }) + + it('publisher is verified, no pending notifications', () => { + const state: RewardsExtension.State = { + notifications: {} + } + + setBadgeText(state, true, 1) + + expect(spyText).toHaveBeenCalled() + const data = spyText.mock.calls[0][0] + expect(data.tabId).toEqual(1) + expect(data.text).toEqual('✓️') + + expect(spyColor).toHaveBeenCalled() + expect(spyColor.mock.calls[0][0]).toEqual({ + color: '#4C54D2', + tabId: 1 + }) + }) + + it('publisher is verified, pending notifications', () => { + const state: RewardsExtension.State = { + notifications: { + '1': { + id: 'test' + } + } + } + + setBadgeText(state, true, 1) + + expect(spyText).toHaveBeenCalled() + const data = spyText.mock.calls[0][0] + expect(data.tabId).toEqual(1) + expect(data.text).toEqual('✓️') + + expect(spyColor).toHaveBeenCalled() + expect(spyColor.mock.calls[0][0]).toEqual({ + color: '#4C54D2', + tabId: 1 + }) + }) + + it('publisher is not verified with tabId, pending notifications', () => { + const state: RewardsExtension.State = { + notifications: { + '1': { + id: 'test' + } + } + } + + setBadgeText(state, false, 1) + + expect(spyText).toHaveBeenCalled() + expect(spyText.mock.calls[0][0]).toEqual({ + text: '1', + tabId: 1 + }) + + expect(spyColor).toHaveBeenCalled() + expect(spyColor.mock.calls[0][0]).toEqual({ + color: '#FB542B', + tabId: 1 + }) + }) + }) +}) diff --git a/components/test/brave_rewards/extension/brave_rewards/background/reducers/rewards_panel_reducer_test.ts b/components/test/brave_rewards/extension/brave_rewards/background/reducers/rewards_panel_reducer_test.ts index 713e58a894877..6cc7c67ad6830 100644 --- a/components/test/brave_rewards/extension/brave_rewards/background/reducers/rewards_panel_reducer_test.ts +++ b/components/test/brave_rewards/extension/brave_rewards/background/reducers/rewards_panel_reducer_test.ts @@ -221,6 +221,49 @@ describe('rewards panel reducer', () => { expect(state.rewardsPanelData).toEqual(expectedState) }) + + it('switching between two tabs that has the same url', () => { + const initState: Rewards.State = { + ...defaultState, + walletCreated: true, + enabledMain: true, + publishers: { + id_1: { + tabUrl: 'https://clifton.io', + publisher_key: 'clifton.io', + tabId: 1 + } + } + } + + const expectedState: Rewards.State = { + ...defaultState, + walletCreated: true, + enabledMain: true, + publishers: { + id_1: { + tabUrl: 'https://clifton.io', + publisher_key: 'clifton.io', + tabId: 2 + } + } + } + + let state = reducers({ rewardsPanelData: initState }, { + type: types.ON_TAB_RETRIEVED, + payload: { + tab: { + url: 'https://clifton.io', + incognito: false, + active: true, + windowId: 1, + id: 2 + } + } + }) + + expect(state.rewardsPanelData).toEqual(expectedState) + }) }) })