mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-02-03 00:33:49 +03:00
feat: adding csp update
This commit is contained in:
parent
5bc424796a
commit
7f600a0cbf
@ -1,4 +1,3 @@
|
|||||||
MAIN_VITE_API_URL=API_URL
|
MAIN_VITE_API_URL=API_URL
|
||||||
MAIN_VITE_AUTH_URL=AUTH_URL
|
MAIN_VITE_AUTH_URL=AUTH_URL
|
||||||
MAIN_VITE_STEAMGRIDDB_API_KEY=YOUR_API_KEY
|
MAIN_VITE_STEAMGRIDDB_API_KEY=YOUR_API_KEY
|
||||||
RENDERER_VITE_INTERCOM_APP_ID=YOUR_APP_ID
|
|
||||||
|
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@ -22,16 +22,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: 20.18.0
|
node-version: 20.18.0
|
||||||
|
|
||||||
- name: Configure AWS credentials
|
|
||||||
uses: aws-actions/configure-aws-credentials@v2
|
|
||||||
with:
|
|
||||||
aws-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
|
|
||||||
aws-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
|
||||||
aws-region: ${{ env.AWS_REGION }}
|
|
||||||
|
|
||||||
- name: Push build to R2
|
|
||||||
run: aws s3 sync ./docs s3://${{ vars.BUILDS_BUCKET_NAME }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { appVersion, defaultDownloadsPath, isStaging } from "@main/constants";
|
import { appVersion, defaultDownloadsPath } from "@main/constants";
|
||||||
import { ipcMain } from "electron";
|
import { ipcMain } from "electron";
|
||||||
|
|
||||||
import "./catalogue/get-catalogue";
|
import "./catalogue/get-catalogue";
|
||||||
@ -72,6 +72,5 @@ import "./misc/show-item-in-folder";
|
|||||||
|
|
||||||
ipcMain.handle("ping", () => "pong");
|
ipcMain.handle("ping", () => "pong");
|
||||||
ipcMain.handle("getVersion", () => appVersion);
|
ipcMain.handle("getVersion", () => appVersion);
|
||||||
ipcMain.handle("isStaging", () => isStaging);
|
|
||||||
ipcMain.handle("isPortableVersion", () => isPortableVersion());
|
ipcMain.handle("isPortableVersion", () => isPortableVersion());
|
||||||
ipcMain.handle("getDefaultDownloadsPath", () => defaultDownloadsPath);
|
ipcMain.handle("getDefaultDownloadsPath", () => defaultDownloadsPath);
|
||||||
|
@ -15,6 +15,7 @@ import type {
|
|||||||
import type { CatalogueCategory } from "@shared";
|
import type { CatalogueCategory } from "@shared";
|
||||||
import type { AxiosProgressEvent } from "axios";
|
import type { AxiosProgressEvent } from "axios";
|
||||||
import { GameAchievement } from "@main/entity";
|
import { GameAchievement } from "@main/entity";
|
||||||
|
import { isStaging } from "@main/constants";
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld("electron", {
|
contextBridge.exposeInMainWorld("electron", {
|
||||||
/* Torrenting */
|
/* Torrenting */
|
||||||
@ -198,7 +199,7 @@ contextBridge.exposeInMainWorld("electron", {
|
|||||||
ping: () => ipcRenderer.invoke("ping"),
|
ping: () => ipcRenderer.invoke("ping"),
|
||||||
getVersion: () => ipcRenderer.invoke("getVersion"),
|
getVersion: () => ipcRenderer.invoke("getVersion"),
|
||||||
getDefaultDownloadsPath: () => ipcRenderer.invoke("getDefaultDownloadsPath"),
|
getDefaultDownloadsPath: () => ipcRenderer.invoke("getDefaultDownloadsPath"),
|
||||||
isStaging: () => ipcRenderer.invoke("isStaging"),
|
isStaging,
|
||||||
isPortableVersion: () => ipcRenderer.invoke("isPortableVersion"),
|
isPortableVersion: () => ipcRenderer.invoke("isPortableVersion"),
|
||||||
openExternal: (src: string) => ipcRenderer.invoke("openExternal", src),
|
openExternal: (src: string) => ipcRenderer.invoke("openExternal", src),
|
||||||
openCheckout: () => ipcRenderer.invoke("openCheckout"),
|
openCheckout: () => ipcRenderer.invoke("openCheckout"),
|
||||||
|
@ -6,8 +6,12 @@
|
|||||||
<title>Hydra</title>
|
<title>Hydra</title>
|
||||||
<meta
|
<meta
|
||||||
http-equiv="Content-Security-Policy"
|
http-equiv="Content-Security-Policy"
|
||||||
content="default-src 'self'; script-src *; style-src 'self' 'unsafe-inline'; img-src 'self' data: local: *; media-src 'self' local: data: *; connect-src *; font-src *;"
|
content="default-src 'self' 'unsafe-inline' *;"
|
||||||
/>
|
/>
|
||||||
|
<script
|
||||||
|
type="text/javascript"
|
||||||
|
src="%RENDERER_VITE_EXTERNAL_RESOURCES_URL%"
|
||||||
|
></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
@ -2,8 +2,6 @@ import { useCallback, useContext, useEffect, useRef } from "react";
|
|||||||
|
|
||||||
import { Sidebar, BottomPanel, Header, Toast } from "@renderer/components";
|
import { Sidebar, BottomPanel, Header, Toast } from "@renderer/components";
|
||||||
|
|
||||||
import Intercom from "@intercom/messenger-js-sdk";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useAppDispatch,
|
useAppDispatch,
|
||||||
useAppSelector,
|
useAppSelector,
|
||||||
@ -36,10 +34,6 @@ export interface AppProps {
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intercom({
|
|
||||||
app_id: import.meta.env.RENDERER_VITE_INTERCOM_APP_ID,
|
|
||||||
});
|
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
const contentRef = useRef<HTMLDivElement>(null);
|
const contentRef = useRef<HTMLDivElement>(null);
|
||||||
const { updateLibrary, library } = useLibrary();
|
const { updateLibrary, library } = useLibrary();
|
||||||
@ -68,6 +62,25 @@ export function App() {
|
|||||||
clearUserDetails,
|
clearUserDetails,
|
||||||
} = useUserDetails();
|
} = useUserDetails();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (userDetails) {
|
||||||
|
const $existingScript = document.getElementById("user-details");
|
||||||
|
|
||||||
|
const content = `window.userDetails = ${JSON.stringify(userDetails)};`;
|
||||||
|
|
||||||
|
if ($existingScript) {
|
||||||
|
$existingScript.textContent = content;
|
||||||
|
} else {
|
||||||
|
const $script = document.createElement("script");
|
||||||
|
$script.id = "user-details";
|
||||||
|
$script.type = "text/javascript";
|
||||||
|
$script.textContent = content;
|
||||||
|
|
||||||
|
document.head.appendChild($script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [userDetails]);
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -215,9 +228,7 @@ export function App() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
new MutationObserver(() => {
|
new MutationObserver(() => {
|
||||||
const modal = document.body.querySelector(
|
const modal = document.body.querySelector("[data-hydra-dialog]");
|
||||||
"[role=dialog]:not([data-intercom-frame='true'])"
|
|
||||||
);
|
|
||||||
|
|
||||||
dispatch(toggleDraggingDisabled(Boolean(modal)));
|
dispatch(toggleDraggingDisabled(Boolean(modal)));
|
||||||
}).observe(document.body, {
|
}).observe(document.body, {
|
||||||
|
@ -107,6 +107,7 @@ export function Modal({
|
|||||||
aria-labelledby={title}
|
aria-labelledby={title}
|
||||||
aria-describedby={description}
|
aria-describedby={description}
|
||||||
ref={modalContentRef}
|
ref={modalContentRef}
|
||||||
|
data-hydra-dialog
|
||||||
>
|
>
|
||||||
<div className={styles.modalHeader}>
|
<div className={styles.modalHeader}>
|
||||||
<div style={{ display: "flex", gap: 4, flexDirection: "column" }}>
|
<div style={{ display: "flex", gap: 4, flexDirection: "column" }}>
|
||||||
|
@ -22,8 +22,6 @@ import { SidebarProfile } from "./sidebar-profile";
|
|||||||
import { sortBy } from "lodash-es";
|
import { sortBy } from "lodash-es";
|
||||||
import { CommentDiscussionIcon } from "@primer/octicons-react";
|
import { CommentDiscussionIcon } from "@primer/octicons-react";
|
||||||
|
|
||||||
import { show, update } from "@intercom/messenger-js-sdk";
|
|
||||||
|
|
||||||
const SIDEBAR_MIN_WIDTH = 200;
|
const SIDEBAR_MIN_WIDTH = 200;
|
||||||
const SIDEBAR_INITIAL_WIDTH = 250;
|
const SIDEBAR_INITIAL_WIDTH = 250;
|
||||||
const SIDEBAR_MAX_WIDTH = 450;
|
const SIDEBAR_MAX_WIDTH = 450;
|
||||||
@ -50,23 +48,7 @@ export function Sidebar() {
|
|||||||
return sortBy(library, (game) => game.title);
|
return sortBy(library, (game) => game.title);
|
||||||
}, [library]);
|
}, [library]);
|
||||||
|
|
||||||
const { userDetails, hasActiveSubscription } = useUserDetails();
|
const { hasActiveSubscription } = useUserDetails();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (userDetails) {
|
|
||||||
window.electron.isStaging().then((isStaging) => {
|
|
||||||
update({
|
|
||||||
user_id: userDetails.id + (isStaging ? "-staging" : ""),
|
|
||||||
name: userDetails.displayName,
|
|
||||||
Username: userDetails.username,
|
|
||||||
email: userDetails.email ?? undefined,
|
|
||||||
Email: userDetails.email,
|
|
||||||
"Subscription expiration date": userDetails?.subscription?.expiresAt,
|
|
||||||
"Payment status": userDetails?.subscription?.status,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [userDetails, hasActiveSubscription]);
|
|
||||||
|
|
||||||
const { lastPacket, progress } = useDownload();
|
const { lastPacket, progress } = useDownload();
|
||||||
|
|
||||||
@ -269,7 +251,11 @@ export function Sidebar() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{hasActiveSubscription && (
|
{hasActiveSubscription && (
|
||||||
<button type="button" className={styles.helpButton} onClick={show}>
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.helpButton}
|
||||||
|
data-open-support-chat
|
||||||
|
>
|
||||||
<div className={styles.helpButtonIcon}>
|
<div className={styles.helpButtonIcon}>
|
||||||
<CommentDiscussionIcon size={14} />
|
<CommentDiscussionIcon size={14} />
|
||||||
</div>
|
</div>
|
||||||
|
3
src/renderer/src/declaration.d.ts
vendored
3
src/renderer/src/declaration.d.ts
vendored
@ -162,7 +162,6 @@ declare global {
|
|||||||
openExternal: (src: string) => Promise<void>;
|
openExternal: (src: string) => Promise<void>;
|
||||||
openCheckout: () => Promise<void>;
|
openCheckout: () => Promise<void>;
|
||||||
getVersion: () => Promise<string>;
|
getVersion: () => Promise<string>;
|
||||||
isStaging: () => Promise<boolean>;
|
|
||||||
ping: () => string;
|
ping: () => string;
|
||||||
getDefaultDownloadsPath: () => Promise<string>;
|
getDefaultDownloadsPath: () => Promise<string>;
|
||||||
isPortableVersion: () => Promise<boolean>;
|
isPortableVersion: () => Promise<boolean>;
|
||||||
@ -232,6 +231,8 @@ declare global {
|
|||||||
|
|
||||||
/* Notifications */
|
/* Notifications */
|
||||||
publishNewRepacksNotification: (newRepacksCount: number) => Promise<void>;
|
publishNewRepacksNotification: (newRepacksCount: number) => Promise<void>;
|
||||||
|
|
||||||
|
isStaging: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Window {
|
interface Window {
|
||||||
|
8
src/renderer/src/vite-env.d.ts
vendored
8
src/renderer/src/vite-env.d.ts
vendored
@ -1,10 +1,2 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
/// <reference types="vite-plugin-svgr/client" />
|
/// <reference types="vite-plugin-svgr/client" />
|
||||||
|
|
||||||
interface ImportMetaEnv {
|
|
||||||
readonly RENDERER_VITE_INTERCOM_APP_ID: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ImportMeta {
|
|
||||||
readonly env: ImportMetaEnv;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user