Skip to content

Commit 40cad20

Browse files
committed
feat: camera support
1 parent 6570054 commit 40cad20

File tree

12 files changed

+215
-5
lines changed

12 files changed

+215
-5
lines changed

demo/App_Resources/Android/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
1515
<uses-permission android:name="android.permission.INTERNET"/>
1616
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
17+
<uses-permission android:name="android.webkit.PermissionRequest" />
18+
<uses-permission android:name="android.permission.CAMERA" />
1719

1820
<application
1921
android:name="com.tns.NativeScriptApplication"

demo/App_Resources/iOS/Info.plist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
<array>
3131
<string>armv7</string>
3232
</array>
33+
34+
35+
<key>NSCameraUsageDescription</key>
36+
<string>lokavaluto needs your camera to scan QRCodes</string>
3337
<key>UISupportedInterfaceOrientations</key>
3438
<array>
3539
<string>UIInterfaceOrientationPortrait</string>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<style>
4+
body {
5+
margin: 0;
6+
width: 100%;
7+
height: 100%;
8+
overflow: hidden;
9+
}
10+
video {
11+
object-fit: cover;
12+
position: absolute;
13+
min-width: 100%;
14+
min-height: 100%;
15+
top: 50%;
16+
left: 50%;
17+
transform: translate(-50%, -50%);
18+
}
19+
</style>
20+
<head>
21+
<title>Blank</title>
22+
</head>
23+
<body>
24+
<video autoplay playsinline style='z-index:-1;'>
25+
</video>
26+
<button onclick="startCam()">startCam</button>
27+
28+
<script>
29+
30+
function startCam() {
31+
console.log('startCam')
32+
const constraints = {
33+
video: true,
34+
};
35+
36+
const video = document.querySelector("video");
37+
38+
navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
39+
video.srcObject = stream;
40+
});
41+
video.onloadedmetadata = function (e) {
42+
video.play();
43+
};
44+
}
45+
46+
</script>
47+
</body>
48+
</html>

demo/app/main-page.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
ShouldOverrideUrlLoadEventData,
88
} from '@nativescript-community/ui-webview';
99
import * as fastEqual from 'fast-deep-equal';
10+
import { request } from '@nativescript-community/perms';
1011

