import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
import {
  PanelContainer,
  useDevtoolsDispatch
} from "./chunk-DWYIZZUB.mjs";

// src/panels/echo/SpaceListPanel/SpaceListPanel.tsx
import React2, { useCallback, useMemo } from "react";
import { Obj } from "@dxos/echo";
import { Format } from "@dxos/echo/internal";
import { log as log2 } from "@dxos/log";
import { useClient } from "@dxos/react-client";
import { useSpaces } from "@dxos/react-client/echo";
import { useFileDownload } from "@dxos/react-ui";
import { DynamicTable } from "@dxos/react-ui-table";
import { createFilename } from "@dxos/util";

// src/panels/echo/SpaceListPanel/backup.ts
import { importSpace } from "@dxos/client/echo";
import { Serializer } from "@dxos/echo-db";
import { log } from "@dxos/log";
var __dxlog_file = "/__w/dxos/dxos/packages/devtools/devtools/src/panels/echo/SpaceListPanel/backup.ts";
var exportData = async (space) => {
  const backup = await new Serializer().export(space.internal.db);
  return new Blob([
    JSON.stringify(backup, null, 2)
  ], {
    type: "application/json"
  });
};
var importData = async (space, backup) => {
  try {
    const backupString = await backup.text();
    await importSpace(space.internal.db, JSON.parse(backupString));
  } catch (err) {
    log.catch(err, void 0, {
      F: __dxlog_file,
      L: 20,
      S: void 0,
      C: (f, a) => f(...a)
    });
  }
};

// src/panels/echo/SpaceListPanel/DialogRestoreSpace.tsx
import React, { useState } from "react";
import { FileUploader } from "react-drag-drop-files";
import { Button, Dialog, Icon } from "@dxos/react-ui";
var DialogRestoreSpace = ({ handleFile }) => {
  const [dialogOpen, setDialogOpen] = useState(false);
  return /* @__PURE__ */ React.createElement("div", {
    className: "flex shrink-0 m-2"
  }, /* @__PURE__ */ React.createElement(Dialog.Root, {
    open: dialogOpen,
    onOpenChange: (nextOpen) => setDialogOpen(nextOpen)
  }, /* @__PURE__ */ React.createElement(Dialog.Trigger, {
    asChild: true
  }, /* @__PURE__ */ React.createElement(Button, null, "Import space")), /* @__PURE__ */ React.createElement(Dialog.Overlay, null, /* @__PURE__ */ React.createElement(Dialog.Content, null, /* @__PURE__ */ React.createElement(Dialog.Title, null, "Import space"), /* @__PURE__ */ React.createElement("p", {
    className: "mlb-4"
  }, "Importing from a backup will create new space from."), /* @__PURE__ */ React.createElement(FileUploader, {
    types: [
      "json",
      "tar"
    ],
    classes: "block mlb-4 p-8 border-2 border-dashed border-neutral-500/50 rounded flex items-center justify-center gap-2 cursor-pointer",
    dropMessageStyle: {
      border: "none",
      backgroundColor: "#EEE"
    },
    handleChange: (backupFile) => handleFile(backupFile).finally(() => setDialogOpen(false))
  }, /* @__PURE__ */ React.createElement(Icon, {
    icon: "ph--file-plus--duotone",
    size: 8
  }), /* @__PURE__ */ React.createElement("span", null, "Drag file here or click to browse")), /* @__PURE__ */ React.createElement(Dialog.Close, {
    asChild: true
  }, /* @__PURE__ */ React.createElement(Button, {
    variant: "primary"
  }, "Cancel"))))));
};

