@tarojs/plugin-platform-harmony-ets 4.0.0-beta.112 → 4.0.0-beta.113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,10 +12,12 @@
12
12
  import fs from '@ohos.file.fs'
13
13
  import picker from '@ohos.file.picker'
14
14
  import image from '@ohos.multimedia.image'
15
+ import { Current } from '@tarojs/runtime'
15
16
  import { isNull } from '@tarojs/shared'
16
17
 
18
+ import { getSystemInfoSync } from '../../base'
17
19
  import { callAsyncFail, callAsyncSuccess, requestPermissions, temporarilyNotSupport, validateParams } from '../../utils'
18
- import { READ_IMAGEVIDEO_PERMISSIONS } from '../../utils/permissions'
20
+ import { IMAGE_PERMISSION } from '../../utils/permissions'
19
21
 
20
22
  import type Taro from '@tarojs/taro/types'
21
23
 
@@ -30,7 +32,7 @@ interface IChooseImageData {
30
32
  tempFiles?: {
31
33
  path: string
32
34
  size: number
33
- }
35
+ }[]
34
36
  }
35
37
 
36
38
  const getImageInfoSchema = {
@@ -78,12 +80,18 @@ class CompressedImageInfo {
78
80
  }
79
81
 
80
82
  async function saveImage(compressedImageData, compressedImageUri) {
81
- // 定义要保存的压缩图片uri。afterCompressiona.jpeg表示压缩后的图片。
83
+ const tempArr = compressedImageUri.split('/')
84
+ const name = tempArr[tempArr.length - 1]
85
+ const context = getContext(Current?.page)
86
+ const applicationContext = context.getApplicationContext()
87
+ const tempDir = applicationContext.tempDir
88
+ const filePath = `${tempDir}/${name}`
89
+
82
90
  try {
83
- const res = fs.accessSync(compressedImageUri)
91
+ const res = fs.accessSync(filePath)
84
92
  if (res) {
85
93
  // 如果图片afterCompressiona.jpeg已存在,则删除
86
- fs.unlinkSync(compressedImageUri)
94
+ fs.unlinkSync(filePath)
87
95
  }
88
96
  } catch (err) {
89
97
  console.error(`[Taro] saveImage Error: AccessSync failed with error message: ${err.message}, error code: ${err.code}`)
@@ -91,13 +99,13 @@ async function saveImage(compressedImageData, compressedImageUri) {
91
99
 
92
100
  // 知识点:保存图片。获取最终图片压缩数据compressedImageData,保存图片。
93
101
  // 压缩图片数据写入文件
94
- const file = fs.openSync(compressedImageUri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
102
+ const file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
95
103
  fs.writeSync(file.fd, compressedImageData)
96
104
  fs.closeSync(file)
97
105
 
98
106
  // 获取压缩图片信息
99
107
  const compressedImageInfo = new CompressedImageInfo()
100
- compressedImageInfo.imageUri = compressedImageUri
108
+ compressedImageInfo.imageUri = filePath
101
109
  compressedImageInfo.imageByteLength = compressedImageData.byteLength
102
110
 
103
111
  return compressedImageInfo
@@ -105,15 +113,15 @@ async function saveImage(compressedImageData, compressedImageUri) {
105
113
 
106
114
  export const compressImage: typeof Taro.compressImage = function (options) {
107
115
  return new Promise((resolve, reject) => {
108
- requestPermissions([READ_IMAGEVIDEO_PERMISSIONS]).then(() => {
116
+ requestPermissions(IMAGE_PERMISSION).then(() => {
109
117
  try {
110
118
  validateParams('compressImage', options, compressImageSchema)
111
119
  } catch (error) {
112
120
  const res = { errMsg: error.message }
113
121
  return callAsyncFail(reject, res, options)
114
122
  }
115
- const { src, quality = 80 } = options
116
- const srcAfterCompress = src.split('.').join('_after_compress.')
123
+ const { src, quality = 80, compressedWidth, compressedHeight } = options
124
+ const srcAfterCompress = src.includes('_after_compress') ? src : src.split('.').join('_after_compress.')
117
125
  const file = fs.openSync(src, fs.OpenMode.READ_ONLY)
118
126
 
119
127
  // const stat = fs.statSync(file.fd)
@@ -126,26 +134,55 @@ export const compressImage: typeof Taro.compressImage = function (options) {
126
134
  return
127
135
  }
128
136
 
129
- const packer = image.createImagePacker(file.fd)
130
- if (isNull(packer)) {
131
- const createImagePackerError = { errMsg: 'compressImage fail: createImagePacker has failed.' }
132
- callAsyncFail(reject, createImagePackerError, options)
137
+ const width = source.getImageInfoSync().size.width
138
+ const height = source.getImageInfoSync().size.height
139
+ let wantWidth = compressedWidth || compressedHeight || 0
140
+ let wantHeight = compressedHeight || compressedWidth || 0
141
+
142
+ if (width > wantWidth || height > wantHeight) {
143
+ const heightRatio = height / wantHeight
144
+ const widthRatio = width / wantWidth
145
+ const finalRatio = heightRatio < widthRatio ? heightRatio : widthRatio
146
+
147
+ wantWidth = Math.round(width / finalRatio)
148
+ wantHeight = Math.round(height / finalRatio)
133
149
  }
134
150
 
135
- const packingOptionsOHOS: IPackingOptionOHOS = {
136
- // TODO:需要获取文件名后缀
137
- format: 'image/jpeg',
138
- quality: quality
151
+ const decodingOptions = {
152
+ editable: true,
153
+ desiredPixelFormat: image.PixelMapFormat.RGBA_8888,
154
+ desiredSize: { width: wantWidth, height: wantHeight }
139
155
  }
140
- packer.packing(source, packingOptionsOHOS).then((value) => {
141
- saveImage(value, srcAfterCompress).then(result => {
142
- callAsyncSuccess(resolve, { tempFilePath: result.imageUri }, options)
143
- })
144
- }).catch((error) => {
145
- callAsyncFail(reject, error, options)
156
+ source.createPixelMap(decodingOptions, (error, pixelMap) => {
157
+ if (error !== undefined) {
158
+ fs.closeSync(file)
159
+ const res = { errMsg: error }
160
+ callAsyncFail(reject, res, options)
161
+ } else {
162
+ const packer = image.createImagePacker(file.fd)
163
+ if (isNull(packer)) {
164
+ fs.closeSync(file)
165
+ const createImagePackerError = { errMsg: 'compressImage fail: createImagePacker has failed.' }
166
+ callAsyncFail(reject, createImagePackerError, options)
167
+ return
168
+ }
169
+
170
+ const isPNG = src.endsWith('.png')
171
+ const packingOptionsOHOS: IPackingOptionOHOS = {
172
+ format: isPNG ? 'image/png' : 'image/jpeg',
173
+ quality: quality
174
+ }
175
+ packer.packing(pixelMap, packingOptionsOHOS).then((value) => {
176
+ fs.closeSync(file)
177
+ saveImage(value, srcAfterCompress).then(result => {
178
+ callAsyncSuccess(resolve, { tempFilePath: result.imageUri }, options)
179
+ })
180
+ }).catch((error) => {
181
+ fs.closeSync(file)
182
+ callAsyncFail(reject, error, options)
183
+ })
184
+ }
146
185
  })
147
-
148
- fs.closeSync(file)
149
186
  }, (error: string) => {
150
187
  const res = { errMsg: error }
151
188
  return callAsyncFail(reject, res, options)
@@ -155,7 +192,7 @@ export const compressImage: typeof Taro.compressImage = function (options) {
155
192
 
156
193
  export const chooseImage: typeof Taro.chooseImage = function (options) {
157
194
  return new Promise((resolve, reject) => {
158
- requestPermissions([READ_IMAGEVIDEO_PERMISSIONS]).then(() => {
195
+ requestPermissions(IMAGE_PERMISSION).then(() => {
159
196
  try {
160
197
  validateParams('chooseImage', options, chooseImageSchema)
161
198
  } catch (error) {
@@ -176,13 +213,18 @@ export const chooseImage: typeof Taro.chooseImage = function (options) {
176
213
 
177
214
  photoViewPicker.select(photoSelectOptions).then((photoSelectResult) => {
178
215
  const result: IChooseImageData = {}
216
+ const isOrigin = photoSelectResult.isOriginalPhoto
179
217
 
180
- if (sizeType.includes('original')) {
218
+ if (isOrigin) {
219
+ const tempFilePaths: string[] = []
181
220
  const tempFiles = photoSelectResult.photoUris.map(uri => {
182
221
  const file = fs.openSync(uri, fs.OpenMode.READ_ONLY)
183
222
  const stat = fs.statSync(file.fd)
184
223
  const size = stat.size
185
224
 
225
+ fs.closeSync(file)
226
+ tempFilePaths.push(uri)
227
+
186
228
  return {
187
229
  size,
188
230
  path: uri,
@@ -190,13 +232,16 @@ export const chooseImage: typeof Taro.chooseImage = function (options) {
190
232
  })
191
233
 
192
234
  result.tempFiles = tempFiles
193
- }
235
+ result.tempFilePaths = tempFilePaths
194
236
 
195
- if (sizeType.includes('compressed')) {
237
+ callAsyncSuccess(resolve, result, options)
238
+ } else {
196
239
  const actions: Promise<string>[] = photoSelectResult.photoUris.map(uri => {
197
240
  return new Promise<string>(resolve => {
198
241
  compressImage({
199
242
  src: uri,
243
+ compressedWidth: getSystemInfoSync().screenWidth / 2,
244
+ compressedHeight: getSystemInfoSync().screenHeight / 2,
200
245
  success: (compressResult) => {
201
246
  resolve(compressResult.tempFilePath)
202
247
  }
@@ -205,14 +250,27 @@ export const chooseImage: typeof Taro.chooseImage = function (options) {
205
250
  })
206
251
 
207
252
  Promise.all(actions).then(tempFilePaths => {
253
+ const tempFiles = tempFilePaths.map(uri => {
254
+ const file = fs.openSync(uri, fs.OpenMode.READ_ONLY)
255
+ const stat = fs.statSync(file.fd)
256
+ const size: number = stat.size
257
+
258
+ fs.closeSync(file)
259
+
260
+ return {
261
+ size,
262
+ path: uri,
263
+ }
264
+ })
265
+
208
266
  result.tempFilePaths = tempFilePaths
267
+ result.tempFiles = tempFiles
268
+
209
269
  callAsyncSuccess(resolve, result, options)
210
270
  }).catch(error => {
211
271
  const res = { errMsg: error }
212
272
  return callAsyncFail(reject, res, options)
213
273
  })
214
- } else {
215
- callAsyncSuccess(resolve, result, options)
216
274
  }
217
275
  }).catch((error) => {
218
276
  callAsyncFail(reject, error, options)
@@ -1 +1,6 @@
1
1
  export const READ_IMAGEVIDEO_PERMISSIONS = 'ohos.permission.READ_IMAGEVIDEO'
2
+ export const READ_MEDIA_PERMISSIONS = 'ohos.permission.READ_MEDIA'
3
+ export const WRITE_MEDIA_PERMISSIONS = 'ohos.permission.WRITE_MEDIA'
4
+ export const MEDIA_LOCATION_PERMISSIONS = 'ohos.permission.MEDIA_LOCATION'
5
+
6
+ export const IMAGE_PERMISSION = [READ_IMAGEVIDEO_PERMISSIONS, READ_MEDIA_PERMISSIONS, WRITE_MEDIA_PERMISSIONS, MEDIA_LOCATION_PERMISSIONS]
@@ -38,10 +38,10 @@ export interface TaroStyleType {
38
38
 
39
39
  // position
40
40
  position?: 'relative' | 'absolute' | 'fixed'
41
- top?: Length
42
- left?: Length
43
- bottom?: Length
44
- right?: Length
41
+ top?: Dimension
42
+ left?: Dimension
43
+ bottom?: Dimension
44
+ right?: Dimension
45
45
 
46
46
  // flex
47
47
  flexBasis?: number | string
@@ -2280,6 +2280,10 @@ const chooseMedia = function (options) {
2280
2280
  };
2281
2281
 
2282
2282
  const READ_IMAGEVIDEO_PERMISSIONS = 'ohos.permission.READ_IMAGEVIDEO';
2283
+ const READ_MEDIA_PERMISSIONS = 'ohos.permission.READ_MEDIA';
2284
+ const WRITE_MEDIA_PERMISSIONS = 'ohos.permission.WRITE_MEDIA';
2285
+ const MEDIA_LOCATION_PERMISSIONS = 'ohos.permission.MEDIA_LOCATION';
2286
+ const IMAGE_PERMISSION = [READ_IMAGEVIDEO_PERMISSIONS, READ_MEDIA_PERMISSIONS, WRITE_MEDIA_PERMISSIONS, MEDIA_LOCATION_PERMISSIONS];
2283
2287
 
2284
2288
  // HarmonyOS 图片模块首批接口从API version 7开始支持。
2285
2289
  // HarmonyOS 文档链接:https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-image-0000001122977382
@@ -2326,12 +2330,17 @@ class CompressedImageInfo {
2326
2330
  }
2327
2331
  function saveImage(compressedImageData, compressedImageUri) {
2328
2332
  return __awaiter(this, void 0, void 0, function* () {
2329
- // 定义要保存的压缩图片uri。afterCompressiona.jpeg表示压缩后的图片。
2333
+ const tempArr = compressedImageUri.split('/');
2334
+ const name = tempArr[tempArr.length - 1];
2335
+ const context = getContext(Current === null || Current === void 0 ? void 0 : Current.page);
2336
+ const applicationContext = context.getApplicationContext();
2337
+ const tempDir = applicationContext.tempDir;
2338
+ const filePath = `${tempDir}/${name}`;
2330
2339
  try {
2331
- const res = fs.accessSync(compressedImageUri);
2340
+ const res = fs.accessSync(filePath);
2332
2341
  if (res) {
2333
2342
  // 如果图片afterCompressiona.jpeg已存在,则删除
2334
- fs.unlinkSync(compressedImageUri);
2343
+ fs.unlinkSync(filePath);
2335
2344
  }
2336
2345
  }
2337
2346
  catch (err) {
@@ -2339,19 +2348,19 @@ function saveImage(compressedImageData, compressedImageUri) {
2339
2348
  }
2340
2349
  // 知识点:保存图片。获取最终图片压缩数据compressedImageData,保存图片。
2341
2350
  // 压缩图片数据写入文件
2342
- const file = fs.openSync(compressedImageUri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
2351
+ const file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
2343
2352
  fs.writeSync(file.fd, compressedImageData);
2344
2353
  fs.closeSync(file);
2345
2354
  // 获取压缩图片信息
2346
2355
  const compressedImageInfo = new CompressedImageInfo();
2347
- compressedImageInfo.imageUri = compressedImageUri;
2356
+ compressedImageInfo.imageUri = filePath;
2348
2357
  compressedImageInfo.imageByteLength = compressedImageData.byteLength;
2349
2358
  return compressedImageInfo;
2350
2359
  });
2351
2360
  }
2352
2361
  const compressImage = function (options) {
2353
2362
  return new Promise((resolve, reject) => {
2354
- requestPermissions([READ_IMAGEVIDEO_PERMISSIONS]).then(() => {
2363
+ requestPermissions(IMAGE_PERMISSION).then(() => {
2355
2364
  try {
2356
2365
  validateParams('compressImage', options, compressImageSchema);
2357
2366
  }
@@ -2359,8 +2368,8 @@ const compressImage = function (options) {
2359
2368
  const res = { errMsg: error.message };
2360
2369
  return callAsyncFail(reject, res, options);
2361
2370
  }
2362
- const { src, quality = 80 } = options;
2363
- const srcAfterCompress = src.split('.').join('_after_compress.');
2371
+ const { src, quality = 80, compressedWidth, compressedHeight } = options;
2372
+ const srcAfterCompress = src.includes('_after_compress') ? src : src.split('.').join('_after_compress.');
2364
2373
  const file = fs.openSync(src, fs.OpenMode.READ_ONLY);
2365
2374
  // const stat = fs.statSync(file.fd)
2366
2375
  // console.log('[Taro] 压缩前图片的大小为:', stat.size)
@@ -2370,24 +2379,52 @@ const compressImage = function (options) {
2370
2379
  callAsyncFail(reject, createImageSourceError, options);
2371
2380
  return;
2372
2381
  }
2373
- const packer = image.createImagePacker(file.fd);
2374
- if (isNull(packer)) {
2375
- const createImagePackerError = { errMsg: 'compressImage fail: createImagePacker has failed.' };
2376
- callAsyncFail(reject, createImagePackerError, options);
2382
+ const width = source.getImageInfoSync().size.width;
2383
+ const height = source.getImageInfoSync().size.height;
2384
+ let wantWidth = compressedWidth || compressedHeight || 0;
2385
+ let wantHeight = compressedHeight || compressedWidth || 0;
2386
+ if (width > wantWidth || height > wantHeight) {
2387
+ const heightRatio = height / wantHeight;
2388
+ const widthRatio = width / wantWidth;
2389
+ const finalRatio = heightRatio < widthRatio ? heightRatio : widthRatio;
2390
+ wantWidth = Math.round(width / finalRatio);
2391
+ wantHeight = Math.round(height / finalRatio);
2377
2392
  }
2378
- const packingOptionsOHOS = {
2379
- // TODO:需要获取文件名后缀
2380
- format: 'image/jpeg',
2381
- quality: quality
2393
+ const decodingOptions = {
2394
+ editable: true,
2395
+ desiredPixelFormat: image.PixelMapFormat.RGBA_8888,
2396
+ desiredSize: { width: wantWidth, height: wantHeight }
2382
2397
  };
2383
- packer.packing(source, packingOptionsOHOS).then((value) => {
2384
- saveImage(value, srcAfterCompress).then(result => {
2385
- callAsyncSuccess(resolve, { tempFilePath: result.imageUri }, options);
2386
- });
2387
- }).catch((error) => {
2388
- callAsyncFail(reject, error, options);
2398
+ source.createPixelMap(decodingOptions, (error, pixelMap) => {
2399
+ if (error !== undefined) {
2400
+ fs.closeSync(file);
2401
+ const res = { errMsg: error };
2402
+ callAsyncFail(reject, res, options);
2403
+ }
2404
+ else {
2405
+ const packer = image.createImagePacker(file.fd);
2406
+ if (isNull(packer)) {
2407
+ fs.closeSync(file);
2408
+ const createImagePackerError = { errMsg: 'compressImage fail: createImagePacker has failed.' };
2409
+ callAsyncFail(reject, createImagePackerError, options);
2410
+ return;
2411
+ }
2412
+ const isPNG = src.endsWith('.png');
2413
+ const packingOptionsOHOS = {
2414
+ format: isPNG ? 'image/png' : 'image/jpeg',
2415
+ quality: quality
2416
+ };
2417
+ packer.packing(pixelMap, packingOptionsOHOS).then((value) => {
2418
+ fs.closeSync(file);
2419
+ saveImage(value, srcAfterCompress).then(result => {
2420
+ callAsyncSuccess(resolve, { tempFilePath: result.imageUri }, options);
2421
+ });
2422
+ }).catch((error) => {
2423
+ fs.closeSync(file);
2424
+ callAsyncFail(reject, error, options);
2425
+ });
2426
+ }
2389
2427
  });
2390
- fs.closeSync(file);
2391
2428
  }, (error) => {
2392
2429
  const res = { errMsg: error };
2393
2430
  return callAsyncFail(reject, res, options);
@@ -2396,7 +2433,7 @@ const compressImage = function (options) {
2396
2433
  };
2397
2434
  const chooseImage = function (options) {
2398
2435
  return new Promise((resolve, reject) => {
2399
- requestPermissions([READ_IMAGEVIDEO_PERMISSIONS]).then(() => {
2436
+ requestPermissions(IMAGE_PERMISSION).then(() => {
2400
2437
  try {
2401
2438
  validateParams('chooseImage', options, chooseImageSchema);
2402
2439
  }
@@ -2414,23 +2451,31 @@ const chooseImage = function (options) {
2414
2451
  photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE
2415
2452
  photoViewPicker.select(photoSelectOptions).then((photoSelectResult) => {
2416
2453
  const result = {};
2417
- if (sizeType.includes('original')) {
2454
+ const isOrigin = photoSelectResult.isOriginalPhoto;
2455
+ if (isOrigin) {
2456
+ const tempFilePaths = [];
2418
2457
  const tempFiles = photoSelectResult.photoUris.map(uri => {
2419
2458
  const file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
2420
2459
  const stat = fs.statSync(file.fd);
2421
2460
  const size = stat.size;
2461
+ fs.closeSync(file);
2462
+ tempFilePaths.push(uri);
2422
2463
  return {
2423
2464
  size,
2424
2465
  path: uri,
2425
2466
  };
2426
2467
  });
2427
2468
  result.tempFiles = tempFiles;
2469
+ result.tempFilePaths = tempFilePaths;
2470
+ callAsyncSuccess(resolve, result, options);
2428
2471
  }
2429
- if (sizeType.includes('compressed')) {
2472
+ else {
2430
2473
  const actions = photoSelectResult.photoUris.map(uri => {
2431
2474
  return new Promise(resolve => {
2432
2475
  compressImage({
2433
2476
  src: uri,
2477
+ compressedWidth: getSystemInfoSync().screenWidth / 2,
2478
+ compressedHeight: getSystemInfoSync().screenHeight / 2,
2434
2479
  success: (compressResult) => {
2435
2480
  resolve(compressResult.tempFilePath);
2436
2481
  }
@@ -2438,16 +2483,24 @@ const chooseImage = function (options) {
2438
2483
  });
2439
2484
  });
2440
2485
  Promise.all(actions).then(tempFilePaths => {
2486
+ const tempFiles = tempFilePaths.map(uri => {
2487
+ const file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
2488
+ const stat = fs.statSync(file.fd);
2489
+ const size = stat.size;
2490
+ fs.closeSync(file);
2491
+ return {
2492
+ size,
2493
+ path: uri,
2494
+ };
2495
+ });
2441
2496
  result.tempFilePaths = tempFilePaths;
2497
+ result.tempFiles = tempFiles;
2442
2498
  callAsyncSuccess(resolve, result, options);
2443
2499
  }).catch(error => {
2444
2500
  const res = { errMsg: error };
2445
2501
  return callAsyncFail(reject, res, options);
2446
2502
  });
2447
2503
  }
2448
- else {
2449
- callAsyncSuccess(resolve, result, options);
2450
- }
2451
2504
  }).catch((error) => {
2452
2505
  callAsyncFail(reject, error, options);
2453
2506
  });