diff --git a/app/resources/brave_generated_resources_ja.xtb b/app/resources/brave_generated_resources_ja.xtb index dab99aa901e6..8a0ccc912aaa 100644 --- a/app/resources/brave_generated_resources_ja.xtb +++ b/app/resources/brave_generated_resources_ja.xtb @@ -233,6 +233,9 @@ アバター「ボンボン・コーン」 アバター「ボンボン・ロイヤル」 アバター「ボンボン・ニンジャ」 +Brave をデフォルト ブラウザに設定する +デフォルトとして設定 +後で Braveは完全に匿名の製品分析を使い、特定の機能が全体でどの程度使われているか予測します 閉じる 無効にする diff --git a/browser/extensions/api/brave_rewards_api.cc b/browser/extensions/api/brave_rewards_api.cc index 9658fda64a54..eddc6e0ff13a 100644 --- a/browser/extensions/api/brave_rewards_api.cc +++ b/browser/extensions/api/brave_rewards_api.cc @@ -47,6 +47,25 @@ BraveRewardsOpenBrowserActionUIFunction::Run() { std::unique_ptr params( brave_rewards::OpenBrowserActionUI::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); + + auto* profile = Profile::FromBrowserContext(browser_context()); + + // Start the rewards ledger process if it is not already started + auto* rewards_service = RewardsServiceFactory::GetForProfile(profile); + if (!rewards_service) + return RespondNow(Error("Rewards service is not initialized")); + + rewards_service->StartProcess(base::DoNothing()); + + // Load the rewards extension if it is not already loaded + auto* extension_service = + extensions::ExtensionSystem::Get(profile)->extension_service(); + if (!extension_service) + return RespondNow(Error("Extension service is not initialized")); + + static_cast(extension_service->component_loader()) + ->AddRewardsExtension(); + std::string error; if (!BraveActionAPI::ShowActionUI(this, brave_rewards_extension_id, diff --git a/browser/ui/brave_actions/brave_action_view_controller.cc b/browser/ui/brave_actions/brave_action_view_controller.cc index c5411ed8acb4..eca009f86d43 100644 --- a/browser/ui/brave_actions/brave_action_view_controller.cc +++ b/browser/ui/brave_actions/brave_action_view_controller.cc @@ -63,6 +63,11 @@ bool BraveActionViewController::TriggerPopupWithUrl( PopupShowAction show_action, const GURL& popup_url, bool grant_tab_permissions) { + // If this extension is currently showing a popup, hide it. This behavior is + // a bit different than ExtensionActionViewController, which will hide any + // popup, regardless of extension. Consider duplicating the original behavior. + HidePopup(); + std::unique_ptr host = extensions::ExtensionViewHostFactory::CreatePopupHost(popup_url, browser_); diff --git a/browser/ui/webui/brave_webui_source.cc b/browser/ui/webui/brave_webui_source.cc index 9c0ce609d12c..6fda7d4ba21a 100644 --- a/browser/ui/webui/brave_webui_source.cc +++ b/browser/ui/webui/brave_webui_source.cc @@ -250,6 +250,10 @@ void CustomizeWebUIHTMLSource(const std::string &name, { "editCardsTitle", IDS_EDIT_CARDS_TITLE }, { "tosAndPp", IDS_REWARDS_WIDGET_TOS_AND_PP}, // NOLINT { "rewardsWidgetStartUsing", IDS_REWARDS_WIDGET_START_USING}, // NOLINT + // Rewards BAP Deprecation Alert + { "bapDeprecationAlertText", IDS_REWARDS_BAP_DEPRECATION_ALERT_TEXT }, + { "bapDeprecationHeader", IDS_REWARDS_BAP_DEPRECATION_HEADER }, + { "bapDeprecationOK", IDS_REWARDS_BAP_DEPRECATION_OK }, // Together Widget { "togetherWidgetTitle", IDS_TOGETHER_WIDGET_TITLE }, { "togetherWidgetWelcomeTitle", IDS_TOGETHER_WIDGET_WELCOME_TITLE }, diff --git a/components/brave_ads/browser/ads_service_impl_unittest.cc b/components/brave_ads/browser/ads_service_impl_unittest.cc index fce994f596df..6cc3c8e10d08 100644 --- a/components/brave_ads/browser/ads_service_impl_unittest.cc +++ b/components/brave_ads/browser/ads_service_impl_unittest.cc @@ -182,7 +182,7 @@ class MockRewardsService : public RewardsService { MOCK_METHOD1(DisconnectWallet, void(const std::string& wallet_type)); - MOCK_METHOD0(OnlyAnonWallet, bool()); + MOCK_CONST_METHOD0(OnlyAnonWallet, bool()); MOCK_METHOD1(AddPrivateObserver, void(RewardsServicePrivateObserver* observer)); diff --git a/components/brave_new_tab_ui/api/initialData.ts b/components/brave_new_tab_ui/api/initialData.ts index 0ef62740d66b..4cd157308c0a 100644 --- a/components/brave_new_tab_ui/api/initialData.ts +++ b/components/brave_new_tab_ui/api/initialData.ts @@ -24,6 +24,7 @@ export type InitialData = { export type PreInitialRewardsData = { enabledAds: boolean adsSupported: boolean + onlyAnonWallet: boolean } export type InitialRewardsData = { @@ -103,18 +104,23 @@ export async function getRewardsPreInitialData (): Promise chrome.braveRewards.getAdsEnabled((enabledAds: boolean) => { resolve(enabledAds) })), new Promise(resolve => chrome.braveRewards.getAdsSupported((adsSupported: boolean) => { resolve(adsSupported) + })), + new Promise(resolve => chrome.braveRewards.onlyAnonWallet((onlyAnonWallet: boolean) => { + resolve(onlyAnonWallet) })) ]) return { enabledAds, - adsSupported + adsSupported, + onlyAnonWallet } as PreInitialRewardsData } catch (err) { throw Error(err) diff --git a/components/brave_new_tab_ui/components/default/rewards/bapDeprecationModal.tsx b/components/brave_new_tab_ui/components/default/rewards/bapDeprecationModal.tsx new file mode 100644 index 000000000000..d3e12c8f3cd1 --- /dev/null +++ b/components/brave_new_tab_ui/components/default/rewards/bapDeprecationModal.tsx @@ -0,0 +1,92 @@ +/* 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/. */ + +import * as React from 'react' + +import { getLocale } from '../../../../common/locale' + +import { WithThemeVariables } from '../../../../brave_rewards/resources/shared/components/with_theme_variables' +import { LocaleContext } from '../../../../brave_rewards/resources/shared/lib/locale_context' +import { + BAPDeprecationAlert, + shouldShowBAPAlert, + shouldShowBAPPopup, + saveBAPAlertDismissed, + saveBAPPopupShown +} from '../../../../brave_rewards/resources/shared/components/bap_deprecation' + +const locale = { + getString: getLocale +} + +function modalRequestInHash () { + return /^#?bap-deprecation$/i.test(window.location.hash) +} + +interface Props { + rewardsState: NewTab.RewardsWidgetState +} + +// A modal that will display a BAP deprecation notice for Rewards users +// in Japan. This component is temporary and should be removed in 1.23.x +export default function BAPDeprecationModal (props: Props) { + const { onlyAnonWallet, balance } = props.rewardsState + + const [popupShown, setPopupShown] = React.useState(false) + + const [showModal, setShowModal] = React.useState( + modalRequestInHash() || + shouldShowBAPAlert(onlyAnonWallet, balance.total)) + + React.useEffect(() => { + if (popupShown || showModal) { + return + } + if (shouldShowBAPPopup(onlyAnonWallet, balance.total)) { + setPopupShown(true) + saveBAPPopupShown() + const popupURL = 'brave_rewards_panel.html#bap-deprecation' + chrome.braveRewards.openBrowserActionUI(popupURL) + } + }, [popupShown, showModal, onlyAnonWallet, balance]) + + React.useEffect(() => { + if (modalRequestInHash()) { + window.location.hash = '' + } + + // Attach a hashchange listener while this component is rendered. If the + // BAP deprecation popup has been opened in the brave rewards extension + // panel and the user clicks "Learn more", it will update the hash on + // this page. + const onHashChange = () => { + if (modalRequestInHash()) { + window.location.hash = '' + setShowModal(true) + } + } + + window.addEventListener('hashchange', onHashChange) + return () => { window.removeEventListener('hashchange', onHashChange) } + }, []) + + if (!showModal) { + return null + } + + const onClose = () => { + setShowModal(false) + if (!popupShown) { + saveBAPAlertDismissed() + } + } + + return ( + + + + + + ) +} diff --git a/components/brave_new_tab_ui/containers/newTab/index.tsx b/components/brave_new_tab_ui/containers/newTab/index.tsx index 82d0a47dce83..db1d6d542fee 100644 --- a/components/brave_new_tab_ui/containers/newTab/index.tsx +++ b/components/brave_new_tab_ui/containers/newTab/index.tsx @@ -24,6 +24,7 @@ import BrandedWallpaperLogo from '../../components/default/brandedWallpaper/logo import { brandedWallpaperLogoClicked } from '../../api/brandedWallpaper' import BraveTodayHint from '../../components/default/braveToday/hint' import BraveToday from '../../components/default/braveToday' +import BAPDeprecationModal from '../../components/default/rewards/bapDeprecationModal' // Helpers import VisibilityTimer from '../../helpers/visibilityTimer' @@ -1157,6 +1158,7 @@ class NewTabPage extends React.Component { cardsHidden={this.allWidgetsHidden()} toggleCards={this.toggleAllCards} /> + ) } diff --git a/components/brave_new_tab_ui/reducers/rewards_reducer.ts b/components/brave_new_tab_ui/reducers/rewards_reducer.ts index 91e11335d997..fca2db5a3648 100644 --- a/components/brave_new_tab_ui/reducers/rewards_reducer.ts +++ b/components/brave_new_tab_ui/reducers/rewards_reducer.ts @@ -115,7 +115,8 @@ const rewardsReducer: Reducer = (state: NewTab.State, rewardsState: { ...state.rewardsState, enabledAds: preInitialRewardsDataPayload.enabledAds, - adsSupported: preInitialRewardsDataPayload.adsSupported + adsSupported: preInitialRewardsDataPayload.adsSupported, + onlyAnonWallet: preInitialRewardsDataPayload.onlyAnonWallet } } break diff --git a/components/brave_rewards/browser/rewards_service.h b/components/brave_rewards/browser/rewards_service.h index d346f9033c41..8657fa988311 100644 --- a/components/brave_rewards/browser/rewards_service.h +++ b/components/brave_rewards/browser/rewards_service.h @@ -322,7 +322,7 @@ class RewardsService : public KeyedService { virtual void DisconnectWallet(const std::string& wallet_type) = 0; - virtual bool OnlyAnonWallet() = 0; + virtual bool OnlyAnonWallet() const = 0; virtual void GetAnonWalletStatus(GetAnonWalletStatusCallback callback) = 0; diff --git a/components/brave_rewards/browser/rewards_service_impl.cc b/components/brave_rewards/browser/rewards_service_impl.cc index c6c6dd474940..856a671248de 100644 --- a/components/brave_rewards/browser/rewards_service_impl.cc +++ b/components/brave_rewards/browser/rewards_service_impl.cc @@ -1489,6 +1489,20 @@ void RewardsServiceImpl::ClearState(const std::string& name) { bool RewardsServiceImpl::GetBooleanOption(const std::string& name) const { DCHECK(!name.empty()); + if (name == ledger::option::kContributionsDisabledForBAPMigration) { + if (OnlyAnonWallet()) { + base::Time::Exploded cutoff_exploded{ + .year = 2021, .month = 3, .day_of_month = 13}; + base::Time cutoff; + bool ok = base::Time::FromUTCExploded(cutoff_exploded, &cutoff); + DCHECK(ok); + if (ok && base::Time::Now() >= cutoff) { + return true; + } + } + return false; + } + const auto it = kBoolOptions.find(name); DCHECK(it != kBoolOptions.end()); @@ -3005,7 +3019,7 @@ void RewardsServiceImpl::ShowNotification( callback(ledger::type::Result::LEDGER_OK); } -bool RewardsServiceImpl::OnlyAnonWallet() { +bool RewardsServiceImpl::OnlyAnonWallet() const { const int32_t current_country = country_codes::GetCountryIDFromPrefs(profile_->GetPrefs()); diff --git a/components/brave_rewards/browser/rewards_service_impl.h b/components/brave_rewards/browser/rewards_service_impl.h index 8f15027c8916..1e45e50eaffc 100644 --- a/components/brave_rewards/browser/rewards_service_impl.h +++ b/components/brave_rewards/browser/rewards_service_impl.h @@ -303,7 +303,7 @@ class RewardsServiceImpl : public RewardsService, void DisconnectWallet(const std::string& wallet_type) override; - bool OnlyAnonWallet() override; + bool OnlyAnonWallet() const override; void GetAnonWalletStatus(GetAnonWalletStatusCallback callback) override; diff --git a/components/brave_rewards/browser/test/rewards_browsertest.cc b/components/brave_rewards/browser/test/rewards_browsertest.cc index 9d3a4decb782..bc4043130872 100644 --- a/components/brave_rewards/browser/test/rewards_browsertest.cc +++ b/components/brave_rewards/browser/test/rewards_browsertest.cc @@ -8,8 +8,11 @@ #include "base/containers/flat_map.h" #include "base/test/bind.h" +#include "base/time/time.h" +#include "base/time/time_override.h" #include "bat/ledger/internal/uphold/uphold_util.h" #include "brave/browser/brave_rewards/rewards_service_factory.h" +#include "brave/browser/extensions/api/brave_action_api.h" #include "brave/common/brave_paths.h" #include "brave/components/brave_rewards/browser/rewards_service_impl.h" #include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_context_helper.h" @@ -23,12 +26,27 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/country_codes/country_codes.h" #include "components/network_session_configurator/common/network_switches.h" #include "content/public/test/browser_test.h" #include "net/dns/mock_host_resolver.h" // npm run test -- brave_browser_tests --filter=RewardsBrowserTest.* +namespace { + +base::Time GetDate(int year, int month, int day_of_month) { + base::Time time; + bool ok = base::Time::FromUTCExploded( + base::Time::Exploded{ + .year = year, .month = month, .day_of_month = day_of_month}, + &time); + DCHECK(ok); + return time; +} + +} // namespace + namespace rewards_browsertest { class RewardsBrowserTest : public InProcessBrowserTest { @@ -109,6 +127,18 @@ class RewardsBrowserTest : public InProcessBrowserTest { return url; } + double FetchBalance() { + double total = -1.0; + base::RunLoop run_loop; + rewards_service_->FetchBalance(base::BindLambdaForTesting( + [&](ledger::type::Result result, ledger::type::BalancePtr balance) { + total = balance ? balance->total : -1.0; + run_loop.Quit(); + })); + run_loop.Run(); + return total; + } + brave_rewards::RewardsServiceImpl* rewards_service_; std::unique_ptr https_server_; std::unique_ptr response_; @@ -428,4 +458,68 @@ IN_PROC_BROWSER_TEST_F(RewardsBrowserTest, DISABLED_UpholdLimitNoBAT) { } } +IN_PROC_BROWSER_TEST_F(RewardsBrowserTest, BAPCutoffNonJP) { + rewards_browsertest_util::StartProcess(rewards_service_); + rewards_browsertest_util::CreateWallet(rewards_service_); + rewards_service_->FetchPromotions(); + promotion_->WaitForPromotionInitialization(); + promotion_->ClaimPromotionViaCode(); + + { + base::subtle::ScopedTimeClockOverrides time_override( + []() { return GetDate(2021, 3, 13); }, nullptr, nullptr); + ASSERT_EQ(FetchBalance(), 30.0); + } +} + +IN_PROC_BROWSER_TEST_F(RewardsBrowserTest, BAPCutoffBefore) { + rewards_browsertest_util::StartProcess(rewards_service_); + rewards_browsertest_util::CreateWallet(rewards_service_); + rewards_service_->FetchPromotions(); + promotion_->WaitForPromotionInitialization(); + promotion_->ClaimPromotionViaCode(); + + browser()->profile()->GetPrefs()->SetInteger( + country_codes::kCountryIDAtInstall, 19024); + + { + base::subtle::ScopedTimeClockOverrides time_override( + []() { return GetDate(2021, 3, 12); }, nullptr, nullptr); + ASSERT_EQ(FetchBalance(), 30.0); + } +} + +IN_PROC_BROWSER_TEST_F(RewardsBrowserTest, BAPCutoffAfter) { + rewards_browsertest_util::StartProcess(rewards_service_); + rewards_browsertest_util::CreateWallet(rewards_service_); + rewards_service_->FetchPromotions(); + promotion_->WaitForPromotionInitialization(); + promotion_->ClaimPromotionViaCode(); + + browser()->profile()->GetPrefs()->SetInteger( + country_codes::kCountryIDAtInstall, 19024); + + { + base::subtle::ScopedTimeClockOverrides time_override( + []() { return GetDate(2021, 3, 13); }, nullptr, nullptr); + ASSERT_EQ(FetchBalance(), 0.0); + } +} + +IN_PROC_BROWSER_TEST_F(RewardsBrowserTest, BAPPopup) { + // Open the rewards popup. + content::WebContents* popup_contents = context_helper_->OpenRewardsPopup(); + ASSERT_TRUE(popup_contents); + + // Attempt to open the BAP deprecation popup at the same time. The rewards + // panel popup should close. If both popups are shown at the same time, this + // test will crash on exit. + std::string error; + bool popup_shown = extensions::BraveActionAPI::ShowActionUI( + browser(), brave_rewards_extension_id, + std::make_unique("brave_rewards_panel.html#bap-deprecation"), + &error); + EXPECT_TRUE(popup_shown); +} + } // namespace rewards_browsertest diff --git a/components/brave_rewards/resources/extension/brave_rewards/_locales/en_US/messages.json b/components/brave_rewards/resources/extension/brave_rewards/_locales/en_US/messages.json index ba59fe911e29..723aa15d4401 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/_locales/en_US/messages.json +++ b/components/brave_rewards/resources/extension/brave_rewards/_locales/en_US/messages.json @@ -740,5 +740,17 @@ "onboardingPanelCompleteText": { "message": "By using Brave Rewards you are helping make the web a better place for everyone. And that’s awesome!", "description": "" + }, + "bapDeprecationHeader": { + "message": "Brave Rewards in Japan is switching to a new system!", + "description": "Header text for BAP deprecation warning message" + }, + "bapDeprecationLearnMore": { + "message": "Learn more", + "description": "Link to learn more about BAP deprecation" + }, + "bapDeprecationPopupText": { + "message": "Please use your BAP by March 13th. After that, BAP will be discontinued.", + "description": "Text for BAP deprecation popup" } } diff --git a/components/brave_rewards/resources/extension/brave_rewards/_locales/ja/messages.json b/components/brave_rewards/resources/extension/brave_rewards/_locales/ja/messages.json index e1b54ca2d8c2..600398c68c5d 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/_locales/ja/messages.json +++ b/components/brave_rewards/resources/extension/brave_rewards/_locales/ja/messages.json @@ -635,6 +635,22 @@ "message": "プライバシーを尊重する広告を表示してトークンを獲得し、お気に入りのサイトやコンテンツクリエイターを自動的にサポートします。", "description": "" }, + "onboardingSetupAdsHeader": { + "message": "How often do you want to see ads?", + "description": "" + }, + "onboardingSetupAdsSubheader": { + "message": "(ads per hour)", + "description": "" + }, + "onboardingSetupContributeHeader": { + "message": "How much monthly support do you want to give to your favorite creators?", + "description": "" + }, + "onboardingSetupContributeSubheader": { + "message": "(from your ads earnings)", + "description": "" + }, "onboardingStartUsingRewards": { "message": "Brave Rewardsの使用を開始", "description": "" @@ -733,6 +749,14 @@ "message": "トークンはクリエイターをサポートする以外にも使用できます。加盟店が参加すると、デジタルコンテンツやその他の商品を購入することができます。", "description": "" }, + "onboardingPanelSetupHeader": { + "message": "Lastly, let’s get you set up on the basic settings", + "description": "" + }, + "onboardingPanelSetupText": { + "message": "これを後で変更できます。", + "description": "" + }, "onboardingPanelCompleteHeader": { "message": "やったー、準備完了です!", "description": "" @@ -740,5 +764,17 @@ "onboardingPanelCompleteText": { "message": "Brave Rewardsを使用することで、ウェブを誰にとってもより良い場所にすることができます。そしてそれは素晴らしいことです!", "description": "" + }, + "bapDeprecationHeader": { + "message": "日本でのBrave Rewardsが新システムに移行します!", + "description": "Header text for BAP deprecation warning message" + }, + "bapDeprecationLearnMore": { + "message": "詳しくはこちら", + "description": "Link to learn more about BAP deprecation" + }, + "bapDeprecationPopupText": { + "message": "お持ちのBATポイント(BAP)は、3月13日までにご使用ください。BAPはそれ以降に廃止されます。", + "description": "Text for BAP deprecation popup" } } diff --git a/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx b/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx index 2165e56d62c0..9c58f3c6924e 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx +++ b/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx @@ -7,6 +7,8 @@ import { bindActionCreators, Dispatch } from 'redux' import { connect } from 'react-redux' import { getTabData } from '../background/api/tabs_api' +import { BAPDeprecationPopup } from '../../../shared/components/bap_deprecation' + // Components import Panel from './panel' @@ -174,6 +176,30 @@ export class RewardsPanel extends React.Component { } render () { + if (/^#?bap-deprecation$/i.test(window.location.hash)) { + const onLearnMore = () => { + const targetURL = 'chrome://newtab#bap-deprecation' + chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { + // If the currently active tab is the newtab page, then update + // the hash value for that page's URL. Otherwise, open a new + // tab pointed to the newtab page. + const [tab] = tabs + const tabID = tab ? tab.id : undefined + const tabURL = tab ? (tab.url || '') : '' + if (tabID && /^chrome:\/\/newtab(\/|$)/i.test(tabURL)) { + chrome.tabs.update(tabID, { url: targetURL }) + } else { + chrome.tabs.create({ url: targetURL }) + } + window.close() + }) + } + + return ( + + ) + } + return ( + + + + + + + + + + + + + + diff --git a/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_alert.style.ts b/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_alert.style.ts new file mode 100644 index 000000000000..dd2cc976d1bf --- /dev/null +++ b/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_alert.style.ts @@ -0,0 +1,75 @@ +/* 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/. */ + +import styled from 'styled-components' + +import bannerBackground from './assets/alert_background.svg' + +export const root = styled.div` + background-image: url('${bannerBackground}'); + background-repeat: no-repeat; + background-size: contain; + background-color: var(--brave-palette-white); + box-shadow: 0px 0px 16px rgba(99, 105, 110, 0.2); + border-radius: 8px; + width: 440px; + padding: 12px; + font-family: var(--brave-font-heading); + + .icon { + color: #fff; + } +` + +export const banner = styled.div` + color: var(--brave-palette-white); + text-align: center; + margin-top: -12px; + + .icon { + height: 35px; + width: auto; + } +` + +export const content = styled.div` + padding: 30px 22px 18px; +` + +export const header = styled.div` + text-align: center; + font-weight: 600; + font-size: 22px; + line-height: 32px; +` + +export const text = styled.div` + margin-top: 9px; + font-size: 14px; + line-height: 22px; + color: var(--brave-palette-neutral700); +` + +export const action = styled.div` + margin-top: 25px; + text-align: center; + + button { + color: var(--brave-palette-white); + min-width: 160px; + padding: 10px 20px; + font-weight: 600; + font-size: 14px; + line-height: 22px; + border: none; + border-radius: 40px; + background: var(--brave-color-brandBat); + cursor: pointer; + text-transform: uppercase; + } + + button:active { + background: var(--brave-color-brandBatActive); + } +` diff --git a/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_alert.tsx b/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_alert.tsx new file mode 100644 index 000000000000..7e4b9a4f7026 --- /dev/null +++ b/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_alert.tsx @@ -0,0 +1,40 @@ +/* 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/. */ + +import * as React from 'react' + +import { LocaleContext } from '../../lib/locale_context' +import { Modal, ModalCloseButton } from '../modal' +import { WarningIcon } from './icons/warning_icon' + +import * as style from './bap_deprecation_alert.style' + +interface Props { + onClose: () => void +} + +export function BAPDeprecationAlert (props: Props) { + const { getString } = React.useContext(LocaleContext) + return ( + + + + + + + {getString('bapDeprecationHeader')} + + + {getString('bapDeprecationAlertText')} + + + + + + + + ) +} diff --git a/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_popup.style.ts b/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_popup.style.ts new file mode 100644 index 000000000000..eb2c1fce0274 --- /dev/null +++ b/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_popup.style.ts @@ -0,0 +1,56 @@ +/* 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/. */ + +import styled from 'styled-components' + +export const root = styled.div` + background: linear-gradient(328.73deg, #A1A8F2 8.09%, #4C54D2 97.6%); + color: var(--brave-palette-white); + font-family: var(--brave-font-heading); + font-size: 14px; + font-weight: 600; + line-height: 22px; + width: 248px; + padding: 28px 16px 16px; + + .icon { + color: var(--brave-palette-white); + } +` + +export const content = styled.div`` + +export const heading = styled.div` + .icon { + vertical-align: middle; + margin-bottom: 3px; + margin-right: 4px; + height: 20px; + width: 20px; + } +` + +export const text = styled.div` + color: rgba(255, 255, 255, 0.7); +` + +export const action = styled.div` + text-align: center; + margin-top: 16px; + + button { + cursor: pointer; + font-weight: 600; + font-size: 13px; + line-height: 19px; + padding: 10px 40px; + border: solid 1px var(--brave-palette-white); + border-radius: 26px; + background: none; + } + + button:active { + background: #A1A8F2; + } +` diff --git a/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_popup.tsx b/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_popup.tsx new file mode 100644 index 000000000000..90a4f8c58e24 --- /dev/null +++ b/components/brave_rewards/resources/shared/components/bap_deprecation/bap_deprecation_popup.tsx @@ -0,0 +1,35 @@ +/* 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/. */ + +import * as React from 'react' + +import { LocaleContext } from '../../lib/locale_context' +import { WarningIcon } from './icons/warning_icon' + +import * as style from './bap_deprecation_popup.style' + +interface Props { + onLearnMore: () => void +} + +export function BAPDeprecationPopup (props: Props) { + const { getString } = React.useContext(LocaleContext) + return ( + + + + {getString('bapDeprecationHeader')} + + + {getString('bapDeprecationPopupText')} + + + + + + + ) +} diff --git a/components/brave_rewards/resources/shared/components/bap_deprecation/icons/warning_icon.tsx b/components/brave_rewards/resources/shared/components/bap_deprecation/icons/warning_icon.tsx new file mode 100644 index 000000000000..eb2bc568af67 --- /dev/null +++ b/components/brave_rewards/resources/shared/components/bap_deprecation/icons/warning_icon.tsx @@ -0,0 +1,9 @@ +import * as React from 'react' + +export function WarningIcon () { + return ( + + + + ) +} diff --git a/components/brave_rewards/resources/shared/components/bap_deprecation/index.ts b/components/brave_rewards/resources/shared/components/bap_deprecation/index.ts new file mode 100644 index 000000000000..d036bfb61744 --- /dev/null +++ b/components/brave_rewards/resources/shared/components/bap_deprecation/index.ts @@ -0,0 +1,97 @@ +/* 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 { BAPDeprecationAlert } from './bap_deprecation_alert' +export { BAPDeprecationPopup } from './bap_deprecation_popup' + +const bapAlertBegins = Date.parse('2021-03-06T00:00:00Z') +const bapCutoffBegins = Date.parse('2021-03-13T00:00:00Z') + +interface InteractionState { + popupShown: number + alertDismissed: number +} + +const interactionStateKey = 'bapDeprecationState' + +function loadInteractionState (): InteractionState { + let data: any + try { + data = JSON.parse(localStorage.getItem(interactionStateKey) || '{}') + } catch { + // Ignore + } + data = data || {} + return { + popupShown: Number(data.popupShown || 0), + alertDismissed: Number(data.alertDismissed || 0) + } +} + +function saveInteractionState (state: Partial) { + localStorage.setItem(interactionStateKey, JSON.stringify({ + ...loadInteractionState(), + ...state + })) +} + +export function saveBAPPopupShown () { + saveInteractionState({ popupShown: Date.now() }) +} + +export function saveBAPAlertDismissed () { + saveInteractionState({ alertDismissed: Date.now() }) +} + +function daysInPast (time: number) { + const span = Date.now() - time + return span / 1000 / 60 / 60 / 24 +} + +export function shouldShowBAPAlert (onlyAnonWallet: boolean, balance: number) { + // Do not show the modal if external wallets are supported or if + // the user has zero balance + if (!onlyAnonWallet || balance <= 0) { + return false + } + + // Do not show the modal before the alert start date + if (Date.now() < bapAlertBegins) { + return false + } + + const { alertDismissed } = loadInteractionState() + + if (alertDismissed) { + // Do not show the modal if the user has dismissed it within the last 3 days + // or if they have dismissed it and we are now past the BAP cutoff date + if (daysInPast(alertDismissed) < 3 || Date.now() >= bapCutoffBegins) { + return false + } + } + + return true +} + +export function shouldShowBAPPopup (onlyAnonWallet: boolean, balance: number) { + // Do not show the popup if external wallets are supported or if + // the user has zero balance + if (!onlyAnonWallet || balance <= 0) { + return false + } + + // Do not show the popup after the alert start date + if (Date.now() >= bapAlertBegins) { + return false + } + + const { popupShown } = loadInteractionState() + + // Do not show the popup if it has been shown within the last 3 days + if (popupShown && daysInPast(popupShown) < 3) { + return false + } + + return true +} diff --git a/components/brave_rewards/resources/shared/components/bap_deprecation/stories/index.tsx b/components/brave_rewards/resources/shared/components/bap_deprecation/stories/index.tsx new file mode 100644 index 000000000000..e67022c3f6ab --- /dev/null +++ b/components/brave_rewards/resources/shared/components/bap_deprecation/stories/index.tsx @@ -0,0 +1,56 @@ +/* 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/. */ + +import * as React from 'react' +import { storiesOf } from '@storybook/react' + +import { LocaleContext } from '../../../lib/locale_context' +import { WithThemeVariables } from '../../with_theme_variables' + +import { BAPDeprecationPopup } from '../bap_deprecation_popup' +import { BAPDeprecationAlert } from '../bap_deprecation_alert' + +import { localeStrings } from './locale_strings' + +const localeContext = { + getString (key: string) { + return localeStrings[key] || 'MISSING' + } +} + +function actionLogger (name: string) { + return (...args: any[]) => { + console.log(name, ...args) + } +} + +interface StoryWrapperProps { + children: React.ReactNode +} + +function StoryWrapper (props: StoryWrapperProps) { + return ( + + + {props.children} + + + ) +} + +storiesOf('Rewards/BAP Deprecation', module) + .add('Popup', () => { + return ( + + + + ) + }) + .add('Alert', () => { + return ( + + + + ) + }) diff --git a/components/brave_rewards/resources/shared/components/bap_deprecation/stories/locale_strings.ts b/components/brave_rewards/resources/shared/components/bap_deprecation/stories/locale_strings.ts new file mode 100644 index 000000000000..e35f62974bdc --- /dev/null +++ b/components/brave_rewards/resources/shared/components/bap_deprecation/stories/locale_strings.ts @@ -0,0 +1,11 @@ +/* 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 localeStrings = { + bapDeprecationAlertText: 'The tipping feature will be unavailable from March 13th until April 13th. All BAPs will be discontinued by April 13th. Please use your BAP by March 13th. Any BAP remaining in your Brave browser after March 13th cannot be held or transferred by you or Brave, and will be lost. A new and improved system awaits!', + bapDeprecationHeader: 'Brave Rewards in Japan is switching to a new system!', + bapDeprecationLearnMore: 'Learn more', + bapDeprecationOK: 'OK', + bapDeprecationPopupText: 'Please use your BAP by March 13th. After that, BAP will be discontinued.' +} diff --git a/components/resources/brave_components_strings.grd b/components/resources/brave_components_strings.grd index 3a9a686fade3..1739d0619ae2 100644 --- a/components/resources/brave_components_strings.grd +++ b/components/resources/brave_components_strings.grd @@ -946,6 +946,18 @@ > Hide sponsored images + + + The tipping feature will be unavailable from March 13th until April + 13th. All BAPs will be discontinued by April 13th. Please use your BAP + by March 13th. Any BAP remaining in your Brave browser after March 13th + cannot be held or transferred by you or Brave, and will be lost. A new + and improved system awaits! + + + Brave Rewards in Japan is switching to a new system! + + OK Edit Cards By clicking {{title}}, you agree to the $1Terms of Service$2 and $3Privacy Policy$4. Start using Brave Rewards diff --git a/components/resources/strings/brave_components_resources_ja.xtb b/components/resources/strings/brave_components_resources_ja.xtb index 06c40c7a672b..06b8df908d72 100644 --- a/components/resources/strings/brave_components_resources_ja.xtb +++ b/components/resources/strings/brave_components_resources_ja.xtb @@ -354,6 +354,8 @@ チッピングは、あなたが好きなコンテンツやクリエイターを個人的に応援し、サポートする方法の1つです。チッピングしよう! トークンで何ができますか? トークンはクリエイターをサポートする以外にも使用できます。加盟店が参加すると、デジタルコンテンツやその他の商品を購入することができます。 +最後に、基本設定を設定しましょう +これを後で変更できます。 やったー、準備完了です! Brave Rewardsを使用することで、ウェブを誰にとってもより良い場所にすることができます。そしてそれは素晴らしいことです! について @@ -630,14 +632,14 @@ 今月のこれまでの推定収益 今月のチップと支援実績 報酬を受け取る -スポンサー背景画像を見て、報酬を受け取りましょう -Brave Adsをオンにして、分け前をもらいましょう。またスポンサー画像を隠すことも選択できます。 おめでとうございます! Adsから得た報酬はこちらです! UGPからポイントが付与されました。 この背景画像を見ると、報酬が支払われます。 Brave Rewardsのスポンサー画像に関する詳細を確認 スポンサー画像を非表示にする +3月13日から4月13日チップを送る機能が停止されます。すべてのBATポイント(BAP)は4月13日に廃止されます。お持ちのBAPは、3月13日までにご使用ください。3月13日以降にBraveブラウザ上に残っているBAPについては、ユーザーもBraveも保持・移転をできず、消失されます。改良された新システムへの移行をご期待ください! +日本でのBrave Rewardsが新システムに移行します! カードを編集 {{title}}をクリックすることで、 利用規約 および プライバシーポリシーに同意することとなります。 友人や同僚とプライベートなビデオ通話を開始する。 @@ -718,6 +720,8 @@ API ゲートウェイ Swarm +サイズ +パス ローンチ済み 中止 インストールされていません diff --git a/vendor/bat-native-ledger/include/bat/ledger/option_keys.h b/vendor/bat-native-ledger/include/bat/ledger/option_keys.h index 7702a6eac85f..1c7fb87bb095 100644 --- a/vendor/bat-native-ledger/include/bat/ledger/option_keys.h +++ b/vendor/bat-native-ledger/include/bat/ledger/option_keys.h @@ -13,6 +13,8 @@ namespace option { const char kPublisherListRefreshInterval[] = "publisher_list_refresh_interval"; const char kClaimUGP[] = "claim_ugp"; +const char kContributionsDisabledForBAPMigration[] = + "contributions_disabled_for_bap_migration"; } // namespace option } // namespace ledger diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/contribution/contribution.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/contribution/contribution.cc index dbd8ee13192a..8c7bc2d6d218 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/contribution/contribution.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/contribution/contribution.cc @@ -19,6 +19,7 @@ #include "bat/ledger/internal/ledger_impl.h" #include "bat/ledger/internal/publisher/publisher_status_helper.h" #include "bat/ledger/internal/wallet/wallet_balance.h" +#include "bat/ledger/option_keys.h" using std::placeholders::_1; using std::placeholders::_2; @@ -148,6 +149,12 @@ void Contribution::ResetReconcileStamp() { } void Contribution::StartMonthlyContribution() { + if (ledger_->ledger_client()->GetBooleanOption( + option::kContributionsDisabledForBAPMigration)) { + BLOG(1, "Monthly contributions disabled for BAP migration"); + return; + } + const auto reconcile_stamp = ledger_->state()->GetReconcileStamp(); ResetReconcileStamp(); @@ -272,6 +279,12 @@ void Contribution::OneTimeTip( const std::string& publisher_key, const double amount, ledger::ResultCallback callback) { + if (ledger_->ledger_client()->GetBooleanOption( + option::kContributionsDisabledForBAPMigration)) { + BLOG(1, "One-time tips disabled for BAP migration"); + callback(type::Result::LEDGER_ERROR); + return; + } tip_->Process(publisher_key, amount, callback); } diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/promotion/promotion.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/promotion/promotion.cc index c9156c19d000..9e39af56c20f 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/promotion/promotion.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/promotion/promotion.cc @@ -14,12 +14,13 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "bat/ledger/internal/common/time_util.h" +#include "bat/ledger/internal/constants.h" #include "bat/ledger/internal/credentials/credentials_util.h" #include "bat/ledger/internal/ledger_impl.h" #include "bat/ledger/internal/legacy/wallet_info_properties.h" #include "bat/ledger/internal/promotion/promotion_transfer.h" #include "bat/ledger/internal/promotion/promotion_util.h" -#include "bat/ledger/internal/constants.h" +#include "bat/ledger/option_keys.h" #include "wrapper.hpp" // NOLINT @@ -107,6 +108,13 @@ void Promotion::Initialize() { } void Promotion::Fetch(ledger::FetchPromotionCallback callback) { + if (ledger_->ledger_client()->GetBooleanOption( + option::kContributionsDisabledForBAPMigration)) { + BLOG(1, "Fetch promotions disabled for BAP migration"); + callback(type::Result::LEDGER_OK, {}); + return; + } + // If we fetched promotions recently, fulfill this request from the // database instead of querying the server again if (!ledger::is_testing) { diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/wallet/wallet_balance.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/wallet/wallet_balance.cc index 1fd32be55214..11e7ccb8f148 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/wallet/wallet_balance.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/wallet/wallet_balance.cc @@ -11,8 +11,9 @@ #include #include "bat/ledger/global_constants.h" -#include "bat/ledger/internal/ledger_impl.h" #include "bat/ledger/internal/constants.h" +#include "bat/ledger/internal/ledger_impl.h" +#include "bat/ledger/option_keys.h" using std::placeholders::_1; using std::placeholders::_2; @@ -28,6 +29,13 @@ WalletBalance::WalletBalance(LedgerImpl* ledger) : WalletBalance::~WalletBalance() = default; void WalletBalance::Fetch(ledger::FetchBalanceCallback callback) { + if (ledger_->ledger_client()->GetBooleanOption( + option::kContributionsDisabledForBAPMigration)) { + BLOG(1, "Fetch balance disabled for BAP migration"); + callback(type::Result::LEDGER_OK, type::Balance::New()); + return; + } + // if we don't have user funds in anon card anymore // we can skip balance server ping if (!ledger_->state()->GetFetchOldBalanceEnabled()) {