From d4c9020140bfa855885285c4c1fe0f204f6fad53 Mon Sep 17 00:00:00 2001 From: Christian Liebel Date: Sat, 27 Jun 2020 13:38:40 +0200 Subject: [PATCH] Add support for fullscreen display mode --- packages/cli/src/lib/cmds/init.ts | 10 +++++++++- packages/cli/src/lib/inputHelpers.ts | 8 ++++++++ packages/cli/src/spec/inputHelpersSpec.ts | 13 +++++++++++++ packages/core/src/lib/TwaManifest.ts | 6 ++++++ packages/core/src/lib/types/WebManifest.ts | 1 + packages/core/src/spec/lib/TwaManifestSpec.ts | 2 ++ .../app/src/main/AndroidManifest.xml | 5 +++++ 7 files changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/lib/cmds/init.ts b/packages/cli/src/lib/cmds/init.ts index ba1f329c..4d06194c 100644 --- a/packages/cli/src/lib/cmds/init.ts +++ b/packages/cli/src/lib/cmds/init.ts @@ -18,7 +18,8 @@ import * as fs from 'fs'; import Color = require('color'); import * as inquirer from 'inquirer'; import {Config, JdkHelper, KeyTool, Log, TwaGenerator, TwaManifest, util} from '@bubblewrap/core'; -import {validateColor, validateKeyPassword, validateUrl, notEmpty} from '../inputHelpers'; +import {validateColor, validateDisplayMode, validateKeyPassword, validateUrl, + notEmpty} from '../inputHelpers'; import {ParsedArgs} from 'minimist'; import {APP_NAME} from '../constants'; @@ -49,6 +50,12 @@ async function confirmTwaConfig(twaManifest: TwaManifest): Promise message: 'Name to be shown on the Android Launcher:', default: twaManifest.launcherName, validate: async (input): Promise => notEmpty(input, 'Launcher name'), + }, { + name: 'display', + type: 'input', + message: 'Display mode to be used:', + default: twaManifest.display, + validate: validateDisplayMode, }, { name: 'themeColor', type: 'input', @@ -131,6 +138,7 @@ async function confirmTwaConfig(twaManifest: TwaManifest): Promise twaManifest.host = result.host; twaManifest.name = result.name; twaManifest.launcherName = result.launcherName; + twaManifest.display = result.display; twaManifest.themeColor = new Color(result.themeColor); twaManifest.backgroundColor = new Color(result.backgroundColor); twaManifest.startUrl = result.startUrl; diff --git a/packages/cli/src/lib/inputHelpers.ts b/packages/cli/src/lib/inputHelpers.ts index 7d54658e..422d6de0 100644 --- a/packages/cli/src/lib/inputHelpers.ts +++ b/packages/cli/src/lib/inputHelpers.ts @@ -50,3 +50,11 @@ export async function validateUrl(url: string): Promise { } return true; } + +export async function validateDisplayMode(displayMode: string): Promise { + const validModes = ['browser', 'minimal-ui', 'standalone', 'fullscreen']; + if (!validModes.includes(displayMode)) { + throw new Error(`${displayMode} is not a valid display mode (${validModes.join(', ')})`); + } + return true; +} diff --git a/packages/cli/src/spec/inputHelpersSpec.ts b/packages/cli/src/spec/inputHelpersSpec.ts index b9ed2207..7cc1d5b1 100644 --- a/packages/cli/src/spec/inputHelpersSpec.ts +++ b/packages/cli/src/spec/inputHelpersSpec.ts @@ -61,4 +61,17 @@ describe('inputHelpers', () => { inputHelpers.validateColor('rgb(23, 0 30')).toBeRejectedWithError(); }); }); + + describe('#validateDisplayMode', () => { + it('returns true for valid colors', async () => { + expect(await inputHelpers.validateDisplayMode('browser')); + expect(await inputHelpers.validateDisplayMode('minimal-ui')); + expect(await inputHelpers.validateDisplayMode('standalone')); + expect(await inputHelpers.validateDisplayMode('fullscreen')); + }); + + it('throws Error for invalid display modes', async () => { + await expectAsync(inputHelpers.validateColor('bogus')).toBeRejectedWithError(); + }); + }); }); diff --git a/packages/core/src/lib/TwaManifest.ts b/packages/core/src/lib/TwaManifest.ts index e0764f9f..7f3a1bbd 100644 --- a/packages/core/src/lib/TwaManifest.ts +++ b/packages/core/src/lib/TwaManifest.ts @@ -38,6 +38,7 @@ const MIN_NOTIFICATION_ICON_SIZE = 48; // Default values used on the Twa Manifest const DEFAULT_SPLASHSCREEN_FADEOUT_DURATION = 300; const DEFAULT_APP_NAME = 'My TWA'; +const DEFAULT_DISPLAY_MODE = 'standalone'; const DEFAULT_THEME_COLOR = '#FFFFFF'; const DEFAULT_NAVIGATION_COLOR = '#000000'; const DEFAULT_BACKGROUND_COLOR = '#FFFFFF'; @@ -72,6 +73,7 @@ export class ShortcutInfo { * hostName: '<%= host %>', // The domain being opened in the TWA. * launchUrl: '<%= startUrl %>', // The start path for the TWA. Must be relative to the domain. * name: '<%= name %>', // The name shown on the Android Launcher. + * display: '<%= display %>', // The display mode for the TWA. * themeColor: '<%= themeColor %>', // The color used for the status bar. * navigationColor: '<%= themeColor %>', // The color used for the navigation bar. * backgroundColor: '<%= backgroundColor %>', // The color used for the splash screen background. @@ -94,6 +96,7 @@ export class TwaManifest { host: string; name: string; launcherName: string; + display: string; themeColor: Color; navigationColor: Color; backgroundColor: Color; @@ -118,6 +121,7 @@ export class TwaManifest { this.host = data.host; this.name = data.name; this.launcherName = data.launcherName || data.name; // Older Manifests may not have this field. + this.display = data.display || DEFAULT_DISPLAY_MODE; // Older Manifests may not have this field. this.themeColor = new Color(data.themeColor); this.navigationColor = new Color(data.navigationColor); this.backgroundColor = new Color(data.backgroundColor); @@ -254,6 +258,7 @@ export class TwaManifest { name: webManifest['name'] || webManifest['short_name'] || DEFAULT_APP_NAME, launcherName: webManifest['short_name'] || webManifest['name']?.substring(0, SHORT_NAME_MAX_SIZE) || DEFAULT_APP_NAME, + display: webManifest['display'] || DEFAULT_DISPLAY_MODE, themeColor: webManifest['theme_color'] || DEFAULT_THEME_COLOR, navigationColor: DEFAULT_NAVIGATION_COLOR, backgroundColor: webManifest['background_color'] || DEFAULT_BACKGROUND_COLOR, @@ -306,6 +311,7 @@ export interface TwaManifestJson { host: string; name: string; launcherName?: string; // Older Manifests may not have this field. + display?: string; // Older Manifests may not have this field. themeColor: string; navigationColor: string; backgroundColor: string; diff --git a/packages/core/src/lib/types/WebManifest.ts b/packages/core/src/lib/types/WebManifest.ts index d28c136a..cf61d918 100644 --- a/packages/core/src/lib/types/WebManifest.ts +++ b/packages/core/src/lib/types/WebManifest.ts @@ -34,6 +34,7 @@ export interface WebManifestJson { name?: string; short_name?: string; start_url?: string; + display?: string; theme_color?: string; background_color?: string; icons?: Array; diff --git a/packages/core/src/spec/lib/TwaManifestSpec.ts b/packages/core/src/spec/lib/TwaManifestSpec.ts index 95272b9c..aeeb2940 100644 --- a/packages/core/src/spec/lib/TwaManifestSpec.ts +++ b/packages/core/src/spec/lib/TwaManifestSpec.ts @@ -24,6 +24,7 @@ describe('TwaManifest', () => { 'name': 'PWA Directory', 'short_name': 'PwaDirectory', 'start_url': '/?utm_source=homescreen', + 'display': 'standalone', 'icons': [{ 'src': '/favicons/android-chrome-192x192.png', 'sizes': '192x192', @@ -50,6 +51,7 @@ describe('TwaManifest', () => { expect(twaManifest.packageId).toBe('com.pwa_directory.twa'); expect(twaManifest.name).toBe('PWA Directory'); expect(twaManifest.launcherName).toBe('PwaDirectory'); + expect(twaManifest.display).toBe('standalone'); expect(twaManifest.startUrl).toBe('/?utm_source=homescreen'); expect(twaManifest.iconUrl) .toBe('https://pwa-directory.com/favicons/android-chrome-512x512.png'); diff --git a/packages/core/template_project/app/src/main/AndroidManifest.xml b/packages/core/template_project/app/src/main/AndroidManifest.xml index 76a92a24..a04f2554 100644 --- a/packages/core/template_project/app/src/main/AndroidManifest.xml +++ b/packages/core/template_project/app/src/main/AndroidManifest.xml @@ -77,6 +77,11 @@ + <% if (display === 'fullscreen') { %> + + + <% }%>