mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feature(platform): implement a web component that provides access to a small subset of platform information
This commit is contained in:
@@ -2,10 +2,10 @@ import { Component, Element, Event, EventEmitter, Listen, Method, Prop, State }
|
||||
import { Config, NavEvent, OverlayController, PublicNav, PublicViewController } from '../../index';
|
||||
|
||||
import { getOrAppendElement } from '../../utils/helpers';
|
||||
import { isCordova } from '../../global/platform-utils';
|
||||
|
||||
const rootNavs = new Map<number, HTMLIonNavElement>();
|
||||
const ACTIVE_SCROLLING_TIME = 100;
|
||||
let backButtonActions: BackButtonAction[] = [];
|
||||
|
||||
@Component({
|
||||
tag: 'ion-app',
|
||||
@@ -143,8 +143,51 @@ export class App {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The back button event is triggered when the user presses the native
|
||||
* platform's back button, also referred to as the "hardware" back button.
|
||||
* This event is only used within Cordova apps running on Android and
|
||||
* Windows platforms. This event is not fired on iOS since iOS doesn't come
|
||||
* with a hardware back button in the same sense an Android or Windows device
|
||||
* does.
|
||||
*
|
||||
* Registering a hardware back button action and setting a priority allows
|
||||
* apps to control which action should be called when the hardware back
|
||||
* button is pressed. This method decides which of the registered back button
|
||||
* actions has the highest priority and should be called.
|
||||
*
|
||||
* @param {Function} fn Called when the back button is pressed,
|
||||
* if this registered action has the highest priority.
|
||||
* @param {number} priority Set the priority for this action. Only the highest priority will execute. Defaults to `0`.
|
||||
* @returns {Function} A function that, when called, will unregister
|
||||
* the back button action.
|
||||
*/
|
||||
@Method()
|
||||
registerBackButtonAction(fn: Function, priority = 0): () => void {
|
||||
const newAction = {
|
||||
fn,
|
||||
priority
|
||||
};
|
||||
backButtonActions.push(newAction);
|
||||
|
||||
return () => {
|
||||
backButtonActions = backButtonActions.filter(bbAction => bbAction !== newAction);
|
||||
};
|
||||
}
|
||||
|
||||
@Listen('document:backbutton')
|
||||
hardwareBackButtonPressed() {
|
||||
// okay cool, we need to execute the user's custom method if they have one
|
||||
const actionToExecute = backButtonActions.reduce((previous, current) => {
|
||||
if (current.priority >= previous.priority) {
|
||||
return current;
|
||||
}
|
||||
return previous;
|
||||
});
|
||||
actionToExecute && actionToExecute.fn && actionToExecute.fn();
|
||||
|
||||
// okay great, we've done the user action, now do the default actions
|
||||
// check if menu exists and is open
|
||||
return checkIfMenuIsOpen().then((done: boolean) => {
|
||||
if (!done) {
|
||||
@@ -199,9 +242,9 @@ export class App {
|
||||
render() {
|
||||
const isDevice = true;
|
||||
return [
|
||||
isCordova() && <ion-cordova-platform/>,
|
||||
isDevice && <ion-tap-click />,
|
||||
isDevice && <ion-status-tap />,
|
||||
<ion-platform />,
|
||||
<slot></slot>
|
||||
];
|
||||
}
|
||||
@@ -347,3 +390,8 @@ export interface ExitAppEvent extends CustomEvent {
|
||||
|
||||
export interface ExitAppEventDetail {
|
||||
}
|
||||
|
||||
export interface BackButtonAction {
|
||||
fn: Function;
|
||||
priority: number;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,21 @@ Returns whether the application is enabled or not
|
||||
Boolean if the app is actively scrolling or not.
|
||||
|
||||
|
||||
#### registerBackButtonAction()
|
||||
|
||||
The back button event is triggered when the user presses the native
|
||||
platform's back button, also referred to as the "hardware" back button.
|
||||
This event is only used within Cordova apps running on Android and
|
||||
Windows platforms. This event is not fired on iOS since iOS doesn't come
|
||||
with a hardware back button in the same sense an Android or Windows device
|
||||
does.
|
||||
|
||||
Registering a hardware back button action and setting a priority allows
|
||||
apps to control which action should be called when the hardware back
|
||||
button is pressed. This method decides which of the registered back button
|
||||
actions has the highest priority and should be called.
|
||||
|
||||
|
||||
#### setExternalNavPromise()
|
||||
|
||||
Updates the Promise set by an external navigation system
|
||||
|
||||
133
packages/core/src/components/platform/platform.tsx
Normal file
133
packages/core/src/components/platform/platform.tsx
Normal file
@@ -0,0 +1,133 @@
|
||||
import { Component, Element, Method, Prop } from '@stencil/core';
|
||||
|
||||
import { PlatformConfig } from '../../index';
|
||||
import { isCordova } from '../../global/platform-utils';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-platform',
|
||||
})
|
||||
export class Platform {
|
||||
|
||||
@Prop({ context: 'platforms' }) _platforms: PlatformConfig[];
|
||||
@Prop({ context: 'readQueryParam'}) readQueryParam: (url: string, key: string) => string;
|
||||
@Element() el: HTMLElement;
|
||||
|
||||
/**
|
||||
* Depending on the platform the user is on, `is(platformName)` will
|
||||
* return `true` or `false`. Note that the same app can return `true`
|
||||
* for more than one platform name. For example, an app running from
|
||||
* an iPad would return `true` for the platform names: `mobile`,
|
||||
* `ios`, `ipad`, and `tablet`. Additionally, if the app was running
|
||||
* from Cordova then `cordova` would be true, and if it was running
|
||||
* from a web browser on the iPad then `mobileweb` would be `true`.
|
||||
*
|
||||
* *
|
||||
* ```
|
||||
* import { Platform } from 'ionic-angular';
|
||||
*
|
||||
* @Component({...})
|
||||
* export MyPage {
|
||||
* constructor(public platform: Platform) {
|
||||
* if (this.platform.is('ios')) {
|
||||
* // This will only print when on iOS
|
||||
* console.log('I am an iOS device!');
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* | Platform Name | Description |
|
||||
* |-----------------|------------------------------------|
|
||||
* | android | on a device running Android. |
|
||||
* | cordova | on a device running Cordova. |
|
||||
* | core | on a desktop device. |
|
||||
* | ios | on a device running iOS. |
|
||||
* | ipad | on an iPad device. |
|
||||
* | iphone | on an iPhone device. |
|
||||
* | mobile | on a mobile device. |
|
||||
* | mobileweb | in a browser on a mobile device. |
|
||||
* | phablet | on a phablet device. |
|
||||
* | tablet | on a tablet device. |
|
||||
* | windows | on a device running Windows. |
|
||||
*
|
||||
* @param {string} platformName
|
||||
*/
|
||||
@Method()
|
||||
is(platformName: string): boolean {
|
||||
for (const platform of this._platforms) {
|
||||
if (platform.name === platformName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {array} the array of platforms
|
||||
* @description
|
||||
* Depending on what device you are on, `platforms` can return multiple values.
|
||||
* Each possible value is a hierarchy of platforms. For example, on an iPhone,
|
||||
* it would return `mobile`, `ios`, and `iphone`.
|
||||
*
|
||||
* ```
|
||||
* import { Platform } from 'ionic-angular';
|
||||
*
|
||||
* @Component({...})
|
||||
* export MyPage {
|
||||
* constructor(public platform: Platform) {
|
||||
* // This will print an array of the current platforms
|
||||
* console.log(this.platform.platforms());
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@Method()
|
||||
platforms() {
|
||||
return this._platforms.map(platform => platform.name);
|
||||
}
|
||||
|
||||
@Method()
|
||||
versions() {
|
||||
return this._platforms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the device is in landscape orientation
|
||||
*/
|
||||
@Method()
|
||||
isLandscape(): boolean {
|
||||
return !this.isPortrait();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the device is in portration orientation
|
||||
*/
|
||||
@Method()
|
||||
isPortrait(): boolean {
|
||||
return window.matchMedia('(orientation: portrait)').matches;
|
||||
}
|
||||
|
||||
@Method()
|
||||
ready() {
|
||||
// revisit this later on
|
||||
if (isCordova()) {
|
||||
const cordovaPlatform = this.el.querySelector('ion-cordova-plaform') as any;
|
||||
return cordovaPlatform.componentOnReady().then(() => {
|
||||
return cordovaPlatform.ready();
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@Method()
|
||||
getQueryParam(param: string): string {
|
||||
return this.readQueryParam(window.location.href, param);
|
||||
}
|
||||
|
||||
render() {
|
||||
return [
|
||||
<ion-cordova-platform/>
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
50
packages/core/src/components/platform/readme.md
Normal file
50
packages/core/src/components/platform/readme.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# ion-platform
|
||||
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
#### getQueryParam()
|
||||
|
||||
|
||||
#### is()
|
||||
|
||||
Depending on the platform the user is on, `is(platformName)` will
|
||||
return `true` or `false`. Note that the same app can return `true`
|
||||
for more than one platform name. For example, an app running from
|
||||
an iPad would return `true` for the platform names: `mobile`,
|
||||
`ios`, `ipad`, and `tablet`. Additionally, if the app was running
|
||||
from Cordova then `cordova` would be true, and if it was running
|
||||
from a web browser on the iPad then `mobileweb` would be `true`.
|
||||
|
||||
*
|
||||
```
|
||||
import { Platform } from 'ionic-angular';
|
||||
|
||||
|
||||
#### isLandscape()
|
||||
|
||||
Returns whether the device is in landscape orientation
|
||||
|
||||
|
||||
#### isPortrait()
|
||||
|
||||
Returns whether the device is in portration orientation
|
||||
|
||||
|
||||
#### platforms()
|
||||
|
||||
|
||||
#### ready()
|
||||
|
||||
|
||||
#### versions()
|
||||
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
*Built with [StencilJS](https://stenciljs.com/)*
|
||||
76
packages/core/src/components/platform/test/basic/index.html
Normal file
76
packages/core/src/components/platform/test/basic/index.html
Normal file
@@ -0,0 +1,76 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Platform Basic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<script src="/dist/ionic.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="initialize()">
|
||||
<ion-app>
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Platform - basic</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<h2>The Platforms are:</h2>
|
||||
<ul class="platform-name-list"></ul>
|
||||
|
||||
<h2>The Platforms versions are:</h2>
|
||||
<ul class="platform-version-list"></ul>
|
||||
|
||||
<h2>The orientation is <span class="orientation"></span></h2>
|
||||
|
||||
<h2>The ready event has fired: <span class="ready"></span></h2>
|
||||
</ion-content>
|
||||
|
||||
</ion-page>
|
||||
</ion-app>
|
||||
|
||||
<script>
|
||||
async function initialize() {
|
||||
const app = document.querySelector('ion-app');
|
||||
await app.componentOnReady();
|
||||
const platform = document.querySelector('ion-platform');
|
||||
await platform.componentOnReady();
|
||||
|
||||
const platforms = platform.platforms();
|
||||
const platformListElement = document.querySelector('.platform-name-list');
|
||||
platforms.forEach(platform => {
|
||||
const element = document.createElement('li');
|
||||
element.textContent = platform;
|
||||
platformListElement.appendChild(element);
|
||||
});
|
||||
|
||||
const platformVersionList = document.querySelector('.platform-version-list');
|
||||
const versions = platform.versions();
|
||||
versions.forEach(version => {
|
||||
const element = document.createElement('li');
|
||||
element.textContent = JSON.stringify(version);
|
||||
platformVersionList.appendChild(element);
|
||||
});
|
||||
|
||||
const orientationText = platform.isPortrait() ? 'portrait' : 'landscape';
|
||||
document.querySelector('.orientation').textContent = orientationText;
|
||||
|
||||
|
||||
const readyElement = document.querySelector('.ready');
|
||||
readyElement.textContent = 'No';
|
||||
|
||||
// use artificial timeout to see the visual
|
||||
setTimeout(() => {
|
||||
platform.ready().then(() => {
|
||||
readyElement.textContent = 'Yes';
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user