mirror of
https://github.com/upscayl/upscayl.git
synced 2025-02-12 09:03:00 +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.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) {
|
||||
autoUpdater.on("update-downloaded", autoUpdate);
|
||||
}
|
||||
|
@ -1,5 +1,10 @@
|
||||
import { ipcRenderer, contextBridge } from "electron";
|
||||
import { getPlatform } from "./utils/get-device-specs";
|
||||
import { ipcRenderer, contextBridge, app } from "electron";
|
||||
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'
|
||||
contextBridge.exposeInMainWorld("electron", {
|
||||
@ -11,4 +16,6 @@ contextBridge.exposeInMainWorld("electron", {
|
||||
invoke: (command: string, payload: any) =>
|
||||
ipcRenderer.invoke(command, payload),
|
||||
platform: getPlatform(),
|
||||
getSystemInfo: async () => await getDeviceSpecs(),
|
||||
getAppVersion: async () => await getAppVersion(),
|
||||
});
|
||||
|
@ -1,9 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
import { platform, arch } from "os";
|
||||
import { ipcRenderer } from "electron";
|
||||
import os from "os";
|
||||
|
||||
export const getPlatform = () => {
|
||||
switch (platform()) {
|
||||
switch (os.platform()) {
|
||||
case "aix":
|
||||
case "freebsd":
|
||||
case "linux":
|
||||
@ -19,7 +20,7 @@ export const getPlatform = () => {
|
||||
};
|
||||
|
||||
export const getArch = () => {
|
||||
switch (arch()) {
|
||||
switch (os.arch()) {
|
||||
case "x64":
|
||||
return "x64";
|
||||
case "x32":
|
||||
@ -30,3 +31,33 @@ export const getArch = () => {
|
||||
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",
|
||||
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 ProgressBar from "./progress-bar";
|
||||
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 MacTitlebarDragRegion from "./mac-titlebar-drag-region";
|
||||
import LensViewer from "./lens-view";
|
||||
@ -292,7 +292,7 @@ const MainContent = ({
|
||||
<InstructionsCard version={version} batchMode={batchMode} />
|
||||
)}
|
||||
|
||||
<ImageViewSettings
|
||||
<MoreOptionsDrawer
|
||||
zoomAmount={zoomAmount}
|
||||
setZoomAmount={setZoomAmount}
|
||||
resetImagePaths={resetImagePaths}
|
||||
|
@ -106,6 +106,7 @@ const LensViewer = ({
|
||||
className="relative h-full w-full cursor-crosshair"
|
||||
ref={originalImageContainerRef}
|
||||
>
|
||||
ORIGINAL IMAGE
|
||||
<img
|
||||
src={originalImage}
|
||||
alt="Original"
|
||||
@ -113,12 +114,15 @@ const LensViewer = ({
|
||||
onMouseMove={handleMouseMove}
|
||||
ref={originalImageRef}
|
||||
/>
|
||||
{/* Lens */}
|
||||
<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={{
|
||||
left: `${hoverPosition.relativeMouseX}px`,
|
||||
top: `${hoverPosition.mouseY}px`,
|
||||
transform: "translate(-50%, -50%)",
|
||||
height: `48px`,
|
||||
width: `48px`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -132,6 +136,7 @@ const LensViewer = ({
|
||||
transform: "translate(-50%, 0)",
|
||||
}}
|
||||
>
|
||||
{/* ORIGINAL IMAGE */}
|
||||
<div
|
||||
className="relative h-48 w-48 border border-gray-300 bg-cover bg-no-repeat"
|
||||
style={{
|
||||
@ -144,6 +149,7 @@ const LensViewer = ({
|
||||
Original
|
||||
</span>
|
||||
</div>
|
||||
{/* UPSCALED IMAGE */}
|
||||
<div
|
||||
className="relative h-48 w-48 border border-gray-300 bg-cover bg-no-repeat"
|
||||
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",
|
||||
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(
|
||||
"flex h-full w-full flex-col rounded-sm bg-primary p-8",
|
||||
currentStepData.type === "settings" && "h-auto w-auto gap-8",
|
||||
currentStepData.configurationOptions[0].type === "video" && "p-0",
|
||||
)}
|
||||
>
|
||||
{currentStepData.configurationOptions.map((option) => (
|
||||
<div
|
||||
key={option.key}
|
||||
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 && (
|
||||
<label
|
||||
@ -190,7 +198,7 @@ export function OnboardingDialog() {
|
||||
)}
|
||||
{option.type === "video" && (
|
||||
<iframe
|
||||
className="h-full w-full"
|
||||
className="h-full w-full rounded-sm"
|
||||
src={option.videoSrc}
|
||||
title="YouTube video player"
|
||||
frameBorder="0"
|
||||
@ -202,6 +210,11 @@ export function OnboardingDialog() {
|
||||
{option.type === "component" && option.component}
|
||||
</div>
|
||||
))}
|
||||
{currentStepData.type === "settings" && (
|
||||
<p className="text-sm text-base-content/70">
|
||||
{t("ONBOARDING_DIALOG.SETTINGS_NOTE")}
|
||||
</p>
|
||||
)}
|
||||
</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,
|
||||
gpuIdAtom,
|
||||
saveImageAsAtom,
|
||||
userStatsAtom,
|
||||
} from "../../atoms/user-settings-atom";
|
||||
import useLogger from "../hooks/use-logger";
|
||||
import {
|
||||
@ -89,6 +90,7 @@ const Sidebar = ({
|
||||
const useCustomWidth = useAtomValue(useCustomWidthAtom);
|
||||
const tileSize = useAtomValue(tileSizeAtom);
|
||||
const [showSidebar, setShowSidebar] = useAtom(showSidebarAtom);
|
||||
const setUserStats = useSetAtom(userStatsAtom);
|
||||
|
||||
const upscaylHandler = async () => {
|
||||
logit("🔄 Resetting Upscaled Image Path");
|
||||
@ -114,6 +116,13 @@ const Sidebar = ({
|
||||
tileSize,
|
||||
},
|
||||
);
|
||||
setUserStats((prev) => ({
|
||||
...prev,
|
||||
totalUpscayls: prev.totalUpscayls + 1,
|
||||
lastUsedAt: new Date().getTime(),
|
||||
doubleUpscayls: prev.doubleUpscayls + 1,
|
||||
imageUpscayls: prev.imageUpscayls + 1,
|
||||
}));
|
||||
logit("🏁 DOUBLE_UPSCAYL");
|
||||
} else if (batchMode) {
|
||||
// Batch Upscayl
|
||||
@ -134,6 +143,12 @@ const Sidebar = ({
|
||||
tileSize,
|
||||
},
|
||||
);
|
||||
setUserStats((prev) => ({
|
||||
...prev,
|
||||
totalUpscayls: prev.totalUpscayls + 1,
|
||||
lastUsedAt: new Date().getTime(),
|
||||
batchUpscayls: prev.doubleUpscayls + 1,
|
||||
}));
|
||||
logit("🏁 FOLDER_UPSCAYL");
|
||||
} else {
|
||||
// Single Image Upscayl
|
||||
@ -151,6 +166,12 @@ const Sidebar = ({
|
||||
useCustomWidth,
|
||||
tileSize,
|
||||
});
|
||||
setUserStats((prev) => ({
|
||||
...prev,
|
||||
totalUpscayls: prev.totalUpscayls + 1,
|
||||
lastUsedAt: new Date().getTime(),
|
||||
imageUpscayls: prev.imageUpscayls + 1,
|
||||
}));
|
||||
logit("🏁 UPSCAYL");
|
||||
}
|
||||
} else {
|
||||
|
@ -16,6 +16,7 @@ import { useAtom, useAtomValue } from "jotai";
|
||||
import { selectedModelIdAtom } from "@/atoms/user-settings-atom";
|
||||
import { customModelIdsAtom } from "@/atoms/models-list-atom";
|
||||
import useTranslation from "@/components/hooks/use-translation";
|
||||
import posthog from "posthog-js";
|
||||
|
||||
const SelectModelDialog = () => {
|
||||
const t = useTranslation();
|
||||
@ -28,6 +29,12 @@ const SelectModelDialog = () => {
|
||||
const handleModelSelect = (model: ModelId | string) => {
|
||||
setSelectedModelId(model);
|
||||
setOpen(false);
|
||||
|
||||
posthog.capture("model_selected", {
|
||||
$ip: "0.0.0.0",
|
||||
$geoip_disable: true,
|
||||
model,
|
||||
});
|
||||
};
|
||||
|
||||
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"
|
||||
onClick={() => handleModelSelect(modelId)}
|
||||
>
|
||||
<div className="font-semibold">
|
||||
<p className="font-semibold">
|
||||
{t(`APP.MODEL_SELECTION.MODELS.${modelId}.NAME`)}
|
||||
</div>
|
||||
<div className="mb-2 text-left font-normal leading-normal text-opacity-50">
|
||||
</p>
|
||||
<p className="mb-2 text-left font-normal leading-normal text-base-content/70">
|
||||
{t(`APP.MODEL_SELECTION.MODELS.${modelId}.DESCRIPTION`)}
|
||||
</div>
|
||||
</p>
|
||||
<div className="relative h-52 w-full overflow-hidden rounded-sm">
|
||||
<div className="flex h-full w-full">
|
||||
<img
|
||||
|
@ -270,11 +270,6 @@ function UpscaylSteps({
|
||||
: t("APP.SCALE_SELECTION.START_BUTTON_TITLE")}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Tooltip
|
||||
className="z-[999] max-w-sm break-words !bg-secondary"
|
||||
id="tooltip"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -160,12 +160,19 @@
|
||||
"START_BUTTON_TITLE": "Upscayl 🚀",
|
||||
"IN_PROGRESS_BUTTON_TITLE": "Upscayling ⏳"
|
||||
},
|
||||
"IMAGE_OPTIONS": {
|
||||
"MORE_OPTIONS_DRAWER": {
|
||||
"RESET_BUTTON_TITLE": "Reset Image",
|
||||
"LENS_VIEW_TITLE": "Lens View",
|
||||
"SLIDER_VIEW_TITLE": "Slider View",
|
||||
"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": {
|
||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Batch Upscayl In Progress:",
|
||||
@ -178,7 +185,7 @@
|
||||
"SELECT_IMAGE": "Select an Image",
|
||||
"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.",
|
||||
"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": {
|
||||
"PROCESSING_TITLE": "Processing the image...",
|
||||
@ -254,6 +261,7 @@
|
||||
"NEXT_BUTTON_TITLE": "Next",
|
||||
"BACK_BUTTON_TITLE": "Back",
|
||||
"GET_STARTED_BUTTON_TITLE": "Get Started",
|
||||
"SETTINGS_NOTE": "You can always change these settings later.",
|
||||
"STEP_1": {
|
||||
"TITLE": "Welcome to Upscayl 🎉",
|
||||
"DESCRIPTION": "Let's get you started with a few quick steps."
|
||||
|
@ -161,12 +161,19 @@
|
||||
"START_BUTTON_TITLE": "Upscayl 🚀",
|
||||
"IN_PROGRESS_BUTTON_TITLE": "Aumentando ⏳"
|
||||
},
|
||||
"IMAGE_OPTIONS": {
|
||||
"MORE_OPTIONS_DRAWER": {
|
||||
"RESET_BUTTON_TITLE": "Restablecer imagen",
|
||||
"LENS_VIEW_TITLE": "Vista de lente",
|
||||
"SLIDER_VIEW_TITLE": "Vista de deslizador",
|
||||
"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": {
|
||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Aumento por lotes en progreso:",
|
||||
@ -179,7 +186,7 @@
|
||||
"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_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": {
|
||||
"PROCESSING_TITLE": "Procesando la imagen...",
|
||||
@ -255,6 +262,7 @@
|
||||
"NEXT_BUTTON_TITLE": "Siguiente",
|
||||
"BACK_BUTTON_TITLE": "Atrás",
|
||||
"GET_STARTED_BUTTON_TITLE": "Comenzar",
|
||||
"SETTINGS_NOTE": "Siempre puedes cambiar estos ajustes más tarde.",
|
||||
"STEP_1": {
|
||||
"TITLE": "Bienvenido a Upscayl 🎉",
|
||||
"DESCRIPTION": "Vamos a empezar con unos pocos pasos rápidos."
|
||||
|
@ -160,12 +160,19 @@
|
||||
"START_BUTTON_TITLE": "Suréchantillonner 🚀",
|
||||
"IN_PROGRESS_BUTTON_TITLE": "Suréchantillonnage ⏳"
|
||||
},
|
||||
"IMAGE_OPTIONS": {
|
||||
"MORE_OPTIONS_DRAWER": {
|
||||
"RESET_BUTTON_TITLE": "Réinitialiser l'image",
|
||||
"LENS_VIEW_TITLE": "Vue de la lentille",
|
||||
"SLIDER_VIEW_TITLE": "Vue du curseur",
|
||||
"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": {
|
||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Suréchantillonnage par lot en cours :",
|
||||
@ -178,7 +185,7 @@
|
||||
"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_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": {
|
||||
"PROCESSING_TITLE": "Traitement de l'image...",
|
||||
@ -254,6 +261,7 @@
|
||||
"NEXT_BUTTON_TITLE": "Suivant",
|
||||
"BACK_BUTTON_TITLE": "Retour",
|
||||
"GET_STARTED_BUTTON_TITLE": "Commencer",
|
||||
"SETTINGS_NOTE": "Vous pouvez toujours modifier ces paramètres plus tard.",
|
||||
"STEP_1": {
|
||||
"TITLE": "Bienvenue sur Upscayl 🎉",
|
||||
"DESCRIPTION": "Commençons par quelques étapes rapides."
|
||||
|
@ -160,12 +160,19 @@
|
||||
"START_BUTTON_TITLE": "Upscayl 🚀",
|
||||
"IN_PROGRESS_BUTTON_TITLE": "Upscayl中 ⏳"
|
||||
},
|
||||
"IMAGE_OPTIONS": {
|
||||
"MORE_OPTIONS_DRAWER": {
|
||||
"RESET_BUTTON_TITLE": "画像をリセット",
|
||||
"LENS_VIEW_TITLE": "レンズビュー",
|
||||
"SLIDER_VIEW_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": {
|
||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "バッチUpscayl進行中:",
|
||||
@ -178,7 +185,7 @@
|
||||
"SELECT_IMAGE": "Upscaylする画像を選択",
|
||||
"SELECT_FOLDER_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": {
|
||||
"PROCESSING_TITLE": "画像を処理中...",
|
||||
@ -254,6 +261,7 @@
|
||||
"NEXT_BUTTON_TITLE": "次へ",
|
||||
"BACK_BUTTON_TITLE": "戻る",
|
||||
"GET_STARTED_BUTTON_TITLE": "始める",
|
||||
"SETTINGS_NOTE": "これらの設定は後でいつでも変更できます。",
|
||||
"STEP_1": {
|
||||
"TITLE": "Upscaylへようこそ 🎉",
|
||||
"DESCRIPTION": "いくつかの簡単なステップで始めましょう。"
|
||||
|
@ -160,12 +160,19 @@
|
||||
"START_BUTTON_TITLE": "Увеличить 🚀",
|
||||
"IN_PROGRESS_BUTTON_TITLE": "Увеличение ⏳"
|
||||
},
|
||||
"IMAGE_OPTIONS": {
|
||||
"MORE_OPTIONS_DRAWER": {
|
||||
"RESET_BUTTON_TITLE": "Сбросить изображение",
|
||||
"LENS_VIEW_TITLE": "Просмотр через линзу",
|
||||
"SLIDER_VIEW_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": {
|
||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "Пакетное увеличение в процессе:",
|
||||
@ -178,7 +185,7 @@
|
||||
"SELECT_IMAGE": "Выберите изображение для увеличения",
|
||||
"SELECT_FOLDER_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": {
|
||||
"PROCESSING_TITLE": "Обработка изображения...",
|
||||
@ -254,6 +261,7 @@
|
||||
"NEXT_BUTTON_TITLE": "Далее",
|
||||
"BACK_BUTTON_TITLE": "Назад",
|
||||
"GET_STARTED_BUTTON_TITLE": "Начать",
|
||||
"SETTINGS_NOTE": "Вы всегда можете изменить эти настройки позже.",
|
||||
"STEP_1": {
|
||||
"TITLE": "Добро пожаловать в Upscayl 🎉",
|
||||
"DESCRIPTION": "Давайте начнем с нескольких быстрых шагов."
|
||||
|
@ -160,12 +160,19 @@
|
||||
"START_BUTTON_TITLE": "升图!🚀",
|
||||
"IN_PROGRESS_BUTTON_TITLE": "正在升图 ⏳"
|
||||
},
|
||||
"IMAGE_OPTIONS": {
|
||||
"MORE_OPTIONS_DRAWER": {
|
||||
"RESET_BUTTON_TITLE": "重置图片",
|
||||
"LENS_VIEW_TITLE": "透镜视图",
|
||||
"SLIDER_VIEW_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": {
|
||||
"BATCH_UPSCAYL_IN_PROGRESS_TITLE": "批量阿普升图中",
|
||||
@ -178,7 +185,7 @@
|
||||
"SELECT_IMAGE": "选择要增强的图片",
|
||||
"SELECT_FOLDER_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": {
|
||||
"PROCESSING_TITLE": "正在处理图片...",
|
||||
@ -254,6 +261,7 @@
|
||||
"NEXT_BUTTON_TITLE": "下一步",
|
||||
"BACK_BUTTON_TITLE": "上一步",
|
||||
"GET_STARTED_BUTTON_TITLE": "开始使用",
|
||||
"SETTINGS_NOTE": "你可以随时更改这些设置。",
|
||||
"STEP_1": {
|
||||
"TITLE": "欢迎使用阿普升图 🎉",
|
||||
"DESCRIPTION": "让我们通过几个快速步骤来开始吧。"
|
||||
|
@ -4,22 +4,10 @@ import { AppProps } from "next/app";
|
||||
import { Provider } from "jotai";
|
||||
import "react-tooltip/dist/react-tooltip.css";
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
import posthog from "posthog-js";
|
||||
import { useEffect } from "react";
|
||||
import { PostHogProvider } from "posthog-js/react";
|
||||
import { Tooltip } from "react-tooltip";
|
||||
import PostHogProviderWrapper from "@/components/posthog-provider-wrapper";
|
||||
|
||||
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 (
|
||||
<>
|
||||
<Head>
|
||||
@ -27,10 +15,14 @@ const MyApp = ({ Component, pageProps }: AppProps) => {
|
||||
</Head>
|
||||
|
||||
<Provider>
|
||||
<PostHogProvider client={posthog}>
|
||||
<PostHogProviderWrapper>
|
||||
<Component {...pageProps} data-theme="upscayl" />
|
||||
<Toaster />
|
||||
</PostHogProvider>
|
||||
<Tooltip
|
||||
className="z-[999] max-w-sm break-words !bg-secondary"
|
||||
id="tooltip"
|
||||
/>
|
||||
</PostHogProviderWrapper>
|
||||
</Provider>
|
||||
</>
|
||||
);
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
savedOutputPathAtom,
|
||||
progressAtom,
|
||||
rememberOutputFolderAtom,
|
||||
userStatsAtom,
|
||||
} from "../atoms/user-settings-atom";
|
||||
import useLogger from "../components/hooks/use-logger";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
@ -44,6 +45,7 @@ const Home = () => {
|
||||
const setProgress = useSetAtom(progressAtom);
|
||||
const [doubleUpscaylCounter, setDoubleUpscaylCounter] = useState(0);
|
||||
const setModelIds = useSetAtom(customModelIdsAtom);
|
||||
const setUserStats = useSetAtom(userStatsAtom);
|
||||
|
||||
const selectImageHandler = async () => {
|
||||
resetImagePaths();
|
||||
@ -226,6 +228,14 @@ const Home = () => {
|
||||
window.electron.on(ELECTRON_COMMANDS.UPSCAYL_DONE, (_, data: string) => {
|
||||
setProgress("");
|
||||
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(`💯 UPSCAYL_DONE: `, data);
|
||||
});
|
||||
@ -236,6 +246,14 @@ const Home = () => {
|
||||
setProgress("");
|
||||
setUpscaledBatchFolderPath(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
|
||||
@ -246,6 +264,14 @@ const Home = () => {
|
||||
setTimeout(() => setUpscaledImagePath(data), 500);
|
||||
setDoubleUpscaylCounter(0);
|
||||
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
|
||||
|
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;
|
||||
invoke: (command, func?) => any;
|
||||
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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user