diff --git a/browser/ui/webui/brave_new_tab/BUILD.gn b/browser/ui/webui/brave_new_tab/BUILD.gn index 2b82e708170e..e6d8023ad325 100644 --- a/browser/ui/webui/brave_new_tab/BUILD.gn +++ b/browser/ui/webui/brave_new_tab/BUILD.gn @@ -30,6 +30,7 @@ source_set("brave_new_tab") { "//brave/components/brave_new_tab", "//brave/components/brave_new_tab:mojom", "//brave/components/brave_new_tab/resources:generated_resources", + "//brave/components/brave_perf_predictor/common", "//brave/components/brave_private_cdn", "//brave/components/brave_search_conversion", "//brave/components/l10n/common", diff --git a/browser/ui/webui/brave_new_tab/DEPS b/browser/ui/webui/brave_new_tab/DEPS index df98d65694ae..3164da3fead0 100644 --- a/browser/ui/webui/brave_new_tab/DEPS +++ b/browser/ui/webui/brave_new_tab/DEPS @@ -1,3 +1,4 @@ include_rules = [ + "+brave/components/brave_perf_predictor/common", "+brave/components/brave_private_cdn", ] diff --git a/browser/ui/webui/brave_new_tab/new_tab_page_handler.cc b/browser/ui/webui/brave_new_tab/new_tab_page_handler.cc index ef08c01e82d6..c4c0e9637332 100644 --- a/browser/ui/webui/brave_new_tab/new_tab_page_handler.cc +++ b/browser/ui/webui/brave_new_tab/new_tab_page_handler.cc @@ -12,6 +12,7 @@ #include "brave/browser/ui/webui/brave_new_tab/background_adapter.h" #include "brave/browser/ui/webui/brave_new_tab/custom_image_chooser.h" #include "brave/browser/ui/webui/brave_new_tab/top_sites_adapter.h" +#include "brave/components/brave_perf_predictor/common/pref_names.h" #include "brave/components/brave_private_cdn/private_cdn_helper.h" #include "brave/components/brave_private_cdn/private_cdn_request_helper.h" #include "brave/components/brave_search_conversion/pref_names.h" @@ -427,6 +428,27 @@ void NewTabPageHandler::SetClockFormat(const std::string& clock_format, std::move(callback).Run(); } +void NewTabPageHandler::GetShowShieldsStats( + GetShowShieldsStatsCallback callback) { + std::move(callback).Run(pref_service_->GetBoolean(kNewTabPageShowStats)); +} + +void NewTabPageHandler::SetShowShieldsStats( + bool show_shields_stats, + SetShowShieldsStatsCallback callback) { + pref_service_->SetBoolean(kNewTabPageShowStats, show_shields_stats); + std::move(callback).Run(); +} + +void NewTabPageHandler::GetShieldsStats(GetShieldsStatsCallback callback) { + auto stats = mojom::ShieldsStats::New(); + stats->ads_blocked = pref_service_->GetUint64(kAdsBlocked) + + pref_service_->GetUint64(kTrackersBlocked); + stats->bandwidth_saved_bytes = pref_service_->GetUint64( + brave_perf_predictor::prefs::kBandwidthSavedBytes); + std::move(callback).Run(std::move(stats)); +} + void NewTabPageHandler::OnUpdate(UpdateObserver::Source update_source) { if (!page_.is_bound()) { return; @@ -444,6 +466,9 @@ void NewTabPageHandler::OnUpdate(UpdateObserver::Source update_source) { case UpdateObserver::Source::kTopSitesPrefs: page_->OnTopSitesPrefsUpdated(); break; + case UpdateObserver::Source::kShieldsStatsPrefs: + page_->OnShieldsStatsPrefsUpdated(); + break; } } diff --git a/browser/ui/webui/brave_new_tab/new_tab_page_handler.h b/browser/ui/webui/brave_new_tab/new_tab_page_handler.h index fee87d1832d9..982a6d0cb06a 100644 --- a/browser/ui/webui/brave_new_tab/new_tab_page_handler.h +++ b/browser/ui/webui/brave_new_tab/new_tab_page_handler.h @@ -135,6 +135,10 @@ class NewTabPageHandler : public mojom::NewTabPageHandler { void GetClockFormat(GetClockFormatCallback callback) override; void SetClockFormat(const std::string& clock_format, SetClockFormatCallback callback) override; + void GetShowShieldsStats(GetShowShieldsStatsCallback callback) override; + void SetShowShieldsStats(bool show_shields_stats, + SetShowShieldsStatsCallback callback) override; + void GetShieldsStats(GetShieldsStatsCallback callback) override; private: void OnCustomBackgroundsSelected(ShowCustomBackgroundChooserCallback callback, diff --git a/browser/ui/webui/brave_new_tab/new_tab_page_ui.cc b/browser/ui/webui/brave_new_tab/new_tab_page_ui.cc index c660b715f2c6..9dc3e70007cf 100644 --- a/browser/ui/webui/brave_new_tab/new_tab_page_ui.cc +++ b/browser/ui/webui/brave_new_tab/new_tab_page_ui.cc @@ -86,9 +86,15 @@ static constexpr webui::LocalizedString kStrings[] = { {"showClockLabel", IDS_NEW_TAB_SHOW_CLOCK_LABEL}, {"showSearchBoxLabel", IDS_NEW_TAB_SHOW_SEARCH_BOX_LABEL}, {"showSponsoredImagesLabel", IDS_NEW_TAB_SHOW_SPONSORED_IMAGES_LABEL}, + {"showStatsLabel", IDS_NEW_TAB_SHOW_STATS_LABEL}, {"showTopSitesLabel", IDS_NEW_TAB_SHOW_TOP_SITES_LABEL}, {"solidBackgroundLabel", IDS_NEW_TAB_SOLID_BACKGROUND_LABEL}, {"solidBackgroundTitle", IDS_NEW_TAB_SOLID_BACKGROUND_LABEL}, + {"statsAdsBlockedText", IDS_NEW_TAB_STATS_ADS_BLOCKED_TEXT}, + {"statsBandwidthSavedText", IDS_NEW_TAB_STATS_BANDWIDTH_SAVED_TEXT}, + {"statsSettingsTitle", IDS_NEW_TAB_STATS_SETTINGS_TITLE}, + {"statsTimeSavedText", IDS_NEW_TAB_STATS_TIME_SAVED_TEXT}, + {"statsTitle", IDS_NEW_TAB_STATS_TITLE}, {"topSiteRemovedText", IDS_NEW_TAB_TOP_SITE_REMOVED_TEXT}, {"topSiteRemovedTitle", IDS_NEW_TAB_TOP_SITE_REMOVED_TITLE}, {"topSitesCustomOptionText", IDS_NEW_TAB_TOP_SITES_CUSTOM_OPTION_TEXT}, diff --git a/browser/ui/webui/brave_new_tab/update_observer.cc b/browser/ui/webui/brave_new_tab/update_observer.cc index 378be3ff04f4..3d5a5af33d89 100644 --- a/browser/ui/webui/brave_new_tab/update_observer.cc +++ b/browser/ui/webui/brave_new_tab/update_observer.cc @@ -8,6 +8,7 @@ #include #include "brave/browser/ntp_background/ntp_background_prefs.h" +#include "brave/components/brave_perf_predictor/common/pref_names.h" #include "brave/components/brave_search_conversion/pref_names.h" #include "brave/components/constants/pref_names.h" #include "brave/components/ntp_background_images/common/pref_names.h" @@ -35,6 +36,11 @@ UpdateObserver::UpdateObserver(PrefService& pref_service) { AddPrefListener(ntp_prefs::kNtpUseMostVisitedTiles, Source::kTopSitesPrefs); AddPrefListener(kNewTabPageShowClock, Source::kClockPrefs); AddPrefListener(kNewTabPageClockFormat, Source::kClockPrefs); + AddPrefListener(kNewTabPageShowStats, Source::kShieldsStatsPrefs); + AddPrefListener(kAdsBlocked, Source::kShieldsStatsPrefs); + AddPrefListener(kTrackersBlocked, Source::kShieldsStatsPrefs); + AddPrefListener(brave_perf_predictor::prefs::kBandwidthSavedBytes, + Source::kShieldsStatsPrefs); } UpdateObserver::~UpdateObserver() = default; diff --git a/browser/ui/webui/brave_new_tab/update_observer.h b/browser/ui/webui/brave_new_tab/update_observer.h index 3d9177091003..5e8ab98736f9 100644 --- a/browser/ui/webui/brave_new_tab/update_observer.h +++ b/browser/ui/webui/brave_new_tab/update_observer.h @@ -24,7 +24,8 @@ class UpdateObserver { kBackgroundPrefs, kClockPrefs, kSearchPrefs, - kTopSitesPrefs + kTopSitesPrefs, + kShieldsStatsPrefs }; explicit UpdateObserver(PrefService& pref_service); diff --git a/components/brave_new_tab/new_tab_page.mojom b/components/brave_new_tab/new_tab_page.mojom index 43fab4812e82..c6ce26f67777 100644 --- a/components/brave_new_tab/new_tab_page.mojom +++ b/components/brave_new_tab/new_tab_page.mojom @@ -63,6 +63,11 @@ enum TopSitesListKind { kMostVisited }; +struct ShieldsStats { + double ads_blocked; + double bandwidth_saved_bytes; +}; + // WebUI-side handler for notifications from the browser. interface NewTabPage { @@ -81,6 +86,9 @@ interface NewTabPage { // Called when the list of most-visited sites has been updated. OnTopSitesListUpdated(); + // Called when preferences related to shields stats have been updated. + OnShieldsStatsPrefsUpdated(); + }; // Browser-side handler for requests from the WebUI page. @@ -200,4 +208,11 @@ interface NewTabPageHandler { GetClockFormat() => (string clock_format); SetClockFormat(string clock_format) => (); + // Gets or sets whether the shields stats widget is displayed. + GetShowShieldsStats() => (bool show_shields_stats); + SetShowShieldsStats(bool show_shields_stats) => (); + + // Returns shields browsing stats for the current user. + GetShieldsStats() => (ShieldsStats shields_stats); + }; diff --git a/components/brave_new_tab/resources/brave_new_tab_strings.grdp b/components/brave_new_tab/resources/brave_new_tab_strings.grdp index 7d6b283b4a85..963c5da05f46 100644 --- a/components/brave_new_tab/resources/brave_new_tab_strings.grdp +++ b/components/brave_new_tab/resources/brave_new_tab_strings.grdp @@ -136,6 +136,11 @@ Show Sponsored Images + + Show Brave Stats + + + Show top sites @@ -144,6 +149,26 @@ Solid colors + + Trackers & ads blocked + + + + Bandwidth saved + + + + Brave Stats + + + + Time saved + + + + STATS + + Top site removed diff --git a/components/brave_new_tab/resources/components/app.style.ts b/components/brave_new_tab/resources/components/app.style.ts index 966a221837ea..9f6cabd31703 100644 --- a/components/brave_new_tab/resources/components/app.style.ts +++ b/components/brave_new_tab/resources/components/app.style.ts @@ -63,7 +63,12 @@ export const style = scoped.css` } .widget-container { - min-height: 8px; + margin: 0 24px 16px; + max-height: 120px; + display: flex; + justify-content: space-between; + align-items: flex-end; + gap: 16px; } ` diff --git a/components/brave_new_tab/resources/components/app.tsx b/components/brave_new_tab/resources/components/app.tsx index 89a0a1516ddc..e508b14f00fa 100644 --- a/components/brave_new_tab/resources/components/app.tsx +++ b/components/brave_new_tab/resources/components/app.tsx @@ -12,6 +12,7 @@ import { BackgroundCaption } from './background_caption' import { SettingsModal, SettingsView } from './settings/settings_modal' import { TopSites } from './top_sites/top_sites' import { Clock } from './clock' +import { StatsWidget } from './widgets/stats_widget' import { style } from './app.style' @@ -47,7 +48,9 @@ export function App() {
-
+
+ +
+ {props.children} +
+ ) +} diff --git a/components/brave_new_tab/resources/components/settings/settings_modal.tsx b/components/brave_new_tab/resources/components/settings/settings_modal.tsx index 6f2937d5e699..47d16e625ada 100644 --- a/components/brave_new_tab/resources/components/settings/settings_modal.tsx +++ b/components/brave_new_tab/resources/components/settings/settings_modal.tsx @@ -12,11 +12,17 @@ import { BackgroundPanel } from './background_panel' import { TopSitesPanel } from './top_sites_panel' import { SearchPanel } from './search_panel' import { ClockPanel } from './clock_panel' +import { StatsPanel } from './stats_panel' import { useLocale } from '../locale_context' import { style } from './settings_modal.style' -export type SettingsView = 'background' | 'top-sites' | 'search' | 'clock' +export type SettingsView = + 'background' | + 'top-sites' | + 'search' | + 'clock' | + 'stats' interface Props { initialView: SettingsView | null @@ -42,6 +48,7 @@ export function SettingsModal(props: Props) { case 'top-sites': return case 'search': return case 'clock': return + case 'stats': return } } @@ -51,6 +58,7 @@ export function SettingsModal(props: Props) { case 'top-sites': return getString('topSitesSettingsTitle') case 'search': return getString('searchSettingsTitle') case 'clock': return getString('clockSettingsTitle') + case 'stats': return getString('statsSettingsTitle') } } @@ -76,6 +84,7 @@ export function SettingsModal(props: Props) { {renderNavItem('background')} {renderNavItem('search')} + {renderNavItem('stats')} {renderNavItem('top-sites')} {renderNavItem('clock')} diff --git a/components/brave_new_tab/resources/components/settings/stats_panel.style.ts b/components/brave_new_tab/resources/components/settings/stats_panel.style.ts new file mode 100644 index 000000000000..85ea9278b928 --- /dev/null +++ b/components/brave_new_tab/resources/components/settings/stats_panel.style.ts @@ -0,0 +1,23 @@ +/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */ + +import { scoped } from '../../lib/scoped_css' + +export const style = scoped.css` + & { + display: flex; + flex-direction: column; + gap: 16px; + + > * { + display: flex; + align-items: center; + + label { + flex: 1 1 auto; + } + } + } +` diff --git a/components/brave_new_tab/resources/components/settings/stats_panel.tsx b/components/brave_new_tab/resources/components/settings/stats_panel.tsx new file mode 100644 index 000000000000..93b4f8368577 --- /dev/null +++ b/components/brave_new_tab/resources/components/settings/stats_panel.tsx @@ -0,0 +1,32 @@ +/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import Toggle from '@brave/leo/react/toggle' + +import { useLocale } from '../locale_context' +import { useNewTabModel, useNewTabState } from '../new_tab_context' + +import { style } from './stats_panel.style' + +export function StatsPanel() { + const { getString } = useLocale() + const model = useNewTabModel() + + const showStats = useNewTabState((state) => state.showShieldsStats) + + return ( +
+
+ + { model.setShowShieldsStats(checked) }} + /> +
+
+ ) +} diff --git a/components/brave_new_tab/resources/components/widgets/stats_widget.style.ts b/components/brave_new_tab/resources/components/widgets/stats_widget.style.ts new file mode 100644 index 000000000000..864ec3ab7bdb --- /dev/null +++ b/components/brave_new_tab/resources/components/widgets/stats_widget.style.ts @@ -0,0 +1,45 @@ +/* Copyright (c) 2025 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 https://mozilla.org/MPL/2.0/. */ + +import { color, font } from '@brave/leo/tokens/css/variables' +import { scoped } from '../../lib/scoped_css' + +export const style = scoped.css` + & { + display: flex; + flex-direction: column; + gap: 8px; + } + + .title { + font: ${font.components.buttonSmall}; + } + + .data { + display: flex; + align-items: top; + gap: 24px; + color: ${color.primitive.neutral[90]}; + font: ${font.xSmall.regular}; + } + + .ads-blocked { + --self-value-color: ${color.primitive.orange[70]}; + } + + .bandwidth-saved { + --self-value-color: ${color.primitive.primary[70]}; + } + + .value { + color: var(--self-value-color, #fff); + font: ${font.heading.h3}; + } + + .units { + font: ${font.default.semibold}; + text-transform: capitalize; + } +` diff --git a/components/brave_new_tab/resources/components/widgets/stats_widget.tsx b/components/brave_new_tab/resources/components/widgets/stats_widget.tsx new file mode 100644 index 000000000000..23d0bab29ba2 --- /dev/null +++ b/components/brave_new_tab/resources/components/widgets/stats_widget.tsx @@ -0,0 +1,141 @@ +/* Copyright (c) 2025 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 https://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' + +import { useNewTabState } from '../new_tab_context' +import { useLocale } from '../locale_context' +import { NtpWidget } from '../ntp_widget' + +import { style } from './stats_widget.style' + +const adsBlockedFormatter = new Intl.NumberFormat(undefined, { + maximumFractionDigits: 0, + useGrouping: true +}) + +function getTimeSaved(adsBlocked: number) { + return adsBlocked * 50 +} + +function formatTimeInterval( + value: number, + unit: 'day' | 'hour' | 'minute' | 'second', + maximumFractionDigits: number = 0 +) { + return new Intl.NumberFormat(undefined, { + style: 'unit', + unit, + unitDisplay: 'long', + maximumFractionDigits, + // @ts-expect-error + roundingMode: 'ceil' + }).formatToParts(value) +} + +function formatTimeSaved(ms: number) { + const seconds = ms / 1000 + const minutes = seconds / 60 + const hours = minutes / 60 + const days = hours / 24 + + if (days >= 1) { + return formatTimeInterval(days, 'day', 2) + } + if (hours >= 1) { + return formatTimeInterval(hours, 'hour', 1) + } + if (minutes >= 1) { + return formatTimeInterval(minutes, 'minute') + } + if (seconds >= 1) { + return formatTimeInterval(seconds, 'second') + } + return formatTimeInterval(0, 'second') +} + +function formatMemoryValue( + value: number, + unit: 'kilobyte' | 'megabyte' | 'gigabyte', + maximumFractionDigits: number = 0 +) { + return new Intl.NumberFormat(undefined, { + style: 'unit', + unit, + unitDisplay: 'short', + maximumFractionDigits, + // @ts-expect-error + roundingMode: 'ceil' + }).formatToParts(value) +} + +function formatBandwidth(bytes: number) { + const kb = bytes / 1024 + const mb = kb / 1024 + const gb = mb / 1024 + + if (gb >= 1) { + return formatMemoryValue(gb, 'gigabyte', 2) + } + if (mb >= 1) { + return formatMemoryValue(mb, 'megabyte', 1) + } + if (kb >= 1) { + return formatMemoryValue(kb, 'kilobyte') + } + return formatMemoryValue(kb, 'kilobyte') +} + +export function StatsWidget() { + const { getString } = useLocale() + const [showStats, stats] = useNewTabState((state) => [ + state.showShieldsStats, + state.shieldsStats + ]) + + if (!showStats) { + return null + } + + function renderUnits(parts: Intl.NumberFormatPart[]) { + return parts.map(({ type, value }) => { + if (type === 'unit') { + return {value} + } + return value + }) + } + + return ( + +
+
+ {getString('statsTitle')} +
+
+
+
+ {stats && adsBlockedFormatter.format(stats.adsBlocked)} +
+ {getString('statsAdsBlockedText')} +
+
+
+ {stats && renderUnits(formatBandwidth(stats.bandwidthSavedBytes))} +
+ {getString('statsBandwidthSavedText')} +
+
+
+ {stats && + renderUnits(formatTimeSaved(getTimeSaved(stats.adsBlocked)))} +
+ {getString('statsTimeSavedText')} +
+
+
+
+ ) +} diff --git a/components/brave_new_tab/resources/lib/locale_strings.ts b/components/brave_new_tab/resources/lib/locale_strings.ts index 251021900028..f000cc36c655 100644 --- a/components/brave_new_tab/resources/lib/locale_strings.ts +++ b/components/brave_new_tab/resources/lib/locale_strings.ts @@ -41,9 +41,15 @@ export type StringKey = 'showClockLabel' | 'showSearchBoxLabel' | 'showSponsoredImagesLabel' | + 'showStatsLabel' | 'showTopSitesLabel' | 'solidBackgroundLabel' | 'solidBackgroundTitle' | + 'statsAdsBlockedText' | + 'statsBandwidthSavedText' | + 'statsSettingsTitle' | + 'statsTimeSavedText' | + 'statsTitle' | 'topSiteRemovedText' | 'topSiteRemovedTitle' | 'topSitesCustomOptionText' | diff --git a/components/brave_new_tab/resources/models/new_tab_model.ts b/components/brave_new_tab/resources/models/new_tab_model.ts index 5f728eee7132..ee3170573c1e 100644 --- a/components/brave_new_tab/resources/models/new_tab_model.ts +++ b/components/brave_new_tab/resources/models/new_tab_model.ts @@ -44,6 +44,11 @@ export type Background = export type ClockFormat = '' | 'h12' | 'h24' +export interface ShieldsStats { + bandwidthSavedBytes: number + adsBlocked: number +} + export interface NewTabState { backgroundsEnabled: boolean backgroundsCustomizable: boolean @@ -56,6 +61,8 @@ export interface NewTabState { sponsoredImageBackground: SponsoredImageBackground | null showClock: boolean clockFormat: ClockFormat + showShieldsStats: boolean + shieldsStats: ShieldsStats | null } export function defaultState(): NewTabState { @@ -70,7 +77,9 @@ export function defaultState(): NewTabState { currentBackground: null, sponsoredImageBackground: null, showClock: false, - clockFormat: '' + clockFormat: '', + showShieldsStats: false, + shieldsStats: null } } @@ -85,6 +94,7 @@ export interface NewTabModel { removeCustomBackground: (background: string) => Promise setShowClock: (showClock: boolean) => void setClockFormat: (format: ClockFormat) => void + setShowShieldsStats: (showShieldsStats: boolean) => void } export function defaultModel(): NewTabModel { @@ -99,6 +109,7 @@ export function defaultModel(): NewTabModel { async showCustomBackgroundChooser() { return false }, async removeCustomBackground(background) {}, setShowClock(showClock) {}, - setClockFormat(format) {} + setClockFormat(format) {}, + setShowShieldsStats(showShieldsStats) {} } } diff --git a/components/brave_new_tab/resources/stories/sb_locale.ts b/components/brave_new_tab/resources/stories/sb_locale.ts index a0e89e671f7e..07f0ee0379da 100644 --- a/components/brave_new_tab/resources/stories/sb_locale.ts +++ b/components/brave_new_tab/resources/stories/sb_locale.ts @@ -43,9 +43,15 @@ const localeStrings: { [K in StringKey]: string } = { showClockLabel: 'Show clock', showSearchBoxLabel: 'Show search widget in new tabs', showSponsoredImagesLabel: 'Show Sponsored Images', + showStatsLabel: 'Show Brave Stats', showTopSitesLabel: 'Show top sites', solidBackgroundLabel: 'Solid colors', solidBackgroundTitle: 'Solid colors', + statsAdsBlockedText: 'Trackers & ads blocked', + statsBandwidthSavedText: 'Bandwidth saved', + statsSettingsTitle: 'Brave Stats', + statsTimeSavedText: 'Time saved', + statsTitle: 'STATS', topSiteRemovedText: 'Top site removed', topSiteRemovedTitle: 'Removed', topSitesCustomOptionText: 'Top sites are curated by you', diff --git a/components/brave_new_tab/resources/stories/sb_new_tab_model.ts b/components/brave_new_tab/resources/stories/sb_new_tab_model.ts index 0d4a61569e2d..9f210d8aa21b 100644 --- a/components/brave_new_tab/resources/stories/sb_new_tab_model.ts +++ b/components/brave_new_tab/resources/stories/sb_new_tab_model.ts @@ -45,7 +45,12 @@ export function createNewTabModel(): NewTabModel { } ], sponsoredImageBackground: sampleSponsoredImage && null, - showClock: true + showClock: true, + showShieldsStats: true, + shieldsStats: { + adsBlocked: 3245, + bandwidthSavedBytes: 1024 * 1024 + } }) store.update({ @@ -108,6 +113,10 @@ export function createNewTabModel(): NewTabModel { setShowClock(showClock) { store.update({ showClock }) + }, + + setShowShieldsStats(showShieldsStats) { + store.update({ showShieldsStats }) } } } diff --git a/components/brave_new_tab/resources/webui/debounce_listener.ts b/components/brave_new_tab/resources/webui/debounce_listener.ts new file mode 100644 index 000000000000..0efcce0a638c --- /dev/null +++ b/components/brave_new_tab/resources/webui/debounce_listener.ts @@ -0,0 +1,10 @@ +/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */ + +import { debounce } from '$web-common/debounce' + +export function debounceListener(listener: (data: T) => void) { + return debounce(listener, 10) +} diff --git a/components/brave_new_tab/resources/webui/webui_new_tab_model.ts b/components/brave_new_tab/resources/webui/webui_new_tab_model.ts index fa664842f754..157dfd15931b 100644 --- a/components/brave_new_tab/resources/webui/webui_new_tab_model.ts +++ b/components/brave_new_tab/resources/webui/webui_new_tab_model.ts @@ -9,7 +9,7 @@ import { NewTabPageProxy } from './new_tab_page_proxy' import { NewTabModel, BackgroundType, defaultState } from '../models/new_tab_model' import { createStore } from '../lib/store' import { getCurrentBackground } from '../models/backgrounds' -import { debounce } from '$web-common/debounce' +import { debounceListener } from './debounce_listener' export function backgroundTypeFromMojo(type: number): BackgroundType { switch (type) { @@ -109,15 +109,28 @@ export function createNewTabModel(): NewTabModel { }) } + async function updateShieldsStats() { + const [ + { showShieldsStats }, + { shieldsStats } + ] = await Promise.all([ + handler.getShowShieldsStats(), + handler.getShieldsStats() + ]) + + store.update({ showShieldsStats, shieldsStats }) + } + newTabProxy.addListeners({ - onBackgroundPrefsUpdated: debounce(async () => { + onBackgroundPrefsUpdated: debounceListener(async () => { await Promise.all([ updateCustomBackgrounds(), updateSelectedBackground(), ]) updateCurrentBackground() - }, 10), - onClockPrefsUpdated: debounce(updateClockPrefs, 10) + }), + onClockPrefsUpdated: debounceListener(updateClockPrefs), + onShieldsStatsPrefsUpdated: debounceListener(updateShieldsStats) }) async function loadData() { @@ -129,7 +142,8 @@ export function createNewTabModel(): NewTabModel { updateCustomBackgrounds(), updateSelectedBackground(), updateSponsoredImageBackground(), - updateClockPrefs() + updateClockPrefs(), + updateShieldsStats() ]) updateCurrentBackground() @@ -190,6 +204,10 @@ export function createNewTabModel(): NewTabModel { async setClockFormat(format) { await handler.setClockFormat(format) + }, + + async setShowShieldsStats(showShieldsStats) { + await handler.setShowShieldsStats(showShieldsStats) } } } diff --git a/components/brave_new_tab/resources/webui/webui_top_sites_model.ts b/components/brave_new_tab/resources/webui/webui_top_sites_model.ts index 33cee7487453..ea2f3fbf2ca5 100644 --- a/components/brave_new_tab/resources/webui/webui_top_sites_model.ts +++ b/components/brave_new_tab/resources/webui/webui_top_sites_model.ts @@ -8,7 +8,7 @@ import * as mojom from 'gen/brave/components/brave_new_tab/new_tab_page.mojom.m. import { NewTabPageProxy } from './new_tab_page_proxy' import { TopSitesModel, TopSitesListKind, defaultState } from '../models/top_sites_model' import { createStore } from '../lib/store' -import { debounce } from '$web-common/debounce' +import { debounceListener } from './debounce_listener' export function listKindFromMojo(type: number): TopSitesListKind { switch (type) { @@ -52,7 +52,7 @@ export function createTopSitesModel(): TopSitesModel { } newTabProxy.addListeners({ - onTopSitesPrefsUpdated: debounce(loadData, 10), + onTopSitesPrefsUpdated: debounceListener(loadData), onTopSitesListUpdated: () => loadData() })