Skip to content

Commit 740b196

Browse files
authored
update mobile template (#304)
1 parent a6514d1 commit 740b196

16 files changed

Lines changed: 325 additions & 114 deletions

plugins/mobile-apps/template/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@ node_modules/
1010
# ── Expo / Metro ─────────────────────────────────────────────────────────────
1111
.expo/
1212
dist/
13+
dist-web/
1314
web-build/
1415
.tamagui/
1516

1617
# ── Local environment overrides ──────────────────────────────────────────────
1718
.env
1819
.env*.local
1920

21+
# ── Wrap build config (contains secrets — never commit) ──────────────────────
22+
wrap.config.json
23+
24+
# ── Build output / vendor ────────────────────────────────────────────────────
25+
vendor/
26+
2027
# ── Native projects ──────────────────────────────────────────────────────────
2128
# Regenerated by `npx expo prebuild --clean`
2229
android/
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"schemaVersion": 1,
3+
"templateVersion": 1
4+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Customize Your App Safely
2+
3+
You can customize this app while continuing to receive template upgrades.
4+
5+
## Change freely
6+
7+
You can make any changes under:
8+
9+
- `app/`
10+
- `src/`
11+
12+
Add, edit, move, rename, or delete screens, components, services, styles, and
13+
other app code in these directories. `upgrade-template` never changes them.
14+
15+
You can also add your own dependencies, scripts, assets, and other files. Custom
16+
dependencies are kept during upgrades, although incompatible packages may need
17+
to be updated for a newer Expo SDK.
18+
19+
## Generated connector schemas
20+
21+
Do not edit `src/generated/connectorSchemas.ts` manually. After adding or
22+
removing connectors, regenerate it with:
23+
24+
```bash
25+
npm run generate-schemas
26+
```
27+
28+
Commit the generated file with your app. Template upgrades never change it.
29+
30+
## Be careful with root files
31+
32+
JavaScript and configuration files in the project root may be updated by future
33+
template upgrades. Examples include:
34+
35+
- `app.config.js`
36+
- `babel.config.js`
37+
- `metro.config.js`
38+
- `tamagui.config.ts`
39+
- `tsconfig.json`
40+
41+
Keep changes to these files small and focused. If your changes overlap a future
42+
template update, the upgrader may create a `.rej` file that you must resolve
43+
manually.
44+
45+
When a root file contains customization markers, edit only inside marked
46+
sections. Do not remove or rename comments that say `DO NOT REMOVE OR RENAME THE COMMENT`.
47+
Future template updates keep marked sections unchanged, which reduces upgrade conflicts.
48+
49+
In `app.config.js`, use `CUSTOMER APP SETTINGS` for app identity, package names,
50+
icon, and version defaults. Use `CUSTOMIZATION` for additional Expo config
51+
overrides.
52+
53+
Do not edit, move, or delete `.powerapps-native/version.json`. It records which
54+
template upgrades have been applied.
55+
56+
The upgrader does not change `android/` or `ios/`. If you maintain native
57+
projects, update them separately when required.
58+
59+
## Before upgrading
60+
61+
1. Commit or back up your work.
62+
2. Preview the upgrade:
63+
64+
```bash
65+
npx --package @microsoft/power-apps-native-host@latest upgrade-template --dry-run
66+
```
67+
68+
3. Review warnings and run the upgrade.
69+
4. Resolve any `.rej` files, then test your app.

plugins/mobile-apps/template/README.md

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Power Apps Standalone App Template
22

3-
This template is an Expo, React Native, and TypeScript starter for building a standalone mobile app that connects to Power Platform data through `@microsoft/power-apps-native-host`.
3+
This template is an Expo, React Native, and TypeScript starter for building an
4+
iOS, Android, or hosted web app that connects to Power Platform data through
5+
`@microsoft/power-apps-native-host`.
46

57
## Requirements
68

@@ -28,14 +30,9 @@ connector wiring.
2830

2931
For GitHub Copilot in VS Code:
3032

31-
1. Open the Command Palette.
32-
2. Run **Chat: Install Plugin From Source**.
33-
3. Paste the mobile-app plugin manifest URL:
34-
35-
```text
36-
https://github.com/microsoft/power-platform-skills/tree/main/plugins/mobile-apps/.plugin/plugin.json
37-
```
38-
33+
1. Open the Extensions view.
34+
2. Enter `@agentplugin` in the search box.
35+
3. Find the Power Platform mobile-app plugin and select **Install**.
3936
4. Reload VS Code if prompted, then open Copilot Chat in Agent mode.
4037

4138
Alternatively, install it from a terminal with GitHub Copilot CLI:
@@ -99,6 +96,62 @@ connector wiring.
9996
- Play store: (coming soon)
10097
- App center: https://install.appcenter.ms/orgs/appmagic-player-x6ys/apps/rn-dev-player-preview/distribution_groups/public_distribution/releases
10198

99+
## Upgrade the Native Host
100+
101+
From the app directory, preview the next template upgrade:
102+
103+
```bash
104+
npx --package @microsoft/power-apps-native-host@latest upgrade-template --dry-run
105+
```
106+
107+
Apply it:
108+
109+
```bash
110+
npx --package @microsoft/power-apps-native-host@latest upgrade-template
111+
```
112+
113+
Each run upgrades one template version, installs compatible dependencies, and
114+
runs Expo validation. If another version is available, run the command again.
115+
The current version is stored in `.powerapps-native/version.json`; do not edit
116+
this file.
117+
118+
Apps created before this version file existed must specify their source template
119+
version:
120+
121+
```bash
122+
npx --package @microsoft/power-apps-native-host@latest \
123+
upgrade-template --from-version 1
124+
```
125+
126+
The upgrader never changes `app/`, `src/`, `android/`, or `ios/`. If a root
127+
configuration change conflicts with your customization, it writes a `.rej` file
128+
for manual resolution. Failed validation restores files managed by the upgrade.
129+
130+
Supported package managers are npm, pnpm, and Bun. See
131+
[CUSTOMIZATION.md](CUSTOMIZATION.md) before changing root configuration files.
132+
133+
## Web
134+
135+
Start the browser app:
136+
137+
```bash
138+
npm run web
139+
```
140+
141+
The command opens **Local Play** in your default browser and embeds the local
142+
Expo app in the hosted Power Apps player. Use the same browser profile as your
143+
Power Platform tenant.
144+
145+
Web builds are supported in Code Apps. They are also supported in Power Pages
146+
when the app uses Dataverse only.
147+
148+
To publish as a Code App, run `npm run bundle:web`, set `appType` to `CodeApp`
149+
and `distPath` to `dist-web` in `power.config.json`, then run
150+
`npx power-apps push`.
151+
152+
To publish to Power Pages, run `npm run bundle:web -- powerpages`, then use the Power Pages
153+
skills to upload the generated `dist-web` directory.
154+
102155
## License and notices
103156

104157
This template is provided under the license in `LICENSE`.

plugins/mobile-apps/template/app.config.js

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,41 @@
44

55
const IS_DEV_CLIENT = process.env.DEV_CLIENT === 'true';
66

7+
// CUSTOMER APP SETTINGS START - DO NOT REMOVE OR RENAME THE COMMENT
8+
// App identity, package names, icon, and version defaults are customer-owned.
79
const APP_NAME = process.env.APP_DISPLAY_NAME || 'Power Apps Standalone App';
810
const APP_SLUG = process.env.APP_SLUG || 'powerapps-standalone-app';
911
const APP_SCHEME = process.env.APP_SCHEME || APP_SLUG;
1012
const ANDROID_PACKAGE = process.env.ANDROID_PACKAGE || 'com.contoso.powerappsapp';
1113
const IOS_BUNDLE_IDENTIFIER = process.env.IOS_BUNDLE_IDENTIFIER || 'com.contoso.powerappsapp';
1214

15+
// App icon — set APP_ICON_PATH to a 1024×1024 PNG before running expo prebuild.
16+
// Expo uses this single image to generate all required icon sizes for both
17+
// Android (adaptive icon foreground + legacy) and iOS (all @1x/@2x/@3x slots).
18+
const APP_ICON_PATH = process.env.APP_ICON_PATH || null;
19+
20+
// Version — set by wrap.js from wrap.config.json; falls back to defaults for dev.
21+
const APP_VERSION = process.env.APP_VERSION || '1.0.0';
22+
const APP_VERSION_CODE = parseInt(process.env.APP_VERSION_CODE || '1', 10);
23+
// CUSTOMER APP SETTINGS END - DO NOT REMOVE OR RENAME THE COMMENT
24+
25+
// CUSTOMIZATION START - DO NOT REMOVE OR RENAME THE COMMENT
26+
// Add Expo config overrides in this function only.
27+
function customizeExpoConfig(config) {
28+
return config;
29+
}
30+
// CUSTOMIZATION END - DO NOT REMOVE OR RENAME THE COMMENT
1331

1432
/** @type {import('expo/config').ExpoConfig} */
15-
module.exports = ({ config }) => ({
33+
module.exports = ({ config }) => customizeExpoConfig({
1634
...config,
1735
name: APP_NAME,
1836
slug: APP_SLUG,
19-
version: '1.0.0',
37+
version: APP_VERSION,
2038
scheme: APP_SCHEME,
39+
// Icon — only set when APP_ICON_PATH is provided (production builds via wrap.js).
40+
// Expo generates all required sizes from this single 1024×1024 PNG.
41+
...(APP_ICON_PATH ? { icon: APP_ICON_PATH } : {}),
2142
web: {
2243
bundler: 'metro',
2344
output: 'static',
@@ -46,6 +67,16 @@ module.exports = ({ config }) => ({
4667
'@react-native-community/datetimepicker'],
4768
android: {
4869
package: ANDROID_PACKAGE,
70+
versionCode: APP_VERSION_CODE,
71+
// Adaptive icon — uses the same source image with a white background.
72+
// Override adaptiveIcon.backgroundColor in app.config.js if your icon
73+
// needs a different background (e.g. a branded colour).
74+
...(APP_ICON_PATH ? {
75+
adaptiveIcon: {
76+
foregroundImage: APP_ICON_PATH,
77+
backgroundColor: '#ffffff',
78+
},
79+
} : {}),
4980
},
5081
ios: {
5182
supportsTablet: true,
@@ -60,19 +91,9 @@ module.exports = ({ config }) => ({
6091
'msauthv2',
6192
'msauthv3',
6293
// msauth.<bundleId> for broker - downstream packaging can add an
63-
// app-specific variant to CFBundleURLTypes when needed, while the
94+
// bundle-specific variant to CFBundleURLTypes when needed, while the
6495
// generic msauthv2/v3 entries here cover SDK detection.
6596
],
66-
// IntuneMAMSettings — read at runtime by the host auth bridge.
67-
// Downstream packaging can patch ADALClientId and ADALRedirectUri here
68-
// via `plutil -replace IntuneMAMSettings.*`.
69-
// Placeholder values are replaced during packaging; the app falls back to
70-
// auth.config.json values when a placeholder tag is still present.
71-
IntuneMAMSettings: {
72-
ADALClientId: 'ADAL_CLIENT_ID_TAG',
73-
ADALRedirectUri: 'ADAL_REDIRECT_URI_TAG',
74-
ADALTenantId: 'ADAL_TENANT_ID_TAG',
75-
},
7697
},
7798
},
7899
});

plugins/mobile-apps/template/app/_layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { StatusBar } from 'expo-status-bar';
33
import { PowerAppsProvider } from '@microsoft/power-apps-native-host';
44

55
import authConfig from '../auth.config.json';
6+
import tamaguiConfig from '../tamagui.config';
67
// @ts-ignore - power.config.json is auto-generated at build time
78
import powerConfig from '../power.config.json';
89
// @ts-ignore - connectorSchemas is auto-generated at build time
@@ -14,6 +15,7 @@ export default function RootLayout() {
1415
msalConfig={authConfig.msal}
1516
powerConfig={powerConfig}
1617
schemaMap={schemaMap}
18+
tamaguiConfig={tamaguiConfig}
1719
>
1820
<StatusBar style="auto" />
1921
<Slot />

plugins/mobile-apps/template/app/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default function Index() {
1212

1313
if (isLoading) {
1414
return (
15-
<View flex={1} alignItems="center" justifyContent="center">
15+
<View flex={1} items="center" justify="center">
1616
<ActivityIndicator size="large" />
1717
</View>
1818
);

plugins/mobile-apps/template/app/login.tsx

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import {
77
import { MaterialCommunityIcons } from '@expo/vector-icons';
88
import { Redirect } from 'expo-router';
99
import { useAuth } from '@microsoft/power-apps-native-host';
10+
// @ts-ignore - power.config.json is auto-generated at build time
11+
import powerConfig from '../power.config.json';
1012

1113
export default function LoginScreen() {
1214
const { isLoading, isAuthReady, isSignedIn, signIn, error } = useAuth();
1315
const busy = isLoading || !isAuthReady;
16+
const appName = powerConfig.appDisplayName || 'Power Apps Standalone';
1417

1518
if (isSignedIn) {
1619
return <Redirect href="/(app)/home" />;
@@ -19,43 +22,41 @@ export default function LoginScreen() {
1922
return (
2023
<YStack
2124
flex={1}
22-
alignItems="center"
23-
justifyContent="center"
24-
paddingHorizontal="$6"
25-
backgroundColor="$background"
25+
items="center"
26+
justify="center"
27+
px="$6"
28+
bg="$background"
2629
gap="$4"
2730
>
2831
<YStack
29-
width={72}
30-
height={72}
31-
borderRadius={18}
32-
backgroundColor="$blue10"
33-
alignItems="center"
34-
justifyContent="center"
35-
marginBottom="$2"
32+
style={{ width: 72, height: 72, borderRadius: 18 }}
33+
bg="$blue10"
34+
items="center"
35+
justify="center"
36+
mb="$2"
3637
>
3738
<MaterialCommunityIcons name="microsoft-powerpoint" size={34} color="white" />
3839
</YStack>
3940

40-
<Text fontSize="$8" fontWeight="700" color="$color12" textAlign="center">
41-
Power Apps Standalone
41+
<Text fontSize="$8" fontWeight="700" color="$color12" text="center">
42+
{appName}
4243
</Text>
4344

44-
<Text fontSize="$4" color="$color10" textAlign="center" lineHeight="$5">
45-
Sign in to connect this app to Power Platform data.
45+
<Text fontSize="$4" color="$color10" style={{ textAlign: 'center', lineHeight: 22 }}>
46+
Sign in with your work or school email account
4647
</Text>
4748

4849

4950
{error ? (
50-
<Text color="$red10" fontSize="$3" textAlign="center">
51+
<Text color="$red10" fontSize="$3" text="center">
5152
{error.message}
5253
</Text>
5354
) : null}
5455

5556
<Button
5657
size="$5"
57-
width="100%"
58-
backgroundColor="$blue10"
58+
style={{ width: '100%' }}
59+
bg="$blue10"
5960
color="white"
6061
fontWeight="600"
6162
onPress={signIn}

0 commit comments

Comments
 (0)