• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an 'AS IS' BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15const pickerHelper = requireInternal('file.picker');
16
17let gContext = undefined;
18
19const PhotoViewMIMETypes = {
20  IMAGE_TYPE: 'image/*',
21  VIDEO_TYPE: 'video/*',
22  IMAGE_VIDEO_TYPE: '*/*',
23  INVALID_TYPE: ''
24};
25
26const DocumentSelectMode = {
27  FILE: 0,
28  FOLDER: 1,
29  MIXED: 2,
30};
31
32const MergeTypeMode = {
33  DEFAULT: 0,
34  AUDIO: 1,
35  VIDEO: 2,
36  DOCUMENT: 3,
37  PICTURE: 4,
38};
39
40const DocumentPickerMode = {
41  DEFAULT: 0,
42  DOWNLOAD: 1,
43};
44
45const ExtTypes = {
46  DOWNLOAD_TYPE: 'filePicker',
47  AUDIO_PICKER_TYPE: 'audioPicker',
48  PHOTO_PICKER_TYPE: 'photoPicker',
49};
50
51const PickerDetailType = {
52  FILE_MGR_AUTH: 'downloadAuth',
53  FILE_MGR_SELECT:'select',
54  FILE_MGR_SAVE:'save',
55};
56
57const ErrCode = {
58  INVALID_ARGS: 13900020,
59  RESULT_ERROR: 13900042,
60  NAME_TOO_LONG: 13900030,
61  CONTEXT_NO_EXIST: 16000011,
62};
63
64const ERRCODE_MAP = new Map([
65  [ErrCode.INVALID_ARGS, 'Invalid argument'],
66  [ErrCode.RESULT_ERROR, 'Unknown error'],
67  [ErrCode.NAME_TOO_LONG, 'File name too long'],
68  [ErrCode.CONTEXT_NO_EXIST, 'Current ability failed to obtain context'],
69]);
70
71const PHOTO_VIEW_MIME_TYPE_MAP = new Map([
72  [PhotoViewMIMETypes.IMAGE_TYPE, 'FILTER_MEDIA_TYPE_IMAGE'],
73  [PhotoViewMIMETypes.VIDEO_TYPE, 'FILTER_MEDIA_TYPE_VIDEO'],
74  [PhotoViewMIMETypes.IMAGE_VIDEO_TYPE, 'FILTER_MEDIA_TYPE_ALL'],
75]);
76
77const ACTION = {
78  SELECT_ACTION: 'ohos.want.action.OPEN_FILE',
79  SELECT_ACTION_MODAL: 'ohos.want.action.OPEN_FILE_SERVICE',
80  SAVE_ACTION: 'ohos.want.action.CREATE_FILE',
81  SAVE_ACTION_MODAL: 'ohos.want.action.CREATE_FILE_SERVICE',
82};
83
84const CREATE_FILE_NAME_LENGTH_LIMIT = 256;
85const ARGS_ZERO = 0;
86const ARGS_ONE = 1;
87const ARGS_TWO = 2;
88const RESULT_CODE_ERROR = -1;
89const RESULT_CODE_OK = 0;
90const LENGTH_TWO = 2;
91const LENGTH_THREE = 3;
92let suffixIndex = -1;
93
94/*
95* UTF-8字符编码数值对应的存储长度:
96* 0000 - 0x007F (eg: a~z A~Z 0~9)
97* 0080 - 0x07FF (eg: 希腊字母)
98* 0800 - 0xFFFF (eg: 中文)
99* 其他 (eg: 平面符号)
100*/
101function strSizeUTF8(str) {
102  let strLen = str.length;
103  let bytesLen = 0;
104  let greeceLen = 2;
105  let chineseLen = 3;
106  let othersLen = 4;
107  for (let i = 0; i < strLen; i++) {
108    let charCode = str.charCodeAt(i);
109    if (charCode <= 0x007f) {
110      bytesLen++;
111    } else if (charCode <= 0x07ff) {
112      bytesLen += greeceLen;
113    } else if (charCode <= 0xffff) {
114      bytesLen += chineseLen;
115    } else {
116      bytesLen += othersLen;
117    }
118  }
119  return bytesLen;
120}
121
122function checkArguments(args) {
123  let checkArgumentsResult = undefined;
124  if (args.length === ARGS_TWO && typeof args[ARGS_ONE] !== 'function') {
125    checkArgumentsResult = getErr(ErrCode.INVALID_ARGS);
126  }
127
128  if (args.length > 0 && typeof args[ARGS_ZERO] === 'object') {
129    let option = args[ARGS_ZERO];
130    if (option.maxSelectNumber !== undefined) {
131      if (option.maxSelectNumber.toString().indexOf('.') !== -1) {
132        checkArgumentsResult = getErr(ErrCode.INVALID_ARGS);
133      }
134    }
135
136    if (option.newFileNames === undefined || option.newFileNames.length <= 0) {
137      return checkArgumentsResult;
138    }
139
140    for (let i = 0; i < option.newFileNames.length; i++) {
141      let value = option.newFileNames[i];
142      if (strSizeUTF8(value) >= CREATE_FILE_NAME_LENGTH_LIMIT) {
143        console.log('[picker] checkArguments Invalid name: ' + value);
144        checkArgumentsResult = getErr(ErrCode.NAME_TOO_LONG);
145      }
146    }
147  }
148
149  return checkArgumentsResult;
150}
151
152function getErr(errCode) {
153  return {code: errCode, message: ERRCODE_MAP.get(errCode)};
154}
155
156function parsePhotoPickerSelectOption(args) {
157  let config = {
158    action: 'ohos.want.action.photoPicker',
159    type: 'multipleselect',
160    parameters: {
161      uri: 'multipleselect',
162      extType: ExtTypes.PHOTO_PICKER_TYPE,
163    },
164  };
165  console.log('[picker] parse Photo SelectOption start ');
166  if (args.length > ARGS_ZERO && typeof args[ARGS_ZERO] === 'object') {
167    let option = args[ARGS_ZERO];
168    if (option.maxSelectNumber && option.maxSelectNumber > 0) {
169      let select = (option.maxSelectNumber === 1) ? 'singleselect' : 'multipleselect';
170      config.type = select;
171      config.parameters.uri = select;
172      config.parameters.maxSelectCount = option.maxSelectNumber;
173    }
174    if (option.MIMEType && PHOTO_VIEW_MIME_TYPE_MAP.has(option.MIMEType)) {
175      config.parameters.filterMediaType = PHOTO_VIEW_MIME_TYPE_MAP.get(option.MIMEType);
176    }
177  }
178  console.log('[picker] parse Photo SelectOption end ');
179  return config;
180}
181
182function anonymousPathArray(geturi) {
183  let anonymousPathArrays = [];
184  let anonymousPath = '';
185  if (geturi === undefined) {
186    return anonymousPathArrays;
187  }
188  for (let i = 0; i < geturi.length; ++i) {
189    let lastSlashIndex = geturi[i].lastIndexOf('/');
190    if (lastSlashIndex === -1) {
191      anonymousPathArrays.push(geturi[i]);
192    } else {
193      let dirPath = geturi[i].substring(0, lastSlashIndex + 1);
194      let fileName = geturi[i].substring(lastSlashIndex + 1);
195      if (fileName.length <= 0) {
196        anonymousPath = '******';
197      } else {
198        let lastLetter = fileName.slice(-1);
199        let maskedName = '******' + lastLetter;
200        anonymousPath = dirPath + maskedName;
201      }
202      anonymousPathArrays.push(anonymousPath);
203    }
204    }
205  return anonymousPathArrays;
206}
207
208function getPhotoPickerSelectResult(args) {
209  let selectResult = {
210    error: undefined,
211    data: undefined,
212  };
213
214  if (args.resultCode === 0) {
215    let uris = args.photoUris;
216    if (uris === undefined) {
217      console.log('[picker] Photo uris is undefined');
218      uris = [];
219    }
220    let isOriginal = args.isOriginal;
221    selectResult.data = new PhotoSelectResult(uris, isOriginal);
222  } else if (args.resultCode === -1) {
223    selectResult.data = new PhotoSelectResult([], undefined);
224  } else {
225    selectResult.error = getErr(ErrCode.RESULT_ERROR);
226  }
227  console.log('[picker] photo selectResult end');
228  return selectResult;
229}
230
231async function photoPickerSelect(...args) {
232  if (args.length !== LENGTH_TWO) {
233    console.error('[picker] args error: ' + args.length);
234    return undefined;
235  }
236  let checkPhotoArgsResult = checkArguments(args[ARGS_ZERO]);
237  if (checkPhotoArgsResult !== undefined) {
238    console.log('[picker] Photo Invalid argument');
239    throw checkPhotoArgsResult;
240  }
241
242  const config = parsePhotoPickerSelectOption(args[ARGS_ZERO]);
243
244  let photoSelectContext = undefined;
245  let photoSelectWindow = undefined;
246  try {
247    if (args[ARGS_ONE] !== undefined) {
248      photoSelectContext = args[ARGS_ONE];
249    } else {
250      photoSelectContext = getContext(this);
251    }
252  } catch (getContextError) {
253    console.error('[picker] getContext error: ' + getContextError);
254    throw getErr(ErrCode.CONTEXT_NO_EXIST);
255  }
256  try {
257    if (photoSelectContext === undefined) {
258      console.error('[picker] photoSelectContext == undefined');
259      throw getErr(ErrCode.CONTEXT_NO_EXIST);
260    }
261    let modalSelectResult = await modalPicker(photoSelectContext, config, photoSelectWindow);
262    console.log('[picker] photo modalSelectResult is ready');
263    const photoSelectResult = getPhotoPickerSelectResult(modalSelectResult);
264    let inputArgs = args[ARGS_ZERO];
265    if (inputArgs.length === ARGS_TWO && typeof inputArgs[ARGS_ONE] === 'function') {
266      return inputArgs[ARGS_ONE](photoSelectResult.error, photoSelectResult.data);
267    } else if (inputArgs.length === ARGS_ONE && typeof inputArgs[ARGS_ZERO] === 'function') {
268      return inputArgs[ARGS_ZERO](photoSelectResult.error, photoSelectResult.data);
269    }
270    return new Promise((resolve, reject) => {
271      if (photoSelectResult.data !== undefined) {
272        resolve(photoSelectResult.data);
273      } else {
274        reject(photoSelectResult.error);
275      }
276    });
277  } catch (error) {
278    console.error('[picker] photo select error: ' + error);
279  }
280  return undefined;
281}
282
283function parseDocumentPickerSelectOption(args, action) {
284  let config = {
285    action: action,
286    parameters: {
287      startMode: 'choose',
288      extType: ExtTypes.DOWNLOAD_TYPE,
289      pickerType: PickerDetailType.FILE_MGR_SELECT,
290    }
291  };
292
293  if (args.length > ARGS_ZERO && typeof args[ARGS_ZERO] === 'object') {
294    let option = args[ARGS_ZERO];
295    console.log('[picker] parseDocumentPickerSelectOption start');
296    config.parameters.key_select_mode = option.selectMode;
297    config.parameters.key_merge_type_mode = option.mergeMode;
298    config.parameters.key_is_encryption_supported = option.isEncryptionSupported;
299    if ((option.maxSelectNumber !== undefined) && option.maxSelectNumber > 0) {
300      config.parameters.key_pick_num = option.maxSelectNumber;
301    }
302    if (option.defaultFilePathUri !== undefined) {
303      config.parameters.key_pick_dir_path = option.defaultFilePathUri;
304    }
305    if ((option.fileSuffixFilters !== undefined) && option.fileSuffixFilters.length > 0) {
306      config.parameters.key_file_suffix_filter = option.fileSuffixFilters;
307    }
308    if (option.authMode !== undefined) {
309      config.parameters.key_auth_mode = option.authMode;
310    }
311    config.parameters.key_mult_auth_mode = option.multiAuthMode;
312    if (option.multiUriArray !== undefined) {
313      config.parameters.key_mult_uri_arr = option.multiUriArray;
314      console.log('[picker] parseDocumentPickerSelectOption multiUriArray length: ' + option.multiUriArray.length);
315    }
316  }
317  console.log('[picker] parseDocumentPickerSelectOption end');
318  return config;
319}
320
321function parseAudioPickerSelectOption(args, action) {
322  let config = {
323    action: action,
324    parameters: {
325      extType: ExtTypes.AUDIO_PICKER_TYPE,
326    }
327  };
328  if (args.length > ARGS_ZERO && typeof args[ARGS_ZERO] === 'object') {
329    let option = args[ARGS_ZERO];
330    if ((option.maxSelectNumber !== undefined) && option.maxSelectNumber > 0) {
331      config.parameters.key_pick_num = option.maxSelectNumber;
332    }
333  }
334  console.log('[picker] audio select config: ' + JSON.stringify(config));
335  return config;
336}
337
338function getDocumentPickerSelectResult(args) {
339  let selectResult = {
340    error: undefined,
341    data: undefined
342  };
343  if (args === undefined || args.resultCode === undefined) {
344    selectResult.error = getErr(ErrCode.RESULT_ERROR);
345    console.log('[picker] document select selectResult: ' + JSON.stringify(selectResult));
346    return selectResult;
347  }
348  if (args.resultCode === RESULT_CODE_OK) {
349    if (args.ability_params_stream) {
350      selectResult.data = args.ability_params_stream;
351      selectResult.error = args.resultCode;
352    }
353  } else if (args.resultCode === RESULT_CODE_ERROR) {
354    selectResult.data = [];
355    selectResult.error = args.resultCode;
356  }
357
358  console.log('[picker] document select selectResult: : errorcode is = ' + selectResult.error +
359              ', selecturi is = ' + anonymousPathArray(selectResult.data));
360  return selectResult;
361}
362
363async function documentPickerSelect(...args) {
364  if (args.length !== LENGTH_THREE) {
365    console.error('[picker] args error: ' + args.length);
366    return undefined;
367  }
368  let checkDocumentSelectArgsResult = checkArguments(args[ARGS_ZERO]);
369  if (checkDocumentSelectArgsResult !== undefined) {
370    console.log('[picker] Document Select Invalid argument');
371    throw checkDocumentSelectArgsResult;
372  }
373
374  let documentSelectContext = undefined;
375  let documentSelectConfig = undefined;
376  let documentSelectResult = undefined;
377  let selectResult = undefined;
378  let documentSelectWindow = undefined;
379
380  try {
381    if (args[ARGS_ONE] !== undefined) {
382      documentSelectContext = args[ARGS_ONE];
383    } else {
384      documentSelectContext = getContext(this);
385    }
386  } catch (getContextError) {
387    console.error('[picker] getContext error: ' + getContextError);
388    throw getErr(ErrCode.CONTEXT_NO_EXIST);
389  }
390  try {
391    if (documentSelectContext === undefined) {
392      console.error('[picker] documentSelectContext == undefined');
393      throw getErr(ErrCode.CONTEXT_NO_EXIST);
394    }
395    if (args[ARGS_TWO] !== undefined) {
396        documentSelectWindow = args[ARGS_TWO];
397    }
398    documentSelectConfig = parseDocumentPickerSelectOption(args[ARGS_ZERO], ACTION.SELECT_ACTION_MODAL);
399    documentSelectResult = await modalPicker(documentSelectContext, documentSelectConfig, documentSelectWindow);
400  } catch (paramError) {
401    console.error('[picker] DocumentSelect paramError: ' + JSON.stringify(paramError));
402  }
403  selectResult = getDocumentPickerSelectResult(documentSelectResult);
404  return sendResult(args[ARGS_ZERO], selectResult);
405}
406
407function parseDocumentPickerSaveOption(args, action) {
408  let config = {
409    action: action,
410    parameters: {
411      startMode: 'save',
412      pickerMode: DocumentPickerMode.DEFAULT,
413      extType: ExtTypes.DOWNLOAD_TYPE,
414      pickerType: PickerDetailType.FILE_MGR_SAVE,
415    }
416  };
417  console.log('[picker] parse document save option start');
418  if (args.length > ARGS_ZERO && typeof args[ARGS_ZERO] === 'object') {
419    let option = args[ARGS_ZERO];
420    console.log('[picker] document save option: ' + JSON.stringify(option));
421    if ((option.newFileNames !== undefined) && option.newFileNames.length > 0) {
422      config.parameters.key_pick_file_name = option.newFileNames;
423      config.parameters.saveFile = option.newFileNames[0];
424    }
425
426    if (option.defaultFilePathUri !== undefined) {
427      config.parameters.key_pick_dir_path = option.defaultFilePathUri;
428    }
429    if ((option.fileSuffixChoices !== undefined) && option.fileSuffixChoices.length > 0) {
430      config.parameters.key_file_suffix_choices = option.fileSuffixChoices;
431    }
432    if (option.pickerMode === DocumentPickerMode.DOWNLOAD) {
433      config.parameters.pickerMode = option.pickerMode;
434      config.parameters.pickerType = PickerDetailType.FILE_MGR_AUTH;
435    }
436  }
437  console.log('[picker] document save config pickerMode is ' + config.parameters.pickerMode +
438    ',pickerType is ' + config.parameters.pickerType);
439  return config;
440}
441
442function getAudioPickerSelectResult(args) {
443  let selectResult = {
444    error: undefined,
445    data: undefined
446  };
447  if (args === undefined || args.resultCode === undefined) {
448    selectResult.error = getErr(ErrCode.RESULT_ERROR);
449    console.log('[picker] getAudioPickerSelectResult selectResult: ' + JSON.stringify(selectResult));
450    return selectResult;
451  }
452  if (args.resultCode === RESULT_CODE_OK) {
453    if (args.uriArr) {
454      selectResult.data = args.uriArr;
455      selectResult.error = args.resultCode;
456    } else {
457      selectResult.data = [];
458      selectResult.error = args.resultCode;
459    }
460  } else if (args.resultCode === RESULT_CODE_ERROR) {
461    selectResult.data = [];
462    selectResult.error = args.resultCode;
463  }
464
465  console.log('[picker] getAudioPickerSelectResult selectResult: errorcode is = ' + selectResult.error +
466              ', selecturi is = ' + anonymousPathArray(selectResult.data));
467  return selectResult;
468}
469
470
471function getDocumentPickerSaveResult(args) {
472  let saveResult = {
473    error: undefined,
474    data: undefined,
475    suffix: -1
476  };
477  if (args === undefined || args.resultCode === undefined) {
478    saveResult.error = getErr(ErrCode.RESULT_ERROR);
479    console.log('[picker] getDocumentPickerSaveResult saveResult: ' + JSON.stringify(saveResult));
480    return saveResult;
481  }
482  if (args.resultCode === RESULT_CODE_OK) {
483    if (args.ability_params_stream) {
484      saveResult.data = args.ability_params_stream;
485      saveResult.error = args.resultCode;
486      if (args.userSuffixIndex >= 0) {
487        saveResult.suffix = args.userSuffixIndex;
488      }
489    }
490  } else if (args.resultCode === RESULT_CODE_ERROR) {
491    saveResult.data = [];
492    saveResult.error = args.resultCode;
493  }
494
495  console.log('[picker] getDocumentPickerSaveResult saveResult: errorcode is = ' + saveResult.error +
496              ', selecturi is = ' + anonymousPathArray(saveResult.data) + ', usersavesuffix = ' + saveResult.suffix);
497  return saveResult;
498}
499
500function startModalPicker(context, config, window) {
501  if (context === undefined) {
502    throw Error('[picker] Context undefined.');
503  }
504  if (config === undefined) {
505    throw Error('[picker] Config undefined.');
506  }
507  gContext = context;
508  if (pickerHelper === undefined) {
509    throw Error('[picker] PickerHelper undefined.');
510  }
511  let helper;
512  if (window !== undefined) {
513    helper = pickerHelper.startModalPicker(gContext, config, window);
514  } else {
515    helper = pickerHelper.startModalPicker(gContext, config);
516  }
517  if (helper === undefined) {
518    throw Error('[picker] Please check the parameter you entered.');
519  }
520  return helper;
521}
522
523async function modalPicker(context, config, window) {
524  try {
525    console.log('[picker] modalPicker start ');
526    let modalResult = await startModalPicker(context, config, window);
527    return modalResult;
528  } catch (resultError) {
529    console.error('[picker] Result error: ' + resultError);
530    return undefined;
531  }
532}
533
534async function documentPickerSave(...args) {
535  if (args.length < LENGTH_TWO || args.length > LENGTH_THREE) {
536    console.error('[picker] args error: ' + args.length);
537    return undefined;
538  }
539  let checkDocumentSaveArgsResult = checkArguments(args[ARGS_ZERO]);
540  if (checkDocumentSaveArgsResult !== undefined) {
541    console.log('[picker] Document Save Invalid argument');
542    throw checkDocumentSaveArgsResult;
543  }
544
545  let documentSaveContext = undefined;
546  let documentSaveConfig = undefined;
547  let documentSaveResult = undefined;
548  let saveResult = undefined;
549  let documentSaveWindow = undefined;
550
551  try {
552    if (args[ARGS_ONE] !== undefined) {
553      documentSaveContext = args[ARGS_ONE];
554    } else {
555      documentSaveContext = getContext(this);
556    }
557  } catch (getContextError) {
558    console.error('[picker] getContext error: ' + getContextError);
559    throw getErr(ErrCode.CONTEXT_NO_EXIST);
560  }
561  if (args.length === LENGTH_THREE && args[ARGS_TWO] !== undefined) {
562      documentSaveWindow = args[ARGS_TWO];
563  }
564
565  documentSaveConfig = parseDocumentPickerSaveOption(args[ARGS_ZERO], ACTION.SAVE_ACTION_MODAL);
566  console.log('[picker] document save start');
567
568  documentSaveResult = await modalPicker(documentSaveContext, documentSaveConfig, documentSaveWindow);
569  saveResult = getDocumentPickerSaveResult(documentSaveResult);
570  suffixIndex = saveResult.suffix;
571  return sendResult(args[ARGS_ZERO], saveResult);
572}
573
574function getSelectedSuffixIndex() {
575  console.log('[picker] Get Selected Suffix Index start');
576  let index = suffixIndex;
577  suffixIndex = -1;
578  console.log('[picker] Get Selected Suffix Index end: ' + index);
579  return index;
580}
581
582async function sendResult(args, result) {
583  try {
584    if (result === undefined) {
585      console.log('[picker] result is undefined.');
586      return undefined;
587    }
588    if (args.length === ARGS_TWO && typeof args[ARGS_ONE] === 'function') {
589      return args[ARGS_ONE](result.error, result.data);
590    } else if (args.length === ARGS_ONE && typeof args[ARGS_ZERO] === 'function') {
591      return args[ARGS_ZERO](result.error, result.data);
592    }
593    return new Promise((resolve, reject) => {
594      if (result.data !== undefined) {
595        resolve(result.data);
596      } else {
597        reject(result.error);
598      }
599    });
600  } catch (resultError) {
601    console.error('[picker] Result error: ' + resultError);
602  }
603  return undefined;
604}
605
606async function audioPickerSelect(...args) {
607  if (args.length !== LENGTH_TWO) {
608    console.error('[picker] args error: ' + args.length);
609    return undefined;
610  }
611  let checkAudioArgsResult = checkArguments(args[ARGS_ZERO]);
612  if (checkAudioArgsResult !== undefined) {
613    console.log('[picker] Audio Invalid argument');
614    throw checkAudioArgsResult;
615  }
616
617  const audioSelectConfig = parseAudioPickerSelectOption(args[ARGS_ZERO], ACTION.SELECT_ACTION);
618  console.log('[picker] audio select config: ' + JSON.stringify(audioSelectConfig));
619
620  let audioSelectContext = undefined;
621  let audipSelectWindow = undefined;
622  try {
623    if (args[ARGS_ONE] !== undefined) {
624      audioSelectContext = args[ARGS_ONE];
625    } else {
626      audioSelectContext = getContext(this);
627    }
628  } catch (getContextError) {
629    console.error('[picker] getContext error: ' + getContextError);
630    throw getErr(ErrCode.CONTEXT_NO_EXIST);
631  }
632  try {
633    if (audioSelectContext === undefined) {
634      console.error('[picker] audioSelectContext == undefined');
635      throw getErr(ErrCode.CONTEXT_NO_EXIST);
636    }
637    let modalSelectResult = await modalPicker(audioSelectContext, audioSelectConfig, audipSelectWindow);
638    let saveResult = getAudioPickerSelectResult(modalSelectResult);
639    return sendResult(args[ARGS_ZERO], saveResult);
640  } catch (error) {
641    console.error('[picker] audio select error: ' + error);
642  }
643  return undefined;
644}
645
646class PhotoSelectOptions {
647  constructor() {
648    this.MIMEType = PhotoViewMIMETypes.INVALID_TYPE;
649    this.maxSelectNumber = -1;
650  }
651}
652
653class PhotoSelectResult {
654  constructor(uris, isOriginalPhoto) {
655    this.photoUris = uris;
656    this.isOriginalPhoto = isOriginalPhoto;
657  }
658}
659
660class PhotoSaveOptions {
661  constructor() {
662    this.newFileNames = undefined;
663  }
664}
665
666class DocumentSelectOptions {
667  constructor() {
668    this.defaultFilePathUri = undefined;
669    this.fileSuffixFilters = undefined;
670    this.maxSelectNumber = undefined;
671    this.authMode = false;
672    this.selectMode = DocumentSelectMode.FILE;
673    this.mergeMode = MergeTypeMode.DEFAULT;
674    this.multiAuthMode = false;
675    this.multiUriArray = undefined;
676    this.isEncryptionSupported = false;
677  }
678}
679
680class DocumentSaveOptions {
681  constructor() {
682    this.newFileNames = undefined;
683    this.defaultFilePathUri = undefined;
684    this.fileSuffixChoices = undefined;
685    this.pickerMode = DocumentPickerMode.DEFAULT;
686  }
687}
688
689class AudioSelectOptions {
690  constructor() {}
691}
692
693class AudioSaveOptions {
694  constructor() {
695    this.newFileNames = undefined;
696  }
697}
698
699function ParseContext(args)
700{
701  if (args.length > ARGS_TWO || args.length < ARGS_ZERO || typeof args[ARGS_ZERO] !== 'object') {
702    return undefined;
703  }
704  return args[ARGS_ZERO];
705}
706
707function parseWindow(args)
708{
709  if (args.length !== ARGS_TWO) {
710    console.log('[picker] ParseWindow: not window mode.');
711    return undefined;
712  }
713  if (args.length === ARGS_TWO && typeof args[ARGS_ONE] !== 'object') {
714    console.log('[picker] ParseWindow: not window mode or type err.');
715    return undefined;
716  }
717  console.log('[picker] ParseWindow: window mode.');
718  return args[ARGS_ONE];
719}
720
721class PhotoViewPicker {
722  constructor(...args) {
723    this.context = ParseContext(args);
724  }
725  select(...args) {
726    return photoPickerSelect(args, this.context);
727  }
728  save(...args) {
729    return documentPickerSave(args, this.context);
730  }
731}
732
733class DocumentViewPicker {
734  constructor(...args) {
735    this.context = ParseContext(args);
736    this.window = parseWindow(args);
737  }
738  select(...args) {
739    return documentPickerSelect(args, this.context, this.window);
740  }
741  save(...args) {
742    return documentPickerSave(args, this.context, this.window);
743  }
744  getSelectedIndex() {
745    return getSelectedSuffixIndex();
746  }
747}
748
749class AudioViewPicker {
750  constructor(...args) {
751    this.context = ParseContext(args);
752  }
753  select(...args) {
754    return audioPickerSelect(args, this.context);
755  }
756  save(...args) {
757    return documentPickerSave(args, this.context);
758  }
759}
760
761export default {
762  getSelectedSuffixIndex,
763  startModalPicker,
764  ExtTypes : ExtTypes,
765  PickerDetailType: PickerDetailType,
766  PhotoViewMIMETypes : PhotoViewMIMETypes,
767  PhotoSelectOptions : PhotoSelectOptions,
768  PhotoSelectResult : PhotoSelectResult,
769  PhotoSaveOptions : PhotoSaveOptions,
770  DocumentSelectMode : DocumentSelectMode,
771  DocumentPickerMode : DocumentPickerMode,
772  MergeTypeMode : MergeTypeMode,
773  DocumentSelectOptions : DocumentSelectOptions,
774  DocumentSaveOptions : DocumentSaveOptions,
775  AudioSelectOptions : AudioSelectOptions,
776  AudioSaveOptions : AudioSaveOptions,
777  PhotoViewPicker : PhotoViewPicker,
778  DocumentViewPicker: DocumentViewPicker,
779  AudioViewPicker : AudioViewPicker,
780};
781