1112
let webview: AWebView;
1213
let page: Page;
@@ -26,7 +27,7 @@ export function webviewLoaded(args: LoadEventData) {
2627
// } else {
2728
// webview.src = 'http://localhost:8080';
2829
// }
29-
webview.src = "~/assets/test-data/html/javascript-calls.html";
30+
webview.src = "~/assets/test-data/html/camera.html";
3031

3132
webview.on(AWebView.shouldOverrideUrlLoadingEvent, (args: ShouldOverrideUrlLoadEventData) => {
3233
console.log(`${args.httpMethod} ${args.url}`);
@@ -37,13 +38,19 @@ export function webviewLoaded(args: LoadEventData) {
3738

3839
webview.on(AWebView.loadFinishedEvent, (args: LoadFinishedEventData) => {
3940
console.log(`WebViewExt.loadFinishedEvent: ${args.url}`);
40-
webview.loadStyleSheetFile('local-stylesheet.css', '~/assets/test-data/css/local-stylesheet.css', false);
41+
// webview.loadStyleSheetFile('local-stylesheet.css', '~/assets/test-data/css/local-stylesheet.css', false);
4142
});
4243

4344
webview.on('gotMessage', (msg) => {
4445
gotMessageData = msg.data;
4546
console.log(`webview.gotMessage: ${JSON.stringify(msg.data)} (${typeof msg})`);
4647
});
48+
49+
webview.on('requestPermissions', async (args: any) => {
50+
// only android
51+
const res = await request(args.permissions[0]);
52+
args.callback(res[0] === 'authorized');
53+
});
4754
}
4855

4956
async function executeJavaScriptTest<T>(js: string, expected?: T): Promise<T> {

demo/app/main-page.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
xmlns:nota="@nativescript-community/ui-webview">
44
<GridLayout class="p-2" rows="auto, *" columns="*">
55
<Button id="test_button" row="0" text="Run Tests" tap="runTests" class="btn btn-primary"></Button>
6-
<nota:AWebView row="1" loaded="webviewLoaded" webConsoleEnabled="false" debugMode="true" viewPortSize="initial-scale=1.2" enterFullscreen="enterFullscreen" exitFullscreen="exitFullscreen"></nota:AWebView>
6+
<nota:AWebView row="1" loaded="webviewLoaded" webRTC="true" webConsoleEnabled="true" debugMode="true" viewPortSize="initial-scale=1.2" enterFullscreen="enterFullscreen" exitFullscreen="exitFullscreen"></nota:AWebView>
77
</GridLayout>
88
</Page>

demo/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
},
3131
"homepage": "https://github.com/NativeScript/nativescript-app-templates",
3232
"dependencies": {
33+
"@nativescript-community/perms": "^2.1.6",
3334
"@nativescript-community/ui-webview": "file:../plugin",
3435
"@nativescript/core": "~8.0.7",
3536
"@nativescript/theme": "~3.0.1",

plugin/platforms/ios/Podfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
platform :ios, '11'
2+
pod 'WKWebViewRTC', :git => 'https://github.com/pplink/WKWebViewRTC.git', :branch => 'objc-support'

references.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
/// <reference path="./src/types/url.d.ts" />
44
/// <reference path="./src/types/android/webviewinterface.d.ts" />
55
/// <reference path="./src/types/ios/NotaWebViewExt.d.ts" />
6+
/// <reference path="./src/types/ios/objc!WKWebViewRTC.d.ts" />

src/types/ios/objc!WKWebViewRTC.d.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
2+
declare class WKWebViewRTC extends NSObject implements WKScriptMessageHandler {
3+
4+
static alloc(): WKWebViewRTC; // inherited from NSObject
5+
6+
static new(): WKWebViewRTC; // inherited from NSObject
7+
8+
readonly debugDescription: string; // inherited from NSObjectProtocol
9+
10+
readonly description: string; // inherited from NSObjectProtocol
11+
12+
readonly hash: number; // inherited from NSObjectProtocol
13+
14+
readonly isProxy: boolean; // inherited from NSObjectProtocol
15+
16+
readonly superclass: typeof NSObject; // inherited from NSObjectProtocol
17+
18+
readonly // inherited from NSObjectProtocol
19+
20+
constructor(o: { wkwebview: WKWebView; contentController: WKUserContentController; });
21+
22+
class(): typeof NSObject;
23+
24+
conformsToProtocol(aProtocol: any /* Protocol */): boolean;
25+
26+
dispose(): void;
27+
28+
initWithWkwebviewContentController(wkwebview: WKWebView, contentController: WKUserContentController): this;
29+
30+
isEqual(object: any): boolean;
31+
32+
isKindOfClass(aClass: typeof NSObject): boolean;
33+
34+
isMemberOfClass(aClass: typeof NSObject): boolean;
35+
36+
performSelector(aSelector: string): any;
37+
38+
performSelectorWithObject(aSelector: string, object: any): any;
39+
40+
performSelectorWithObjectWithObject(aSelector: string, object1: any, object2: any): any;
41+
42+
respondsToSelector(aSelector: string): boolean;
43+
44+
retainCount(): number;
45+
46+
self(): this;
47+
48+
userContentControllerDidReceiveScriptMessage(userContentController: WKUserContentController, message: WKScriptMessage): void;
49+
}
50+
51+
declare var WKWebViewRTCVersionNumber: number;
52+
53+
declare var WKWebViewRTCVersionString: interop.Reference<number>;

src/webview-ext-common.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ export const supportZoomProperty = new Property<WebViewExtBase, boolean>({
7878
defaultValue: false,
7979
valueConverter: booleanConverter,
8080
});
81+
export const webRTCProperty = new Property<WebViewExtBase, boolean>({
82+
name: 'webRTC',
83+
defaultValue: false,
84+
valueConverter: booleanConverter,
85+
});
8186

8287
export const srcProperty = new Property<WebViewExtBase, string>({
8388
name: 'src',
@@ -223,6 +228,7 @@ export enum EventNames {
223228
EnterFullscreen = 'enterFullscreen',
224229
ExitFullscreen = 'exitFullscreen',
225230
WebPrompt = 'webPrompt',
231+
RequestPermissions = 'requestPermissions',
226232
}
227233

228234
export interface LoadJavaScriptResource {
@@ -329,6 +335,12 @@ export interface WebConsoleEventData extends WebViewExtEventData {
329335
};
330336
}
331337

338+
export interface RequestPermissionsEventData extends WebViewExtEventData {
339+
eventName: EventNames.RequestPermissions;
340+
url: string;
341+
permissions: string[]
342+
}
343+
332344
/**
333345
* Event data containing information for the loading events of a WebView.
334346
*/
@@ -436,6 +448,9 @@ export class WebViewExtBase extends ContainerView {
436448
public static get exitFullscreenEvent() {
437449
return EventNames.ExitFullscreen;
438450
}
451+
public static get requestPermissionsEvent() {
452+
return EventNames.RequestPermissions;
453+
}
439454

440455
public readonly supportXLocalScheme: boolean;
441456

@@ -1536,6 +1551,29 @@ export class WebViewExtBase extends ContainerView {
15361551
[isEnabledProperty.getDefault]() {
15371552
return true;
15381553
}
1554+
1555+
async _onRequestPermissions (permissions) {
1556+
if (!this.hasListeners(EventNames.RequestPermissions)) {
1557+
return false
1558+
}
1559+
return new Promise<void>((resolve, reject)=>{
1560+
const args = {
1561+
eventName: EventNames.RequestPermissions,
1562+
object: this,
1563+
url: this.src,
1564+
permissions: permissions,
1565+
callback: function (allow) {
1566+
if (allow) {
1567+
resolve();
1568+
}
1569+
else {
1570+
reject();
1571+
}
1572+
},
1573+
};
1574+
this.notify(args);
1575+
});
1576+
}
15391577
}
15401578

15411579
// eslint-disable-next-line no-redeclare
@@ -1606,6 +1644,11 @@ export interface WebViewExtBase {
16061644
*/
16071645
on(event: EventNames.WebConsole, callback: (args: WebConsoleEventData) => void, thisArg?: any);
16081646
once(event: EventNames.WebConsole, callback: (args: WebConsoleEventData) => void, thisArg?: any);
1647+
/**
1648+
* Get Android WebView console entries.
1649+
*/
1650+
on(event: EventNames.RequestPermissions, callback: (args: WebConsoleEventData) => void, thisArg?: any);
1651+
once(event: EventNames.RequestPermissions, callback: (args: WebConsoleEventData) => void, thisArg?: any);
16091652
}
16101653

16111654
autoInjectJSBridgeProperty.register(WebViewExtBase);
@@ -1622,3 +1665,4 @@ scrollBounceProperty.register(WebViewExtBase);
16221665
viewPortProperty.register(WebViewExtBase);
16231666
isScrollEnabledProperty.register(WebViewExtBase);
16241667
scalesPageToFitProperty.register(WebViewExtBase);
1668+
webRTCProperty.register(WebViewExtBase);

0 commit comments

Comments
 (0)