Add basic New Stars theme.

This commit is contained in:
theADAMJR 2023-05-30 21:02:29 +01:00
parent c11d516911
commit 01e0d7d454
14 changed files with 115 additions and 33 deletions

View File

@ -16,7 +16,7 @@ Built with React, TypeScript, and Node.js.
## Setup
1. Clone the repo (from GitHub).
2. Generate SSH keys (secure user logins).
2. Generate JWT key (secure user logins).
From app directory (with Git bash):
```
mkdir -p backend/keys

View File

@ -20,4 +20,10 @@ connect(process.env.MONGO_URI, {
.then(async () => {
log.info(`Connected to database.`, { uri: process.env.MONGO_URI });
await User.updateMany({ $set: { status: 'OFFLINE' } })
});
});
try {
process.env.SSH_KEY = fs.readFileSync('./keys/jwt', { encoding: 'utf-8' });
log.info("JWT key initialized.");
}
catch { log.error("JWT key not setup correctly. Refer to the setup guide."); }

View File

@ -68,11 +68,9 @@ export default class Users extends DBWrapper<string, UserDocument> {
}
public async createToken(user: SelfUserDocument, expire = true) {
// too insecure to keep in memory
const key = await readFileAsync('./keys/jwt', { encoding: 'utf-8' });
return jwt.sign(
{ id: user.id },
key,
process.env.SSH_KEY,
{ algorithm: 'RS512', expiresIn: (expire) ? '7d' : undefined },
);
}

View File

@ -9,6 +9,8 @@ declare global {
ROOT_ENDPOINT: string;
WEBSITE_URL: string;
SESSION_SECRET: string;
/** Set during runtime. */
SSH_KEY: string;
}
}
}

View File

@ -5,4 +5,5 @@ REACT_APP_WEBSITE_URL="http://localhost:4200"
REACT_APP_REPO_URL="https://github.com/theadamjr/acrd.app"
REACT_APP_VERSION_NAME="Cyan"
REACT_APP_VERSION_NUMBER="0.6.0-dev-release"
REACT_APP_ROOT_API_URL="http://localhost:3000"
REACT_APP_ROOT_API_URL="http://localhost:3000"
REACT_APP_OWNER_USER_ID="450428712295456768"

View File

@ -5,4 +5,5 @@ REACT_APP_WEBSITE_URL="https://acrd.app"
REACT_APP_REPO_URL="https://github.com/theadamjr/acrd.app"
REACT_APP_VERSION_NAME="Cyan"
REACT_APP_VERSION_NUMBER="0.6.0-dev-release"
REACT_APP_ROOT_API_URL="https://api.acrd.app"
REACT_APP_ROOT_API_URL="https://api.acrd.app"
REACT_APP_OWNER_USER_ID="451453819310678016"

View File

@ -57,7 +57,7 @@ const TextBasedChannel: React.FunctionComponent = () => {
<div
id="messages"
ref={messagesRef}
className="overflow-auto mb-5 mr-1 mt-1 flex-grow"
className="main-content bg-bg-primary overflow-auto mb-5 mr-1 mt-1 flex-grow"
onScroll={onScroll}>
<TextChannelHeader canRead={canRead} />
<LoadingIndicator />

View File

@ -6,13 +6,15 @@ import fetchEntities from '../../../store/actions/fetch-entities';
import { uploadFile } from '../../../store/api';
import { createTheme, deleteTheme, getTheme, unlockTheme, updateTheme } from '../../../store/themes';
import { openSaveChanges } from '../../../store/ui';
import { updateSelf } from '../../../store/users';
import { getUser, updateSelf } from '../../../store/users';
import FileInput from '../../inputs/file-input';
import Input from '../../inputs/input';
import SidebarIcon from '../../navigation/sidebar/sidebar-icon';
import CircleButton from '../../utils/buttons/circle-button';
import NormalButton from '../../utils/buttons/normal-button';
import SaveChanges from '../../utils/save-changes';
import { Entity } from '@acrd/types';
import FoundUsername from '../../user/username';
const UserSettingsThemes: React.FunctionComponent = () => {
const dispatch = useDispatch();
@ -57,6 +59,7 @@ const UserSettingsThemes: React.FunctionComponent = () => {
const ThemeDetails: React.FunctionComponent = () => {
const { register, setValue, handleSubmit } = useForm();
const theme = themes.find(t => t.id === themeId);
const creatorUser: Entity.User = useSelector(getUser(theme?.creatorId));
if (!theme) return null;
const onApply = () => dispatch(updateSelf({ activeThemeId: themeId }));
@ -70,8 +73,8 @@ const UserSettingsThemes: React.FunctionComponent = () => {
};
const copyCode = () => {
const inviteURL = `${process.env.REACT_APP_WEBSITE_URL}/themes/${theme?.code}`;
window.navigator.clipboard.writeText(inviteURL);
const themeURL = `${process.env.REACT_APP_WEBSITE_URL}/themes/${theme?.code}`;
window.navigator.clipboard.writeText(themeURL);
}
const shortURL = process.env.REACT_APP_WEBSITE_URL
@ -125,22 +128,29 @@ const UserSettingsThemes: React.FunctionComponent = () => {
<header className="mb-5">
<h1 className="text-3xl font-bold inline">{theme.name}</h1>
</header>
<div className="w-1/3">
<FileInput
disabled
// disabled={true}!selfIsManager}
name="icon"
label="Icon"
options={{ value: theme.iconURL }}
tooltip="An optional icon for your theme."
onChange={(e) => {
const file = e.currentTarget?.files?.[0];
if (!file) return;
<div className="flex">
<div className="w-1/3">
<FileInput
disabled={!selfIsManager}
name="icon"
label="Icon"
options={{ value: theme.iconURL }}
tooltip="An optional icon for your theme."
onChange={(e) => {
const file = e.currentTarget?.files?.[0];
if (!file) return;
dispatch(uploadFile(file, ({ url }) => {
dispatch(updateTheme(themeId, { iconURL: url }));
}));
}} />
dispatch(uploadFile(file, ({ url }) => {
dispatch(updateTheme(themeId, { iconURL: url }));
}));
}} />
</div>
<div style={{ margin: '20px' }}>
<span className='text-center'>
<div className="font-bold pb-1">Created By</div>
<FoundUsername user={creatorUser} />
</span>
</div>
</div>
<form
@ -162,7 +172,7 @@ const UserSettingsThemes: React.FunctionComponent = () => {
onClick={copyCode}
className="float-right py-0">Copy</CircleButton>
<span className="text-lg">
<span className='muted'>{shortURL + '/join/'}</span>
<span className='muted'>{shortURL + '/themes/'}</span>
<span className='primary'>{theme?.code}</span>
</span>
</div>

View File

@ -11,7 +11,7 @@ const AppNavbar: React.FunctionComponent = () => {
const memberListToggled = useSelector((s: Store.AppState) => s.config.memberListToggled);
return (
<div className="shadow-elevation flex items-center h-12 px-5">
<div className="bg-bg-primary shadow-elevation flex items-center h-12 px-5">
{channel && <FontAwesomeIcon
color="var(--muted)"
icon={faHashtag}

View File

@ -4,9 +4,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useEffect } from 'react';
import { useDispatch, useSelector, useStore } from 'react-redux';
import { Link, useHistory, useParams } from 'react-router-dom';
import fetchEntities from '../../store/actions/fetch-entities';
import { getGuild, getGuildMembers } from '../../store/guilds';
import { joinGuild } from '../../store/members';
import { applyTheme, getThemeByCode, getTheme, unlockTheme } from '../../store/themes';
import { getUser, updateSelf } from '../../store/users';
import SidebarIcon from '../navigation/sidebar/sidebar-icon';

View File

@ -56,7 +56,7 @@ const MemberList: React.FunctionComponent = () => {
.map(r => r!.id);
return (isActive) ? (
<div className="overflow-auto bg-bg-secondary w-64">
<div className="member-list overflow-auto bg-bg-secondary w-64">
{hoistedRoles.map(r =>
<UserList
key={r.id}

View File

@ -7,6 +7,7 @@ import { getHeaders } from './utils/rest-headers';
import accordTheme from '!!raw-loader!../styles/theme/accord-theme.css';
import discordTheme from '!!raw-loader!../styles/theme/discord-theme.css';
import winterTheme from '!!raw-loader!../styles/theme/winter-theme.css';
import newStarsTheme from '!!raw-loader!../styles/theme/new-stars-theme.css';
import themeTemplate from '!!raw-loader!../styles/theme/winter-theme.css';
const slice = createSlice({
@ -33,11 +34,20 @@ const slice = createSlice({
id: 'winter',
code: 'winter',
createdAt: new Date('30/12/2021'),
creatorId: '177127942839676928',
creatorId: process.env.REACT_APP_OWNER_USER_ID,
iconURL: '/images/themes/winter.svg',
isFeatured: true,
name: 'Winter (built-in)',
styles: winterTheme,
}, {
id: 'new_stars',
code: 'new_stars',
createdAt: new Date('30/12/2021'),
creatorId: process.env.REACT_APP_OWNER_USER_ID,
iconURL: '/images/themes/.svg',
isFeatured: true,
name: 'New Stars (built-in)',
styles: newStarsTheme,
}] as Store.AppState['entities']['themes'],
reducers: {
deleted: (themes, { payload }: Store.Action<string>) => {

View File

@ -0,0 +1,56 @@
/* newstarsgame.com */
:root {
--primary: yellow;
--secondary: yellow;
--tertiary: #30C0B8;
--heading: white;
--font: #c9c9c9;
--muted: #6c757d;
--success: #09f7a0;
--danger: #f43e5c;
--warning: #f77d26;
--normal: #dcddde;
--link: hsl(197, calc(var(--saturation-factor, 1) * 100%), 47.8%);
--channel: #8e9297;
--saturation-factor: 1;
--bg-primary: transparent;
--bg-secondary: transparent;
--bg-secondary-alt: transparent;
--bg-tertiary: #050219;
--bg-textarea: #40444b;
--bg-modifier-accent: hsla(0, 0%, 100%, 0.06);
--bg-modifier-selected: rgba(79, 84, 92, 0.32);
--bg-floating: #18191c;
--elevation: 0 1px 0 rgba(4, 4, 5, 0.2), 0 1.5px 0 rgba(6, 6, 7, 0.05),
0 2px 0 rgba(4, 4, 5, 0.05);
--font-primary: Inter, 'Helvetica Neue', Helvetica, Arial, sans-serif;
--light: #fdf0ed;
--dark: #16161c;
}
html,
body {
background-image: url("https://newstarsgame.com/public/Purple/Layer%203/Space%20Background%201.png") !important;
}
.member-list {
background-image: url("https://newstarsgame.com/public/Purple/Layer%201/Space%20Background%201.png");
}
.sidebar-tabs {
background-image: url("https://newstarsgame.com/public/Purple/Layer%201/Space%20Background%2010.png");
}
.bg-bg-secondary {
/* background-image: url("https://newstarsgame.com/public/Purple/Layer%202/Space%20Background%202.png"); */
}
.bg-bg-tertiary {
}

View File

@ -9,6 +9,7 @@ declare global {
REACT_APP_VERSION_NAME: string;
REACT_APP_VERSION_NUMBER: string;
REACT_APP_ROOT_API_URL: string;
REACT_APP_OWNER_USER_ID: string;
}
}
}