diff --git a/package.json b/package.json
index 1a29b564..457f2ff8 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"@electron-toolkit/utils": "^3.0.0",
"@fontsource/noto-sans": "^5.0.22",
"@hookform/resolvers": "^3.9.0",
+ "@intercom/messenger-js-sdk": "^0.0.14",
"@primer/octicons-react": "^19.9.0",
"@reduxjs/toolkit": "^2.2.3",
"@vanilla-extract/css": "^1.14.2",
diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json
index abecb50d..e70eb519 100644
--- a/src/locales/en/translation.json
+++ b/src/locales/en/translation.json
@@ -25,7 +25,8 @@
"queued": "{{title}} (Queued)",
"game_has_no_executable": "Game has no executable selected",
"sign_in": "Sign in",
- "friends": "Friends"
+ "friends": "Friends",
+ "need_help": "Need help?"
},
"header": {
"search": "Search games",
diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json
index d155bcd6..2830eb0c 100644
--- a/src/locales/es/translation.json
+++ b/src/locales/es/translation.json
@@ -25,7 +25,8 @@
"queued": "{{title}} (En cola)",
"game_has_no_executable": "El juego no tiene un ejecutable seleccionado",
"sign_in": "Iniciar sesión",
- "friends": "Amigos"
+ "friends": "Amigos",
+ "need_help": "¿Necesitas ayuda?"
},
"header": {
"search": "Buscar juegos",
diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json
index 41e60338..b61a08be 100644
--- a/src/locales/pt-BR/translation.json
+++ b/src/locales/pt-BR/translation.json
@@ -25,7 +25,8 @@
"queued": "{{title}} (Na fila)",
"game_has_no_executable": "Jogo não possui executável selecionado",
"sign_in": "Login",
- "friends": "Amigos"
+ "friends": "Amigos",
+ "need_help": "Precisa de ajuda?"
},
"header": {
"search": "Buscar jogos",
diff --git a/src/locales/ru/translation.json b/src/locales/ru/translation.json
index 47bfe30c..d1282951 100644
--- a/src/locales/ru/translation.json
+++ b/src/locales/ru/translation.json
@@ -24,7 +24,8 @@
"queued": "{{title}} (В очереди)",
"game_has_no_executable": "Файл запуска игры не выбран",
"sign_in": "Войти",
- "friends": "Друзья"
+ "friends": "Друзья",
+ "need_help": "Нужна помощь?"
},
"header": {
"search": "Поиск",
diff --git a/src/main/services/user/get-user-data.ts b/src/main/services/user/get-user-data.ts
index a283aecb..fd4e5e1d 100644
--- a/src/main/services/user/get-user-data.ts
+++ b/src/main/services/user/get-user-data.ts
@@ -56,6 +56,7 @@ export const getUserData = () => {
id: loggedUser.userId,
username: "",
bio: "",
+ email: null,
profileVisibility: "PUBLIC" as ProfileVisibility,
subscription: loggedUser.subscription
? {
diff --git a/src/main/services/window-manager.ts b/src/main/services/window-manager.ts
index 8da2dd5e..4f65ef2a 100644
--- a/src/main/services/window-manager.ts
+++ b/src/main/services/window-manager.ts
@@ -85,6 +85,10 @@ export class WindowManager {
return callback(details);
}
+ if (details.url.includes("intercom.io")) {
+ return callback(details);
+ }
+
const headers = {
"access-control-allow-origin": ["*"],
"access-control-allow-methods": ["GET, POST, PUT, DELETE, OPTIONS"],
diff --git a/src/renderer/index.html b/src/renderer/index.html
index b53595ff..c1d8f50c 100644
--- a/src/renderer/index.html
+++ b/src/renderer/index.html
@@ -6,7 +6,7 @@
Hydra
diff --git a/src/renderer/src/app.css.ts b/src/renderer/src/app.css.ts
index a52d81f6..25c453c8 100644
--- a/src/renderer/src/app.css.ts
+++ b/src/renderer/src/app.css.ts
@@ -126,3 +126,9 @@ export const titleBar = style({
zIndex: "4",
borderBottom: `1px solid ${vars.color.border}`,
} as ComplexStyleRule);
+
+export const cloudText = style({
+ background: "linear-gradient(270deg, #16B195 50%, #3E62C0 100%)",
+ backgroundClip: "text",
+ color: "transparent",
+});
diff --git a/src/renderer/src/app.tsx b/src/renderer/src/app.tsx
index 7c572a56..11522273 100644
--- a/src/renderer/src/app.tsx
+++ b/src/renderer/src/app.tsx
@@ -2,6 +2,8 @@ import { useCallback, useContext, useEffect, useRef } from "react";
import { Sidebar, BottomPanel, Header, Toast } from "@renderer/components";
+import Intercom from "@intercom/messenger-js-sdk";
+
import {
useAppDispatch,
useAppSelector,
@@ -34,6 +36,10 @@ export interface AppProps {
children: React.ReactNode;
}
+Intercom({
+ app_id: "pq96v8fh",
+});
+
export function App() {
const contentRef = useRef(null);
const { updateLibrary, library } = useLibrary();
@@ -54,8 +60,13 @@ export function App() {
hideFriendsModal,
} = useUserDetails();
- const { userDetails, fetchUserDetails, updateUserDetails, clearUserDetails } =
- useUserDetails();
+ const {
+ userDetails,
+ hasActiveSubscription,
+ fetchUserDetails,
+ updateUserDetails,
+ clearUserDetails,
+ } = useUserDetails();
const dispatch = useAppDispatch();
@@ -204,7 +215,9 @@ export function App() {
useEffect(() => {
new MutationObserver(() => {
- const modal = document.body.querySelector("[role=dialog]");
+ const modal = document.body.querySelector(
+ "[role=dialog]:not([data-intercom-frame='true'])"
+ );
dispatch(toggleDraggingDisabled(Boolean(modal)));
}).observe(document.body, {
@@ -270,7 +283,12 @@ export function App() {
<>
{window.electron.platform === "win32" && (
-
Hydra
+
+ Hydra
+ {hasActiveSubscription && (
+ Cloud
+ )}
+
)}
diff --git a/src/renderer/src/components/badge/badge.scss b/src/renderer/src/components/badge/badge.scss
index f1ed89e9..f32c398f 100644
--- a/src/renderer/src/components/badge/badge.scss
+++ b/src/renderer/src/components/badge/badge.scss
@@ -4,7 +4,7 @@
color: globals.$muted-color;
font-size: 10px;
padding: calc(globals.$spacing-unit / 2) globals.$spacing-unit;
- border: solid 1px globals.$border-color;
+ border: solid 1px globals.$muted-color;
border-radius: 4px;
display: flex;
align-items: center;
diff --git a/src/renderer/src/components/sidebar/sidebar.css.ts b/src/renderer/src/components/sidebar/sidebar.css.ts
index bfdb4eea..9b061d68 100644
--- a/src/renderer/src/components/sidebar/sidebar.css.ts
+++ b/src/renderer/src/components/sidebar/sidebar.css.ts
@@ -124,3 +124,29 @@ export const section = style({
flexDirection: "column",
paddingBottom: `${SPACING_UNIT}px`,
});
+
+export const helpButton = style({
+ color: vars.color.muted,
+ padding: `${SPACING_UNIT}px ${SPACING_UNIT * 2}px`,
+ gap: "9px",
+ display: "flex",
+ alignItems: "center",
+ cursor: "pointer",
+ boxShadow: "0px 0px 15px 0px rgba(0, 0, 0, 0.6)",
+ borderTop: `solid 1px ${vars.color.border}`,
+ transition: "background-color ease 0.1s",
+ ":hover": {
+ backgroundColor: "rgba(255, 255, 255, 0.15)",
+ },
+});
+
+export const helpButtonIcon = style({
+ background: "linear-gradient(0deg, #16B195 50%, #3E62C0 100%)",
+ width: "24px",
+ height: "24px",
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ color: "#fff",
+ borderRadius: "50%",
+});
diff --git a/src/renderer/src/components/sidebar/sidebar.tsx b/src/renderer/src/components/sidebar/sidebar.tsx
index 3159ecac..d529e942 100644
--- a/src/renderer/src/components/sidebar/sidebar.tsx
+++ b/src/renderer/src/components/sidebar/sidebar.tsx
@@ -5,7 +5,12 @@ import { useLocation, useNavigate } from "react-router-dom";
import type { LibraryGame } from "@types";
import { TextField } from "@renderer/components";
-import { useDownload, useLibrary, useToast } from "@renderer/hooks";
+import {
+ useDownload,
+ useLibrary,
+ useToast,
+ useUserDetails,
+} from "@renderer/hooks";
import { routes } from "./routes";
@@ -15,6 +20,9 @@ import { buildGameDetailsPath } from "@renderer/helpers";
import SteamLogo from "@renderer/assets/steam-logo.svg?react";
import { SidebarProfile } from "./sidebar-profile";
import { sortBy } from "lodash-es";
+import { CommentDiscussionIcon } from "@primer/octicons-react";
+
+import { show, update } from "@intercom/messenger-js-sdk";
const SIDEBAR_MIN_WIDTH = 200;
const SIDEBAR_INITIAL_WIDTH = 250;
@@ -42,6 +50,20 @@ export function Sidebar() {
return sortBy(library, (game) => game.title);
}, [library]);
+ const { userDetails, hasActiveSubscription } = useUserDetails();
+
+ useEffect(() => {
+ if (userDetails) {
+ update({
+ name: userDetails.displayName,
+ Username: userDetails.username,
+ Email: userDetails.email,
+ "Subscription expiration date": userDetails?.subscription?.expiresAt,
+ "Payment status": userDetails?.subscription?.status,
+ });
+ }
+ }, [userDetails, hasActiveSubscription]);
+
const { lastPacket, progress } = useDownload();
const { showWarningToast } = useToast();
@@ -237,6 +259,15 @@ export function Sidebar() {
+ {hasActiveSubscription && (
+
+ )}
+