[Brave News]: Add news-internals page (#19615)

This commit is contained in:
Jay Harris
2023-08-10 09:02:47 +09:00
committed by GitHub
parent d7486f4a43
commit 69cd6759bf
22 changed files with 360 additions and 9 deletions
+17 -9
View File
@@ -253,15 +253,23 @@
brave_wallet::features::kBraveWalletDappsSupportFeature), \
})
#define BRAVE_NEWS_FEATURE_ENTRIES \
EXPAND_FEATURE_ENTRIES({ \
"brave-news-peek", \
"Brave News prompts on New Tab Page", \
"Prompt Brave News via the top featured article peeking up from " \
"the bottom of the New Tab Page, after a short delay.", \
kOsDesktop, \
FEATURE_VALUE_TYPE(brave_news::features::kBraveNewsCardPeekFeature), \
})
#define BRAVE_NEWS_FEATURE_ENTRIES \
EXPAND_FEATURE_ENTRIES( \
{ \
"brave-news-peek", \
"Brave News prompts on New Tab Page", \
"Prompt Brave News via the top featured article peeking up from " \
"the bottom of the New Tab Page, after a short delay.", \
kOsDesktop, \
FEATURE_VALUE_TYPE(brave_news::features::kBraveNewsCardPeekFeature), \
}, \
{ \
"brave-news-feed-update", \
"Brave News Feed Update", \
"Use the updated Brave News feed", \
kOsDesktop, \
FEATURE_VALUE_TYPE(brave_news::features::kBraveNewsFeedUpdate), \
})
#define BRAVE_FEDERATED_FEATURE_ENTRIES \
EXPAND_FEATURE_ENTRIES({ \
+10
View File
@@ -205,6 +205,7 @@ using extensions::ChromeContentBrowserClientExtensionsPart;
#if !BUILDFLAG(IS_ANDROID)
#include "brave/browser/new_tab/new_tab_shows_navigation_throttle.h"
#include "brave/browser/ui/webui/brave_news_internals/brave_news_internals_ui.h"
#include "brave/browser/ui/webui/brave_rewards/rewards_panel_ui.h"
#include "brave/browser/ui/webui/brave_rewards/tip_panel_ui.h"
#include "brave/browser/ui/webui/brave_settings_ui.h"
@@ -216,6 +217,7 @@ using extensions::ChromeContentBrowserClientExtensionsPart;
#include "brave/browser/ui/webui/private_new_tab_page/brave_private_new_tab_ui.h"
#include "brave/components/brave_new_tab_ui/brave_new_tab_page.mojom.h"
#include "brave/components/brave_news/common/brave_news.mojom.h"
#include "brave/components/brave_news/common/features.h"
#include "brave/components/brave_private_new_tab_ui/common/brave_private_new_tab.mojom.h"
#include "brave/components/brave_rewards/common/features.h"
#include "brave/components/brave_rewards/common/mojom/rewards_panel.mojom.h"
@@ -565,6 +567,14 @@ void BraveContentBrowserClient::RegisterWebUIInterfaceBrokers(
if (base::FeatureList::IsEnabled(skus::features::kSkusFeature)) {
registry.ForWebUI<SkusInternalsUI>().Add<skus::mojom::SkusInternals>();
}
#if !BUILDFLAG(IS_ANDROID)
if (base::FeatureList::IsEnabled(
brave_news::features::kBraveNewsFeedUpdate)) {
registry.ForWebUI<BraveNewsInternalsUI>()
.Add<brave_news::mojom::BraveNewsController>();
}
#endif
}
bool BraveContentBrowserClient::AllowWorkerFingerprinting(
+4
View File
@@ -935,6 +935,8 @@ source_set("ui") {
"views/wallet_bubble_focus_observer.h",
"wallet_bubble_manager_delegate_impl.cc",
"wallet_bubble_manager_delegate_impl.h",
"webui/brave_news_internals/brave_news_internals_ui.cc",
"webui/brave_news_internals/brave_news_internals_ui.h",
"webui/brave_wallet/ledger/ledger_ui.cc",
"webui/brave_wallet/ledger/ledger_ui.h",
"webui/brave_wallet/market/market_ui.cc",
@@ -958,6 +960,8 @@ source_set("ui") {
"//brave/browser/ui/brave_wallet",
"//brave/browser/ui/webui/brave_wallet/common_handler",
"//brave/browser/ui/webui/brave_wallet/panel_handler",
"//brave/components/brave_news/browser",
"//brave/components/brave_news/browser/resources:generated_resources",
"//brave/components/brave_wallet/common",
"//brave/components/brave_wallet/common:mojom",
"//brave/components/brave_wallet_ui:resources",
@@ -0,0 +1,40 @@
// Copyright (c) 2023 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/.
#include "brave/browser/ui/webui/brave_news_internals/brave_news_internals_ui.h"
#include <string>
#include <utility>
#include "brave/browser/brave_news/brave_news_controller_factory.h"
#include "brave/browser/ui/webui/brave_webui_source.h"
#include "brave/components/brave_news/browser/brave_news_controller.h"
#include "brave/components/brave_news/browser/resources/grit/brave_news_internals_generated_map.h"
#include "chrome/browser/profiles/profile.h"
#include "components/grit/brave_components_resources.h"
BraveNewsInternalsUI::BraveNewsInternalsUI(content::WebUI* web_ui,
const std::string& host)
: content::WebUIController(web_ui) {
auto* source = CreateAndAddWebUIDataSource(
web_ui, host, kBraveNewsInternalsGenerated,
kBraveNewsInternalsGeneratedSize, IDR_BRAVE_NEWS_INTERNALS_HTML);
DCHECK(source);
}
BraveNewsInternalsUI::~BraveNewsInternalsUI() = default;
WEB_UI_CONTROLLER_TYPE_IMPL(BraveNewsInternalsUI)
void BraveNewsInternalsUI::BindInterface(
mojo::PendingReceiver<brave_news::mojom::BraveNewsController> receiver) {
auto* profile = Profile::FromWebUI(web_ui());
auto* controller =
brave_news::BraveNewsControllerFactory::GetForContext(profile);
if (!controller) {
return;
}
controller->Bind(std::move(receiver));
}
@@ -0,0 +1,31 @@
// Copyright (c) 2023 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/.
#ifndef BRAVE_BROWSER_UI_WEBUI_BRAVE_NEWS_INTERNALS_BRAVE_NEWS_INTERNALS_UI_H_
#define BRAVE_BROWSER_UI_WEBUI_BRAVE_NEWS_INTERNALS_BRAVE_NEWS_INTERNALS_UI_H_
#include <memory>
#include <string>
#include "brave/components/brave_news/common/brave_news.mojom-forward.h"
#include "content/public/browser/web_ui_controller.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
class BraveNewsInternalsUI : public content::WebUIController {
public:
explicit BraveNewsInternalsUI(content::WebUI* web_ui,
const std::string& host);
BraveNewsInternalsUI(const BraveNewsInternalsUI&) = delete;
BraveNewsInternalsUI& operator=(const BraveNewsInternalsUI&) = delete;
~BraveNewsInternalsUI() override;
void BindInterface(
mojo::PendingReceiver<brave_news::mojom::BraveNewsController> receiver);
private:
WEB_UI_CONTROLLER_TYPE_DECL();
};
#endif // BRAVE_BROWSER_UI_WEBUI_BRAVE_NEWS_INTERNALS_BRAVE_NEWS_INTERNALS_UI_H_
@@ -36,6 +36,7 @@
#if !BUILDFLAG(IS_ANDROID)
#include "brave/browser/brave_wallet/brave_wallet_context_utils.h"
#include "brave/browser/ui/webui/brave_news_internals/brave_news_internals_ui.h"
#include "brave/browser/ui/webui/brave_rewards/rewards_panel_ui.h"
#include "brave/browser/ui/webui/brave_rewards/tip_panel_ui.h"
#include "brave/browser/ui/webui/brave_settings_ui.h"
@@ -48,6 +49,7 @@
#include "brave/browser/ui/webui/speedreader/speedreader_toolbar_ui.h"
#include "brave/browser/ui/webui/webcompat_reporter_ui.h"
#include "brave/browser/ui/webui/welcome_page/brave_welcome_ui.h"
#include "brave/components/brave_news/common/features.h"
#include "brave/components/brave_wallet/browser/brave_wallet_utils.h"
#include "brave/components/brave_wallet/common/brave_wallet.mojom.h"
#include "brave/components/commands/common/features.h"
@@ -149,6 +151,10 @@ WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) {
} else if (host == kBraveTipPanelHost &&
brave_rewards::IsSupportedForProfile(profile)) {
return new brave_rewards::TipPanelUI(web_ui);
} else if (base::FeatureList::IsEnabled(
brave_news::features::kBraveNewsFeedUpdate) &&
host == kBraveNewsInternalsHost) {
return new BraveNewsInternalsUI(web_ui, url.host());
#endif // !BUILDFLAG(IS_ANDROID)
#if !BUILDFLAG(IS_ANDROID)
} else if (host == kWelcomeHost && !profile->IsGuestSession()) {
@@ -204,6 +210,9 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
url.path() == kWalletSendPagePath || url.path() == kWalletBuyPagePath ||
url.path() == kWalletDepositPagePath)) ||
#else
(base::FeatureList::IsEnabled(
brave_news::features::kBraveNewsFeedUpdate) &&
url.host_piece() == kBraveNewsInternalsHost) ||
((url.host_piece() == kWalletPanelHost ||
url.host_piece() == kWalletPageHost) &&
brave_wallet::IsAllowedForContext(profile)) ||
@@ -0,0 +1,28 @@
# Copyright (c) 2023 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("//brave/components/common/typescript.gni")
transpile_web_ui("brave_news_internals") {
entry_points = [ [
"brave_news_internals",
rebase_path("internals.tsx"),
] ]
deps = [
"//brave/components/brave_news/common",
"//brave/components/brave_news/common:mojom",
"//brave/components/brave_news/common:mojom_js",
]
resource_name = "brave_news_internals"
}
pack_web_resources("generated_resources") {
resource_name = "brave_news_internals"
output_dir = "$root_gen_dir/brave/components/brave_news/browser/resources"
deps = [ ":brave_news_internals" ]
}
@@ -0,0 +1,15 @@
// Copyright (c) 2023 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';
interface Props {
}
export default function FeedPage (props: Props) {
return <div>
The Feed
</div>
}
@@ -0,0 +1,31 @@
// Copyright (c) 2023 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 Dropdown from '@brave/leo/react/dropdown';
import * as React from 'react';
import { pages, useInspectContext } from './context';
interface Props {
}
export default function PageInfo(props: Props) {
const { page, setPage, publishers, locale, setLocale } = useInspectContext();
const locales = React.useMemo(() => Array.from(new Set(Object.values(publishers).flatMap(p => p.locales.map(l => l.locale)))), [publishers])
return <div>
<div>
<Dropdown value={page} onChange={e => setPage(e.detail.value)}>
<span slot="label">Page</span>
{pages.map(p => <leo-option key={p}>{p}</leo-option>)}
</Dropdown>
</div>
<div>
<Dropdown value={locale} onChange={e => setLocale(e.detail.value)}>
<span slot="label">Locale</span>
{locales.map(l => <leo-option key={l}>{l}</leo-option>)}
</Dropdown>
</div>
</div>
}
@@ -0,0 +1,15 @@
// Copyright (c) 2023 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';
interface Props {
}
export default function SignalsPage (props: Props) {
return <div>
Signals Page
</div>
}
@@ -0,0 +1,58 @@
// Copyright (c) 2023 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 {
BraveNewsController, Channel, Publisher
} from 'gen/brave/components/brave_news/common/brave_news.mojom.m'
import * as React from 'react'
import usePromise from '../../../brave_new_tab_ui/hooks/usePromise'
export const pages = ['feed', 'signals'] as const;
export type Page = (typeof pages)[number]
export interface InspectContext {
publishers: { [key: string]: Publisher },
channels: { [key: string]: Channel },
page: Page,
setPage: (page: Page) => void,
locale: string,
setLocale: (locale: string) => void
}
export const api = BraveNewsController.getRemote();
const Context = React.createContext<InspectContext>({
publishers: {},
channels: {},
page: 'feed',
setPage: () => { },
locale: 'en_US',
setLocale: () => { }
})
export const useInspectContext = () => {
return React.useContext(Context);
}
export default function InspectContext(props: React.PropsWithChildren<{}>) {
const { result: publishers } = usePromise(() => api.getPublishers().then(p => p.publishers as { [key: string]: Publisher }), [])
const { result: channels } = usePromise(() => api.getChannels().then(c => c.channels as { [key: string]: Channel }), [])
const [page, setPage] = React.useState<Page>('feed')
const [locale, setLocale] = React.useState<string>('en_US')
const context = React.useMemo<InspectContext>(() => ({
publishers: publishers ?? {},
channels: channels ?? {},
page,
setPage,
locale,
setLocale
}), [publishers, channels, page, locale])
return <Context.Provider value={context}>
{props.children}
</Context.Provider>
}
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en" dir="$i18n{textdirection}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Brave News Internals</title>
<link rel="stylesheet" href="chrome://resources/brave/css/reset.css">
<link rel="stylesheet" href="chrome://resources/brave/fonts/poppins.css">
<link
rel="stylesheet"
href="chrome://resources/brave/leo/css/variables.css">
<style>
body {
overflow-x: hidden;
background: var(--leo-color-page-background);
color: var(--leo-color-text-primary);
font: var(--leo-font-primary-default-regular);
}
</style>
</head>
<body>
<div id="root"></div>
<script src="/brave_news_internals.bundle.js"></script>
</body>
</html>
@@ -0,0 +1,51 @@
// Copyright (c) 2023 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 { render } from 'react-dom'
import styled from 'styled-components'
import InspectContext, { useInspectContext } from './context'
import PageInfo from './PageInfo'
import FeedPage from './FeedPage'
import SignalsPage from './SignalsPage'
const Grid = styled.div`
display: grid;
grid-template-columns: 200px auto 200px;
padding: 16px;
gap: 8px;
`
const Container = styled.div`
display: flex;
flex-direction: column;
gap: var(--leo-spacing-8);
max-width: 800px;
margin: 0 auto;
`
function App() {
const { page, publishers, channels } = useInspectContext()
return (
<Grid>
<PageInfo />
<Container>
{page === 'feed' && <FeedPage />}
{page === 'signals' && <SignalsPage />}
</Container>
<div>
Publishers: {Object.keys(publishers).length}
<br />
Channels: {Object.keys(channels).length}
</div>
</Grid>
)
}
render(<InspectContext>
<App />
</InspectContext>, document.getElementById('root'))
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<grit-part>
<include name="IDR_BRAVE_NEWS_INTERNALS_HTML" file="../brave_news/browser/resources/internals.html" type="BINDATA" />
</grit-part>
@@ -0,0 +1,4 @@
{
"extends": "../../../../tsconfig",
"include": ["**/*.ts", "**/*.tsx", "**/*.d.ts", "../../definitions/*.d.ts"]
}
+4
View File
@@ -13,4 +13,8 @@ BASE_FEATURE(kBraveNewsCardPeekFeature,
"BraveNewsCardPeek",
base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kBraveNewsFeedUpdate,
"BraveNewsFeedUpdate",
base::FEATURE_DISABLED_BY_DEFAULT);
} // namespace brave_news::features
+1
View File
@@ -11,6 +11,7 @@
namespace brave_news::features {
BASE_DECLARE_FEATURE(kBraveNewsCardPeekFeature);
BASE_DECLARE_FEATURE(kBraveNewsFeedUpdate);
} // namespace brave_news::features
@@ -25,6 +25,7 @@ const char kBraveRewardsPanelHost[] = "rewards-panel.top-chrome";
const char kBraveTipPanelURL[] = "chrome://tip-panel.top-chrome";
const char kBraveTipPanelHost[] = "tip-panel.top-chrome";
const char kBraveNewTabJS[] = "brave_new_tab.js";
const char kBraveNewsInternalsHost[] = "news-internals";
const char kBraveUIRewardsURL[] = "chrome://rewards/";
const char kBraveUIAdblockURL[] = "chrome://adblock/";
const char kBraveUIWebcompatReporterURL[] = "chrome://webcompat/";
@@ -23,6 +23,7 @@ extern const char kRewardsInternalsHost[];
extern const char kWelcomeHost[];
extern const char kWelcomeJS[];
extern const char kBraveNewTabJS[];
extern const char kBraveNewsInternalsHost[];
extern const char kBraveRewardsPanelURL[];
extern const char kBraveRewardsPanelHost[];
extern const char kBraveTipPanelURL[];
+3
View File
@@ -72,6 +72,8 @@ repack("resources") {
if (!is_android && !is_ios) {
deps += [
"//brave/components/brave_new_tab_ui:generated_resources",
"//brave/components/brave_news/browser/resources:generated_resources",
"//brave/components/brave_news/browser/resources:generated_resources",
"//brave/components/brave_private_new_tab_ui/resources/page:generated_resources",
"//brave/components/brave_shields/resources/cookie_list_opt_in:cookie_list_opt_in_generated",
"//brave/components/brave_shields/resources/panel:brave_shields_panel_generated",
@@ -82,6 +84,7 @@ repack("resources") {
sources += [
"$root_gen_dir/brave/components/brave_new_tab/resources/brave_new_tab_generated.pak",
"$root_gen_dir/brave/components/brave_news/browser/resources/brave_news_internals_generated.pak",
"$root_gen_dir/brave/components/brave_private_new_tab/resources/page/brave_private_new_tab_generated.pak",
"$root_gen_dir/brave/components/brave_shields/resources/cookie_list_opt_in/cookie_list_opt_in_generated.pak",
"$root_gen_dir/brave/components/brave_shields/resources/panel/brave_shields_panel_generated.pak",
@@ -82,6 +82,7 @@
<part file="../brave_perf_predictor/resources/brave_perf_predictor_resources.grdp" />
<part file="../playlist/browser/resources/playlist_resources.grdp" />
<part file="../brave_news/browser/resources/news_resources.grdp" />
<part file="../skus/browser/resources/skus_internals_resources.grdp" />
<if expr="not is_android">
<part file="brave_blank_page_resources.grdp" />
+4
View File
@@ -234,5 +234,9 @@
"<(SHARED_INTERMEDIATE_DIR)/brave/web-ui-skus_internals/skus_internals.grd": {
"META": {"sizes": {"includes": [100]}},
"includes": [63550],
},
"<(SHARED_INTERMEDIATE_DIR)/brave/web-ui-brave_news_internals/brave_news_internals.grd": {
"META": {"sizes": {"includes": [100]}},
"includes": [63650],
}
}