mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
fix(workspace): start the macOS rail below the traffic lights (#1806)
This commit is contained in:
1 parent
7fd3d1dab0
commit
6f247fb538
7 files changed
+168
-4
No files matched your search
+5
-1
@@ -1,6 +1,10 @@
|
||||
<!-- No brand mark: it linked to the page the first workspace link opens.
|
||||
The page's Back lives in the header's leading slot. -->
|
||||
<aside class="app-rail" [class.is-macos]="isMacOS()">
|
||||
<aside
|
||||
class="app-rail"
|
||||
[class.is-macos]="isMacOS()"
|
||||
[style.--rail-zoom-factor]="isMacOS() ? zoomFactor() : null"
|
||||
>
|
||||
<app-workspace-shell-rail-links [links]="workspaceLinks()" />
|
||||
|
||||
@if (primaryContextLinks().length > 0) {
|
||||
|
||||
+6
-1
@@ -29,8 +29,13 @@
|
||||
--rail-link-active-border: var(--app-selection-border);
|
||||
--rail-link-active-glow: var(--app-selection-glow);
|
||||
|
||||
// The traffic lights sit in the header band (56px, see the shell grid).
|
||||
// The first link starts below that band, where the content area and the
|
||||
// dashboard hero start, so its hover surface never touches the lights.
|
||||
// App zoom scales CSS pixels but not the lights: zoomed out, the inset
|
||||
// keeps 48 window pixels (lights' bottom plus a gap) instead.
|
||||
&.is-macos {
|
||||
padding-top: 36px;
|
||||
padding-top: max(56px, calc(48px / var(--rail-zoom-factor, 1)));
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
|
||||
+42
@@ -84,6 +84,48 @@ describe('WorkspaceShellRailComponent', () => {
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
describe('macOS zoom inset', () => {
|
||||
const setWindowWidths = (outer: number, inner: number) => {
|
||||
Object.defineProperty(window, 'outerWidth', {
|
||||
configurable: true,
|
||||
value: outer,
|
||||
});
|
||||
Object.defineProperty(window, 'innerWidth', {
|
||||
configurable: true,
|
||||
value: inner,
|
||||
});
|
||||
};
|
||||
const zoomVar = () =>
|
||||
(
|
||||
fixture.nativeElement.querySelector('.app-rail') as HTMLElement
|
||||
).style.getPropertyValue('--rail-zoom-factor');
|
||||
|
||||
afterEach(() => setWindowWidths(1024, 1024));
|
||||
|
||||
it('publishes the page zoom factor on macOS and follows resize', () => {
|
||||
setWindowWidths(1200, 1200);
|
||||
fixture.componentRef.setInput('isMacOS', true);
|
||||
fixture.detectChanges();
|
||||
TestBed.tick();
|
||||
fixture.detectChanges();
|
||||
expect(zoomVar()).toBe('1');
|
||||
|
||||
// Zoomed out to 50%: the viewport holds twice the CSS pixels.
|
||||
setWindowWidths(1200, 2400);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
fixture.detectChanges();
|
||||
expect(zoomVar()).toBe('0.5');
|
||||
});
|
||||
|
||||
it('leaves the inset alone off macOS', () => {
|
||||
setWindowWidths(1200, 2400);
|
||||
fixture.detectChanges();
|
||||
TestBed.tick();
|
||||
fixture.detectChanges();
|
||||
expect(zoomVar()).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
it('has no brand mark duplicating the first workspace link', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
|
||||
+34
-1
@@ -1,4 +1,12 @@
|
||||
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
effect,
|
||||
inject,
|
||||
input,
|
||||
signal,
|
||||
} from '@angular/core';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { RouterLink } from '@angular/router';
|
||||
@@ -32,4 +40,29 @@ export class WorkspaceShellRailComponent {
|
||||
>(null);
|
||||
readonly railProviderClass = input('rail-context-region');
|
||||
readonly isSettingsRoute = input(false);
|
||||
|
||||
/**
|
||||
* The page zoom factor. App zoom (`webFrame.setZoomLevel`) scales CSS
|
||||
* pixels but not the native traffic lights, so the macOS top inset is
|
||||
* kept in window pixels when zoomed out. Chromium reports the window in
|
||||
* window pixels and the viewport in CSS pixels, and fires `resize` when
|
||||
* the zoom changes.
|
||||
*/
|
||||
protected readonly zoomFactor = signal(1);
|
||||
|
||||
constructor() {
|
||||
const view = inject(DOCUMENT).defaultView;
|
||||
effect((onCleanup) => {
|
||||
if (!this.isMacOS() || !view) return;
|
||||
const update = () =>
|
||||
this.zoomFactor.set(
|
||||
view.innerWidth > 0 && view.outerWidth > 0
|
||||
? view.outerWidth / view.innerWidth
|
||||
: 1
|
||||
);
|
||||
update();
|
||||
view.addEventListener('resize', update);
|
||||
onCleanup(() => view.removeEventListener('resize', update));
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user