Skip to content

Commit 7c3c5dd

Browse files
committed
feat(ui): show HUD overlay with zoom percentage on zoom in/out
Add NotificationUI.showHUD() for centered, macOS-style HUD notifications with icon and label. Used by zoom commands to display a magnifying glass icon with the current zoom percentage that auto-dismisses after 1 second.
1 parent 54cf453 commit 7c3c5dd

3 files changed

Lines changed: 130 additions & 5 deletions

File tree

src/styles/brackets.less

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3409,6 +3409,41 @@ label input {
34093409
opacity: 1;
34103410
}
34113411

3412+
/* HUD overlay: centered macOS-style notification (zoom, volume, etc.) */
3413+
.hud-overlay {
3414+
position: fixed;
3415+
top: 50%;
3416+
left: 50%;
3417+
transform: translate(-50%, -50%) scale(0.9);
3418+
display: flex;
3419+
flex-direction: column;
3420+
align-items: center;
3421+
justify-content: center;
3422+
width: 140px;
3423+
height: 120px;
3424+
border-radius: 16px;
3425+
background: rgba(30, 30, 30, 0.85);
3426+
color: #e0e0e0;
3427+
z-index: 10000;
3428+
opacity: 0;
3429+
transition: opacity 0.2s ease, transform 0.2s ease;
3430+
pointer-events: none;
3431+
user-select: none;
3432+
i {
3433+
font-size: 40px;
3434+
margin-bottom: 8px;
3435+
}
3436+
.hud-label {
3437+
font-size: 18px;
3438+
font-weight: 600;
3439+
letter-spacing: 0.5px;
3440+
}
3441+
}
3442+
.hud-overlay.visible {
3443+
opacity: 1;
3444+
transform: translate(-50%, -50%) scale(1);
3445+
}
3446+
34123447
.inline-toast kbd {
34133448
display: inline-block;
34143449
padding: 1px 5px;

src/view/ViewCommandHandlers.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ define(function (require, exports, module) {
4949
KeyBindingManager = require("command/KeyBindingManager"),
5050
WorkspaceManager = require("view/WorkspaceManager"),
5151
_ = require("thirdparty/lodash"),
52-
FontRuleTemplate = require("text!view/fontrules/font-based-rules.less");
52+
FontRuleTemplate = require("text!view/fontrules/font-based-rules.less"),
53+
NotificationUI = require("widgets/NotificationUI");
5354

5455
var prefs = PreferencesManager.getExtensionPrefs("fonts");
5556

@@ -370,14 +371,26 @@ define(function (require, exports, module) {
370371
}
371372
}
372373

374+
function _showZoomHUD(zoomFactor, zoomingIn) {
375+
const pct = Math.round(zoomFactor * 100);
376+
const icon = zoomingIn
377+
? "fa-solid fa-magnifying-glass-plus"
378+
: "fa-solid fa-magnifying-glass-minus";
379+
NotificationUI.showHUD(icon, pct + "%", {
380+
autoCloseTimeS: 1
381+
});
382+
}
383+
373384
function _handleZoomIn(event) {
374385
if(!Phoenix.isNativeApp) {
375386
return _handleBrowserZoom(event);
376387
}
377388
const currentZoom = prefs.get(PREF_DESKTOP_ZOOM_SCALE);
378389
if(currentZoom < MAX_ZOOM_SCALE){
379-
prefs.set(PREF_DESKTOP_ZOOM_SCALE, currentZoom + 0.1);
380-
PhStore.setItem(PhStore._PHSTORE_BOOT_DESKTOP_ZOOM_SCALE_KEY, currentZoom + 0.1);
390+
const newZoom = currentZoom + 0.1;
391+
prefs.set(PREF_DESKTOP_ZOOM_SCALE, newZoom);
392+
PhStore.setItem(PhStore._PHSTORE_BOOT_DESKTOP_ZOOM_SCALE_KEY, newZoom);
393+
_showZoomHUD(newZoom, true);
381394
}
382395
}
383396

@@ -387,8 +400,10 @@ define(function (require, exports, module) {
387400
}
388401
const currentZoom = prefs.get(PREF_DESKTOP_ZOOM_SCALE);
389402
if(currentZoom > MIN_ZOOM_SCALE){
390-
prefs.set(PREF_DESKTOP_ZOOM_SCALE, currentZoom - 0.1);
391-
PhStore.setItem(PhStore._PHSTORE_BOOT_DESKTOP_ZOOM_SCALE_KEY, currentZoom - 0.1);
403+
const newZoom = currentZoom - 0.1;
404+
prefs.set(PREF_DESKTOP_ZOOM_SCALE, newZoom);
405+
PhStore.setItem(PhStore._PHSTORE_BOOT_DESKTOP_ZOOM_SCALE_KEY, newZoom);
406+
_showZoomHUD(newZoom, false);
392407
}
393408
}
394409

src/widgets/NotificationUI.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,9 +480,84 @@ define(function (require, exports, module) {
480480
return notification;
481481
}
482482

483+
let _activeHUD = null;
484+
485+
/**
486+
* Shows a large, centered HUD overlay (like macOS volume/brightness indicator) with an icon and label.
487+
* The HUD fades in/out and auto-dismisses. Only one HUD is shown at a time — calling this while a
488+
* previous HUD is visible replaces it instantly.
489+
*
490+
* ```js
491+
* NotificationUI.showHUD("fa-solid fa-magnifying-glass-plus", "110%");
492+
* ```
493+
*
494+
* @param {string} iconClass Font Awesome class string for the icon (e.g. "fa-solid fa-magnifying-glass-plus").
495+
* @param {string} label Text to display below the icon (e.g. "110%").
496+
* @param {Object} [options] optional, supported options:
497+
* * `autoCloseTimeS` - Time in seconds after which the HUD auto-closes. Default is 1.
498+
* @return {Notification} Object with a done handler that resolves when the HUD closes.
499+
* @type {function}
500+
*/
501+
function showHUD(iconClass, label, options = {}) {
502+
const autoCloseTimeS = options.autoCloseTimeS !== undefined ? options.autoCloseTimeS : 1;
503+
504+
// Close any existing HUD immediately
505+
if (_activeHUD && _activeHUD.$notification) {
506+
_activeHUD.$notification.remove();
507+
_activeHUD._result.resolve(CLOSE_REASON.TIMEOUT);
508+
_activeHUD.$notification = null;
509+
}
510+
511+
const $hud = $('<div class="hud-overlay">' +
512+
'<i class="' + iconClass + '"></i>' +
513+
'<div class="hud-label">' + label + '</div>' +
514+
'</div>');
515+
$("body").append($hud);
516+
517+
const notification = new Notification($hud, "hud");
518+
_activeHUD = notification;
519+
520+
// Fade in on next frame
521+
requestAnimationFrame(function () {
522+
$hud.addClass("visible");
523+
});
524+
525+
function closeHUD(reason) {
526+
if (!notification.$notification) {
527+
return;
528+
}
529+
notification.$notification = null;
530+
_activeHUD = null;
531+
$hud.removeClass("visible");
532+
function cleanup() {
533+
$hud.remove();
534+
notification._result.resolve(reason);
535+
}
536+
$hud.one("transitionend transitioncancel", cleanup);
537+
// Safety fallback
538+
setTimeout(cleanup, 600);
539+
}
540+
541+
notification.close = function (closeType) {
542+
closeHUD(closeType || CLOSE_REASON.CLICK_DISMISS);
543+
return this;
544+
};
545+
546+
if (autoCloseTimeS) {
547+
setTimeout(function () {
548+
if (notification.$notification) {
549+
notification.close(CLOSE_REASON.TIMEOUT);
550+
}
551+
}, autoCloseTimeS * 1000);
552+
}
553+
554+
return notification;
555+
}
556+
483557
exports.createFromTemplate = createFromTemplate;
484558
exports.createToastFromTemplate = createToastFromTemplate;
485559
exports.showToastOn = showToastOn;
560+
exports.showHUD = showHUD;
486561
exports.CLOSE_REASON = CLOSE_REASON;
487562
exports.NOTIFICATION_STYLES_CSS_CLASS = NOTIFICATION_STYLES_CSS_CLASS;
488563
});

0 commit comments

Comments
 (0)