diff --git a/package.json b/package.json
index ba514b8..2a17a0a 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,8 @@
},
"scripts": {
"dev": "vite",
- "build": "tsc && vite build && electron-builder",
+ "watch-tailwind": "tailwindcss --watch",
+ "build": "tsc && vite build && electron-builder && tailwindcss",
"preview": "vite preview",
"pree2e": "vite build --mode=test",
"e2e": "playwright test"
@@ -26,10 +27,12 @@
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"@vitejs/plugin-react": "^4.0.4",
+ "autoprefixer": "^10.4.16",
"electron": "^26.0.0",
"electron-builder": "^24.6.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "tailwindcss": "^3.3.3",
"typescript": "^5.1.6",
"vite": "^4.4.9",
"vite-plugin-electron": "^0.13.0-beta.3",
diff --git a/postcss.config.cjs b/postcss.config.cjs
new file mode 100644
index 0000000..f204746
--- /dev/null
+++ b/postcss.config.cjs
@@ -0,0 +1,7 @@
+module.exports = {
+ plugins: {
+ // 'tailwindcss/nesting': {}, // https://tailwindcss.com/docs/using-with-preprocessors#nesting
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
\ No newline at end of file
diff --git a/src/App.tsx b/src/App.tsx
index d5703ce..31c52f5 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,5 +1,5 @@
import { useState } from 'react'
-import Update from '@/components/update'
+import UpdateElectron from '@/components/update-tailwind'
import logoVite from './assets/logo-vite.svg'
import logoElectron from './assets/logo-electron.svg'
import './App.css'
@@ -32,9 +32,9 @@ function App() {
Place static files into the/public
folder
-
+
)
}
-export default App
+export default App
\ No newline at end of file
diff --git a/src/components/update-tailwind/Modal/index.tsx b/src/components/update-tailwind/Modal/index.tsx
new file mode 100644
index 0000000..b04f4f6
--- /dev/null
+++ b/src/components/update-tailwind/Modal/index.tsx
@@ -0,0 +1,87 @@
+import React, { ReactNode } from "react";
+import { createPortal } from "react-dom";
+
+const ModalTemplate: React.FC<
+ React.PropsWithChildren<{
+ title?: ReactNode;
+ footer?: ReactNode;
+ cancelText?: string;
+ okText?: string;
+ onCancel?: () => void;
+ onOk?: () => void;
+ width?: number;
+ }>
+> = (props) => {
+ const {
+ title,
+ children,
+ footer,
+ cancelText = "Cancel",
+ okText = "OK",
+ onCancel,
+ onOk,
+ width = 530,
+ } = props;
+
+ return (
+
+
+
+
+
+
{children}
+ {typeof footer !== "undefined" ? (
+
+
+
+
+ ) : (
+ footer
+ )}
+
+
+
+ );
+};
+
+const Modal = (
+ props: Parameters[0] & { open: boolean },
+) => {
+ const { open, ...omit } = props;
+
+ return createPortal(open ? ModalTemplate(omit) : null, document.body);
+};
+
+export default Modal;
diff --git a/src/components/update-tailwind/Progress/index.tsx b/src/components/update-tailwind/Progress/index.tsx
new file mode 100644
index 0000000..5912399
--- /dev/null
+++ b/src/components/update-tailwind/Progress/index.tsx
@@ -0,0 +1,25 @@
+import React from "react";
+
+const Progress: React.FC<
+ React.PropsWithChildren<{
+ percent?: number;
+ }>
+> = (props) => {
+ const { percent = 0 } = props;
+
+ return (
+
+
+
+ {(percent ?? 0).toString().substring(0, 4)}%
+
+
+ );
+};
+
+export default Progress;
diff --git a/src/components/update-tailwind/README.md b/src/components/update-tailwind/README.md
new file mode 100644
index 0000000..e2a0be3
--- /dev/null
+++ b/src/components/update-tailwind/README.md
@@ -0,0 +1,25 @@
+# electron-updater-tailwindcss
+
+[tailwindcss docs](https://tailwindcss.com/).
+
+
+## If you don't want to use tailwindcss, want to use the default css style:
+
+[`` Written entirely in CSS](../update/)
+
+### remove dependencies:
+```diff
+- autoprefixer
+- tailwindcss
+```
+### remove files:
+```diff
+- postcss.config.cjs
+- tailwind.config.cjs
+```
+### remove import:
+```diff
+//src/main.tsx
+- import "@/components/update-tailwind/tailwind.css";
+```
+
diff --git a/src/components/update-tailwind/index.tsx b/src/components/update-tailwind/index.tsx
new file mode 100644
index 0000000..11ceafb
--- /dev/null
+++ b/src/components/update-tailwind/index.tsx
@@ -0,0 +1,148 @@
+import { ipcRenderer } from "electron";
+import type { ProgressInfo } from "electron-updater";
+import { useCallback, useEffect, useState } from "react";
+import Modal from "@/components/update-tailwind/Modal";
+import Progress from "@/components/update-tailwind/Progress";
+
+const UpdateElectron = () => {
+ const [checking, setChecking] = useState(false);
+ const [updateAvailable, setUpdateAvailable] = useState(false);
+ const [versionInfo, setVersionInfo] = useState();
+ const [updateError, setUpdateError] = useState();
+ const [progressInfo, setProgressInfo] = useState>();
+ const [modalOpen, setModalOpen] = useState(false);
+ const [modalBtn, setModalBtn] = useState<{
+ cancelText?: string;
+ okText?: string;
+ onCancel?: () => void;
+ onOk?: () => void;
+ }>({
+ onCancel: () => setModalOpen(false),
+ onOk: () => ipcRenderer.invoke("start-download"),
+ });
+
+ const checkUpdate = async () => {
+ setChecking(true);
+ /**
+ * @type {import('electron-updater').UpdateCheckResult | null | { message: string, error: Error }}
+ */
+ const result = await ipcRenderer.invoke("check-update");
+ setProgressInfo({ percent: 0 });
+ setChecking(false);
+ setModalOpen(true);
+ if (result?.error) {
+ setUpdateAvailable(false);
+ setUpdateError(result?.error);
+ }
+ };
+
+ const onUpdateCanAvailable = useCallback(
+ (_event: Electron.IpcRendererEvent, arg1: VersionInfo) => {
+ setVersionInfo(arg1);
+ setUpdateError(undefined);
+ // Can be update
+ if (arg1.update) {
+ setModalBtn((state) => ({
+ ...state,
+ cancelText: "Cancel",
+ okText: "Update",
+ onOk: () => ipcRenderer.invoke("start-download"),
+ }));
+ setUpdateAvailable(true);
+ } else {
+ setUpdateAvailable(false);
+ }
+ },
+ [],
+ );
+
+ const onUpdateError = useCallback(
+ (_event: Electron.IpcRendererEvent, arg1: ErrorType) => {
+ setUpdateAvailable(false);
+ setUpdateError(arg1);
+ },
+ [],
+ );
+
+ const onDownloadProgress = useCallback(
+ (_event: Electron.IpcRendererEvent, arg1: ProgressInfo) => {
+ setProgressInfo(arg1);
+ },
+ [],
+ );
+
+ const onUpdateDownloaded = useCallback(
+ (_event: Electron.IpcRendererEvent, ...args: any[]) => {
+ setProgressInfo({ percent: 100 });
+ setModalBtn((state) => ({
+ ...state,
+ cancelText: "Later",
+ okText: "Install now",
+ onOk: () => ipcRenderer.invoke("quit-and-install"),
+ }));
+ },
+ [],
+ );
+
+ useEffect(() => {
+ // Get version information and whether to update
+ ipcRenderer.on("update-can-available", onUpdateCanAvailable);
+ ipcRenderer.on("update-error", onUpdateError);
+ ipcRenderer.on("download-progress", onDownloadProgress);
+ ipcRenderer.on("update-downloaded", onUpdateDownloaded);
+
+ return () => {
+ ipcRenderer.off("update-can-available", onUpdateCanAvailable);
+ ipcRenderer.off("update-error", onUpdateError);
+ ipcRenderer.off("download-progress", onDownloadProgress);
+ ipcRenderer.off("update-downloaded", onUpdateDownloaded);
+ };
+ }, []);
+
+ return (
+ <>
+
+
+ {updateError ? (
+
+
Error downloading the latest version.
+
{updateError.message}
+
+ ) : updateAvailable ? (
+
+
The last version is: v{versionInfo?.newVersion}
+
+ v{versionInfo?.version} -> v{versionInfo?.newVersion}
+
+
+
+ ) : (
+
+ {JSON.stringify(versionInfo ?? {}, null, 2)}
+
+ )}
+
+
+
+ >
+ );
+};
+
+export default UpdateElectron;
diff --git a/src/components/update-tailwind/tailwind.css b/src/components/update-tailwind/tailwind.css
new file mode 100644
index 0000000..bd6213e
--- /dev/null
+++ b/src/components/update-tailwind/tailwind.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
\ No newline at end of file
diff --git a/src/main.tsx b/src/main.tsx
index c4647c7..815321c 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -3,6 +3,7 @@ import ReactDOM from 'react-dom/client'
import App from './App'
import './samples/node-api'
import './index.css'
+import '@/components/update-tailwind/tailwind.css';
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
diff --git a/src/components/update/electron-updater.d.ts b/src/type/electron-updater.d.ts
similarity index 100%
rename from src/components/update/electron-updater.d.ts
rename to src/type/electron-updater.d.ts
diff --git a/tailwind.config.cjs b/tailwind.config.cjs
new file mode 100644
index 0000000..746ff4c
--- /dev/null
+++ b/tailwind.config.cjs
@@ -0,0 +1,20 @@
+module.exports = {
+ content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
+ theme: {
+ extend: {
+ colors: {
+ crimson: "#e01e5a",
+ darkGrey1: "#333",
+ purple1: "#8256d0",
+ modalMask: "rgba(0, 0, 0, 0.5)",
+ },
+ boxShadow: {
+ modalContent: "0 0 10px -4px #8256d0",
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ plugins: [],
+};