-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 041b573
Showing
45 changed files
with
31,002 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** @type {import('eslint').Linter.Config} */ | ||
module.exports = { | ||
extends: ['@remix-run/eslint-config', '@remix-run/eslint-config/node'], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
node_modules | ||
|
||
/.cache | ||
/build | ||
/dist | ||
/public/build | ||
.env | ||
user*.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"$schema": "https://json.schemastore.org/prettierrc", | ||
"singleQuote": true, | ||
"useTabs": true, | ||
"tabWidth": 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"editor.comments.insertSpace": false, | ||
"editor.formatOnSave": true, | ||
"editor.tabSize": 2, | ||
"files.insertFinalNewline": true, | ||
"files.trimTrailingWhitespace": true, | ||
"typescript.tsdk": "node_modules/typescript/lib", | ||
"search.exclude": { | ||
"**/node_modules": true, | ||
"**/bower_components": true, | ||
"**/*.code-search": true, | ||
"**/lib": true, | ||
"**/build": true, | ||
"**/dist": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# ValPal | ||
|
||
I've created this project to allow Valorant players to create loadouts which can be randomized when joining a game. It supports agent specific loadouts, player cards, player titles, sprays, buddies, skin levels, and skin chromas. | ||
|
||
# Screenshots | ||
|
||
Configurator main screen showing a loadout | ||
<img src="images/main-loadout.png" /> | ||
Configurator main screen showing an agent specific loadout | ||
<img src="images/agent-loadout.png" /> | ||
|
||
# Installation | ||
|
||
1. You can find the latest release [here](https://github.com/zachrip/valpal/releases/latest) - download valpal.exe | ||
2. Create a folder somewhere (desktop or your user directory, or wherever else, you do you) | ||
3. Run the .exe - windows will probably complain, click "more info" then "run anyway" | ||
4. You should see an item added to your system tray - right click on it and click "Open ValPal" - this will open your browser to the configurator | ||
5. Open Valorant (you must run the game for this to work) | ||
6. Add a loadout and configure it with your skins | ||
7. When you join a match, the app will detect when you've locked in as an agent. If you have `Agent specific loadouts` enabled it will configure loadouts for that agent if there are any (otherwise it will fall back to all enabled loadouts). You can disable the loadout shuffling all together if you prefer to equip loadouts by hand in the configurator | ||
|
||
# Architecture | ||
|
||
This app is based around [Remix](https://remix.run) and packaged using [pkg](https://github.com/vercel/pkg). It uses the local websocket/http server that Valorant runs to authenticate and detect when matches start. | ||
|
||
# Contribute | ||
|
||
1. Clone this repo | ||
2. `npm install` | ||
3. `npm run dev` | ||
4. Run Valorant | ||
5. Open [http://localhost:3000](http://localhost:3000) | ||
6. The configurator code mostly lives in app/ - the rest of the stuff is in server/ (such as the game detection, system tray stuff, etc) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import type { ReactNode } from 'react'; | ||
import { useEffect, useState } from 'react'; | ||
|
||
export const Gallery = <T extends Array<{ duration: number }>>({ | ||
items, | ||
render, | ||
}: { | ||
items: T; | ||
render: (data: T[number]) => JSX.Element; | ||
}) => { | ||
const [selectedElement, setSelectedElement] = useState(0); | ||
|
||
useEffect(() => { | ||
if (items.length === 0) return; | ||
|
||
const interval = setInterval(() => { | ||
setSelectedElement((el) => (el + 1) % items.length); | ||
}, 1500); | ||
|
||
return () => clearInterval(interval); | ||
}, [items]); | ||
|
||
if (items.length === 0) return null; | ||
|
||
return render(items[selectedElement]); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import type { FunctionComponent } from 'react'; | ||
import { useEffect, useState } from 'react'; | ||
|
||
export const SwitchImage: FunctionComponent< | ||
{ | ||
images: Array<{ | ||
src: string; | ||
alt: string; | ||
}>; | ||
} & React.DetailedHTMLProps< | ||
React.ImgHTMLAttributes<HTMLImageElement>, | ||
HTMLImageElement | ||
> | ||
> = ({ images, ...props }) => { | ||
const [selectedImage, setSelectedImage] = useState(0); | ||
|
||
useEffect(() => { | ||
const interval = setInterval(() => { | ||
setSelectedImage((selectedImage + 1) % images.length); | ||
}, 1500); | ||
|
||
return () => clearInterval(interval); | ||
}, [selectedImage, images]); | ||
|
||
const image = images[selectedImage]; | ||
|
||
if (!image) { | ||
return null; | ||
} | ||
|
||
const { src, alt } = image; | ||
return <img {...props} src={src} alt={alt} />; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { RemixBrowser } from '@remix-run/react'; | ||
import { startTransition, StrictMode } from 'react'; | ||
import { hydrateRoot } from 'react-dom/client'; | ||
|
||
function hydrate() { | ||
startTransition(() => { | ||
hydrateRoot( | ||
document, | ||
<StrictMode> | ||
<RemixBrowser /> | ||
</StrictMode> | ||
); | ||
}); | ||
} | ||
|
||
if (typeof requestIdleCallback === 'function') { | ||
requestIdleCallback(hydrate); | ||
} else { | ||
// Safari doesn't support requestIdleCallback | ||
// https://caniuse.com/requestidlecallback | ||
setTimeout(hydrate, 1); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import { PassThrough } from 'stream'; | ||
import type { EntryContext } from '@remix-run/node'; | ||
import { Response } from '@remix-run/node'; | ||
import { RemixServer } from '@remix-run/react'; | ||
import isbot from 'isbot'; | ||
import { renderToPipeableStream } from 'react-dom/server'; | ||
|
||
const ABORT_DELAY = 5000; | ||
|
||
export default function handleRequest( | ||
request: Request, | ||
responseStatusCode: number, | ||
responseHeaders: Headers, | ||
remixContext: EntryContext | ||
) { | ||
return isbot(request.headers.get('user-agent')) | ||
? handleBotRequest( | ||
request, | ||
responseStatusCode, | ||
responseHeaders, | ||
remixContext | ||
) | ||
: handleBrowserRequest( | ||
request, | ||
responseStatusCode, | ||
responseHeaders, | ||
remixContext | ||
); | ||
} | ||
|
||
function handleBotRequest( | ||
request: Request, | ||
responseStatusCode: number, | ||
responseHeaders: Headers, | ||
remixContext: EntryContext | ||
) { | ||
return new Promise((resolve, reject) => { | ||
let didError = false; | ||
|
||
const { pipe, abort } = renderToPipeableStream( | ||
<RemixServer context={remixContext} url={request.url} />, | ||
{ | ||
onAllReady() { | ||
const body = new PassThrough(); | ||
|
||
responseHeaders.set('Content-Type', 'text/html'); | ||
|
||
resolve( | ||
new Response(body, { | ||
headers: responseHeaders, | ||
status: didError ? 500 : responseStatusCode, | ||
}) | ||
); | ||
|
||
pipe(body); | ||
}, | ||
onShellError(error: unknown) { | ||
reject(error); | ||
}, | ||
onError(error: unknown) { | ||
didError = true; | ||
|
||
console.error(error); | ||
}, | ||
} | ||
); | ||
|
||
setTimeout(abort, ABORT_DELAY); | ||
}); | ||
} | ||
|
||
function handleBrowserRequest( | ||
request: Request, | ||
responseStatusCode: number, | ||
responseHeaders: Headers, | ||
remixContext: EntryContext | ||
) { | ||
return new Promise((resolve, reject) => { | ||
let didError = false; | ||
|
||
const { pipe, abort } = renderToPipeableStream( | ||
<RemixServer context={remixContext} url={request.url} />, | ||
{ | ||
onShellReady() { | ||
const body = new PassThrough(); | ||
|
||
responseHeaders.set('Content-Type', 'text/html'); | ||
|
||
resolve( | ||
new Response(body, { | ||
headers: responseHeaders, | ||
status: didError ? 500 : responseStatusCode, | ||
}) | ||
); | ||
|
||
pipe(body); | ||
}, | ||
onShellError(err: unknown) { | ||
reject(err); | ||
}, | ||
onError(error: unknown) { | ||
didError = true; | ||
|
||
console.error(error); | ||
}, | ||
} | ||
); | ||
|
||
setTimeout(abort, ABORT_DELAY); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import type { MetaFunction } from '@remix-run/node'; | ||
import { | ||
Links, | ||
LiveReload, | ||
Meta, | ||
Outlet, | ||
Scripts, | ||
ScrollRestoration, | ||
} from '@remix-run/react'; | ||
|
||
import stylesheet from '~/tailwind.css'; | ||
|
||
export function links() { | ||
return [ | ||
{ rel: 'stylesheet', href: stylesheet }, | ||
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' }, | ||
{ | ||
rel: 'preconnect', | ||
href: 'https://fonts.gstatic.com', | ||
crossOrigin: 'true', | ||
}, | ||
{ | ||
rel: 'stylesheet', | ||
href: 'https://fonts.googleapis.com/css2?family=Readex+Pro:wght@200;300;400;500;600;700&display=swap', | ||
}, | ||
]; | ||
} | ||
|
||
export const meta: MetaFunction = () => ({ | ||
charset: 'utf-8', | ||
title: 'ValPal', | ||
viewport: 'width=device-width,initial-scale=1', | ||
}); | ||
|
||
export default function App() { | ||
return ( | ||
<html lang="en"> | ||
<head> | ||
<Meta /> | ||
<Links /> | ||
</head> | ||
<body className="bg-slate-800 text-white"> | ||
<Outlet /> | ||
<ScrollRestoration /> | ||
<Scripts /> | ||
<LiveReload /> | ||
</body> | ||
</html> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { redirect } from '@remix-run/node'; | ||
import { useLoaderData } from '@remix-run/react'; | ||
import { getUser } from '~/utils.server'; | ||
|
||
export async function loader() { | ||
const user = await getUser(); | ||
|
||
if (!user) { | ||
return redirect('/login'); | ||
} | ||
|
||
return redirect('/loadouts'); | ||
} | ||
|
||
export default function Index() { | ||
const { userId } = useLoaderData<typeof loader>(); | ||
|
||
return <div>{userId}</div>; | ||
} |
Oops, something went wrong.