// src/panels/echo/SpaceListPanel/SpaceListPanel.tsx
var __dxlog_file2 = "/__w/dxos/dxos/packages/devtools/devtools/src/panels/echo/SpaceListPanel/SpaceListPanel.tsx";
var rowActions = [
  {
    id: "toggleOpen",
    label: "Toggle space open closed"
  },
  {
    id: "snapshot",
    label: "Download space snapshot"
  },
  {
    id: "archive",
    label: "Download space archive"
  }
];
var SpaceListPanel = ({ onSelect }) => {
  const client = useClient();
  const spaces = useSpaces({
    all: true
  });
  const setState = useDevtoolsDispatch();
  const download = useFileDownload();
  const rows = useMemo(() => {
    return spaces.map((space) => {
      const { open, ready } = space.internal.data.metrics ?? {};
      return {
        id: space.id.toString(),
        name: space.isOpen ? space.properties.name : void 0,
        objects: -1,
        members: space.members.get().length,
        startup: open && ready ? ready.getTime() - open.getTime() : -1,
        isDefault: client.spaces.default === space,
        isOpen: space.isOpen
      };
    });
  }, [
    spaces
  ]);
  const handleRowClicked = useCallback((row) => {
    if (!row) {
      return;
    }
    const selectedId = row.id;
    const space = spaces.find((space2) => space2.key.toString() === selectedId);
    setState((state) => ({
      ...state,
      space
    }));
    onSelect?.(row._original);
  }, [
    onSelect,
    setState,
    spaces
  ]);
  const handleToggleOpen = useCallback(async (spaceId) => {
    const space = spaces.find((space2) => space2.id === spaceId);
    if (space.isOpen) {
      await space.close();
    } else {
      await space.open();
    }
  }, [
    spaces
  ]);
  const handleSnapshot = useCallback(async (spaceId) => {
    const space = spaces.find((space2) => space2.id === spaceId);
    await space.waitUntilReady();
    const backupBlob = await exportData(space);
    download(backupBlob, createFilename({
      parts: [
        space.id
      ],
      ext: "json"
    }));
  }, [
    download,
    spaces
  ]);
  const handleArchive = useCallback(async (spaceId) => {
    const space = spaces.find((space2) => space2.id === spaceId);
    const archive = await space.internal.export();
    download(new Blob([
      archive.contents
    ]), archive.filename);
  }, [
    download,
    spaces
  ]);
  const handleImport = useCallback(async (backup) => {
    try {
      if (backup instanceof File) {
        if (backup.type === "application/json") {
          const backupString = await backup.text();
          JSON.parse(backupString);
          const space = await client.spaces.create();
          await space.waitUntilReady();
          await importData(space, backup);
          Obj.change(space.properties, (p) => {
            p.name = p.name + " - IMPORTED";
          });
        } else if (backup.type === "application/x-tar") {
          const archive = {
            filename: backup.name,
            contents: new Uint8Array(await backup.arrayBuffer())
          };
          await client.spaces.import(archive);
        } else {
          throw new Error("Invalid backup type");
        }
      } else {
        const backupString = await backup.text();
        JSON.parse(backupString);
        const space = await client.spaces.create();
        await space.waitUntilReady();
        await importData(space, backup);
        Obj.change(space.properties, (p) => {
          p.name = p.name + " - IMPORTED";
        });
      }
    } catch (err) {
      log2.catch(err, void 0, {
        F: __dxlog_file2,
        L: 143,
        S: void 0,
        C: (f, a) => f(...a)
      });
    }
  }, [
    client
  ]);
  const properties = useMemo(() => [
    {
      name: "id",
      format: Format.TypeFormat.DID
    },
    {
      name: "name",
      format: Format.TypeFormat.String
    },
    {
      name: "objects",
      format: Format.TypeFormat.Number,
      size: 120
    },
    {
      name: "members",
      format: Format.TypeFormat.Number,
      size: 120
    },
    {
      name: "startup",
      format: Format.TypeFormat.Number,
      size: 120
    },
    {
      name: "isDefault",
      format: Format.TypeFormat.Boolean,
      title: "default?",
      size: 120
    },
    {
      name: "isOpen",
      format: Format.TypeFormat.Boolean,
      title: "open?",
      size: 120
    }
  ], []);
  const handleRowAction = (actionId, item) => {
    const spaceId = item.id;
    if (actionId === "toggleOpen") {
      void handleToggleOpen(spaceId);
    } else if (actionId === "snapshot") {
      void handleSnapshot(spaceId);
    } else if (actionId === "archive") {
      void handleArchive(spaceId);
    }
  };
  const features = useMemo(() => ({
    selection: {
      enabled: true,
      mode: "single"
    }
  }), []);
  return /* @__PURE__ */ React2.createElement(PanelContainer, {
    classNames: "overflow-auto flex-1"
  }, /* @__PURE__ */ React2.createElement(DialogRestoreSpace, {
    handleFile: handleImport
  }), /* @__PURE__ */ React2.createElement(DynamicTable, {
    properties,
    rows,
    features,
    rowActions,
    onRowClick: handleRowClicked,
    onRowAction: handleRowAction
  }));
};

// src/panels/echo/SpaceListPanel/index.ts
var SpaceListPanel_default = SpaceListPanel;
export {
  SpaceListPanel_default as default
};
//# sourceMappingURL=SpaceListPanel-6XGSN2IX.mjs.map
