plugin.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import { IconButton } from "./button";
  2. import { ErrorBoundary } from "./error";
  3. import styles from "./mask.module.scss";
  4. import DownloadIcon from "../icons/download.svg";
  5. import EditIcon from "../icons/edit.svg";
  6. import AddIcon from "../icons/add.svg";
  7. import CloseIcon from "../icons/close.svg";
  8. import DeleteIcon from "../icons/delete.svg";
  9. import EyeIcon from "../icons/eye.svg";
  10. import CopyIcon from "../icons/copy.svg";
  11. import { Plugin, usePluginStore } from "../store/plugin";
  12. import {
  13. Input,
  14. List,
  15. ListItem,
  16. Modal,
  17. Popover,
  18. Select,
  19. showConfirm,
  20. } from "./ui-lib";
  21. import Locale from "../locales";
  22. import { useNavigate } from "react-router-dom";
  23. import { useEffect, useState } from "react";
  24. import { Path } from "../constant";
  25. import { nanoid } from "nanoid";
  26. export function PluginPage() {
  27. const navigate = useNavigate();
  28. const pluginStore = usePluginStore();
  29. const plugins = pluginStore.getAll();
  30. const [editingPluginId, setEditingPluginId] = useState<string | undefined>();
  31. const editingPlugin = pluginStore.get(editingPluginId);
  32. const closePluginModal = () => setEditingPluginId(undefined);
  33. return (
  34. <ErrorBoundary>
  35. <div className={styles["mask-page"]}>
  36. <div className="window-header">
  37. <div className="window-header-title">
  38. <div className="window-header-main-title">
  39. {Locale.Plugin.Page.Title}
  40. </div>
  41. <div className="window-header-submai-title">
  42. {Locale.Plugin.Page.SubTitle(plugins.length)}
  43. </div>
  44. </div>
  45. <div className="window-actions">
  46. <div className="window-action-button">
  47. <IconButton
  48. icon={<CloseIcon />}
  49. bordered
  50. onClick={() => navigate(-1)}
  51. />
  52. </div>
  53. </div>
  54. </div>
  55. <div className={styles["mask-page-body"]}>
  56. <div>
  57. {plugins.map((m) => (
  58. <div className={styles["mask-item"]} key={m.id}>
  59. <div className={styles["mask-header"]}>
  60. <div className={styles["mask-icon"]}></div>
  61. <div className={styles["mask-title"]}>
  62. <div className={styles["mask-name"]}>
  63. {m.title}@<small>{m.version}</small>
  64. </div>
  65. <div className={styles["mask-info"] + " one-line"}>
  66. {`${Locale.Plugin.Item.Info(m.content.length)} / / `}
  67. </div>
  68. </div>
  69. </div>
  70. <div className={styles["mask-actions"]}>
  71. {m.builtin ? (
  72. <IconButton
  73. icon={<EyeIcon />}
  74. text={Locale.Plugin.Item.View}
  75. onClick={() => setEditingPluginId(m.id)}
  76. />
  77. ) : (
  78. <IconButton
  79. icon={<EditIcon />}
  80. text={Locale.Plugin.Item.Edit}
  81. onClick={() => setEditingPluginId(m.id)}
  82. />
  83. )}
  84. {!m.builtin && (
  85. <IconButton
  86. icon={<DeleteIcon />}
  87. text={Locale.Plugin.Item.Delete}
  88. onClick={async () => {
  89. if (
  90. await showConfirm(Locale.Plugin.Item.DeleteConfirm)
  91. ) {
  92. pluginStore.delete(m.id);
  93. }
  94. }}
  95. />
  96. )}
  97. </div>
  98. </div>
  99. ))}
  100. </div>
  101. </div>
  102. </div>
  103. {editingPlugin && (
  104. <div className="modal-mask">
  105. <Modal
  106. title={Locale.Plugin.EditModal.Title(editingPlugin?.builtin)}
  107. onClose={closePluginModal}
  108. actions={[
  109. <IconButton
  110. icon={<DownloadIcon />}
  111. text={Locale.Plugin.EditModal.Download}
  112. key="export"
  113. bordered
  114. onClick={() =>
  115. downloadAs(
  116. JSON.stringify(editingPlugin),
  117. `${editingPlugin.name}.json`,
  118. )
  119. }
  120. />,
  121. <IconButton
  122. key="copy"
  123. icon={<CopyIcon />}
  124. bordered
  125. text={Locale.Plugin.EditModal.Clone}
  126. onClick={() => {
  127. navigate(Path.Plugins);
  128. pluginStore.create(editingPlugin);
  129. setEditingPluginId(undefined);
  130. }}
  131. />,
  132. ]}
  133. >
  134. PluginConfig
  135. </Modal>
  136. </div>
  137. )}
  138. </ErrorBoundary>
  139. );
  140. }