message: open zip files with multiple entries
diff: import { PluginContext } from '../../mol-plugin/context';
  import { StateAction } from '../../mol-state';
  import { Task } from '../../mol-task';
  +import { Asset } from '../../mol-util/assets';
  import { getFileInfo } from '../../mol-util/file-info';
  import { ParamDefinition as PD } from '../../mol-util/param-definition';
  +import { unzip } from '../../mol-util/zip/zip';
  import { PluginStateObject } from '../objects';
  export const OpenFiles = StateAction.build({
  @@ -33,8 +35,8 @@ export const OpenFiles = StateAction.build({
  plugin.log.error('No file(s) selected');
  return;
  }
  - for (const file of params.files) {
  - try {
  +
  + const processFile = async (file: Asset.File) => {
  const info = getFileInfo(file.file!);
  const isBinary = plugin.dataFormats.binaryExtensions.has(info.ext);
  const { data } = await plugin.builders.data.readFile({ file, isBinary });
  @@ -44,7 +46,7 @@ export const OpenFiles = StateAction.build({
  if (!provider) {
  plugin.log.warn(`OpenFiles: could not find data provider for '${info.name}.${info.ext}'`);
  - continue;
  + return;
  }
  // need to await so that the enclosing Task finishes after the update is done.
  @@ -52,6 +54,19 @@ export const OpenFiles = StateAction.build({
  if (params.visuals) {
  await provider.visuals?.(plugin, parsed);
  }
  + };
  +
  + for (const file of params.files) {
  + try {
  + if (file.file && file.name.toLowerCase().endsWith('.zip')) {
  + const zippedFiles = await unzip(taskCtx, await file.file.arrayBuffer());
  + for (const [fn, filedata] of Object.entries(zippedFiles)) {
  + const asset = Asset.File(new File([filedata as Uint8Array], fn));
  + await processFile(asset);
  + }
  + } else {
  + await processFile(file);
  + }
  } catch (e) {
  console.error(e);
  plugin.log.error(`Error opening file '${file.name}'`);
  