Use the download bubble
Users of web browsers like to see the files they've downloaded and to know the progress of their downloads that are in progress. Starting in version 43, HERE Core supports showing a download bubble UI component near a download button in the browser toolbar, similar to the one used in Google Chrome and other general-purpose web browsers.
Files that are downloading or downloaded appear in the download bubble user interface. The "bubble" is a menu that shows the most recent downloaded file when it appears automatically after a download completes or shows a list of recent downloads when opened by clicking the download button. If a user wants more detail on their downloads, the download bubble UI contains a Full download history link which can reveal a detailed display of downloaded and downloading files.
You can customize the colors and positioning of the download bubble UI.
The download bubble replaces the download shelf, which is no longer supported and is available only in HERE Core versions 42 and earlier. Use the download bubble for new implementations. Customers wishing to switch from the download shelf to the download bubble must create a new implementation; existing download shelf code cannot be directly migrated. Users' download history is independent of the download UI, so it is preserved when updating from the download shelf to the download bubble.
How the download bubble works
The download bubble requires you to implement a download button in your application UI and handle several events to control the bubble's positioning and appearance. The HERE Core Runtime shows or hides the download bubble UI based on user actions and download state.
Download bubble modes
The bubble is displayed in one of two modes:
-
Active Downloads Mode: This mode is shown automatically whenever a download finishes. It displays only currently active or finished downloads. The bubble appears on the last activated window that has adequately enabled the download bubble option.
-
Recent History Mode: This mode is shown when opened explicitly via the download button. It displays recent download history.
Key concepts
-
Download button: You create and manage a download button in your application UI. The HERE Core Runtime tells you when to show or hide this button.
-
Download bubble position: You specify where the bubble should appear relative to your download button.
-
Download bubble appearance: You can customize the bubble's colors using theme settings.
-
Download history page: You can respond to user requests to view full download history.
How to programmatically use the download bubble
The download bubble requires you to implement a download button in your application UI and handle several events to control the bubble's positioning and appearance. HERE Core shows or hides the download bubble UI based on user actions and download state.
Enable the download bubble in window options
In order for the download bubble to appear on a window, you must enable it for that window by adding the downloadBubble option to the window's options.
You can enable it for each window when on creation or set it for by default for all windows.
The following example shows enabling the download bubble for all windows of a platform in an application manifest by adding downloadBubble to defaultWindowOptions.
{
// Top-level properties
"platform": {
// Other platform properties
"defaultWindowOptions": {
// Other default window properities
"downloadBubble": {
"enabled": true
}
}
}
}
Make the download button visible or hidden
HERE Core emits the download-button-visibility-changed event to indicate when your download button should be visible.
This event is sent to every window object belonging to the same session from which a download originates that has the download bubble enabled.
The visible property on the event indicates whether you should change the button to be visible or hidden.
The visible property is true when:
- A user initiates a download and the button should become visible
It is false in any of the following circumstances:
- The user clears all downloads
- One hour passes after the user interacts with the download bubble
In the following example, the download button is shown or hidden based on the visibility event, and the bubble anchor is updated when the button becomes visible.
const win = fin.Window.getCurrentSync();
win.on('download-button-visibility-changed', (event) => {
if (event.visible) {
const element = document.getElementById("download-bubble-button");
// Show the button and get its bounding rectangle
element.classList.remove("hidden");
const rect = element.getBoundingClientRect();
// Update the anchor rectangle for the download bubble UI
const anchor = {
bounds: rect,
location: "topRight"
};
win.updateDownloadBubbleAnchor(anchor);
} else {
document.getElementById("download-bubble-button")?.classList.add("hidden");
}
});
Download button appearance
HERE Core emits the download-button-icon-updated event when the state of downloads changes.
You can use this information to update your download button's visual state, for example, to show download progress or indicate that downloads are complete.
The event provides the following properties:
isDisabled— Whether the button is clickableisActive— Whether new download information is availableisTouchMode— True if the application has touch mode enabledprogressIndicatorState— Current state:idle,dormant,scanning, ordownloadingprogressDownloadCount— Number of active downloadsprogressPercentage— Percent completed of all in-progress downloadsbuttonTooltip— Text for the button tooltip
In the following example, the download button state is logged to the console.
const win = fin.Window.getCurrentSync();
win.on('update-download-button-icon', (event) => {
console.log('Download button state:', {
isDisabled: event.isDisabled,
isActive: event.isActive,
isTouchMode: event.isTouchMode,
progressIndicatorState: event.progressIndicatorState,
progressDownloadCount: event.progressDownloadCount,
progressPercentage: event.progressPercentage,
buttonTooltip: event.buttonTooltip
});
// Update your download button appearance based on these values
});
Show the download bubble
You can programmatically show the download bubble by calling the showDownloadBubble() method on a BrowserWindow.
In the following example, the download bubble is shown when a user clicks a download button.
const win = fin.Window.getCurrentSync();
// When user clicks your download button
const showDownloadBubble = async () => {
const element = document.getElementById("download-bubble-button");
const rect = element.getBoundingClientRect();
// Create anchor rectangle for the download bubble UI
const anchor = {
bounds: rect,
location: "topRight"
};
// Anchor is optional but highly encouraged
win.showDownloadBubble(anchor);
});
Download bubble position
You can update the download bubble's anchor position at runtime using the updateDownloadBubbleAnchor() method.
This is useful when your download button moves or when the window is resized.
The anchor consists of a bounding rectangle and a location that specifies where the bubble should appear relative to that rectangle.
Available anchor locations:
topLefttopRightbottomLeftbottomRightleftToprightTopleftBottomrightBottomtopCenterbottomCenterleftCenterrightCenternone— positioned under anchorfloat— centered over anchor
In the following example, the download bubble is positioned below a download button.
const win = fin.Window.getCurrentSync();
win.on('download-button-visibility-changed', (event) => {
if (event.visible) {
const element = document.getElementById("download-bubble-button");
element.classList.remove("hidden");
const rect = element.getBoundingClientRect();
const anchor = {
bounds: rect,
location: "bottomLeft"
};
win.updateDownloadBubbleAnchor(anchor);
}
});
Handle download history requests
The show-all-downloads event is raised when the user clicks the Full download history link in the download bubble or when the bubble is requested but has no content to display.
You can use this event to display a full download page, such as the default Chromium download page (chrome://downloads) or a custom page.
In the following example, the chrome://downloads page appears when the user requests the full download history.
const platform = await fin.Platform.getCurrent();
platform.on('window-show-all-downloads', async (event) => {
let windowIdentity;
if (fin.me.isWindow) {
windowIdentity = fin.me.identity;
} else if (fin.me.isView) {
windowIdentity = (await fin.me.getCurrentWindow()).identity;
} else {
throw new Error('Not running in a platform View or Window');
}
const viewOptions = {
url: 'chrome://downloads/'
};
const view = await fin.Platform.getCurrentSync().createView(viewOptions, windowIdentity);
return view;
});
Customize download bubble appearance
You can customize the colors used in the download bubble UI by setting theme palettes for light and dark modes. This allows you to match the download bubble to your application's theme.
Set theme palettes
Theme palettes can be configured at the manifest level or programmatically at runtime. Both approaches require a security realm.
Manifest-level theming
In your platform's application manifest file, add a ThemePalette array to the runtime section.
Each palette specifies a color mode (light or dark) and a map of color values in 0xAARRGGBB format.
{
"runtime": {
"themePalette": [
{
"colorProviderKey": { "colorMode": "light" },
"colorsMap": {
"kColorLabelForeground": 4278190080,
"kColorBubbleBackground": 4293980400
}
},
{
"colorProviderKey": { "colorMode": "dark" },
"colorsMap": {
"kColorLabelForeground": 4294967295,
"kColorBubbleBackground": 4281348144
}
}
]
}
}
Programmatic theming
Use the System.setThemePalette() method to set theme palettes at runtime.
This method requires a security realm.
await fin.System.setThemePalette([
{
colorProviderKey: { colorMode: 'light' },
colorsMap: {
kColorLabelForeground: 4278190080,
kColorBubbleBackground: 4293980400
}
},
{
colorProviderKey: { colorMode: 'dark' },
colorsMap: {
kColorLabelForeground: 4293980400,
kColorBubbleBackground: 4293980400
}
}
]);
Available color IDs
The following color IDs can be customized:
kColorBubbleBackground— Background color for the bubble header and footerkColorBubbleBorder— Border color (Windows only)kColorBubbleBorderShadowLarge— Large border shadow (Windows only)kColorBubbleBorderShadowSmall— Small border shadow (Windows only)kColorDialogBackground— Background color for download item rowskColorDownloadBubbleRowHover— Background color when hovering over a download itemkColorDownloadBubbleShowAllDownloadsIcon— Icon color for the "Full download history" buttonkColorHoverButtonBackgroundHovered— Background color when hovering over the "Full download history" buttonkColorIcon— Default icon colorkColorLabelForeground— Primary text colorkColorLabelBackground— Label background color (set to0for transparent to disable readability adjustment)kColorSecondaryForeground— Secondary text color
The kColorLabelForeground and kColorSecondaryForeground colors may be adjusted by HERE Core to ensure readability against the kColorDialogBackground.
To disable this adjustment, set kColorLabelBackground to 0 (transparent).
For best results, use the same background color for kColorBubbleBackground and kColorDialogBackground to ensure consistent text readability throughout the bubble.
Platform-specific considerations
- On macOS, the 1-pixel border around the bubble is drawn by the operating system and cannot be customized.
- On Windows, the border can be controlled using the
kColorBubbleBordercolor IDs.
Retrieve current color overrides
You can retrieve the currently active theme palettes using the System.getThemePalette() method.
console.log(await fin.System.getThemePalette());
Respond to theme changes
The theme-palette-updated event is emitted when the theme palette changes.
You can listen for this event to update your UI accordingly.
const system = fin.System;
system.on('theme-palette-updated', () => {
console.log('Theme palette has been updated');
// Update your UI or reload theme settings
});
Synchronize with system theme preferences
HERE Core UI and HERE Enterprise Browser allow end users to toggle light and dark mode. You can set it to either mode or synchronize it with the operating system using theme preference APIs.
Set theme preferences
Use the System.setThemePreferences() method to set the theme mode.
This method requires a security realm.
// Set light mode
fin.System.setThemePreferences({ themeSource: 'light' });
// Set dark mode
fin.System.setThemePreferences({ themeSource: 'dark' });
// Use system theme
fin.System.setThemePreferences({ themeSource: 'system' });
Get theme preferences
Use the System.getThemePreferences() method to retrieve the current theme preferences.
console.log(await fin.System.getThemePreferences());
Respond to theme preference changes
The native-theme-updated event is emitted when the native theme state changes.
const system = fin.System;
system.on('native-theme-updated', (themeInfo) => {
console.log('Native theme updated:', themeInfo);
// Update your UI to reflect the new theme
});
Complete example
The following example demonstrates a complete download bubble implementation with a custom download button.
// Set color theme for download bubble
app.setColorProvidersOverrides([
{
colorProviderKey: { colorMode: 'light' },
colorsMap: {
'kColorBubbleBackground': 0xFFF5F5F5,
'kColorDialogBackground': 0xFFFFFFFF,
'kColorLabelForeground': 0xFF000000
}
},
{
colorProviderKey: { colorMode: 'dark' },
colorsMap: {
'kColorBubbleBackground': 0xFF2D2D2D,
'kColorDialogBackground': 0xFF1E1E1E,
'kColorLabelForeground': 0xFFFFFFFF
}
}
]);
app.whenReady().then(() => {
const win = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
win.loadFile('index.html');
// Handle download button visibility
win.on('download-button-visibility-changed', (isVisible) => {
win.webContents.send('toggle-download-button', isVisible);
});
// Handle download button appearance updates
win.on('update-download-button-icon', (event) => {
win.webContents.send('update-download-button', event);
});
// Handle full download history request
win.on('show-all-downloads', () => {
win.loadURL('chrome://downloads');
});
});