mirror of
https://github.com/zen-browser/desktop.git
synced 2026-07-29 19:37:48 +00:00
feat: Add feature callout for live folders, b=no-bug, c=folders, common
This commit is contained in:
@@ -96,3 +96,6 @@ zen-live-folder-github-issues =
|
||||
|
||||
zen-live-folder-github-option-repo-list-note =
|
||||
.label = This list is generated based on your currently active pull requests.
|
||||
|
||||
zen-live-folders-promotion-title = Live Folder Created!
|
||||
zen-live-folders-promotion-description = Latest content from your RSS feeds or GitHub pull requests will appear here automatically.
|
||||
|
||||
@@ -1,3 +1,54 @@
|
||||
diff --git a/browser/components/aboutwelcome/content/aboutwelcome.css b/browser/components/aboutwelcome/content/aboutwelcome.css
|
||||
--- a/browser/components/aboutwelcome/content/aboutwelcome.css
|
||||
+++ b/browser/components/aboutwelcome/content/aboutwelcome.css
|
||||
@@ -329,10 +329,15 @@
|
||||
--panel-color: var(--fc-color);
|
||||
--panel-shadow: none;
|
||||
--panel-shadow-margin: 6px;
|
||||
--panel-arrow-space: calc(var(--panel-shadow-margin) + var(--arrow-visible-height) - 1.5px);
|
||||
--panel-margin-offset: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-corner-distance) + (var(--arrow-width) / 2)));
|
||||
+
|
||||
+ @media -moz-pref("widget.macos.native-popovers") and (-moz-platform: macos) {
|
||||
+ --panel-shadow-margin: 0;
|
||||
+ --panel-arrow-space: 0;
|
||||
+ }
|
||||
}
|
||||
|
||||
panel#feature-callout::part(content) {
|
||||
width: initial;
|
||||
border: 0;
|
||||
@@ -515,10 +520,16 @@
|
||||
border-radius: 4px;
|
||||
padding: var(--callout-padding, 16px);
|
||||
width: 25em;
|
||||
gap: 16px;
|
||||
background: var(--fc-background);
|
||||
+
|
||||
+ @media -moz-pref("widget.macos.native-popovers") and (-moz-platform: macos) {
|
||||
+ --fc-background: transparent;
|
||||
+ box-shadow: none;
|
||||
+ border-width: 0;
|
||||
+ }
|
||||
}
|
||||
#feature-callout .screen[pos=callout] .section-main .main-content .main-content-inner {
|
||||
gap: 12px;
|
||||
}
|
||||
#feature-callout .screen[pos=callout] .section-main .main-content .main-content-inner .legal-paragraph .text-link {
|
||||
@@ -828,10 +839,14 @@
|
||||
#feature-callout .arrow-box {
|
||||
position: absolute;
|
||||
overflow: visible;
|
||||
transform: rotate(45deg);
|
||||
transform-style: preserve-3d;
|
||||
+
|
||||
+ @media -moz-pref("widget.macos.native-popovers") and (-moz-platform: macos) {
|
||||
+ display: none;
|
||||
+ }
|
||||
}
|
||||
#feature-callout:not([arrow-position]) .arrow-box, #feature-callout[hide-arrow] .arrow-box {
|
||||
display: none;
|
||||
}
|
||||
#feature-callout .arrow {
|
||||
diff --git a/browser/components/customizableui/content/panelUI.inc.xhtml b/browser/components/customizableui/content/panelUI.inc.xhtml
|
||||
--- a/browser/components/customizableui/content/panelUI.inc.xhtml
|
||||
+++ b/browser/components/customizableui/content/panelUI.inc.xhtml
|
||||
@@ -80,7 +131,7 @@ diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/Sta
|
||||
diff --git a/toolkit/themes/shared/global-shared.css b/toolkit/themes/shared/global-shared.css
|
||||
--- a/toolkit/themes/shared/global-shared.css
|
||||
+++ b/toolkit/themes/shared/global-shared.css
|
||||
@@ -100,10 +100,19 @@
|
||||
@@ -100,10 +100,20 @@
|
||||
--panel-padding: var(--arrowpanel-padding);
|
||||
--panel-shadow-margin: var(--arrowpanel-shadow-margin);
|
||||
--menuitem-border-radius: var(--arrowpanel-menuitem-border-radius);
|
||||
@@ -94,6 +145,7 @@ diff --git a/toolkit/themes/shared/global-shared.css b/toolkit/themes/shared/glo
|
||||
+ --panel-shadow: none;
|
||||
+ --panel-border-color: transparent;
|
||||
+ --panel-shadow-margin: 0px;
|
||||
+ --panel-padding: 0px;
|
||||
+ }
|
||||
}
|
||||
|
||||
@@ -216,7 +268,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
+
|
||||
+static void SyncPopoverBounds(NSPopover* aPopover,
|
||||
+ nsMenuPopupFrame* aPopupFrame) {
|
||||
+ if (!aPopover || !aPopover.shown) {
|
||||
+ if (!aPopover || !aPopover.shown || !aPopupFrame) {
|
||||
+ return;
|
||||
+ }
|
||||
+ NSWindow* popoverWindow = aPopover.contentViewController.view.window;
|
||||
@@ -246,7 +298,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
|
||||
|
||||
if (!mWindow) {
|
||||
@@ -5227,10 +5280,58 @@
|
||||
@@ -5227,10 +5280,56 @@
|
||||
mWindow.contentView.needsDisplay = YES;
|
||||
if (!nativeParentWindow || mPopupLevel != PopupLevel::Parent) {
|
||||
[mWindow orderFront:nil];
|
||||
@@ -286,11 +338,9 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
+ NSRect positioningRect = [parentView convertRect:windowRect
|
||||
+ fromView:nil];
|
||||
+ BOOL shouldHideAnchor = NO;
|
||||
+ if (auto popoverElement = GetPopupFrame()) {
|
||||
+ auto& element = popoverElement->PopupElement();
|
||||
+ if (element.GetBoolAttr(nsGkAtoms::hidepopovertail)) {
|
||||
+ shouldHideAnchor = YES;
|
||||
+ }
|
||||
+ auto& element = popupFrame->PopupElement();
|
||||
+ if (element.GetBoolAttr(nsGkAtoms::hidepopovertail)) {
|
||||
+ shouldHideAnchor = YES;
|
||||
+ }
|
||||
+ [(PopupWindow*)mWindow showPopoverRelativeToRect:positioningRect
|
||||
+ ofView:parentView
|
||||
@@ -305,7 +355,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
// close other programs' context menus when ours open.
|
||||
if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
||||
[(PopupWindow*)mWindow isContextMenu]) {
|
||||
@@ -5301,10 +5402,15 @@
|
||||
@@ -5301,10 +5400,15 @@
|
||||
// of a window it hides the parent window.
|
||||
if (mWindowType == WindowType::Popup && nativeParentWindow) {
|
||||
[nativeParentWindow removeChildWindow:mWindow];
|
||||
@@ -321,7 +371,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
// other programs) that a menu has closed.
|
||||
if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
||||
[(PopupWindow*)mWindow isContextMenu]) {
|
||||
@@ -5351,10 +5457,17 @@
|
||||
@@ -5351,10 +5455,17 @@
|
||||
return false;
|
||||
}
|
||||
return nsIWidget::ShouldUseOffMainThreadCompositing();
|
||||
@@ -339,7 +389,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
|
||||
return mWindow.isOpaque ? TransparencyMode::Opaque
|
||||
: TransparencyMode::Transparent;
|
||||
@@ -6313,10 +6426,20 @@
|
||||
@@ -6313,10 +6424,20 @@
|
||||
// We ignore aRepaint -- we have to call display:YES, otherwise the
|
||||
// title bar doesn't immediately get repainted and is displayed in
|
||||
// the wrong place, leading to a visual jump.
|
||||
@@ -360,7 +410,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
|
||||
void nsCocoaWindow::Resize(const DesktopRect& aRect, bool aRepaint) {
|
||||
DoResize(aRect.x, aRect.y, aRect.width, aRect.height, aRepaint, false);
|
||||
@@ -8277,18 +8400,27 @@
|
||||
@@ -8277,18 +8398,27 @@
|
||||
backing:(NSBackingStoreType)bufferingType
|
||||
defer:(BOOL)deferCreation {
|
||||
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
|
||||
@@ -388,7 +438,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
// Return 0 in order to match what the system does for sheet windows and
|
||||
// _NSPopoverWindows.
|
||||
- (CGFloat)_backdropBleedAmount {
|
||||
@@ -8342,10 +8474,120 @@
|
||||
@@ -8342,10 +8472,120 @@
|
||||
|
||||
- (void)setIsContextMenu:(BOOL)flag {
|
||||
mIsContextMenu = flag;
|
||||
|
||||
@@ -82,3 +82,12 @@
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-text-gradient {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
100% {
|
||||
background-position: -400% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,3 +614,15 @@
|
||||
:root:not([zen-sidebar-expanded="true"]) zen-sidebar-notification {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Feature allouts */
|
||||
#feature-callout #mainContentHeader {
|
||||
--special-color: color-mix(in srgb, light-dark(white, black), currentColor 50%);
|
||||
--specia-color-2: color-mix(in srgb, light-dark(white, black), currentColor 90%);
|
||||
background: linear-gradient(135deg, var(--specia-color-2), var(--special-color), var(--specia-color-2));
|
||||
background-size: 400%;
|
||||
background-clip: text;
|
||||
/* Still works on firefox */
|
||||
-webkit-text-fill-color: transparent;
|
||||
animation: zen-text-gradient 5s linear infinite;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,6 @@ zen-folder {
|
||||
|
||||
& > label {
|
||||
width: 100% !important;
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
color: var(--sidebar-text-color) !important;
|
||||
margin: 0 !important;
|
||||
@@ -191,6 +190,13 @@ zen-folder {
|
||||
padding: 0 !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
&[live-folder-animation] {
|
||||
background: linear-gradient(90deg, color-mix(in srgb, var(--sidebar-text-color) 50%, transparent), var(--sidebar-text-color));
|
||||
background-size: 400%;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-reset-button[live-folder-action] {
|
||||
|
||||
@@ -8,6 +8,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
setTimeout: "resource://gre/modules/Timer.sys.mjs",
|
||||
TabStateCache: "resource:///modules/sessionstore/TabStateCache.sys.mjs",
|
||||
ZenWindowSync: "resource:///modules/zen/ZenWindowSync.sys.mjs",
|
||||
FeatureCallout: "resource:///modules/asrouter/FeatureCallout.sys.mjs",
|
||||
});
|
||||
|
||||
ChromeUtils.defineLazyGetter(
|
||||
@@ -192,8 +193,11 @@ class nsZenLiveFoldersManager {
|
||||
const folder = this.window.gZenFolders.createFolder([], {
|
||||
label,
|
||||
isLiveFolder: true,
|
||||
collapsed: true,
|
||||
});
|
||||
|
||||
this.#maybeShowPromotion(folder, icon);
|
||||
|
||||
if (icon) {
|
||||
this.window.gZenFolders.setFolderUserIcon(folder, icon);
|
||||
}
|
||||
@@ -220,6 +224,88 @@ class nsZenLiveFoldersManager {
|
||||
return folder.id;
|
||||
}
|
||||
|
||||
#maybeShowPromotion(folder, icon) {
|
||||
let labelElement = folder.labelElement;
|
||||
labelElement.setAttribute("live-folder-animation", "true");
|
||||
labelElement.style.backgroundPositionX = "0%";
|
||||
let animation = folder.ownerGlobal.gZenUIManager.motion
|
||||
.animate(
|
||||
labelElement,
|
||||
{
|
||||
backgroundPositionX: ["0%", "-100%"],
|
||||
},
|
||||
{
|
||||
duration: 2,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
labelElement.style.backgroundPositionX = "";
|
||||
labelElement.removeAttribute("live-folder-animation");
|
||||
});
|
||||
|
||||
if (Services.prefs.getBoolPref("zen.live-folders.promotion.shown", false)) {
|
||||
return;
|
||||
}
|
||||
Services.prefs.setBoolPref("zen.live-folders.promotion.shown", true);
|
||||
let window = this.window;
|
||||
let gBrowser = window.gBrowser;
|
||||
const callout = new lazy.FeatureCallout({
|
||||
win: this.window,
|
||||
location: "chrome",
|
||||
context: "chrome",
|
||||
browser: gBrowser.selectedBrowser,
|
||||
theme: { preset: "chrome" },
|
||||
});
|
||||
animation.then(() => {
|
||||
callout.showFeatureCallout({
|
||||
id: "ZEN_LIVE_FOLDERS_CALLOUT",
|
||||
template: "feature_callout",
|
||||
groups: ["cfr"],
|
||||
content: {
|
||||
id: "ZEN_LIVE_FOLDERS_CALLOUT",
|
||||
template: "spotlight",
|
||||
backdrop: "transparent",
|
||||
transitions: true,
|
||||
autohide: true,
|
||||
screens: [
|
||||
{
|
||||
id: "ZEN_LIVE_FOLDERS_CALLOUT",
|
||||
anchors: [
|
||||
{
|
||||
selector: `[id="${folder.id}"]`,
|
||||
panel_position: {
|
||||
anchor_attachment: "rightcenter",
|
||||
callout_attachment: "topleft",
|
||||
},
|
||||
},
|
||||
],
|
||||
content: {
|
||||
position: "callout",
|
||||
width: "355px",
|
||||
title_logo: {
|
||||
imageURL: icon,
|
||||
width: "18px",
|
||||
height: "18px",
|
||||
marginInline: "0 8px",
|
||||
},
|
||||
title: {
|
||||
string_id: "zen-live-folders-promotion-title",
|
||||
},
|
||||
subtitle: {
|
||||
string_id: "zen-live-folders-promotion-description",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
lazy.setTimeout(() => {
|
||||
callout.endTour();
|
||||
}, 8000);
|
||||
});
|
||||
}
|
||||
|
||||
deleteFolder(id, deleteFolder = true) {
|
||||
const liveFolder = this.liveFolders.get(id);
|
||||
if (!liveFolder) {
|
||||
@@ -286,7 +372,10 @@ class nsZenLiveFoldersManager {
|
||||
existingItemIds.add(itemId);
|
||||
}
|
||||
|
||||
this.window.gBrowser.removeTabs(outdatedTabs);
|
||||
this.window.gBrowser.removeTabs(outdatedTabs, {
|
||||
skipSessionStore: true,
|
||||
animate: !folder.collapsed,
|
||||
});
|
||||
|
||||
// Remove the dismissed items that are no longer in the given list
|
||||
for (const dismissedItemId of this.dismissedItems) {
|
||||
|
||||
Reference in New Issue
Block a user