Skip to content

Commit bf9dd89

Browse files
loongfayallen-zh
authored andcommitted
feat(api): support battery/clipboard/motion/part of media apis (#139)
* fix(api): font style is required when set canvas font * feat(api): support battery/clipboard/motion/part of media apis
1 parent e2449a3 commit bf9dd89

File tree

12 files changed

+424
-37
lines changed

12 files changed

+424
-37
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* @file battery api
3+
* @author zhaolongfei
4+
*/
5+
6+
import {callback} from '../../lib/utils';
7+
8+
export function getBatteryInfo(options = {}) {
9+
const {success, fail, complete} = options;
10+
11+
if (navigator.getBattery) {
12+
return new Promise((resolve, reject) => {
13+
navigator.getBattery().then(battery => {
14+
const res = {
15+
isCharging: battery.charging,
16+
level: battery.level
17+
};
18+
callback(success, res);
19+
callback(complete, res);
20+
resolve(res);
21+
}).catch(e => {
22+
const err = {
23+
errMsg: e
24+
};
25+
callback(fail, err);
26+
callback(complete, err);
27+
reject(err);
28+
});
29+
});
30+
} else {
31+
const err = {
32+
errMsg: 'getBatteryInfo is not supported by browser'
33+
};
34+
callback(fail, err);
35+
callback(complete, err);
36+
return Promise.reject(err);
37+
}
38+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* @file clipboard api
3+
* @author zhaolongfei
4+
*/
5+
6+
import {callback, isIOS} from '../../lib/utils';
7+
import {showToast} from '../interactive';
8+
9+
class FakeClipboard {
10+
constructor() {
11+
this.textArea = document.createElement('textarea');
12+
this.textArea.id = 'mars-clipboard';
13+
this.textArea.style.position = 'absolute';
14+
this.textArea.style.left = '-9999px';
15+
this.textArea.setAttribute('readonly', 'readonly');
16+
document.body.appendChild(this.textArea);
17+
}
18+
19+
setData(data) {
20+
this.textArea.value = data;
21+
}
22+
23+
getData() {
24+
return this.textArea.value;
25+
}
26+
27+
select() {
28+
if (isIOS()) {
29+
const range = document.createRange();
30+
range.selectNodeContents(this.textArea);
31+
const selection = window.getSelection();
32+
selection.removeAllRanges();
33+
selection.addRange(range);
34+
this.textArea.setSelectionRange(0, 999999);
35+
} else {
36+
this.textArea.select();
37+
}
38+
}
39+
40+
copy(cb) {
41+
try {
42+
if (document.execCommand('Copy')) {
43+
cb(true);
44+
} else {
45+
cb(false);
46+
}
47+
} catch (e) {
48+
cb(false);
49+
}
50+
}
51+
}
52+
53+
const clipboard = new FakeClipboard();
54+
55+
export function setClipboardData(options = {}) {
56+
const {data = '', success, fail, complete} = options;
57+
58+
return new Promise((resolve, reject) => {
59+
clipboard.setData(data);
60+
clipboard.select();
61+
clipboard.copy(flag => {
62+
if (flag) {
63+
showToast({
64+
title: '复制成功'
65+
});
66+
callback(success);
67+
callback(complete);
68+
resolve();
69+
} else {
70+
showToast({
71+
title: '复制失败'
72+
});
73+
callback(fail);
74+
callback(complete);
75+
reject();
76+
}
77+
});
78+
});
79+
}
80+
81+
export function getClipboardData(options = {}) {
82+
const {success, fail, complete} = options;
83+
const res = {
84+
data: clipboard.getData()
85+
};
86+
callback(success, res);
87+
callback(complete, res);
88+
return Promise.resolve(res);
89+
}

packages/mars-api/api/file/index.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,10 @@
33
* @author zhaolongfei
44
*/
55

6-
import {
7-
chooseImage,
8-
previewImage
9-
} from './image';
10-
116
import {
127
uploadFile
138
} from './upload';
149

1510
export {
16-
chooseImage,
17-
previewImage,
1811
uploadFile
1912
};

packages/mars-api/api/file/upload.js

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
* @author zhaolongfei(izhaolongfei@gmail.com)
55
*/
66

7-
import {callback} from '../../lib/utils';
7+
import {callback, isIOS} from '../../lib/utils';
88

9-
export function uploader(type = 'image', count = 1) {
9+
export function uploader(type = 'image', count = 1, sourceType) {
1010
return new Promise((resolve, reject) => {
1111
const input = document.getElementById('mars-uploader') || document.createElement('input');
1212
input.id = 'mars-uploader';
@@ -15,6 +15,10 @@ export function uploader(type = 'image', count = 1) {
1515
input.accept = type + '/*';
1616
input.style.width = 0;
1717
input.style.height = 0;
18+
// iOS 下存在 capture 属性时,默认打开相机
19+
if (type === 'image' && isIOS() && !sourceType.includes('album')) {
20+
input.capture = 'camera';
21+
}
1822

1923
document.body.appendChild(input);
2024

@@ -55,7 +59,6 @@ function upload(url, header = null, data) {
5559
if (xhr.readyState === 4 && xhr.status === 200) {
5660
resolve(xhr.response);
5761
}
58-
5962
};
6063

6164
xhr.onerror = e => {
@@ -66,16 +69,7 @@ function upload(url, header = null, data) {
6669
}
6770

6871
export function uploadFile(options) {
69-
const {
70-
url,
71-
filePath,
72-
name,
73-
header = null,
74-
formData = null,
75-
success,
76-
fail,
77-
complete
78-
} = options;
72+
const {url, filePath, name, header = null, formData = null, success, fail, complete} = options;
7973

8074
const rformData = new FormData();
8175

@@ -95,7 +89,6 @@ export function uploadFile(options) {
9589
callback(complete, e);
9690
return e;
9791
}
98-
9992
throw e;
10093
});
10194
}

packages/mars-api/api/file/image.js renamed to packages/mars-api/api/media/image.js

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
/**
22
* @file image
33
* @Date 2019/2/21
4-
* @author zhaolongfei(izhaolongfei@gmail.com)
4+
* @author zhaolongfei
55
*/
66

7-
import {uploader} from './upload';
7+
import {uploader} from '../file/upload';
88
import {callback} from '../../lib/utils';
99

1010
export function chooseImage(options) {
11-
const {
12-
count = 9,
13-
success,
14-
fail,
15-
complete
16-
} = options;
11+
const {count = 9, sourceType = ['album', 'camera'], success, fail, complete} = options;
1712

18-
return uploader('image', count, 'image').then(data => {
13+
return uploader('image', count, sourceType).then(data => {
1914
callback(success, data);
2015
callback(complete, data);
2116
return data;
@@ -26,13 +21,41 @@ export function chooseImage(options) {
2621
callback(complete, e);
2722
return e;
2823
}
29-
3024
throw e;
3125
});
3226
}
3327

34-
export function getImageInfo() {
35-
// TODO
28+
export function getImageInfo(options = {}) {
29+
const {src, success, fail, complete} = options;
30+
if (!src) {
31+
const err = {
32+
errCode: 904,
33+
errMsg: 'src is required and must be "string"'
34+
};
35+
callback(fail, err);
36+
return Promise.reject(err);
37+
}
38+
return new Promise((resolve, reject) => {
39+
const types = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff'];
40+
const imgType = src.substr(src.lastIndexOf('.') + 1) || '';
41+
const img = new Image();
42+
img.src = src;
43+
img.onload = e => {
44+
const info = {
45+
path: src,
46+
width: e.target.naturalWidth || e.target.width,
47+
width: e.target.naturalHeight || e.target.height,
48+
type: types.includes(imgType) ? imgType : null,
49+
orientation: null
50+
};
51+
callback(success, info);
52+
resolve(info);
53+
};
54+
img.onerror = e => {
55+
callback(fail, e);
56+
reject(e);
57+
};
58+
});
3659
}
3760

3861
export function previewImage(options = {}) {

packages/mars-api/api/media/index.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* @file export media api
3+
* @author zhaolongfei
4+
*/
5+
6+
import {
7+
chooseImage,
8+
previewImage,
9+
getImageInfo
10+
} from './image';
11+
12+
import {
13+
chooseVideo
14+
} from './video';
15+
16+
import {
17+
createVideoContext
18+
} from './video-context';
19+
20+
export {
21+
chooseImage,
22+
previewImage,
23+
getImageInfo,
24+
chooseVideo,
25+
createVideoContext
26+
};
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* @file video context
3+
* @author zhaolongfei
4+
*/
5+
6+
class VideoContext {
7+
constructor(id) {
8+
this.video = document.querySelector('#' + id + ' video');
9+
this.poster = document.querySelector('[class*=mars-video-poster]');
10+
}
11+
12+
play() {
13+
this.poster.click();
14+
this.video.play();
15+
}
16+
17+
pause() {
18+
this.video.pause();
19+
}
20+
21+
seek(time) {
22+
if (this.video.seek) {
23+
this.video.seek(time);
24+
} else {
25+
console.warn('video.seek is not supported');
26+
}
27+
}
28+
29+
requestFullScreen() {
30+
if (this.video.requestFullscreen) {
31+
this.video.requestFullscreen();
32+
} else if (this.video.webkitRequestFullScreen) {
33+
this.video.webkitRequestFullScreen();
34+
} else if (this.video.webkitEnterFullScreen) {
35+
this.video.webkitEnterFullScreen();
36+
} else if (this.video.mozRequestFullScreen) {
37+
this.video.mozRequestFullScreen();
38+
}
39+
}
40+
41+
exitFullScreen() {
42+
if (this.video.exitFullscreen) {
43+
this.video.exitFullscreen();
44+
} else if (this.video.webkitExitFullscreen) {
45+
this.video.webkitExitFullscreen();
46+
} else if (this.video.cancelFullScrren) {
47+
this.video.cancelFullScrren();
48+
} else if (this.video.webkitCancelFullScreen) {
49+
this.video.webkitCancelFullScreen();
50+
} else if (this.video.webkitCancelFullScreen) {
51+
this.video.webkitCancelFullScreen();
52+
}
53+
}
54+
55+
sendDanmu() {
56+
console.warn('sendDanmu is not supported');
57+
}
58+
59+
showStatusBar() {
60+
console.warn('showStatusBar is not supported');
61+
}
62+
63+
hideStatusBar() {
64+
console.warn('hideStatusBar is not supported');
65+
}
66+
}
67+
68+
export function createVideoContext(videoId) {
69+
return new VideoContext(videoId);
70+
}

0 commit comments

Comments
 (0)