• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atinc / ngx-tethys / d9ae709b-3c27-4b69-b125-b8b80b54f90b

pending completion
d9ae709b-3c27-4b69-b125-b8b80b54f90b

Pull #2757

circleci

mengshuicmq
fix: fix code review
Pull Request #2757: feat(color-picker): color-picker support disabled (#INFR-8645)

98 of 6315 branches covered (1.55%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

2392 of 13661 relevant lines covered (17.51%)

83.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.86
/src/fullscreen/fullscreen-ref.ts
1
import { coerceElement } from '@angular/cdk/coercion';
2
import { ESCAPE } from '@angular/cdk/keycodes';
3
import { DOCUMENT } from '@angular/common';
4
import { ElementRef, Inject, NgZone } from '@angular/core';
5
import { fromEvent, merge, Observable, Subject } from 'rxjs';
6
import { takeUntil } from 'rxjs/operators';
7
import { ThyFullscreenConfig, ThyFullscreenMode } from './fullscreen.config';
8

9
export class ThyFullscreenRef<TResult = unknown> {
10
    fullscreenConfig: ThyFullscreenConfig;
×
11

×
12
    private isFullscreen = false;
×
13

×
14
    private ngUnsubscribe$ = new Subject<void>();
×
15

×
16
    private readonly _afterLaunched = new Subject<TResult>();
×
17

×
18
    private readonly _afterExited = new Subject<TResult>();
×
19

×
20
    constructor(@Inject(DOCUMENT) protected document: Document, private ngZone: NgZone) {}
21

22
    private onFullscreenChange() {
23
        const isFullScreen = this.isImmersiveFullscreen();
24
        if (isFullScreen) {
25
            this.launchNormalFullscreen();
×
26
        } else {
×
27
            this.exitNormalFullscreen();
×
28
        }
29
    }
30

×
31
    private resetElement(element: string | Element | ElementRef) {
32
        const targetType = typeof element;
33
        if (targetType === 'string') {
34
            return this.document.querySelector(`.${element}`);
×
35
        } else {
×
36
            return coerceElement(element);
×
37
        }
38
    }
39

×
40
    private isImmersiveFullscreen() {
41
        const doc = this.document;
42
        return !!(doc['fullscreenElement'] || doc['mozFullScreenElement'] || doc['webkitFullscreenElement'] || doc['msFullscreenElement']);
43
    }
×
44

×
45
    private handleKeyDown = (event: KeyboardEvent): void => {
46
        if (event.keyCode === ESCAPE) {
47
            if (this.isFullscreen && this.fullscreenConfig.mode === ThyFullscreenMode.emulated) {
×
48
                this.ngZone.run(() => this.exitNormalFullscreen());
×
49
            }
×
50
        }
×
51
    };
×
52

×
53
    private launchNormalFullscreen() {
×
54
        const targetElement = this.resetElement(this.fullscreenConfig.target);
×
55
        const classes = this.fullscreenConfig.targetLaunchedClass;
×
56
        const container = this.fullscreenConfig.emulatedContainer;
×
57
        if (container) {
×
58
            const containerElement = this.resetElement(container);
×
59
            const containerClientRect = containerElement.getBoundingClientRect();
60
            const targetClientRect = targetElement.getBoundingClientRect();
61
            const distanceX = containerClientRect.left - targetClientRect.left;
×
62
            const distanceY = containerClientRect.top - targetClientRect.top;
63
            targetElement.style.transform = `translate(${distanceX}px, ${distanceY}px)`;
×
64
            targetElement.style.width = `${containerClientRect.width}px`;
×
65
            targetElement.style.height = `${containerClientRect.height}px`;
×
66
        } else {
67
            targetElement.classList.add('thy-fullscreen');
×
68
        }
×
69
        targetElement.classList.add('thy-fullscreen-active');
70
        if (classes && classes.length) {
71
            targetElement.classList.add(classes);
×
72
        }
×
73
        this.isFullscreen = true;
×
74
        this._afterLaunched.next(undefined);
×
75
    }
×
76

×
77
    private exitNormalFullscreen() {
×
78
        const targetElement = this.resetElement(this.fullscreenConfig.target);
79
        const classes = this.fullscreenConfig.targetLaunchedClass;
80
        const container = this.fullscreenConfig.emulatedContainer;
×
81
        if (container) {
82
            targetElement.style.transform = ``;
×
83
            targetElement.style.width = ``;
×
84
            targetElement.style.height = ``;
×
85
        } else {
86
            targetElement.classList.remove('thy-fullscreen');
×
87
        }
×
88
        targetElement.classList.remove('thy-fullscreen-active');
×
89
        if (classes && classes.length) {
×
90
            targetElement.classList.remove(classes);
×
91
        }
92

93
        this.isFullscreen = false;
×
94
        this._afterExited.next(undefined);
×
95
        this._afterExited.complete();
96

97
        this.ngUnsubscribe$.next();
98
        this.ngUnsubscribe$.complete();
×
99
    }
100

101
    protected launchImmersiveFullscreen() {
102
        const { documentElement } = this.document;
103

104
        const requestFullscreen: HTMLElement['requestFullscreen'] | undefined =
105
            documentElement.requestFullscreen ||
×
106
            documentElement['mozRequestFullScreen'] ||
107
            documentElement['webkitRequestFullscreen'] ||
108
            documentElement['msRequestFullscreen'];
109

×
110
        if (typeof requestFullscreen === 'function') {
×
111
            // Note: the `requestFullscreen` returns a promise that resolves when the full screen is initiated.
×
112
            // The promise may reject with a `fullscreen error`. The browser warns into the console before rejecting:
×
113
            // `Failed to execute ‘requestFullScreen’ on ‘Element’: API can only be initiated by a user gesture.`.
114
            // We explicitly call `catch` and redirect the rejection to `console.error`.
115
            // Otherwise, this fill fail in unit tests with the following error:
116
            // `An error was thrown in afterAll. Unhandled promise rejection: TypeError: fullscreen error`.
×
117
            requestFullscreen.call(documentElement)?.catch(console.error);
×
118
        }
119
    }
120

×
121
    protected exitImmersiveFullscreen() {
122
        const { document } = this;
×
123

124
        const exitFullscreen: Document['exitFullscreen'] | undefined =
125
            document.exitFullscreen || document['mozCancelFullScreen'] || document['webkitExitFullscreen'] || document['msExitFullscreen'];
×
126

×
127
        if (typeof exitFullscreen === 'function') {
128
            exitFullscreen.call(document)?.catch(console.error);
129
        }
130
    }
×
131

×
132
    launch() {
133
        if (this.fullscreenConfig.mode === ThyFullscreenMode.immersive) {
134
            merge(
×
135
                fromEvent(this.document, 'fullscreenchange'),
136
                fromEvent(this.document, 'MSFullscreenChange'),
137
                fromEvent(this.document, 'webkitfullscreenchange')
138
            )
×
139
                .pipe(takeUntil(this.ngUnsubscribe$))
140
                .subscribe(() => {
141
                    this.onFullscreenChange();
×
142
                });
143
            this.launchImmersiveFullscreen();
1✔
144
        } else {
145
            this.ngZone.runOutsideAngular(() =>
146
                fromEvent<KeyboardEvent>(this.document, 'keydown').pipe(takeUntil(this.ngUnsubscribe$)).subscribe(this.handleKeyDown)
147
            );
148

149
            this.launchNormalFullscreen();
150
        }
151
    }
152

153
    exit() {
154
        if (this.fullscreenConfig.mode === ThyFullscreenMode.immersive) {
155
            this.exitImmersiveFullscreen();
156
        } else {
157
            this.exitNormalFullscreen();
158
        }
159
    }
160

161
    afterLaunched(): Observable<TResult> {
162
        return this._afterLaunched.asObservable();
163
    }
164

165
    afterExited(): Observable<TResult> {
166
        return this._afterExited.asObservable();
167
    }
168
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc