Settings: add safe area inset emulation
This commit is contained in:
		
							parent
							
								
									0255956297
								
							
						
					
					
						commit
						f15a52b3db
					
				
					 1 changed files with 131 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -3,6 +3,7 @@ import {
 | 
			
		|||
  createSignal,
 | 
			
		||||
  For,
 | 
			
		||||
  Show,
 | 
			
		||||
  type JSX,
 | 
			
		||||
  type ParentComponent,
 | 
			
		||||
} from "solid-js";
 | 
			
		||||
import Scaffold from "../material/Scaffold.js";
 | 
			
		||||
| 
						 | 
				
			
			@ -17,6 +18,7 @@ import {
 | 
			
		|||
  ListItemSecondaryAction,
 | 
			
		||||
  ListItemText,
 | 
			
		||||
  ListSubheader,
 | 
			
		||||
  NativeSelect,
 | 
			
		||||
  Switch,
 | 
			
		||||
  Toolbar,
 | 
			
		||||
} from "@suid/material";
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +48,96 @@ import BottomSheet from "../material/BottomSheet.jsx";
 | 
			
		|||
import { useServiceWorker } from "../platform/host.js";
 | 
			
		||||
import { useSessions } from "../masto/clients.js";
 | 
			
		||||
 | 
			
		||||
type Inset = {
 | 
			
		||||
  top?: number;
 | 
			
		||||
  right?: number;
 | 
			
		||||
  bottom?: number;
 | 
			
		||||
  left?: number;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type SafeAreaInsets = {
 | 
			
		||||
  landscape: Inset;
 | 
			
		||||
  protrait: Inset;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const safeAreaInsets: Record<string, SafeAreaInsets> = {
 | 
			
		||||
  iphone15: {
 | 
			
		||||
    protrait: {
 | 
			
		||||
      top: 59,
 | 
			
		||||
      bottom: 34,
 | 
			
		||||
    },
 | 
			
		||||
    landscape: {
 | 
			
		||||
      bottom: 21,
 | 
			
		||||
      left: 59,
 | 
			
		||||
      right: 59,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  iphone12: {
 | 
			
		||||
    protrait: {
 | 
			
		||||
      top: 47,
 | 
			
		||||
      bottom: 34,
 | 
			
		||||
    },
 | 
			
		||||
    landscape: {
 | 
			
		||||
      bottom: 21,
 | 
			
		||||
      left: 47,
 | 
			
		||||
      right: 47,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  iphone13mini: {
 | 
			
		||||
    protrait: {
 | 
			
		||||
      top: 50,
 | 
			
		||||
      bottom: 34,
 | 
			
		||||
    },
 | 
			
		||||
    landscape: {
 | 
			
		||||
      bottom: 21,
 | 
			
		||||
      left: 50,
 | 
			
		||||
      right: 50,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
let screenOrientationCallback: (() => void) | undefined;
 | 
			
		||||
 | 
			
		||||
function applySafeAreaEmulation(root: HTMLElement, insets: Inset) {
 | 
			
		||||
  for (const key of Object.keys(insets) as (keyof Inset)[]) {
 | 
			
		||||
    const value = insets[key];
 | 
			
		||||
    if (!value || value === 0) continue;
 | 
			
		||||
    root.style.setProperty(`--safe-area-inset-${key}`, `${value}px`);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setupSafeAreaEmulation(name: string) {
 | 
			
		||||
  const insets = safeAreaInsets[name];
 | 
			
		||||
  const root = document.querySelector(":root")! as HTMLElement;
 | 
			
		||||
  if (!insets) {
 | 
			
		||||
    if (screenOrientationCallback) {
 | 
			
		||||
      window.screen.orientation.removeEventListener(
 | 
			
		||||
        "change",
 | 
			
		||||
        screenOrientationCallback,
 | 
			
		||||
      );
 | 
			
		||||
      screenOrientationCallback = undefined;
 | 
			
		||||
    }
 | 
			
		||||
    for (const name of ["top", "right", "bottom", "left"]) {
 | 
			
		||||
      root.style.removeProperty(`--safe-area-inset-${name}`);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    screenOrientationCallback = () => {
 | 
			
		||||
      if (window.screen.orientation.type === "portrait-primary") {
 | 
			
		||||
        console.debug("safe area emulation: protrait");
 | 
			
		||||
        applySafeAreaEmulation(root, insets.protrait);
 | 
			
		||||
      } else if (window.screen.orientation.type === "landscape-primary") {
 | 
			
		||||
        console.debug("safe area emulation: landscape");
 | 
			
		||||
        applySafeAreaEmulation(root, insets.landscape);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
    window.screen.orientation.addEventListener(
 | 
			
		||||
      "change",
 | 
			
		||||
      screenOrientationCallback,
 | 
			
		||||
    );
 | 
			
		||||
    screenOrientationCallback();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Strings = {
 | 
			
		||||
  ["lang.auto"]: Template<{ detected: string }>;
 | 
			
		||||
} & Record<string, string | undefined>;
 | 
			
		||||
| 
						 | 
				
			
			@ -235,6 +327,45 @@ const Settings: ParentComponent = (props) => {
 | 
			
		|||
          </ListItem>
 | 
			
		||||
          <Divider />
 | 
			
		||||
        </li>
 | 
			
		||||
        {import.meta.env.DEV ? (
 | 
			
		||||
          <li>
 | 
			
		||||
            <ListSubheader>Developer Tools</ListSubheader>
 | 
			
		||||
            <ListItem
 | 
			
		||||
              secondaryAction={
 | 
			
		||||
                window.screen?.orientation ? (
 | 
			
		||||
                  <NativeSelect
 | 
			
		||||
                    sx={{ maxWidth: "40vw" }}
 | 
			
		||||
                    onChange={(event) => {
 | 
			
		||||
                      const k = event.currentTarget.value;
 | 
			
		||||
                      setupSafeAreaEmulation(k);
 | 
			
		||||
                    }}
 | 
			
		||||
                  >
 | 
			
		||||
                    <option>Don't change</option>
 | 
			
		||||
                    <option value={"ua"}>User agent</option>
 | 
			
		||||
                    <option value={"iphone15"}>
 | 
			
		||||
                      iPhone 15 and Plus, Pro, Pro Max
 | 
			
		||||
                    </option>
 | 
			
		||||
                    <option value={"iphone12"}>iPhone 12, 13 and 14</option>
 | 
			
		||||
                    <option value={"iphone13mini"}>iPhone 13 mini</option>
 | 
			
		||||
                  </NativeSelect>
 | 
			
		||||
                ) : undefined
 | 
			
		||||
              }
 | 
			
		||||
            >
 | 
			
		||||
              <ListItemText
 | 
			
		||||
                secondary={
 | 
			
		||||
                  window.screen?.orientation
 | 
			
		||||
                    ? undefined
 | 
			
		||||
                    : "Unsupported on This Platform"
 | 
			
		||||
                }
 | 
			
		||||
              >
 | 
			
		||||
                Safe Area Insets
 | 
			
		||||
              </ListItemText>
 | 
			
		||||
            </ListItem>
 | 
			
		||||
            <Divider />
 | 
			
		||||
          </li>
 | 
			
		||||
        ) : (
 | 
			
		||||
          <></>
 | 
			
		||||
        )}
 | 
			
		||||
      </List>
 | 
			
		||||
    </Scaffold>
 | 
			
		||||
  );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue