Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit edca0d4

Browse files
authored
fix(core): correctly set and restore breakpoints during print (#1379)
1 parent 5874498 commit edca0d4

File tree

3 files changed

+40
-24
lines changed

3 files changed

+40
-24
lines changed

projects/libs/flex-layout/core/media-marshaller/media-marshaller.spec.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,17 @@ describe('media-marshaller', () => {
301301
expect(mediaMarshaller.onMediaChange).not.toHaveBeenCalledWith({mediaQuery: 'print'} as any);
302302
});
303303

304-
});
304+
it('"print" events restore breakpoints correctly', () => {
305+
mediaController.activate('xs');
306+
const activatedBps = mediaMarshaller.activatedBreakpoints;
307+
// const smMediaQuery = 'screen and (min-width: 600px) and (max-width: 959px)';
308+
mediaController.activate('print');
309+
mediaController.activate('xs');
310+
const secondActivatedBps = mediaMarshaller.activatedBreakpoints;
305311

312+
expect(activatedBps).toEqual(secondActivatedBps);
313+
});
314+
});
306315
});
307316

308317
const fakeElement = {} as HTMLElement;

projects/libs/flex-layout/core/media-marshaller/media-marshaller.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export interface ElementMatcher {
4444
@Injectable({providedIn: 'root'})
4545
export class MediaMarshaller {
4646
private _useFallbacks = true;
47-
private activatedBreakpoints: BreakPoint[] = [];
47+
private _activatedBreakpoints: BreakPoint[] = [];
4848
private elementMap: ElementMap = new Map();
4949
private elementKeyMap: ElementKeyMap = new WeakMap();
5050
private watcherMap: WatcherMap = new WeakMap(); // special triggers to update elements
@@ -57,6 +57,14 @@ export class MediaMarshaller {
5757
return this.activatedBreakpoints[0]?.alias ?? '';
5858
}
5959

60+
set activatedBreakpoints(bps: BreakPoint[]) {
61+
this._activatedBreakpoints = [...bps];
62+
}
63+
64+
get activatedBreakpoints(): BreakPoint[] {
65+
return [...this._activatedBreakpoints];
66+
}
67+
6068
set useFallbacks(value: boolean) {
6169
this._useFallbacks = value;
6270
}
@@ -80,14 +88,14 @@ export class MediaMarshaller {
8088
const bpIndex = this.activatedBreakpoints.indexOf(bp);
8189

8290
if (mc.matches && bpIndex === -1) {
83-
this.activatedBreakpoints.push(bp);
84-
this.activatedBreakpoints.sort(sortDescendingPriority);
91+
this._activatedBreakpoints.push(bp);
92+
this._activatedBreakpoints.sort(sortDescendingPriority);
8593

8694
this.updateStyles();
8795
} else if (!mc.matches && bpIndex !== -1) {
8896
// Remove the breakpoint when it's deactivated
89-
this.activatedBreakpoints.splice(bpIndex, 1);
90-
this.activatedBreakpoints.sort(sortDescendingPriority);
97+
this._activatedBreakpoints.splice(bpIndex, 1);
98+
this._activatedBreakpoints.sort(sortDescendingPriority);
9199

92100
this.updateStyles();
93101
}
@@ -345,13 +353,12 @@ export class MediaMarshaller {
345353
* Watch for mediaQuery breakpoint activations
346354
*/
347355
private observeActivations() {
348-
const target = this as unknown as HookTarget;
349356
const queries = this.breakpoints.items.map(bp => bp.mediaQuery);
350357

351358
this.matchMedia
352359
.observe(this.hook.withPrintQuery(queries))
353360
.pipe(
354-
tap(this.hook.interceptEvents(target)),
361+
tap(this.hook.interceptEvents(this)),
355362
filter(this.hook.blockPropagation())
356363
)
357364
.subscribe(this.onMediaChange.bind(this));

projects/libs/flex-layout/core/media-marshaller/print-hook.ts

+16-16
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ export class PrintHook implements OnDestroy {
5050
}
5151

5252
/** Is the MediaChange event for any 'print' @media */
53-
isPrintEvent(e: MediaChange): Boolean {
53+
isPrintEvent(e: MediaChange): boolean {
5454
return e.mediaQuery.startsWith(PRINT);
5555
}
5656

5757
/** What is the desired mqAlias to use while printing? */
5858
get printAlias(): string[] {
59-
return this.layoutConfig.printWithBreakpoints || [];
59+
return this.layoutConfig.printWithBreakpoints ?? [];
6060
}
6161

6262
/** Lookup breakpoints associated with print aliases. */
@@ -80,22 +80,22 @@ export class PrintHook implements OnDestroy {
8080
if (this.isPrintEvent(event)) {
8181
// Reset from 'print' to first (highest priority) print breakpoint
8282
bp = this.getEventBreakpoints(event)[0];
83-
event.mediaQuery = bp ? bp.mediaQuery : '';
83+
event.mediaQuery = bp?.mediaQuery ?? '';
8484
}
8585
return mergeAlias(event, bp);
8686
}
8787

8888

8989
// registeredBeforeAfterPrintHooks tracks if we registered the `beforeprint`
9090
// and `afterprint` event listeners.
91-
private registeredBeforeAfterPrintHooks: boolean = false;
91+
private registeredBeforeAfterPrintHooks = false;
9292

9393
// isPrintingBeforeAfterEvent is used to track if we are printing from within
94-
// a `beforeprint` event handler. This prevents the typicall `stopPrinting`
94+
// a `beforeprint` event handler. This prevents the typical `stopPrinting`
9595
// form `interceptEvents` so that printing is not stopped while the dialog
9696
// is still open. This is an extension of the `isPrinting` property on
9797
// browsers which support `beforeprint` and `afterprint` events.
98-
private isPrintingBeforeAfterEvent: boolean = false;
98+
private isPrintingBeforeAfterEvent = false;
9999

100100
private beforePrintEventListeners: Function[] = [];
101101
private afterPrintEventListeners: Function[] = [];
@@ -141,8 +141,8 @@ export class PrintHook implements OnDestroy {
141141
}
142142

143143
/**
144-
* Prepare RxJS filter operator with partial application
145-
* @return pipeable filter predicate
144+
* Prepare RxJS tap operator with partial application
145+
* @return pipeable tap predicate
146146
*/
147147
interceptEvents(target: HookTarget) {
148148
this.registerBeforeAfterPrintHooks(target);
@@ -152,7 +152,6 @@ export class PrintHook implements OnDestroy {
152152
if (event.matches && !this.isPrinting) {
153153
this.startPrinting(target, this.getEventBreakpoints(event));
154154
target.updateStyles();
155-
156155
} else if (!event.matches && this.isPrinting && !this.isPrintingBeforeAfterEvent) {
157156
this.stopPrinting(target);
158157
target.updateStyles();
@@ -209,13 +208,14 @@ export class PrintHook implements OnDestroy {
209208
if (!this.isPrinting || this.isPrintingBeforeAfterEvent) {
210209
if (!event.matches) {
211210
const bp = this.breakpoints.findByQuery(event.mediaQuery);
212-
if (bp) { // Deactivating a breakpoint
211+
// Deactivating a breakpoint
212+
if (bp) {
213213
this.deactivations.push(bp);
214214
this.deactivations.sort(sortDescendingPriority);
215215
}
216216
} else if (!this.isPrintingBeforeAfterEvent) {
217217
// Only clear deactivations if we aren't printing from a `beforeprint` event.
218-
// Otherwise this will clear before `stopPrinting()` is called to restore
218+
// Otherwise, this will clear before `stopPrinting()` is called to restore
219219
// the pre-Print Activations.
220220
this.deactivations = [];
221221
}
@@ -230,11 +230,10 @@ export class PrintHook implements OnDestroy {
230230
}
231231
}
232232

233-
/** Is this service currently in Print-mode ? */
233+
// Is this service currently in print mode
234234
private isPrinting = false;
235-
private queue: PrintQueue = new PrintQueue();
235+
private queue = new PrintQueue();
236236
private deactivations: BreakPoint[] = [];
237-
238237
}
239238

240239
// ************************************************************************
@@ -261,6 +260,7 @@ class PrintQueue {
261260
addBreakpoint(bp: OptionalBreakPoint) {
262261
if (!!bp) {
263262
const bpInList = this.printBreakpoints.find(it => it.mediaQuery === bp.mediaQuery);
263+
264264
if (bpInList === undefined) {
265265
// If this is a `printAlias` breakpoint, then append. If a true 'print' breakpoint,
266266
// register as highest priority in the queue
@@ -281,6 +281,6 @@ class PrintQueue {
281281
// ************************************************************************
282282

283283
/** Only support intercept queueing if the Breakpoint is a print @media query */
284-
function isPrintBreakPoint(bp: OptionalBreakPoint) {
285-
return bp ? bp.mediaQuery.startsWith(PRINT) : false;
284+
function isPrintBreakPoint(bp: OptionalBreakPoint): boolean {
285+
return bp?.mediaQuery.startsWith(PRINT) ?? false;
286286
}

0 commit comments

Comments
 (0)