mirror of
https://github.com/upscayl/upscayl.git
synced 2025-02-12 17:04:34 +01:00
Add stats and add posthog systeminfo
This commit is contained in:
parent
c9e00de2b0
commit
5a4b29a840
@ -93,6 +93,21 @@ ipcMain.on(ELECTRON_COMMANDS.DOUBLE_UPSCAYL, doubleUpscayl);
|
|||||||
|
|
||||||
ipcMain.on(ELECTRON_COMMANDS.PASTE_IMAGE, pasteImage);
|
ipcMain.on(ELECTRON_COMMANDS.PASTE_IMAGE, pasteImage);
|
||||||
|
|
||||||
|
ipcMain.handle("get-gpu-info", async () => {
|
||||||
|
try {
|
||||||
|
return await app.getGPUInfo("complete");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to get GPU info:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle("get-app-version", () => {
|
||||||
|
return `${app.getVersion()} ${
|
||||||
|
FEATURE_FLAGS.APP_STORE_BUILD ? "MAC-APP-STORE" : "FOSS"
|
||||||
|
}`;
|
||||||
|
});
|
||||||
|
|
||||||
if (!FEATURE_FLAGS.APP_STORE_BUILD) {
|
if (!FEATURE_FLAGS.APP_STORE_BUILD) {
|
||||||
autoUpdater.on("update-downloaded", autoUpdate);
|
autoUpdater.on("update-downloaded", autoUpdate);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import { ipcRenderer, contextBridge } from "electron";
|
import { ipcRenderer, contextBridge, app } from "electron";
|
||||||
import { getPlatform } from "./utils/get-device-specs";
|
import {
|
||||||
|
getAppVersion,
|
||||||
|
getDeviceSpecs,
|
||||||
|
getPlatform,
|
||||||
|
} from "./utils/get-device-specs";
|
||||||
|
import { FEATURE_FLAGS } from "@common/feature-flags";
|
||||||
|
|
||||||
// 'ipcRenderer' will be available in index.js with the method 'window.electron'
|
// 'ipcRenderer' will be available in index.js with the method 'window.electron'
|
||||||
contextBridge.exposeInMainWorld("electron", {
|
contextBridge.exposeInMainWorld("electron", {
|
||||||
@ -11,4 +16,6 @@ contextBridge.exposeInMainWorld("electron", {
|
|||||||
invoke: (command: string, payload: any) =>
|
invoke: (command: string, payload: any) =>
|
||||||
ipcRenderer.invoke(command, payload),
|
ipcRenderer.invoke(command, payload),
|
||||||
platform: getPlatform(),
|
platform: getPlatform(),
|
||||||
|
getSystemInfo: async () => await getDeviceSpecs(),
|
||||||
|
getAppVersion: async () => await getAppVersion(),
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import { platform, arch } from "os";
|
import { ipcRenderer } from "electron";
|
||||||
|
import os from "os";
|
||||||
|
|
||||||
export const getPlatform = () => {
|
export const getPlatform = () => {
|
||||||
switch (platform()) {
|
switch (os.platform()) {
|
||||||
case "aix":
|
case "aix":
|
||||||
case "freebsd":
|
case "freebsd":
|
||||||
case "linux":
|
case "linux":
|
||||||
@ -19,7 +20,7 @@ export const getPlatform = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getArch = () => {
|
export const getArch = () => {
|
||||||
switch (arch()) {
|
switch (os.arch()) {
|
||||||
case "x64":
|
case "x64":
|
||||||
return "x64";
|
return "x64";
|
||||||
case "x32":
|
case "x32":
|
||||||
@ -30,3 +31,33 @@ export const getArch = () => {
|
|||||||
return "arm64";
|
return "arm64";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getAppVersion = async () => {
|
||||||
|
let appVersion = process.env.npm_package_version;
|
||||||
|
try {
|
||||||
|
appVersion = await ipcRenderer.invoke("get-app-version");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to get app version:", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return appVersion;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getDeviceSpecs = async () => {
|
||||||
|
let gpuInfo;
|
||||||
|
try {
|
||||||
|
gpuInfo = await ipcRenderer.invoke("get-gpu-info");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to get GPU info:", error);
|
||||||
|
gpuInfo = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
platform: getPlatform(),
|
||||||
|
release: os.release(),
|
||||||
|
arch: getArch(),
|
||||||
|
model: os.cpus()[0].model.trim(),
|
||||||
|
cpuCount: os.cpus().length,
|
||||||
|
...(gpuInfo && { gpu: gpuInfo.gpuDevice[0] }),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -83,3 +83,13 @@ export const enableContributionAtom = atomWithStorage(
|
|||||||
"enableContribution",
|
"enableContribution",
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const userStatsAtom = atomWithStorage("userStats", {
|
||||||
|
totalUpscayls: 0,
|
||||||
|
doubleUpscayls: 0,
|
||||||
|
batchUpscayls: 0,
|
||||||
|
imageUpscayls: 0,
|
||||||
|
averageUpscaylTime: 0,
|
||||||
|
lastUpscaylDuration: 0,
|
||||||
|
lastUsedAt: 0,
|
||||||
|
});
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
import { translationAtom } from "@/atoms/translations-atom";
|
|
||||||
import { lensSizeAtom, viewTypeAtom } from "@/atoms/user-settings-atom";
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { useAtom, useAtomValue } from "jotai";
|
|
||||||
import { WrenchIcon } from "lucide-react";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
|
|
||||||
const ImageViewSettings = ({
|
|
||||||
zoomAmount,
|
|
||||||
setZoomAmount,
|
|
||||||
resetImagePaths,
|
|
||||||
}: {
|
|
||||||
zoomAmount: string;
|
|
||||||
setZoomAmount: (arg: any) => void;
|
|
||||||
resetImagePaths: () => void;
|
|
||||||
}) => {
|
|
||||||
const [openSidebar, setOpenSidebar] = useState(false);
|
|
||||||
const [viewType, setViewType] = useAtom(viewTypeAtom);
|
|
||||||
const [lensSize, setLensSize] = useAtom(lensSizeAtom);
|
|
||||||
const t = useAtomValue(translationAtom);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!localStorage.getItem("zoomAmount")) {
|
|
||||||
localStorage.setItem("zoomAmount", zoomAmount);
|
|
||||||
} else {
|
|
||||||
setZoomAmount(localStorage.getItem("zoomAmount"));
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
onDoubleClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
className={`fixed right-0 top-0 z-50 h-screen w-[28rem] bg-base-100 text-base-content shadow-xl shadow-base-300 transition-all duration-500 ${
|
|
||||||
openSidebar ? "right-0" : "-right-full translate-x-full"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={`group absolute right-[100%] top-1/2 z-50 flex cursor-pointer items-center gap-2 rounded-btn rounded-r-none bg-base-100 p-4 transition-all duration-500`}
|
|
||||||
onClick={() => {
|
|
||||||
setOpenSidebar(!openSidebar);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<WrenchIcon
|
|
||||||
className={cn(
|
|
||||||
"animate text-xl text-base-content",
|
|
||||||
openSidebar ? "rotate-180" : "rotate-0",
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col justify-center gap-5 overflow-auto p-5">
|
|
||||||
<button className="btn btn-primary" onClick={resetImagePaths}>
|
|
||||||
{t("APP.IMAGE_OPTIONS.RESET_BUTTON_TITLE")}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div className="flex flex-row items-center gap-2">
|
|
||||||
<p className="text-sm font-medium">
|
|
||||||
{t("APP.IMAGE_OPTIONS.LENS_VIEW_TITLE")}
|
|
||||||
</p>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
className="toggle"
|
|
||||||
checked={viewType === "slider"}
|
|
||||||
onChange={(e) => {
|
|
||||||
setViewType(e.target.checked ? "slider" : "lens");
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<p className="text-sm font-medium">
|
|
||||||
{t("APP.IMAGE_OPTIONS.SLIDER_VIEW_TITLE")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{viewType !== "lens" && (
|
|
||||||
<>
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<p className="text-sm font-medium">
|
|
||||||
{t("APP.IMAGE_OPTIONS.ZOOM_AMOUNT_TITLE")} ({zoomAmount}%)
|
|
||||||
</p>
|
|
||||||
<input
|
|
||||||
type="range"
|
|
||||||
min="100"
|
|
||||||
max="1000"
|
|
||||||
step={10}
|
|
||||||
className="range range-md"
|
|
||||||
value={parseInt(zoomAmount)}
|
|
||||||
onChange={(e) => {
|
|
||||||
setZoomAmount(e.target.value);
|
|
||||||
localStorage.setItem("zoomAmount", e.target.value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<p className="text-sm font-medium">
|
|
||||||
{t("APP.IMAGE_OPTIONS.LENS_SIZE_TITLE")} ({lensSize / 10})
|
|
||||||
</p>
|
|
||||||
<input
|
|
||||||
type="range"
|
|
||||||
min="20"
|
|
||||||
max="400"
|
|
||||||
step={10}
|
|
||||||
className="range range-md"
|
|
||||||
value={lensSize}
|
|
||||||
onChange={(e) => {
|
|
||||||
setLensSize(parseInt(e.target.value));
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ImageViewSettings;
|
|
@ -18,7 +18,7 @@ import { FEATURE_FLAGS } from "@common/feature-flags";
|
|||||||
import { ImageFormat, VALID_IMAGE_FORMATS } from "@/lib/valid-formats";
|
import { ImageFormat, VALID_IMAGE_FORMATS } from "@/lib/valid-formats";
|
||||||
import ProgressBar from "./progress-bar";
|
import ProgressBar from "./progress-bar";
|
||||||
import InstructionsCard from "./instructions-card";
|
import InstructionsCard from "./instructions-card";
|
||||||
import ImageViewSettings from "./image-view-settings";
|
import MoreOptionsDrawer from "./more-options-drawer";
|
||||||
import useUpscaylVersion from "../hooks/use-upscayl-version";
|
import useUpscaylVersion from "../hooks/use-upscayl-version";
|
||||||
import MacTitlebarDragRegion from "./mac-titlebar-drag-region";
|
import MacTitlebarDragRegion from "./mac-titlebar-drag-region";
|
||||||
import LensViewer from "./lens-view";
|
import LensViewer from "./lens-view";
|
||||||
@ -292,7 +292,7 @@ const MainContent = ({
|
|||||||
<InstructionsCard version={version} batchMode={batchMode} />
|
<InstructionsCard version={version} batchMode={batchMode} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<ImageViewSettings
|
<MoreOptionsDrawer
|
||||||
zoomAmount={zoomAmount}
|
zoomAmount={zoomAmount}
|
||||||
setZoomAmount={setZoomAmount}
|
setZoomAmount={setZoomAmount}
|
||||||
resetImagePaths={resetImagePaths}
|
resetImagePaths={resetImagePaths}
|
||||||
|
@ -106,6 +106,7 @@ const LensViewer = ({
|
|||||||
className="relative h-full w-full cursor-crosshair"
|
className="relative h-full w-full cursor-crosshair"
|
||||||
ref={originalImageContainerRef}
|
ref={originalImageContainerRef}
|
||||||
>
|
>
|
||||||
|
ORIGINAL IMAGE
|
||||||
<img
|
<img
|
||||||
src={originalImage}
|
src={originalImage}
|
||||||
alt="Original"
|
alt="Original"
|
||||||
@ -113,12 +114,15 @@ const LensViewer = ({
|
|||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
ref={originalImageRef}
|
ref={originalImageRef}
|
||||||
/>
|
/>
|
||||||
|
{/* Lens */}
|
||||||
<div
|
<div
|
||||||
className="pointer-events-none absolute hidden h-10 w-10 cursor-cell border border-primary bg-black/10 group-hover:block"
|
className="pointer-events-none absolute hidden cursor-cell border border-primary bg-black/10 group-hover:block"
|
||||||
style={{
|
style={{
|
||||||
left: `${hoverPosition.relativeMouseX}px`,
|
left: `${hoverPosition.relativeMouseX}px`,
|
||||||
top: `${hoverPosition.mouseY}px`,
|
top: `${hoverPosition.mouseY}px`,
|
||||||
transform: "translate(-50%, -50%)",
|
transform: "translate(-50%, -50%)",
|
||||||
|
height: `48px`,
|
||||||
|
width: `48px`,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -132,6 +136,7 @@ const LensViewer = ({
|
|||||||
transform: "translate(-50%, 0)",
|
transform: "translate(-50%, 0)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{/* ORIGINAL IMAGE */}
|
||||||
<div
|
<div
|
||||||
className="relative h-48 w-48 border border-gray-300 bg-cover bg-no-repeat"
|
className="relative h-48 w-48 border border-gray-300 bg-cover bg-no-repeat"
|
||||||
style={{
|
style={{
|
||||||
@ -144,6 +149,7 @@ const LensViewer = ({
|
|||||||
Original
|
Original
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
{/* UPSCALED IMAGE */}
|
||||||
<div
|
<div
|
||||||
className="relative h-48 w-48 border border-gray-300 bg-cover bg-no-repeat"
|
className="relative h-48 w-48 border border-gray-300 bg-cover bg-no-repeat"
|
||||||
style={{
|
style={{
|
||||||
|
210
renderer/components/main-content/more-options-drawer.tsx
Normal file
210
renderer/components/main-content/more-options-drawer.tsx
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
import { translationAtom } from "@/atoms/translations-atom";
|
||||||
|
import {
|
||||||
|
lensSizeAtom,
|
||||||
|
userStatsAtom,
|
||||||
|
viewTypeAtom,
|
||||||
|
} from "@/atoms/user-settings-atom";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { useAtom, useAtomValue } from "jotai";
|
||||||
|
import { EllipsisIcon, WrenchIcon } from "lucide-react";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
const formatDuration = (seconds: number): string => {
|
||||||
|
if (seconds < 60) return `${seconds.toFixed(1)}s`;
|
||||||
|
if (seconds < 3600) {
|
||||||
|
const minutes = Math.floor(seconds / 60);
|
||||||
|
const remainingSeconds = seconds % 60;
|
||||||
|
return `${minutes}m ${remainingSeconds.toFixed(0)}s`;
|
||||||
|
}
|
||||||
|
const hours = Math.floor(seconds / 3600);
|
||||||
|
const minutes = Math.floor((seconds % 3600) / 60);
|
||||||
|
return `${hours}h ${minutes}m`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const MoreOptionsDrawer = ({
|
||||||
|
zoomAmount,
|
||||||
|
setZoomAmount,
|
||||||
|
resetImagePaths,
|
||||||
|
}: {
|
||||||
|
zoomAmount: string;
|
||||||
|
setZoomAmount: (arg: any) => void;
|
||||||
|
resetImagePaths: () => void;
|
||||||
|
}) => {
|
||||||
|
const [openSidebar, setOpenSidebar] = useState(false);
|
||||||
|
const [viewType, setViewType] = useAtom(viewTypeAtom);
|
||||||
|
const [lensSize, setLensSize] = useAtom(lensSizeAtom);
|
||||||
|
const t = useAtomValue(translationAtom);
|
||||||
|
const userStats = useAtomValue(userStatsAtom);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!localStorage.getItem("zoomAmount")) {
|
||||||
|
localStorage.setItem("zoomAmount", zoomAmount);
|
||||||
|
} else {
|
||||||
|
setZoomAmount(localStorage.getItem("zoomAmount"));
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onDoubleClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
className={`fixed right-0 top-0 z-50 h-screen w-[28rem] bg-base-100 text-base-content shadow-xl shadow-base-300 transition-all duration-500 ${
|
||||||
|
openSidebar ? "right-0" : "-right-full translate-x-full"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`group absolute right-[100%] top-1/2 z-50 flex cursor-pointer items-center gap-2 rounded-btn rounded-r-none bg-base-100 p-4 transition-all duration-500`}
|
||||||
|
onClick={() => {
|
||||||
|
setOpenSidebar(!openSidebar);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<EllipsisIcon
|
||||||
|
className={cn(
|
||||||
|
"animate text-xl text-base-content",
|
||||||
|
openSidebar ? "rotate-90" : "rotate-0",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex h-full flex-col overflow-hidden p-5">
|
||||||
|
<div className="flex flex-col gap-5">
|
||||||
|
<button className="btn btn-primary" onClick={resetImagePaths}>
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.RESET_BUTTON_TITLE")}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div className="flex flex-row items-center gap-2">
|
||||||
|
<p className="text-sm font-medium">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.LENS_VIEW_TITLE")}
|
||||||
|
</p>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="toggle"
|
||||||
|
checked={viewType === "slider"}
|
||||||
|
onChange={(e) => {
|
||||||
|
setViewType(e.target.checked ? "slider" : "lens");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<p className="text-sm font-medium">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.SLIDER_VIEW_TITLE")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{viewType !== "lens" && (
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<p className="text-sm font-medium">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.ZOOM_AMOUNT_TITLE")} ({zoomAmount}
|
||||||
|
%)
|
||||||
|
</p>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
min="100"
|
||||||
|
max="1000"
|
||||||
|
step={10}
|
||||||
|
className="range range-md"
|
||||||
|
value={parseInt(zoomAmount)}
|
||||||
|
onChange={(e) => {
|
||||||
|
setZoomAmount(e.target.value);
|
||||||
|
localStorage.setItem("zoomAmount", e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<p className="text-sm font-medium">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.LENS_SIZE_TITLE")} (
|
||||||
|
{lensSize / 10})
|
||||||
|
</p>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
min="20"
|
||||||
|
max="400"
|
||||||
|
step={10}
|
||||||
|
className="range range-md"
|
||||||
|
value={lensSize}
|
||||||
|
onChange={(e) => {
|
||||||
|
setLensSize(parseInt(e.target.value));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-5 flex min-h-0 flex-1 flex-col gap-2">
|
||||||
|
<p className="text-sm font-semibold uppercase text-base-content">
|
||||||
|
User Stats
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="stats stats-vertical overflow-y-auto">
|
||||||
|
<div className="stat">
|
||||||
|
<div className="stat-title">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.TOTAL_UPSCAYLS")}
|
||||||
|
</div>
|
||||||
|
<div className="stat-value text-2xl text-primary-content">
|
||||||
|
{userStats.totalUpscayls}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="stat">
|
||||||
|
<div className="stat-title">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.TOTAL_BATCH_UPSCAYLS")}
|
||||||
|
</div>
|
||||||
|
<div className="stat-value text-2xl text-primary-content">
|
||||||
|
{userStats.batchUpscayls}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="stat">
|
||||||
|
<div className="stat-title">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.TOTAL_IMAGE_UPSCAYLS")}
|
||||||
|
</div>
|
||||||
|
<div className="stat-value text-2xl text-primary-content">
|
||||||
|
{userStats.imageUpscayls}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="stat">
|
||||||
|
<div className="stat-title">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.TOTAL_DOUBLE_UPSCAYLS")}
|
||||||
|
</div>
|
||||||
|
<div className="stat-value text-2xl text-primary-content">
|
||||||
|
{userStats.doubleUpscayls}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="stat">
|
||||||
|
<div className="stat-title">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.AVERAGE_UPSCAYL_TIME")}
|
||||||
|
</div>
|
||||||
|
<div className="stat-value text-2xl text-primary-content">
|
||||||
|
{formatDuration(userStats.averageUpscaylTime / 1000)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="stat">
|
||||||
|
<div className="stat-title">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.LAST_UPSCAYL_DURATION")}
|
||||||
|
</div>
|
||||||
|
<div className="stat-value text-2xl text-primary-content">
|
||||||
|
{formatDuration(userStats.lastUpscaylDuration / 1000)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="stat">
|
||||||
|
<div className="stat-title">
|
||||||
|
{t("APP.MORE_OPTIONS_DRAWER.LAST_USED_AT")}
|
||||||
|
</div>
|
||||||
|
<div className="stat-value text-2xl text-primary-content">
|
||||||
|
{new Date(userStats.lastUsedAt).toLocaleString()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MoreOptionsDrawer;
|
@ -77,7 +77,8 @@ export function OnboardingDialog() {
|
|||||||
{
|
{
|
||||||
key: "video",
|
key: "video",
|
||||||
type: "video",
|
type: "video",
|
||||||
videoSrc: "https://www.youtube-nocookie.com/embed/3M77flVZlVY",
|
videoSrc:
|
||||||
|
"https://www.youtube-nocookie.com/embed/3M77flVZlVY?autoplay=1",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -142,12 +143,19 @@ export function OnboardingDialog() {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full w-full flex-col rounded-sm bg-primary p-8",
|
"flex h-full w-full flex-col rounded-sm bg-primary p-8",
|
||||||
currentStepData.type === "settings" && "h-auto w-auto gap-8",
|
currentStepData.type === "settings" && "h-auto w-auto gap-8",
|
||||||
|
currentStepData.configurationOptions[0].type === "video" && "p-0",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{currentStepData.configurationOptions.map((option) => (
|
{currentStepData.configurationOptions.map((option) => (
|
||||||
<div
|
<div
|
||||||
key={option.key}
|
key={option.key}
|
||||||
className="flex h-full w-full items-center justify-between gap-4"
|
className="flex h-full w-full items-center justify-between gap-4"
|
||||||
|
data-tooltip-id="tooltip"
|
||||||
|
data-tooltip-content={
|
||||||
|
option.key === "improveUpscayl"
|
||||||
|
? t("SETTINGS.ENABLE_CONTRIBUTION.DESCRIPTION")
|
||||||
|
: null
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{option.label && (
|
{option.label && (
|
||||||
<label
|
<label
|
||||||
@ -190,7 +198,7 @@ export function OnboardingDialog() {
|
|||||||
)}
|
)}
|
||||||
{option.type === "video" && (
|
{option.type === "video" && (
|
||||||
<iframe
|
<iframe
|
||||||
className="h-full w-full"
|
className="h-full w-full rounded-sm"
|
||||||
src={option.videoSrc}
|
src={option.videoSrc}
|
||||||
title="YouTube video player"
|
title="YouTube video player"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
@ -202,6 +210,11 @@ export function OnboardingDialog() {
|
|||||||
{option.type === "component" && option.component}
|
{option.type === "component" && option.component}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
{currentStepData.type === "settings" && (
|
||||||
|
<p className="text-sm text-base-content/70">
|
||||||
|
{t("ONBOARDING_DIALOG.SETTINGS_NOTE")}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
49
renderer/components/posthog-provider-wrapper.tsx
Normal file
49
renderer/components/posthog-provider-wrapper.tsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { enableContributionAtom } from "@/atoms/user-settings-atom";
|
||||||
|
import { useAtomValue } from "jotai";
|
||||||
|
import posthog from "posthog-js";
|
||||||
|
import { PostHogProvider } from "posthog-js/react";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
const PostHogProviderWrapper = ({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) => {
|
||||||
|
const enableContribution = useAtomValue(enableContributionAtom);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
posthog.init("phc_QMcmlmComdofjfaRPzoN4KV9ziV2KgOwAOVyu4J3dIc", {
|
||||||
|
api_host: "https://us.i.posthog.com",
|
||||||
|
person_profiles: "identified_only",
|
||||||
|
autocapture: false,
|
||||||
|
capture_pageview: false,
|
||||||
|
capture_pageleave: false,
|
||||||
|
disable_session_recording: true,
|
||||||
|
loaded: async (posthog) => {
|
||||||
|
if (process.env.NODE_ENV === "development") posthog.debug();
|
||||||
|
const systemInfo = await window.electron.getSystemInfo();
|
||||||
|
const appVersion = await window.electron.getAppVersion();
|
||||||
|
// Set super properties that will be included with all events
|
||||||
|
posthog.register({
|
||||||
|
...systemInfo,
|
||||||
|
appVersion,
|
||||||
|
$ip: "0.0.0.0",
|
||||||
|
$geoip_disable: true,
|
||||||
|
});
|
||||||
|
// Capture initial session start
|
||||||
|
posthog.capture("app_launched", {
|
||||||
|
...systemInfo,
|
||||||
|
appVersion,
|
||||||
|
$ip: "0.0.0.0",
|
||||||
|
$geoip_disable: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!enableContribution) return <>{children}</>;
|
||||||
|
|
||||||
|
return <PostHogProvider client={posthog}>{children}</PostHogProvider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PostHogProviderWrapper;
|
@ -18,6 +18,7 @@ import {
|
|||||||
doubleUpscaylAtom,
|
doubleUpscaylAtom,
|
||||||
gpuIdAtom,
|
gpuIdAtom,
|
||||||
saveImageAsAtom,
|
saveImageAsAtom,
|
||||||
|
userStatsAtom,
|
||||||
} from "../../atoms/user-settings-atom";
|
} from "../../atoms/user-settings-atom";
|
||||||
import useLogger from "../hooks/use-logger";
|
import useLogger from "../hooks/use-logger";
|
||||||
import {
|
import {
|
||||||
@ -89,6 +90,7 @@ const Sidebar = ({
|
|||||||
const useCustomWidth = useAtomValue(useCustomWidthAtom);
|
const useCustomWidth = useAtomValue(useCustomWidthAtom);
|
||||||
const tileSize = useAtomValue(tileSizeAtom);
|
const tileSize = useAtomValue(tileSizeAtom);
|
||||||
const [showSidebar, setShowSidebar] = useAtom(showSidebarAtom);
|
const [showSidebar, setShowSidebar] = useAtom(showSidebarAtom);
|
||||||
|
const setUserStats = useSetAtom(userStatsAtom);
|
||||||
|
|
||||||
const upscaylHandler = async () => {
|
const upscaylHandler = async () => {
|
||||||
logit("🔄 Resetting Upscaled Image Path");
|
logit("🔄 Resetting Upscaled Image Path");
|
||||||
@ -114,6 +116,13 @@ const Sidebar = ({
|
|||||||
tileSize,
|
tileSize,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
setUserStats((prev) => ({
|
||||||
|
...prev,
|
||||||
|
totalUpscayls: prev.totalUpscayls + 1,
|
||||||
|
lastUsedAt: new Date().getTime(),
|
||||||
|
doubleUpscayls: prev.doubleUpscayls + 1,
|
||||||
|
imageUpscayls: prev.imageUpscayls + 1,
|
||||||
|
}));
|
||||||
logit("🏁 DOUBLE_UPSCAYL");
|
logit("🏁 DOUBLE_UPSCAYL");
|
||||||
} else if (batchMode) {
|
} else if (batchMode) {
|
||||||
// Batch Upscayl
|
// Batch Upscayl
|
||||||
@ -134,6 +143,12 @@ const Sidebar = ({
|
|||||||
tileSize,
|
tileSize,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
setUserStats((prev) => ({
|
||||||
|
...prev,
|
||||||
|
totalUpscayls: prev.totalUpscayls + 1,
|
||||||
|
lastUsedAt: new Date().getTime(),
|
||||||
|
batchUpscayls: prev.doubleUpscayls + 1,
|
||||||
|
}));
|
||||||
logit("🏁 FOLDER_UPSCAYL");
|
logit("🏁 FOLDER_UPSCAYL");
|
||||||
} else {
|
} else {
|
||||||
// Single Image Upscayl
|
// Single Image Upscayl
|
||||||
@ -151,6 +166,12 @@ const Sidebar = ({
|
|||||||
useCustomWidth,
|
useCustomWidth,
|
||||||
tileSize,
|
tileSize,
|
||||||
});
|
});
|
||||||
|
setUserStats((prev) => ({
|
||||||
|
...prev,
|
||||||
|
totalUpscayls: prev.totalUpscayls + 1,
|
||||||
|
lastUsedAt: new Date().getTime(),
|
||||||
|
imageUpscayls: prev.imageUpscayls + 1,
|
||||||
|
}));
|
||||||
logit("🏁 UPSCAYL");
|
logit("🏁 UPSCAYL");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -16,6 +16,7 @@ import { useAtom, useAtomValue } from "jotai";
|
|||||||
import { selectedModelIdAtom } from "@/atoms/user-settings-atom";
|
import { selectedModelIdAtom } from "@/atoms/user-settings-atom";
|
||||||
import { customModelIdsAtom } from "@/atoms/models-list-atom";
|
import { customModelIdsAtom } from "@/atoms/models-list-atom";
|
||||||
import useTranslation from "@/components/hooks/use-translation";
|
import useTranslation from "@/components/hooks/use-translation";
|
||||||
|
import posthog from "posthog-js";
|
||||||
|
|
||||||
const SelectModelDialog = () => {
|
const SelectModelDialog = () => {
|
||||||
const t = useTranslation();
|
const t = useTranslation();
|
||||||
@ -28,6 +29,12 @@ const SelectModelDialog = () => {
|
|||||||
const handleModelSelect = (model: ModelId | string) => {
|
const handleModelSelect = (model: ModelId | string) => {
|
||||||
setSelectedModelId(model);
|
setSelectedModelId(model);
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
|
||||||
|
posthog.capture("model_selected", {
|
||||||
|
$ip: "0.0.0.0",
|
||||||
|
$geoip_disable: true,
|
||||||
|
model,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleZoom = (event: React.MouseEvent, model: ModelId) => {
|
const handleZoom = (event: React.MouseEvent, model: ModelId) => {
|
||||||
@ -61,12 +68,12 @@ const SelectModelDialog = () => {
|
|||||||
className="btn !h-auto !w-full !flex-col !items-start !rounded-sm !p-4"
|
className="btn !h-auto !w-full !flex-col !items-start !rounded-sm !p-4"
|
||||||
onClick={() => handleModelSelect(modelId)}
|
onClick={() => handleModelSelect(modelId)}
|
||||||
>
|
>
|
||||||
<div className="font-semibold">
|
<p className="font-semibold">
|
||||||
{t(`APP.MODEL_SELECTION.MODELS.${modelId}.NAME`)}
|
{t(`APP.MODEL_SELECTION.MODELS.${modelId}.NAME`)}
|
||||||
</div>
|
</p>
|
||||||
<div className="mb-2 text-left font-normal leading-normal text-opacity-50">
|
<p className="mb-2 text-left font-normal leading-normal text-base-content/70">
|
||||||
{t(`APP.MODEL_SELECTION.MODELS.${modelId}.DESCRIPTION`)}
|
{t(`APP.MODEL_SELECTION.MODELS.${modelId}.DESCRIPTION`)}
|
||||||
</div>
|
</p>
|
||||||
<div className="relative h-52 w-full overflow-hidden rounded-sm">
|
<div className="relative h-52 w-full overflow-hidden rounded-sm">
|
||||||
<div className="flex h-full w-full">
|
<div className="flex h-full w-full">
|
||||||
<img
|
<img
|
||||||
|
@ -270,11 +270,6 @@ function UpscaylSteps({
|
|||||||
: t("APP.SCALE_SELECTION.START_BUTTON_TITLE")}
|
: t("APP.SCALE_SELECTION.START_BUTTON_TITLE")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Tooltip
|
|
||||||
className="z-[999] max-w-sm break-words !bg-secondary"
|
|
||||||
id="tooltip"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -160,12 +160,19 @@
|
|||||||
"START_BUTTON_TITLE": "Upscayl 🚀",
|
"START_BUTTON_TITLE": "Upscayl 🚀",
|
||||||
"IN_PROGRESS_BUTTON_TITLE": "Upscayling ⏳"
|
"IN_PROGRESS_BUTTON_TITLE": "Upscayling ⏳"
|
||||||
},
|
},
|
||||||
"IMAGE_OPTIONS": {
|
"MORE_OPTIONS_DRAWER": {
|
||||||
"RESET_BUTTON_TITLE": "Reset Image",
|
"RESET_BUTTON_TITLE": "Reset Image",
|
||||||
"LENS_VIEW_TITLE": "Lens View",
|
"LENS_VIEW_TITLE": "Lens View",
|
||||||
"SLIDER_VIEW_TITLE": "Slider View",
|
"SLIDER_VIEW_TITLE": "Slider View",
|
||||||
"ZOOM_AMOUNT_TITLE": "Zoom Amount",
|
"ZOOM_AMOUNT_TITLE": "Zoom Amount",
|
||||||
"LENS_SIZE_TITLE": "Lens Size"
|
"LENS_SIZE_TITLE": "Lens Size",
|
||||||
|
"TOTAL_UPSCAYLS": "Total Upscayls",
|
||||||
|
"TOTAL_BATCH_UPSCAYLS": "Total Batch Upscayls",
|
||||||
|
"TOTAL_IMAGE_UPSCAYLS": "Total Image Upscayls",
|
||||||
|
"TOTAL_DOUBLE_UPSCAYLS": "Total Double Upscayls",
|
||||||
|
"AVERAGE_UPSCAYL_TIME": "Average Upscayl Time",
|
||||||
|
"LAST_UPSCAYL_DURATION": "Last Upscayl Duration",
|
||||||
|
"LAST_USED_AT": "Last Used At"
|
||||||
},
|
},
|
||||||
"PROGRESS_BAR": {
|
"PROGRESS_BAR": {
|
||||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Batch Upscayl In Progress:",
|
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Batch Upscayl In Progress:",
|
||||||
@ -178,7 +185,7 @@
|
|||||||
"SELECT_IMAGE": "Select an Image",
|
"SELECT_IMAGE": "Select an Image",
|
||||||
"SELECT_FOLDER_DESCRIPTION": "Make sure that the folder doesn't contain anything except PNG, JPG, JPEG & WEBP images.",
|
"SELECT_FOLDER_DESCRIPTION": "Make sure that the folder doesn't contain anything except PNG, JPG, JPEG & WEBP images.",
|
||||||
"SELECT_IMAGES_DESCRIPTION": "Select or drag and drop a PNG, JPG, JPEG or WEBP image.",
|
"SELECT_IMAGES_DESCRIPTION": "Select or drag and drop a PNG, JPG, JPEG or WEBP image.",
|
||||||
"PASTE_IMAGE_DESCRIPTION": "Hit Ctrl + V or Cmd + V to Paste image from Clipboard"
|
"PASTE_IMAGE_DESCRIPTION": "Hit Ctrl+V or ⌘+V to Paste image from Clipboard"
|
||||||
},
|
},
|
||||||
"PROGRESS": {
|
"PROGRESS": {
|
||||||
"PROCESSING_TITLE": "Processing the image...",
|
"PROCESSING_TITLE": "Processing the image...",
|
||||||
@ -254,6 +261,7 @@
|
|||||||
"NEXT_BUTTON_TITLE": "Next",
|
"NEXT_BUTTON_TITLE": "Next",
|
||||||
"BACK_BUTTON_TITLE": "Back",
|
"BACK_BUTTON_TITLE": "Back",
|
||||||
"GET_STARTED_BUTTON_TITLE": "Get Started",
|
"GET_STARTED_BUTTON_TITLE": "Get Started",
|
||||||
|
"SETTINGS_NOTE": "You can always change these settings later.",
|
||||||
"STEP_1": {
|
"STEP_1": {
|
||||||
"TITLE": "Welcome to Upscayl 🎉",
|
"TITLE": "Welcome to Upscayl 🎉",
|
||||||
"DESCRIPTION": "Let's get you started with a few quick steps."
|
"DESCRIPTION": "Let's get you started with a few quick steps."
|
||||||
|
@ -161,12 +161,19 @@
|
|||||||
"START_BUTTON_TITLE": "Upscayl 🚀",
|
"START_BUTTON_TITLE": "Upscayl 🚀",
|
||||||
"IN_PROGRESS_BUTTON_TITLE": "Aumentando ⏳"
|
"IN_PROGRESS_BUTTON_TITLE": "Aumentando ⏳"
|
||||||
},
|
},
|
||||||
"IMAGE_OPTIONS": {
|
"MORE_OPTIONS_DRAWER": {
|
||||||
"RESET_BUTTON_TITLE": "Restablecer imagen",
|
"RESET_BUTTON_TITLE": "Restablecer imagen",
|
||||||
"LENS_VIEW_TITLE": "Vista de lente",
|
"LENS_VIEW_TITLE": "Vista de lente",
|
||||||
"SLIDER_VIEW_TITLE": "Vista de deslizador",
|
"SLIDER_VIEW_TITLE": "Vista de deslizador",
|
||||||
"ZOOM_AMOUNT_TITLE": "Cantidad de zoom",
|
"ZOOM_AMOUNT_TITLE": "Cantidad de zoom",
|
||||||
"LENS_SIZE_TITLE": "Tamaño de lente"
|
"LENS_SIZE_TITLE": "Tamaño de lente",
|
||||||
|
"TOTAL_UPSCAYLS": "Total de aumentos",
|
||||||
|
"TOTAL_BATCH_UPSCAYLS": "Total de aumentos por lotes",
|
||||||
|
"TOTAL_IMAGE_UPSCAYLS": "Total de imágenes aumentadas",
|
||||||
|
"TOTAL_DOUBLE_UPSCAYLS": "Total de dobles aumentos",
|
||||||
|
"AVERAGE_UPSCAYL_TIME": "Tiempo promedio de aumento",
|
||||||
|
"LAST_UPSCAYL_DURATION": "Duración del último aumento",
|
||||||
|
"LAST_USED_AT": "Último uso"
|
||||||
},
|
},
|
||||||
"PROGRESS_BAR": {
|
"PROGRESS_BAR": {
|
||||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Aumento por lotes en progreso:",
|
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Aumento por lotes en progreso:",
|
||||||
@ -179,7 +186,7 @@
|
|||||||
"SELECT_IMAGE": "Selecciona una imagen",
|
"SELECT_IMAGE": "Selecciona una imagen",
|
||||||
"SELECT_FOLDER_DESCRIPTION": "Asegúrate de que la carpeta no contenga nada excepto imágenes PNG, JPG, JPEG y WEBP.",
|
"SELECT_FOLDER_DESCRIPTION": "Asegúrate de que la carpeta no contenga nada excepto imágenes PNG, JPG, JPEG y WEBP.",
|
||||||
"SELECT_IMAGES_DESCRIPTION": "Selecciona o arrastra y suelta una imagen PNG, JPG, JPEG o WEBP.",
|
"SELECT_IMAGES_DESCRIPTION": "Selecciona o arrastra y suelta una imagen PNG, JPG, JPEG o WEBP.",
|
||||||
"PASTE_IMAGE_DESCRIPTION": "Presiona Ctrl + V o Cmd + V para pegar la imagen desde el portapapeles"
|
"PASTE_IMAGE_DESCRIPTION": "Presiona Ctrl+V o ⌘+V para pegar la imagen desde el portapapeles"
|
||||||
},
|
},
|
||||||
"PROGRESS": {
|
"PROGRESS": {
|
||||||
"PROCESSING_TITLE": "Procesando la imagen...",
|
"PROCESSING_TITLE": "Procesando la imagen...",
|
||||||
@ -255,6 +262,7 @@
|
|||||||
"NEXT_BUTTON_TITLE": "Siguiente",
|
"NEXT_BUTTON_TITLE": "Siguiente",
|
||||||
"BACK_BUTTON_TITLE": "Atrás",
|
"BACK_BUTTON_TITLE": "Atrás",
|
||||||
"GET_STARTED_BUTTON_TITLE": "Comenzar",
|
"GET_STARTED_BUTTON_TITLE": "Comenzar",
|
||||||
|
"SETTINGS_NOTE": "Siempre puedes cambiar estos ajustes más tarde.",
|
||||||
"STEP_1": {
|
"STEP_1": {
|
||||||
"TITLE": "Bienvenido a Upscayl 🎉",
|
"TITLE": "Bienvenido a Upscayl 🎉",
|
||||||
"DESCRIPTION": "Vamos a empezar con unos pocos pasos rápidos."
|
"DESCRIPTION": "Vamos a empezar con unos pocos pasos rápidos."
|
||||||
|
@ -160,12 +160,19 @@
|
|||||||
"START_BUTTON_TITLE": "Suréchantillonner 🚀",
|
"START_BUTTON_TITLE": "Suréchantillonner 🚀",
|
||||||
"IN_PROGRESS_BUTTON_TITLE": "Suréchantillonnage ⏳"
|
"IN_PROGRESS_BUTTON_TITLE": "Suréchantillonnage ⏳"
|
||||||
},
|
},
|
||||||
"IMAGE_OPTIONS": {
|
"MORE_OPTIONS_DRAWER": {
|
||||||
"RESET_BUTTON_TITLE": "Réinitialiser l'image",
|
"RESET_BUTTON_TITLE": "Réinitialiser l'image",
|
||||||
"LENS_VIEW_TITLE": "Vue de la lentille",
|
"LENS_VIEW_TITLE": "Vue de la lentille",
|
||||||
"SLIDER_VIEW_TITLE": "Vue du curseur",
|
"SLIDER_VIEW_TITLE": "Vue du curseur",
|
||||||
"ZOOM_AMOUNT_TITLE": "Niveau de zoom",
|
"ZOOM_AMOUNT_TITLE": "Niveau de zoom",
|
||||||
"LENS_SIZE_TITLE": "Taille de la lentille"
|
"LENS_SIZE_TITLE": "Taille de la lentille",
|
||||||
|
"TOTAL_UPSCAYLS": "Total des suréchantillonnages",
|
||||||
|
"TOTAL_BATCH_UPSCAYLS": "Total des suréchantillonnages par lot",
|
||||||
|
"TOTAL_IMAGE_UPSCAYLS": "Total des suréchantillonnages d'images",
|
||||||
|
"TOTAL_DOUBLE_UPSCAYLS": "Total des doubles suréchantillonnages",
|
||||||
|
"AVERAGE_UPSCAYL_TIME": "Temps moyen de suréchantillonnage",
|
||||||
|
"LAST_UPSCAYL_DURATION": "Durée du dernier suréchantillonnage",
|
||||||
|
"LAST_USED_AT": "Dernière utilisation"
|
||||||
},
|
},
|
||||||
"PROGRESS_BAR": {
|
"PROGRESS_BAR": {
|
||||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Suréchantillonnage par lot en cours :",
|
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Suréchantillonnage par lot en cours :",
|
||||||
@ -178,7 +185,7 @@
|
|||||||
"SELECT_IMAGE": "Sélectionnez une image à suréchantillonner",
|
"SELECT_IMAGE": "Sélectionnez une image à suréchantillonner",
|
||||||
"SELECT_FOLDER_DESCRIPTION": "Assurez-vous que le dossier ne contient rien d'autre que des images PNG, JPG, JPEG et WEBP.",
|
"SELECT_FOLDER_DESCRIPTION": "Assurez-vous que le dossier ne contient rien d'autre que des images PNG, JPG, JPEG et WEBP.",
|
||||||
"SELECT_IMAGES_DESCRIPTION": "Sélectionnez ou glissez-déposez une image PNG, JPG, JPEG ou WEBP.",
|
"SELECT_IMAGES_DESCRIPTION": "Sélectionnez ou glissez-déposez une image PNG, JPG, JPEG ou WEBP.",
|
||||||
"PASTE_IMAGE_DESCRIPTION": "Appuyez sur Ctrl + V ou Cmd + V pour coller l'image depuis le presse-papiers"
|
"PASTE_IMAGE_DESCRIPTION": "Appuyez sur Ctrl+V ou ⌘+V pour coller l'image depuis le presse-papiers"
|
||||||
},
|
},
|
||||||
"PROGRESS": {
|
"PROGRESS": {
|
||||||
"PROCESSING_TITLE": "Traitement de l'image...",
|
"PROCESSING_TITLE": "Traitement de l'image...",
|
||||||
@ -254,6 +261,7 @@
|
|||||||
"NEXT_BUTTON_TITLE": "Suivant",
|
"NEXT_BUTTON_TITLE": "Suivant",
|
||||||
"BACK_BUTTON_TITLE": "Retour",
|
"BACK_BUTTON_TITLE": "Retour",
|
||||||
"GET_STARTED_BUTTON_TITLE": "Commencer",
|
"GET_STARTED_BUTTON_TITLE": "Commencer",
|
||||||
|
"SETTINGS_NOTE": "Vous pouvez toujours modifier ces paramètres plus tard.",
|
||||||
"STEP_1": {
|
"STEP_1": {
|
||||||
"TITLE": "Bienvenue sur Upscayl 🎉",
|
"TITLE": "Bienvenue sur Upscayl 🎉",
|
||||||
"DESCRIPTION": "Commençons par quelques étapes rapides."
|
"DESCRIPTION": "Commençons par quelques étapes rapides."
|
||||||
|
@ -160,12 +160,19 @@
|
|||||||
"START_BUTTON_TITLE": "Upscayl 🚀",
|
"START_BUTTON_TITLE": "Upscayl 🚀",
|
||||||
"IN_PROGRESS_BUTTON_TITLE": "Upscayl中 ⏳"
|
"IN_PROGRESS_BUTTON_TITLE": "Upscayl中 ⏳"
|
||||||
},
|
},
|
||||||
"IMAGE_OPTIONS": {
|
"MORE_OPTIONS_DRAWER": {
|
||||||
"RESET_BUTTON_TITLE": "画像をリセット",
|
"RESET_BUTTON_TITLE": "画像をリセット",
|
||||||
"LENS_VIEW_TITLE": "レンズビュー",
|
"LENS_VIEW_TITLE": "レンズビュー",
|
||||||
"SLIDER_VIEW_TITLE": "スライダービュー",
|
"SLIDER_VIEW_TITLE": "スライダービュー",
|
||||||
"ZOOM_AMOUNT_TITLE": "ズーム量",
|
"ZOOM_AMOUNT_TITLE": "ズーム量",
|
||||||
"LENS_SIZE_TITLE": "レンズサイズ"
|
"LENS_SIZE_TITLE": "レンズサイズ",
|
||||||
|
"TOTAL_UPSCAYLS": "総アップスケール数",
|
||||||
|
"TOTAL_BATCH_UPSCAYLS": "総バッチアップスケール数",
|
||||||
|
"TOTAL_IMAGE_UPSCAYLS": "総画像アップスケール数",
|
||||||
|
"TOTAL_DOUBLE_UPSCAYLS": "総ダブルアップスケール数",
|
||||||
|
"AVERAGE_UPSCAYL_TIME": "平均アップスケール時間",
|
||||||
|
"LAST_UPSCAYL_DURATION": "最後のアップスケール時間",
|
||||||
|
"LAST_USED_AT": "最終使用日時"
|
||||||
},
|
},
|
||||||
"PROGRESS_BAR": {
|
"PROGRESS_BAR": {
|
||||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "バッチUpscayl進行中:",
|
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "バッチUpscayl進行中:",
|
||||||
@ -178,7 +185,7 @@
|
|||||||
"SELECT_IMAGE": "Upscaylする画像を選択",
|
"SELECT_IMAGE": "Upscaylする画像を選択",
|
||||||
"SELECT_FOLDER_DESCRIPTION": "フォルダにはPNG、JPG、JPEG、WEBPの画像以外のものが含まれていないことを確認してください。",
|
"SELECT_FOLDER_DESCRIPTION": "フォルダにはPNG、JPG、JPEG、WEBPの画像以外のものが含まれていないことを確認してください。",
|
||||||
"SELECT_IMAGES_DESCRIPTION": "PNG、JPG、JPEG、またはWEBP画像を選択するか、ドラッグアンドドロップしてください。",
|
"SELECT_IMAGES_DESCRIPTION": "PNG、JPG、JPEG、またはWEBP画像を選択するか、ドラッグアンドドロップしてください。",
|
||||||
"PASTE_IMAGE_DESCRIPTION": "Ctrl + V または Cmd + V を押してクリップボードから画像を貼り付けます"
|
"PASTE_IMAGE_DESCRIPTION": "Ctrl+V または ⌘+V を押してクリップボードから画像を貼り付けます"
|
||||||
},
|
},
|
||||||
"PROGRESS": {
|
"PROGRESS": {
|
||||||
"PROCESSING_TITLE": "画像を処理中...",
|
"PROCESSING_TITLE": "画像を処理中...",
|
||||||
@ -254,6 +261,7 @@
|
|||||||
"NEXT_BUTTON_TITLE": "次へ",
|
"NEXT_BUTTON_TITLE": "次へ",
|
||||||
"BACK_BUTTON_TITLE": "戻る",
|
"BACK_BUTTON_TITLE": "戻る",
|
||||||
"GET_STARTED_BUTTON_TITLE": "始める",
|
"GET_STARTED_BUTTON_TITLE": "始める",
|
||||||
|
"SETTINGS_NOTE": "これらの設定は後でいつでも変更できます。",
|
||||||
"STEP_1": {
|
"STEP_1": {
|
||||||
"TITLE": "Upscaylへようこそ 🎉",
|
"TITLE": "Upscaylへようこそ 🎉",
|
||||||
"DESCRIPTION": "いくつかの簡単なステップで始めましょう。"
|
"DESCRIPTION": "いくつかの簡単なステップで始めましょう。"
|
||||||
|
@ -160,12 +160,19 @@
|
|||||||
"START_BUTTON_TITLE": "Увеличить 🚀",
|
"START_BUTTON_TITLE": "Увеличить 🚀",
|
||||||
"IN_PROGRESS_BUTTON_TITLE": "Увеличение ⏳"
|
"IN_PROGRESS_BUTTON_TITLE": "Увеличение ⏳"
|
||||||
},
|
},
|
||||||
"IMAGE_OPTIONS": {
|
"MORE_OPTIONS_DRAWER": {
|
||||||
"RESET_BUTTON_TITLE": "Сбросить изображение",
|
"RESET_BUTTON_TITLE": "Сбросить изображение",
|
||||||
"LENS_VIEW_TITLE": "Просмотр через линзу",
|
"LENS_VIEW_TITLE": "Просмотр через линзу",
|
||||||
"SLIDER_VIEW_TITLE": "Просмотр с ползунком",
|
"SLIDER_VIEW_TITLE": "Просмотр с ползунком",
|
||||||
"ZOOM_AMOUNT_TITLE": "Увеличение",
|
"ZOOM_AMOUNT_TITLE": "Увеличение",
|
||||||
"LENS_SIZE_TITLE": "Размер линзы"
|
"LENS_SIZE_TITLE": "Размер линзы",
|
||||||
|
"TOTAL_UPSCAYLS": "Всего увеличений",
|
||||||
|
"TOTAL_BATCH_UPSCAYLS": "Всего пакетных увеличений",
|
||||||
|
"TOTAL_IMAGE_UPSCAYLS": "Всего увеличений изображений",
|
||||||
|
"TOTAL_DOUBLE_UPSCAYLS": "Всего двойных увеличений",
|
||||||
|
"AVERAGE_UPSCAYL_TIME": "Среднее время увеличения",
|
||||||
|
"LAST_UPSCAYL_DURATION": "Длительность последнего увеличения",
|
||||||
|
"LAST_USED_AT": "Последнее использование"
|
||||||
},
|
},
|
||||||
"PROGRESS_BAR": {
|
"PROGRESS_BAR": {
|
||||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Пакетное увеличение в процессе:",
|
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Пакетное увеличение в процессе:",
|
||||||
@ -178,7 +185,7 @@
|
|||||||
"SELECT_IMAGE": "Выберите изображение для увеличения",
|
"SELECT_IMAGE": "Выберите изображение для увеличения",
|
||||||
"SELECT_FOLDER_DESCRIPTION": "Убедитесь, что в папке нет ничего, кроме изображений PNG, JPG, JPEG и WEBP.",
|
"SELECT_FOLDER_DESCRIPTION": "Убедитесь, что в папке нет ничего, кроме изображений PNG, JPG, JPEG и WEBP.",
|
||||||
"SELECT_IMAGES_DESCRIPTION": "Выберите или перетащите изображение в формате PNG, JPG, JPEG или WEBP.",
|
"SELECT_IMAGES_DESCRIPTION": "Выберите или перетащите изображение в формате PNG, JPG, JPEG или WEBP.",
|
||||||
"PASTE_IMAGE_DESCRIPTION": "Нажмите Ctrl + V или Cmd + V, чтобы вставить изображение из буфера обмена"
|
"PASTE_IMAGE_DESCRIPTION": "Нажмите Ctrl+V или ⌘+V, чтобы вставить изображение из буфера обмена"
|
||||||
},
|
},
|
||||||
"PROGRESS": {
|
"PROGRESS": {
|
||||||
"PROCESSING_TITLE": "Обработка изображения...",
|
"PROCESSING_TITLE": "Обработка изображения...",
|
||||||
@ -254,6 +261,7 @@
|
|||||||
"NEXT_BUTTON_TITLE": "Далее",
|
"NEXT_BUTTON_TITLE": "Далее",
|
||||||
"BACK_BUTTON_TITLE": "Назад",
|
"BACK_BUTTON_TITLE": "Назад",
|
||||||
"GET_STARTED_BUTTON_TITLE": "Начать",
|
"GET_STARTED_BUTTON_TITLE": "Начать",
|
||||||
|
"SETTINGS_NOTE": "Вы всегда можете изменить эти настройки позже.",
|
||||||
"STEP_1": {
|
"STEP_1": {
|
||||||
"TITLE": "Добро пожаловать в Upscayl 🎉",
|
"TITLE": "Добро пожаловать в Upscayl 🎉",
|
||||||
"DESCRIPTION": "Давайте начнем с нескольких быстрых шагов."
|
"DESCRIPTION": "Давайте начнем с нескольких быстрых шагов."
|
||||||
|
@ -160,12 +160,19 @@
|
|||||||
"START_BUTTON_TITLE": "升图!🚀",
|
"START_BUTTON_TITLE": "升图!🚀",
|
||||||
"IN_PROGRESS_BUTTON_TITLE": "正在升图 ⏳"
|
"IN_PROGRESS_BUTTON_TITLE": "正在升图 ⏳"
|
||||||
},
|
},
|
||||||
"IMAGE_OPTIONS": {
|
"MORE_OPTIONS_DRAWER": {
|
||||||
"RESET_BUTTON_TITLE": "重置图片",
|
"RESET_BUTTON_TITLE": "重置图片",
|
||||||
"LENS_VIEW_TITLE": "透镜视图",
|
"LENS_VIEW_TITLE": "透镜视图",
|
||||||
"SLIDER_VIEW_TITLE": "滑块视图",
|
"SLIDER_VIEW_TITLE": "滑块视图",
|
||||||
"ZOOM_AMOUNT_TITLE": "缩放比例",
|
"ZOOM_AMOUNT_TITLE": "缩放比例",
|
||||||
"LENS_SIZE_TITLE": "透镜尺寸"
|
"LENS_SIZE_TITLE": "透镜尺寸",
|
||||||
|
"TOTAL_UPSCAYLS": "总升图次数",
|
||||||
|
"TOTAL_BATCH_UPSCAYLS": "总批量升图次数",
|
||||||
|
"TOTAL_IMAGE_UPSCAYLS": "总图片升图次数",
|
||||||
|
"TOTAL_DOUBLE_UPSCAYLS": "总双重升图次数",
|
||||||
|
"AVERAGE_UPSCAYL_TIME": "平均升图时间",
|
||||||
|
"LAST_UPSCAYL_DURATION": "上次升图时长",
|
||||||
|
"LAST_USED_AT": "上次使用时间"
|
||||||
},
|
},
|
||||||
"PROGRESS_BAR": {
|
"PROGRESS_BAR": {
|
||||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "批量阿普升图中",
|
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "批量阿普升图中",
|
||||||
@ -178,7 +185,7 @@
|
|||||||
"SELECT_IMAGE": "选择要增强的图片",
|
"SELECT_IMAGE": "选择要增强的图片",
|
||||||
"SELECT_FOLDER_DESCRIPTION": "文件夹中只支持 PNG、JPG、JPEG 和 WEBP 图片。",
|
"SELECT_FOLDER_DESCRIPTION": "文件夹中只支持 PNG、JPG、JPEG 和 WEBP 图片。",
|
||||||
"SELECT_IMAGES_DESCRIPTION": "选择或拖放 PNG、JPG、JPEG 或 WEBP 图片。",
|
"SELECT_IMAGES_DESCRIPTION": "选择或拖放 PNG、JPG、JPEG 或 WEBP 图片。",
|
||||||
"PASTE_IMAGE_DESCRIPTION": "按 Ctrl + V 或 Cmd + V 来粘贴图像"
|
"PASTE_IMAGE_DESCRIPTION": "按 Ctrl+V 或 ⌘+V 来粘贴图像"
|
||||||
},
|
},
|
||||||
"PROGRESS": {
|
"PROGRESS": {
|
||||||
"PROCESSING_TITLE": "正在处理图片...",
|
"PROCESSING_TITLE": "正在处理图片...",
|
||||||
@ -254,6 +261,7 @@
|
|||||||
"NEXT_BUTTON_TITLE": "下一步",
|
"NEXT_BUTTON_TITLE": "下一步",
|
||||||
"BACK_BUTTON_TITLE": "上一步",
|
"BACK_BUTTON_TITLE": "上一步",
|
||||||
"GET_STARTED_BUTTON_TITLE": "开始使用",
|
"GET_STARTED_BUTTON_TITLE": "开始使用",
|
||||||
|
"SETTINGS_NOTE": "你可以随时更改这些设置。",
|
||||||
"STEP_1": {
|
"STEP_1": {
|
||||||
"TITLE": "欢迎使用阿普升图 🎉",
|
"TITLE": "欢迎使用阿普升图 🎉",
|
||||||
"DESCRIPTION": "让我们通过几个快速步骤来开始吧。"
|
"DESCRIPTION": "让我们通过几个快速步骤来开始吧。"
|
||||||
|
@ -4,22 +4,10 @@ import { AppProps } from "next/app";
|
|||||||
import { Provider } from "jotai";
|
import { Provider } from "jotai";
|
||||||
import "react-tooltip/dist/react-tooltip.css";
|
import "react-tooltip/dist/react-tooltip.css";
|
||||||
import { Toaster } from "@/components/ui/toaster";
|
import { Toaster } from "@/components/ui/toaster";
|
||||||
import posthog from "posthog-js";
|
import { Tooltip } from "react-tooltip";
|
||||||
import { useEffect } from "react";
|
import PostHogProviderWrapper from "@/components/posthog-provider-wrapper";
|
||||||
import { PostHogProvider } from "posthog-js/react";
|
|
||||||
|
|
||||||
const MyApp = ({ Component, pageProps }: AppProps) => {
|
const MyApp = ({ Component, pageProps }: AppProps) => {
|
||||||
useEffect(() => {
|
|
||||||
posthog.init("phc_QMcmlmComdofjfaRPzoN4KV9ziV2KgOwAOVyu4J3dIc", {
|
|
||||||
api_host: "https://us.i.posthog.com",
|
|
||||||
person_profiles: "identified_only",
|
|
||||||
// Enable debug mode in development
|
|
||||||
loaded: (posthog) => {
|
|
||||||
if (process.env.NODE_ENV === "development") posthog.debug();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
@ -27,10 +15,14 @@ const MyApp = ({ Component, pageProps }: AppProps) => {
|
|||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<Provider>
|
<Provider>
|
||||||
<PostHogProvider client={posthog}>
|
<PostHogProviderWrapper>
|
||||||
<Component {...pageProps} data-theme="upscayl" />
|
<Component {...pageProps} data-theme="upscayl" />
|
||||||
<Toaster />
|
<Toaster />
|
||||||
</PostHogProvider>
|
<Tooltip
|
||||||
|
className="z-[999] max-w-sm break-words !bg-secondary"
|
||||||
|
id="tooltip"
|
||||||
|
/>
|
||||||
|
</PostHogProviderWrapper>
|
||||||
</Provider>
|
</Provider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
savedOutputPathAtom,
|
savedOutputPathAtom,
|
||||||
progressAtom,
|
progressAtom,
|
||||||
rememberOutputFolderAtom,
|
rememberOutputFolderAtom,
|
||||||
|
userStatsAtom,
|
||||||
} from "../atoms/user-settings-atom";
|
} from "../atoms/user-settings-atom";
|
||||||
import useLogger from "../components/hooks/use-logger";
|
import useLogger from "../components/hooks/use-logger";
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
@ -44,6 +45,7 @@ const Home = () => {
|
|||||||
const setProgress = useSetAtom(progressAtom);
|
const setProgress = useSetAtom(progressAtom);
|
||||||
const [doubleUpscaylCounter, setDoubleUpscaylCounter] = useState(0);
|
const [doubleUpscaylCounter, setDoubleUpscaylCounter] = useState(0);
|
||||||
const setModelIds = useSetAtom(customModelIdsAtom);
|
const setModelIds = useSetAtom(customModelIdsAtom);
|
||||||
|
const setUserStats = useSetAtom(userStatsAtom);
|
||||||
|
|
||||||
const selectImageHandler = async () => {
|
const selectImageHandler = async () => {
|
||||||
resetImagePaths();
|
resetImagePaths();
|
||||||
@ -226,6 +228,14 @@ const Home = () => {
|
|||||||
window.electron.on(ELECTRON_COMMANDS.UPSCAYL_DONE, (_, data: string) => {
|
window.electron.on(ELECTRON_COMMANDS.UPSCAYL_DONE, (_, data: string) => {
|
||||||
setProgress("");
|
setProgress("");
|
||||||
setUpscaledImagePath(data);
|
setUpscaledImagePath(data);
|
||||||
|
setUserStats((prev) => ({
|
||||||
|
...prev,
|
||||||
|
lastUpscaylDuration: new Date().getTime() - prev.lastUsedAt,
|
||||||
|
averageUpscaylTime:
|
||||||
|
(prev.averageUpscaylTime * prev.totalUpscayls +
|
||||||
|
(new Date().getTime() - prev.lastUsedAt)) /
|
||||||
|
(prev.totalUpscayls + 1),
|
||||||
|
}));
|
||||||
logit("upscaledImagePath: ", data);
|
logit("upscaledImagePath: ", data);
|
||||||
logit(`💯 UPSCAYL_DONE: `, data);
|
logit(`💯 UPSCAYL_DONE: `, data);
|
||||||
});
|
});
|
||||||
@ -236,6 +246,14 @@ const Home = () => {
|
|||||||
setProgress("");
|
setProgress("");
|
||||||
setUpscaledBatchFolderPath(data);
|
setUpscaledBatchFolderPath(data);
|
||||||
logit(`💯 FOLDER_UPSCAYL_DONE: `, data);
|
logit(`💯 FOLDER_UPSCAYL_DONE: `, data);
|
||||||
|
setUserStats((prev) => ({
|
||||||
|
...prev,
|
||||||
|
lastUpscaylDuration: new Date().getTime() - prev.lastUsedAt,
|
||||||
|
averageUpscaylTime:
|
||||||
|
(prev.averageUpscaylTime * prev.totalUpscayls +
|
||||||
|
(new Date().getTime() - prev.lastUsedAt)) /
|
||||||
|
(prev.totalUpscayls + 1),
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// DOUBLE UPSCAYL DONE
|
// DOUBLE UPSCAYL DONE
|
||||||
@ -246,6 +264,14 @@ const Home = () => {
|
|||||||
setTimeout(() => setUpscaledImagePath(data), 500);
|
setTimeout(() => setUpscaledImagePath(data), 500);
|
||||||
setDoubleUpscaylCounter(0);
|
setDoubleUpscaylCounter(0);
|
||||||
logit(`💯 DOUBLE_UPSCAYL_DONE: `, data);
|
logit(`💯 DOUBLE_UPSCAYL_DONE: `, data);
|
||||||
|
setUserStats((prev) => ({
|
||||||
|
...prev,
|
||||||
|
lastUpscaylDuration: new Date().getTime() - prev.lastUsedAt,
|
||||||
|
averageUpscaylTime:
|
||||||
|
(prev.averageUpscaylTime * prev.totalUpscayls +
|
||||||
|
(new Date().getTime() - prev.lastUsedAt)) /
|
||||||
|
(prev.totalUpscayls + 1),
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// CUSTOM FOLDER LISTENER
|
// CUSTOM FOLDER LISTENER
|
||||||
|
12
renderer/renderer.d.ts
vendored
12
renderer/renderer.d.ts
vendored
@ -6,6 +6,18 @@ export interface IElectronAPI {
|
|||||||
send: <T>(command, func?: T) => IpcRenderer;
|
send: <T>(command, func?: T) => IpcRenderer;
|
||||||
invoke: (command, func?) => any;
|
invoke: (command, func?) => any;
|
||||||
platform: "mac" | "win" | "linux";
|
platform: "mac" | "win" | "linux";
|
||||||
|
getSystemInfo: () => Promise<{
|
||||||
|
platform: string | undefined;
|
||||||
|
release: string;
|
||||||
|
arch: string | undefined;
|
||||||
|
model: string;
|
||||||
|
cpuCount: number;
|
||||||
|
gpu: {
|
||||||
|
vendor: any;
|
||||||
|
model: any;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
getAppVersion: () => Promise<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user