Implement First Time Use UI for Tab Focus (#28363)
* Enable Tab Focus UI * Backend change to support first time use UI for tab focus * Fix Illustration Resource * npm run format * Update showFRE related logics in both backend and frontend * FE Review Changes * Update API method name to SetTabFocusEnabled --------- Co-authored-by: Jocelyn Liu <yrliou@gmail.com>
This commit is contained in:
co-authored by
Jocelyn Liu
parent
8f6ac99cfd
commit
e7cec19db2
@@ -1408,6 +1408,12 @@ Or change later at <ph name="SETTINGS_EXTENIONS_LINK">$2<ex>brave://settings/ext
|
||||
<message name="IDS_BRAVE_ORGANIZE_TAB_DISMISS_BUTTON_LABEL" desc="Text of the dismiss button">
|
||||
Dismiss
|
||||
</message>
|
||||
<message name="IDS_BRAVE_ORGANIZE_TAB_PRIVACY_DISCLAIMER" desc="Disclaimer text for enabling the tab focus feature">
|
||||
When opened, this will automatically send the titles and origin of all non-private tabs to Leo to classify them.
|
||||
</message>
|
||||
<message name="IDS_BRAVE_ORGANIZE_TAB_ENABLE_BUTTON_LABEL" desc="Text of enable tab focus button">
|
||||
Enable
|
||||
</message>
|
||||
<!--Add new items to the appropriate sections above -->
|
||||
</messages>
|
||||
</release>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Example
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 29 KiB |
@@ -7,7 +7,7 @@ brave_tab_search_extras_grdp =
|
||||
"$root_gen_dir/brave/browser/resources/tab_search/brave_extras.grdp"
|
||||
|
||||
brave_tab_search_static_files = [
|
||||
"brave/remove_me.txt",
|
||||
"brave/tab_organizer_illustration.svg",
|
||||
# SVG and other static files
|
||||
]
|
||||
|
||||
|
||||
+48
@@ -148,6 +148,7 @@
|
||||
}
|
||||
|
||||
.learn-more-link {
|
||||
cursor: pointer;
|
||||
color: var(--leo-color-text-tertiary);
|
||||
font-feature-settings: 'ss03' on;
|
||||
text-decoration-line: underline;
|
||||
@@ -166,3 +167,50 @@
|
||||
padding: var(--leo-spacing-l);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.enable-tab-focus-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
box-sizing: border-box;
|
||||
padding: var(--leo-spacing-m);
|
||||
gap: var(--leo-spacing-m);
|
||||
}
|
||||
|
||||
.enable-tab-focus-content-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
box-sizing: border-box;
|
||||
border-radius: var(--leo-radius-m);
|
||||
background-color: var(--leo-color-neutral-10);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.enable-tab-focus-illustration {
|
||||
background-image: url(/brave/tab_organizer_illustration.svg);
|
||||
background-size: cover;
|
||||
align-items: stretch;
|
||||
height: 174px;
|
||||
}
|
||||
|
||||
.enable-tab-focus-info-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: var(--leo-spacing-xl);
|
||||
gap: var(--leo-spacing-m);
|
||||
}
|
||||
|
||||
.enable-tab-focus-info-text {
|
||||
font: var(--leo-font-small-regular);
|
||||
color: var(--leo-color-text-secondary);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.enable-tab-focus-button-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
+60
-16
@@ -62,7 +62,66 @@ function getTopicsHtml(this: AutoTabGroupsPageElement) {
|
||||
`)
|
||||
}
|
||||
|
||||
function getHeaderHtml(this: AutoTabGroupsPageElement) {
|
||||
return html`
|
||||
<div class="title-row">
|
||||
${!this.showBackButton ? html`
|
||||
<div>
|
||||
<leo-button
|
||||
size="medium"
|
||||
kind="plain-faint"
|
||||
fab
|
||||
@click=${this.onBackClick_}
|
||||
>
|
||||
<leo-icon name="arrow-left"></leo-icon>
|
||||
</leo-button>
|
||||
</div>
|
||||
` : ''}
|
||||
<div class='title-column'>
|
||||
<div class="title">${this.getTitle_()}</div>
|
||||
${!this.showFRE_ ? html`
|
||||
<div class="subtitle">${this.getSubtitle_()}</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
function getEnableTabFocusHtml(this: AutoTabGroupsPageElement) {
|
||||
return html`
|
||||
<div class="enable-tab-focus-wrapper">
|
||||
${getHeaderHtml.bind(this)()}
|
||||
<div class="enable-tab-focus-content-wrapper">
|
||||
<div class="enable-tab-focus-illustration"></div>
|
||||
<div class="enable-tab-focus-info-wrapper">
|
||||
<span class="enable-tab-focus-info-text">
|
||||
${this.getPrivacyDisclaimerMessage_()}
|
||||
</span>
|
||||
<div class="enable-tab-focus-button-row">
|
||||
<span class="learn-more-link" @click=${this.onLearnMoreClicked_}>
|
||||
${this.getLearnMoreLabel_()}
|
||||
</span>
|
||||
<div>
|
||||
<leo-button
|
||||
id="enableButton"
|
||||
kind="filled"
|
||||
size="small"
|
||||
@click="${this.onEnableTabFocusClicked_}"
|
||||
>
|
||||
${this.getEnableButtonLabel_()}
|
||||
</leo-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
export function getHtml(this: AutoTabGroupsPageElement) {
|
||||
if (this.showFRE_) {
|
||||
return getEnableTabFocusHtml.bind(this)()
|
||||
}
|
||||
return html`<!--_html_template_start_-->
|
||||
<div id="brave-tab-focus" class="brave-tab-focus">
|
||||
<div
|
||||
@@ -71,22 +130,7 @@ export function getHtml(this: AutoTabGroupsPageElement) {
|
||||
aria-live="polite"
|
||||
aria-relevant="all"
|
||||
>
|
||||
<div class='title-row'>
|
||||
${this.showBackButton ? html`
|
||||
<leo-button
|
||||
size="medium"
|
||||
kind="plain-faint"
|
||||
fab
|
||||
@click=${this.onBackClick_}
|
||||
>
|
||||
<leo-icon name="arrow-left"></leo-icon>
|
||||
</leo-button>
|
||||
` : ''}
|
||||
<div class='title-column'>
|
||||
<div class="title">${this.getTitle_()}</div>
|
||||
<div class="subtitle">${this.getSubtitle_()}</div>
|
||||
</div>
|
||||
</div>
|
||||
${getHeaderHtml.bind(this)()}
|
||||
<div class="input-row">
|
||||
<leo-input
|
||||
id="topic-input"
|
||||
|
||||
+16
@@ -23,6 +23,8 @@ export class AutoTabGroupsPageElement extends CrLitElement {
|
||||
protected topics_: string[] = []
|
||||
protected topic = ''
|
||||
protected undoTopic_ = ''
|
||||
protected showFRE_ =
|
||||
loadTimeData.getBoolean('showTabOrganizationFRE')
|
||||
|
||||
private apiProxy_: BraveTabSearchApiProxy =
|
||||
TabSearchApiProxyImpl.getInstance() as BraveTabSearchApiProxy
|
||||
@@ -41,6 +43,7 @@ export class AutoTabGroupsPageElement extends CrLitElement {
|
||||
isLoadingTopics: {type: Boolean},
|
||||
errorMessage: {type: String},
|
||||
needsPremium: {type: Boolean},
|
||||
showFRE_: {type: Boolean},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,6 +215,14 @@ export class AutoTabGroupsPageElement extends CrLitElement {
|
||||
return loadTimeData.getString('tabOrganizationDismissButtonLabel')
|
||||
}
|
||||
|
||||
protected getPrivacyDisclaimerMessage_(): string {
|
||||
return loadTimeData.getString('tabOrganizationPrivacyDisclaimer')
|
||||
}
|
||||
|
||||
protected getEnableButtonLabel_(): string {
|
||||
return loadTimeData.getString('tabOrganizationEnableButtonLabel')
|
||||
}
|
||||
|
||||
protected onLearnMoreClicked_() {
|
||||
this.apiProxy_.openHelpPage()
|
||||
}
|
||||
@@ -220,6 +231,11 @@ export class AutoTabGroupsPageElement extends CrLitElement {
|
||||
this.apiProxy_.openLeoGoPremiumPage()
|
||||
}
|
||||
|
||||
protected onEnableTabFocusClicked_() {
|
||||
this.apiProxy_.setTabFocusEnabled()
|
||||
this.showFRE_ = false
|
||||
}
|
||||
|
||||
protected onDismissErrorClicked_() {
|
||||
this.errorMessage = ''
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface BraveTabSearchApiProxy extends TabSearchApiProxy {
|
||||
getFocusTabs: (topic: string) => Promise<{ windowCreated: boolean, error: Error | null }>
|
||||
undoFocusTabs: () => Promise<void>
|
||||
openLeoGoPremiumPage: () => void
|
||||
setTabFocusEnabled: () => void
|
||||
}
|
||||
|
||||
export class BraveTabSearchApiProxyImpl extends TabSearchApiProxyImpl implements BraveTabSearchApiProxy {
|
||||
@@ -30,6 +31,10 @@ export class BraveTabSearchApiProxyImpl extends TabSearchApiProxyImpl implements
|
||||
openLeoGoPremiumPage() {
|
||||
this.handler.openLeoGoPremiumPage()
|
||||
}
|
||||
|
||||
setTabFocusEnabled() {
|
||||
this.handler.setTabFocusEnabled()
|
||||
}
|
||||
}
|
||||
|
||||
TabSearchApiProxyImpl.getInstance = () => {
|
||||
|
||||
@@ -36,4 +36,6 @@ interface PageHandler {
|
||||
UndoFocusTabs() => ();
|
||||
// Open a new tab for purchasing Leo premium.
|
||||
OpenLeoGoPremiumPage();
|
||||
// Set the user pref to enable tab focus with Leo.
|
||||
SetTabFocusEnabled();
|
||||
};
|
||||
|
||||
@@ -246,3 +246,8 @@ void TabSearchPageHandler::OpenLeoGoPremiumPage() {
|
||||
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
|
||||
Navigate(¶ms);
|
||||
}
|
||||
|
||||
void TabSearchPageHandler::SetTabFocusEnabled() {
|
||||
Profile::FromWebUI(web_ui_)->GetPrefs()->SetBoolean(
|
||||
ai_chat::prefs::kBraveAIChatTabOrganizationEnabled, true);
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ class TabSearchPageHandler : public TabSearchPageHandler_ChromiumImpl {
|
||||
GetFocusTabsCallback callback) override;
|
||||
void UndoFocusTabs(UndoFocusTabsCallback callback) override;
|
||||
void OpenLeoGoPremiumPage() override;
|
||||
void SetTabFocusEnabled() override;
|
||||
|
||||
void SetOriginalTabsInfoByWindowForTesting(
|
||||
const base::flat_map<SessionID, std::vector<TabInfo>>&
|
||||
|
||||
@@ -26,6 +26,11 @@ TabSearchUI::TabSearchUI(content::WebUI* web_ui)
|
||||
profile->GetPrefs()->GetBoolean(
|
||||
ai_chat::prefs::kBraveAIChatTabOrganizationEnabled));
|
||||
|
||||
// Show FRE if user doesn't explicitly enable/disble the feature pref.
|
||||
update_data.Set("showTabOrganizationFRE",
|
||||
!profile->GetPrefs()->HasPrefPath(
|
||||
ai_chat::prefs::kBraveAIChatTabOrganizationEnabled));
|
||||
|
||||
update_data.Set("autoTabGroupsSelectorHeading",
|
||||
l10n_util::GetStringUTF16(IDS_BRAVE_ORGANIZE_TAB_TITLE));
|
||||
|
||||
@@ -70,6 +75,14 @@ TabSearchUI::TabSearchUI(content::WebUI* web_ui)
|
||||
"tabOrganizationDismissButtonLabel",
|
||||
l10n_util::GetStringUTF16(IDS_BRAVE_ORGANIZE_TAB_DISMISS_BUTTON_LABEL));
|
||||
|
||||
update_data.Set(
|
||||
"tabOrganizationPrivacyDisclaimer",
|
||||
l10n_util::GetStringUTF16(IDS_BRAVE_ORGANIZE_TAB_PRIVACY_DISCLAIMER));
|
||||
|
||||
update_data.Set(
|
||||
"tabOrganizationEnableButtonLabel",
|
||||
l10n_util::GetStringUTF16(IDS_BRAVE_ORGANIZE_TAB_ENABLE_BUTTON_LABEL));
|
||||
|
||||
content::WebUIDataSource::Update(profile, chrome::kChromeUITabSearchHost,
|
||||
std::move(update_data));
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
|
||||
#endif
|
||||
registry->RegisterBooleanPref(kBraveAIChatContextMenuEnabled, true);
|
||||
registry->RegisterBooleanPref(kBraveAIChatShowToolbarButton, true);
|
||||
registry->RegisterBooleanPref(kBraveAIChatTabOrganizationEnabled, false);
|
||||
registry->RegisterBooleanPref(kBraveAIChatTabOrganizationEnabled, true);
|
||||
}
|
||||
registry->RegisterBooleanPref(kEnabledByPolicy, true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user