diff --git a/electron-src/index.ts b/electron-src/index.ts index 6a59c2b1d..048e4c217 100644 --- a/electron-src/index.ts +++ b/electron-src/index.ts @@ -220,6 +220,29 @@ async function createWindow() { const url = `http://localhost:${PORT}`; + mainWindow.webContents.session.webRequest.onHeadersReceived( + (details, callback) => { + callback({ + responseHeaders: { + ...details.responseHeaders, + "Content-Security-Policy": [ + "default-src 'self' 'unsafe-inline' 'unsafe-eval' https://app.uniswap.org https://*.uniswap.org https://x.com https://*.x.com; frame-src 'self' https://app.uniswap.org https://*.uniswap.org https://x.com https://*.x.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://app.uniswap.org https://*.uniswap.org https://x.com https://*.x.com; style-src 'self' 'unsafe-inline' https://app.uniswap.org https://*.uniswap.org https://x.com https://*.x.com; img-src 'self' data: https: blob:; connect-src 'self' https: wss: data: blob:;", + ], + }, + }); + } + ); + + mainWindow.webContents.setWindowOpenHandler(({ url }) => { + if ( + url.startsWith("https://app.uniswap.org") || + url.startsWith("https://x.com") + ) { + return { action: "allow" }; + } + return { action: "deny" }; + }); + mainWindow.loadURL(url); localShortcut.register("CommandOrControl+Shift+C", () => { @@ -265,6 +288,23 @@ async function createWindow() { ); } ); + + mainWindow.webContents.session.webRequest.onHeadersReceived( + (details, callback) => { + callback({ + responseHeaders: { + ...details.responseHeaders, + "Content-Security-Policy": [ + "default-src 'self' 'unsafe-inline' 'unsafe-eval' https://app.uniswap.org https://*.uniswap.org https://x.com https://*.x.com; frame-src 'self' https://app.uniswap.org https://*.uniswap.org https://x.com https://*.x.com; img-src 'self' data: https: blob:; connect-src 'self' https: wss: data: blob:; style-src 'self' 'unsafe-inline';", + ], + }, + }); + } + ); + + mainWindow.webContents.setWindowOpenHandler(() => { + return { action: "deny" }; + }); } protocol.registerSchemesAsPrivileged([ diff --git a/renderer/components/apps/Apps.module.scss b/renderer/components/apps/Apps.module.scss new file mode 100644 index 000000000..d85b104bc --- /dev/null +++ b/renderer/components/apps/Apps.module.scss @@ -0,0 +1,103 @@ +.mainContainer { + padding-bottom: 2rem; +} + +.appCard { + display: block; + text-decoration: none; + color: inherit; + + &:hover { + color: inherit; + text-decoration: none; + + .appCardInner { + transform: translateY(-4px); + + .glowEffect { + opacity: 0.1; + } + + .iconBackground { + transform: scale(1.1); + } + + .appIcon { + transform: scale(1.1); + } + } + } +} + +.appCardInner { + aspect-ratio: 1; + background: rgba(30, 31, 34, 0.6); + border-radius: 1.25rem; + padding: 1.5rem; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + display: flex; + flex-direction: column; + position: relative; + overflow: hidden; + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.glowEffect { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: radial-gradient( + circle at center, + rgba(var(--bs-primary-rgb), 0.3) 0%, + transparent 70% + ); + opacity: 0; + transition: opacity 0.3s ease-in-out; +} + +.appIconWrapper { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + position: relative; + padding: 2rem; +} + +.iconBackground { + position: absolute; + width: 90px; + height: 90px; + background: rgba(255, 255, 255, 0.03); + border-radius: 24px; + transition: transform 0.3s ease-in-out; +} + +.appIcon { + position: relative; + width: 100%; + height: auto; + max-width: 64px; + max-height: 64px; + object-fit: contain; + transition: transform 0.3s ease-in-out; + filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.1)); +} + +.appInfo { + padding-top: 1.25rem; + margin-top: 0.5rem; + border-top: 1px solid rgba(255, 255, 255, 0.08); +} + +.appName { + margin: 0; + font-size: 1.125rem; + font-weight: 500; + text-align: center; + color: var(--bs-gray-200); + letter-spacing: -0.01em; +} diff --git a/renderer/components/apps/AppsGrid.tsx b/renderer/components/apps/AppsGrid.tsx new file mode 100644 index 000000000..8879adb18 --- /dev/null +++ b/renderer/components/apps/AppsGrid.tsx @@ -0,0 +1,87 @@ +import { Container, Row, Col } from "react-bootstrap"; +import styles from "./Apps.module.scss"; +import Image from "next/image"; +import Link from "next/link"; + +interface AppCard { + name: string; + description: string; + icon: string; + path: string; +} + +interface AppSection { + title: string; + apps: AppCard[]; +} + +const APPS_SECTIONS: AppSection[] = [ + { + title: "DApps", + apps: [ + { + name: "Uniswap", + description: + "Swap tokens and provide liquidity with the leading DEX protocol", + icon: "/uniswap-logo.png", + path: "/apps/uniswap", + }, + ], + }, +]; + +export default function AppsGrid() { + return ( + + + + + + +

+ Apps +

+

+ Integrated applications within the 6529 CORE ecosystem +

+ +
+ {APPS_SECTIONS.map((section) => ( +
+ + +

{section.title}

+ +
+ + {section.apps.map((app) => ( + + +
+
+
+
+ {app.name} +
+
+

{app.name}

+
+
+ + + ))} + +
+ ))} + + + + + ); +} diff --git a/renderer/components/apps/uniswap/UniswapApp.module.scss b/renderer/components/apps/uniswap/UniswapApp.module.scss new file mode 100644 index 000000000..731e1732f --- /dev/null +++ b/renderer/components/apps/uniswap/UniswapApp.module.scss @@ -0,0 +1,21 @@ +.mainContainer { + padding-bottom: 2rem; +} + +.connectMessage { + background: var(--bs-dark); + padding: 2rem; + border-radius: 0.5rem; + text-align: center; + color: var(--bs-gray-300); +} + +.uniswapFrame { + border: 1px solid var(--bs-dark); + border-radius: 0.5rem; + background: var(--bs-dark); + width: 100%; + height: 720px; + overflow: hidden; + display: block; +} diff --git a/renderer/components/apps/uniswap/UniswapApp.tsx b/renderer/components/apps/uniswap/UniswapApp.tsx new file mode 100644 index 000000000..1ed016de4 --- /dev/null +++ b/renderer/components/apps/uniswap/UniswapApp.tsx @@ -0,0 +1,50 @@ +import { Container, Row, Col } from "react-bootstrap"; +import styles from "./UniswapApp.module.scss"; +import Image from "next/image"; + +export default function UniswapApp() { + return ( + + + + + + +
+ Uniswap +
+

+ Uniswap +

+ +
+ + + +