1import assert from 'assert';
2import { ExpoConfig } from 'expo/config';
3import { ConfigPlugin, createRunOncePlugin, InfoPlist, withInfoPlist } from 'expo/config-plugins';
4
5const pkg = require('expo-screen-orientation/package.json');
6
7// This value must match the `EXDefaultScreenOrientationMask` string used in `expo-screen-orientation/ios/EXScreenOrientation/EXScreenOrientationViewController.m` (do not change).
8export const INITIAL_ORIENTATION_KEY = 'EXDefaultScreenOrientationMask';
9
10const OrientationLock = {
11  DEFAULT: 'UIInterfaceOrientationMaskAllButUpsideDown',
12  ALL: 'UIInterfaceOrientationMaskAll',
13  PORTRAIT: 'UIInterfaceOrientationMaskPortrait',
14  PORTRAIT_UP: 'UIInterfaceOrientationMaskPortrait',
15  PORTRAIT_DOWN: 'UIInterfaceOrientationMaskPortraitUpsideDown',
16  LANDSCAPE: 'UIInterfaceOrientationMaskLandscape',
17  LANDSCAPE_LEFT: 'UIInterfaceOrientationMaskLandscapeLeft',
18  LANDSCAPE_RIGHT: 'UIInterfaceOrientationMaskLandscapeRight',
19};
20
21type OrientationMasks = keyof typeof OrientationLock;
22
23// `initialOrientation` is not public in expo config yet, we just use it as an internal type.
24interface ExpoConfigWithInitialOrientation extends ExpoConfig {
25  initialOrientation?: OrientationMasks;
26}
27
28const withScreenOrientationViewController: ConfigPlugin<
29  {
30    initialOrientation?: keyof typeof OrientationLock;
31  } | void
32> = (config, { initialOrientation } = {}) => {
33  config = withInfoPlist(config, (config) => {
34    const extendedConfig = {
35      ...config,
36      initialOrientation,
37    };
38    config.modResults = setInitialOrientation(extendedConfig, config.modResults);
39    return config;
40  });
41  return config;
42};
43
44export function setInitialOrientation(
45  config: Pick<ExpoConfigWithInitialOrientation, 'initialOrientation'>,
46  infoPlist: InfoPlist
47): InfoPlist {
48  const initialOrientation = config.initialOrientation;
49
50  if (!initialOrientation) {
51    delete infoPlist[INITIAL_ORIENTATION_KEY];
52    return infoPlist;
53  }
54
55  assert(
56    initialOrientation in OrientationLock,
57    `Invalid initial orientation "${initialOrientation}" expected one of: ${Object.keys(
58      OrientationLock
59    ).join(', ')}`
60  );
61
62  infoPlist[INITIAL_ORIENTATION_KEY] = OrientationLock[initialOrientation];
63
64  return infoPlist;
65}
66
67export default createRunOncePlugin(withScreenOrientationViewController, pkg.name, pkg.version);
68