mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 20:33:32 +08:00
fix(modal): status bar style defaults to app settings (#26291)
Resolves #26173
This commit is contained in:
@ -9,6 +9,7 @@ import {
|
|||||||
import type { GestureDetail } from '../../../utils/gesture';
|
import type { GestureDetail } from '../../../utils/gesture';
|
||||||
import { createGesture } from '../../../utils/gesture';
|
import { createGesture } from '../../../utils/gesture';
|
||||||
import { clamp, getElementRoot } from '../../../utils/helpers';
|
import { clamp, getElementRoot } from '../../../utils/helpers';
|
||||||
|
import type { Style as StatusBarStyle } from '../../../utils/native/status-bar';
|
||||||
import { setCardStatusBarDark, setCardStatusBarDefault } from '../utils';
|
import { setCardStatusBarDark, setCardStatusBarDefault } from '../utils';
|
||||||
|
|
||||||
import { calculateSpringStep, handleCanDismiss } from './utils';
|
import { calculateSpringStep, handleCanDismiss } from './utils';
|
||||||
@ -18,7 +19,12 @@ export const SwipeToCloseDefaults = {
|
|||||||
MIN_PRESENTING_SCALE: 0.93,
|
MIN_PRESENTING_SCALE: 0.93,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: Animation, onDismiss: () => void) => {
|
export const createSwipeToCloseGesture = (
|
||||||
|
el: HTMLIonModalElement,
|
||||||
|
animation: Animation,
|
||||||
|
statusBarStyle: StatusBarStyle,
|
||||||
|
onDismiss: () => void
|
||||||
|
) => {
|
||||||
/**
|
/**
|
||||||
* The step value at which a card modal
|
* The step value at which a card modal
|
||||||
* is eligible for dismissing via gesture.
|
* is eligible for dismissing via gesture.
|
||||||
@ -173,14 +179,14 @@ export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: An
|
|||||||
* should block the gesture from
|
* should block the gesture from
|
||||||
* proceeding,
|
* proceeding,
|
||||||
*/
|
*/
|
||||||
const isAttempingDismissWithCanDismiss = step >= 0 && canDismissBlocksGesture;
|
const isAttemptingDismissWithCanDismiss = step >= 0 && canDismissBlocksGesture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we are blocking the gesture from dismissing,
|
* If we are blocking the gesture from dismissing,
|
||||||
* set the max step value so that the sheet cannot be
|
* set the max step value so that the sheet cannot be
|
||||||
* completely hidden.
|
* completely hidden.
|
||||||
*/
|
*/
|
||||||
const maxStep = isAttempingDismissWithCanDismiss ? canDismissMaxStep : 0.9999;
|
const maxStep = isAttemptingDismissWithCanDismiss ? canDismissMaxStep : 0.9999;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we are blocking the gesture from
|
* If we are blocking the gesture from
|
||||||
@ -190,7 +196,7 @@ export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: An
|
|||||||
* Note that the starting breakpoint is always 0,
|
* Note that the starting breakpoint is always 0,
|
||||||
* so we omit adding 0 to the result.
|
* so we omit adding 0 to the result.
|
||||||
*/
|
*/
|
||||||
const processedStep = isAttempingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
|
const processedStep = isAttemptingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
|
||||||
|
|
||||||
const clampedStep = clamp(0.0001, processedStep, maxStep);
|
const clampedStep = clamp(0.0001, processedStep, maxStep);
|
||||||
|
|
||||||
@ -205,7 +211,7 @@ export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: An
|
|||||||
* crossed a certain threshold.
|
* crossed a certain threshold.
|
||||||
*/
|
*/
|
||||||
if (clampedStep >= DISMISS_THRESHOLD && lastStep < DISMISS_THRESHOLD) {
|
if (clampedStep >= DISMISS_THRESHOLD && lastStep < DISMISS_THRESHOLD) {
|
||||||
setCardStatusBarDefault();
|
setCardStatusBarDefault(statusBarStyle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* However, if we swipe back up, then the
|
* However, if we swipe back up, then the
|
||||||
@ -223,10 +229,10 @@ export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: An
|
|||||||
const velocity = detail.velocityY;
|
const velocity = detail.velocityY;
|
||||||
const step = detail.deltaY / height;
|
const step = detail.deltaY / height;
|
||||||
|
|
||||||
const isAttempingDismissWithCanDismiss = step >= 0 && canDismissBlocksGesture;
|
const isAttemptingDismissWithCanDismiss = step >= 0 && canDismissBlocksGesture;
|
||||||
const maxStep = isAttempingDismissWithCanDismiss ? canDismissMaxStep : 0.9999;
|
const maxStep = isAttemptingDismissWithCanDismiss ? canDismissMaxStep : 0.9999;
|
||||||
|
|
||||||
const processedStep = isAttempingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
|
const processedStep = isAttemptingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
|
||||||
|
|
||||||
const clampedStep = clamp(0.0001, processedStep, maxStep);
|
const clampedStep = clamp(0.0001, processedStep, maxStep);
|
||||||
|
|
||||||
@ -238,7 +244,7 @@ export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: An
|
|||||||
* animation can never complete until
|
* animation can never complete until
|
||||||
* canDismiss is checked.
|
* canDismiss is checked.
|
||||||
*/
|
*/
|
||||||
const shouldComplete = !isAttempingDismissWithCanDismiss && threshold >= DISMISS_THRESHOLD;
|
const shouldComplete = !isAttemptingDismissWithCanDismiss && threshold >= DISMISS_THRESHOLD;
|
||||||
let newStepValue = shouldComplete ? -0.001 : 0.001;
|
let newStepValue = shouldComplete ? -0.001 : 0.001;
|
||||||
|
|
||||||
if (!shouldComplete) {
|
if (!shouldComplete) {
|
||||||
@ -280,7 +286,7 @@ export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: An
|
|||||||
* check canDismiss. 25% was chosen
|
* check canDismiss. 25% was chosen
|
||||||
* to avoid accidental swipes.
|
* to avoid accidental swipes.
|
||||||
*/
|
*/
|
||||||
if (isAttempingDismissWithCanDismiss && clampedStep > maxStep / 4) {
|
if (isAttemptingDismissWithCanDismiss && clampedStep > maxStep / 4) {
|
||||||
handleCanDismiss(el, animation);
|
handleCanDismiss(el, animation);
|
||||||
} else if (shouldComplete) {
|
} else if (shouldComplete) {
|
||||||
onDismiss();
|
onDismiss();
|
||||||
|
@ -22,6 +22,7 @@ import { raf, inheritAttributes } from '../../utils/helpers';
|
|||||||
import type { Attributes } from '../../utils/helpers';
|
import type { Attributes } from '../../utils/helpers';
|
||||||
import { KEYBOARD_DID_OPEN } from '../../utils/keyboard/keyboard';
|
import { KEYBOARD_DID_OPEN } from '../../utils/keyboard/keyboard';
|
||||||
import { printIonWarning } from '../../utils/logging';
|
import { printIonWarning } from '../../utils/logging';
|
||||||
|
import { Style as StatusBarStyle, StatusBar } from '../../utils/native/status-bar';
|
||||||
import { BACKDROP, activeAnimations, dismiss, eventMethod, prepareOverlay, present } from '../../utils/overlays';
|
import { BACKDROP, activeAnimations, dismiss, eventMethod, prepareOverlay, present } from '../../utils/overlays';
|
||||||
import { getClassMap } from '../../utils/theme';
|
import { getClassMap } from '../../utils/theme';
|
||||||
import { deepReady } from '../../utils/transition';
|
import { deepReady } from '../../utils/transition';
|
||||||
@ -68,6 +69,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
|||||||
private keyboardOpenCallback?: () => void;
|
private keyboardOpenCallback?: () => void;
|
||||||
private moveSheetToBreakpoint?: (options: MoveSheetToBreakpointOptions) => Promise<void>;
|
private moveSheetToBreakpoint?: (options: MoveSheetToBreakpointOptions) => Promise<void>;
|
||||||
private inheritedAttributes: Attributes = {};
|
private inheritedAttributes: Attributes = {};
|
||||||
|
private statusBarStyle?: StatusBarStyle;
|
||||||
|
|
||||||
private inline = false;
|
private inline = false;
|
||||||
private workingDelegate?: FrameworkDelegate;
|
private workingDelegate?: FrameworkDelegate;
|
||||||
@ -519,7 +521,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
|||||||
* If we did not do this check, then not using swipeToClose would mean you could
|
* If we did not do this check, then not using swipeToClose would mean you could
|
||||||
* not run canDismiss on swipe as there would be no swipe gesture created.
|
* not run canDismiss on swipe as there would be no swipe gesture created.
|
||||||
*/
|
*/
|
||||||
const hasCardModal = this.swipeToClose || (this.canDismiss !== undefined && this.presentingElement !== undefined);
|
const hasCardModal = this.presentingElement !== undefined && (this.swipeToClose || this.canDismiss !== undefined);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We need to change the status bar at the
|
* We need to change the status bar at the
|
||||||
@ -527,6 +529,8 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
|||||||
* by the time the card animation is done.
|
* by the time the card animation is done.
|
||||||
*/
|
*/
|
||||||
if (hasCardModal && getIonMode(this) === 'ios') {
|
if (hasCardModal && getIonMode(this) === 'ios') {
|
||||||
|
// Cache the original status bar color before the modal is presented
|
||||||
|
this.statusBarStyle = await StatusBar.getStyle();
|
||||||
setCardStatusBarDark();
|
setCardStatusBarDark();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,7 +588,9 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.gesture = createSwipeToCloseGesture(el, ani, () => {
|
const statusBarStyle = this.statusBarStyle ?? StatusBarStyle.Default;
|
||||||
|
|
||||||
|
this.gesture = createSwipeToCloseGesture(el, ani, statusBarStyle, () => {
|
||||||
/**
|
/**
|
||||||
* While the gesture animation is finishing
|
* While the gesture animation is finishing
|
||||||
* it is possible for a user to tap the backdrop.
|
* it is possible for a user to tap the backdrop.
|
||||||
@ -691,9 +697,9 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
|||||||
* finishes when the dismiss animation does.
|
* finishes when the dismiss animation does.
|
||||||
* TODO (FW-937)
|
* TODO (FW-937)
|
||||||
*/
|
*/
|
||||||
const hasCardModal = this.swipeToClose || (this.canDismiss !== undefined && this.presentingElement !== undefined);
|
const hasCardModal = this.presentingElement !== undefined && (this.swipeToClose || this.canDismiss !== undefined);
|
||||||
if (hasCardModal && getIonMode(this) === 'ios') {
|
if (hasCardModal && getIonMode(this) === 'ios') {
|
||||||
setCardStatusBarDefault();
|
setCardStatusBarDefault(this.statusBarStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tslint:disable-next-line */
|
/* tslint:disable-next-line */
|
||||||
|
@ -81,10 +81,10 @@ export const setCardStatusBarDark = () => {
|
|||||||
StatusBar.setStyle({ style: Style.Dark });
|
StatusBar.setStyle({ style: Style.Dark });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setCardStatusBarDefault = () => {
|
export const setCardStatusBarDefault = (defaultStyle = Style.Default) => {
|
||||||
if (!win || win.innerWidth >= 768 || !StatusBar.supportsDefaultStatusBarStyle()) {
|
if (!win || win.innerWidth >= 768 || !StatusBar.supportsDefaultStatusBarStyle()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusBar.setStyle({ style: Style.Default });
|
StatusBar.setStyle({ style: defaultStyle });
|
||||||
};
|
};
|
||||||
|
@ -31,4 +31,12 @@ export const StatusBar = {
|
|||||||
|
|
||||||
engine.setStyle(options);
|
engine.setStyle(options);
|
||||||
},
|
},
|
||||||
|
getStyle: async function (): Promise<Style> {
|
||||||
|
const engine = this.getEngine();
|
||||||
|
if (!engine) {
|
||||||
|
return Style.Default;
|
||||||
|
}
|
||||||
|
const { style } = await engine.getInfo();
|
||||||
|
return style;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user