Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
# [1.13.0](https://github.com/unitystation/unitystation-web/compare/v1.12.0...v1.13.0) (2025-04-21)


### Features

* changes "Weekly Update" pill's text to "Progress update" ([6845ea6](https://github.com/unitystation/unitystation-web/commit/6845ea6b17fe2701e8fbdc4cecf64d1a1319ec97))
* first iteration of the new ledger page ([1cae21d](https://github.com/unitystation/unitystation-web/commit/1cae21d0368529be3fba38b3e8990ff6c61639a4))
* first iteration of the new ledger page ([cd5c42f](https://github.com/unitystation/unitystation-web/commit/cd5c42f3b569956608fcc80886f1b962d1ed1319))

# [1.13.0](https://github.com/unitystation/unitystation-web/compare/v1.12.0...v1.13.0) (2025-03-30)


### Features

* changes "Weekly Update" pill's text to "Progress update" ([6845ea6](https://github.com/unitystation/unitystation-web/commit/6845ea6b17fe2701e8fbdc4cecf64d1a1319ec97))

# [1.12.0](https://github.com/unitystation/unitystation-web/compare/v1.11.0...v1.12.0) (2024-10-27)


### Bug Fixes

* stupidly fix changelog page not loading enough builds to create the scrollbar ([a871f56](https://github.com/unitystation/unitystation-web/commit/a871f5654d7b010b1e18fb824ced75ac0b46cd88))


### Features

* Button component now supports choosing uppercase and side icons. ([1151eab](https://github.com/unitystation/unitystation-web/commit/1151eabdacad7dfdcfe859d26d359c16840eba5d))
* close dropdown after clicking on an element ([bf4e98e](https://github.com/unitystation/unitystation-web/commit/bf4e98e90decc286f7308c948b4a6cfd48631bea))

# [1.11.0](https://github.com/unitystation/unitystation-web/compare/v1.10.0...v1.11.0) (2024-10-12)


Expand Down
2 changes: 1 addition & 1 deletion app/(account)/confirm-email/[token]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const MailConfirmationPage = () => {
fetchData().then(r => {
setResponse(r);
});
}, []);
}, [token]);

if (!token) {
return <main>
Expand Down
2 changes: 1 addition & 1 deletion app/(account)/logout/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const LogoutPage = () => {
authState.logout().then(() => {
redirect("login");
});
}, []);
}, [authState]);
}

export default LogoutPage;
6 changes: 3 additions & 3 deletions app/(account)/register/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"use client"

import React from "react";
import React, {useActionState} from "react";
import Button from "../../common/uiLibrary/Button";
import FormContainer from "../../common/uiLibrary/Layouters/formContainer";
import TextField from "../../common/uiLibrary/forms/textField";
import AlternativeActions from "../../common/uiLibrary/forms/alternativeActions";
import ContactInformation from "../../(home)/contactInformation";
import {useFormState} from "react-dom";
import "react-dom";
import {registerAccount, RegisterResponse} from "./actions";
import {isFieldError} from "../../../lib/auth/guards";
import { useFormStatus } from "react-dom";
Expand All @@ -18,7 +18,7 @@ const RegisterPage = () => {
success: false,
error: undefined
}
const [state, formAction] = useFormState(registerAccount, initialState);
const [state, formAction] = useActionState(registerAccount, initialState);

const uniqueIdHelperText = () =>
<>
Expand Down
5 changes: 2 additions & 3 deletions app/(account)/resend-confirm-email/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ import FormContainer from "../../common/uiLibrary/Layouters/formContainer";
import TextField from "../../common/uiLibrary/forms/textField";
import Button from "../../common/uiLibrary/Button";
import ContactInformation from "../../(home)/contactInformation";
import React from "react";
import React, {useActionState} from "react";
import FullPage from "../../common/uiLibrary/Layouters/fullPage";
import {useFormState} from "react-dom";
import {postResendConfirmationMail, ResendConfirmationMailRequest} from "./actions";

const ResendConfirmationMail = () => {
const initialState: ResendConfirmationMailRequest = {
success: false,
}

const [state, formAction] = useFormState(postResendConfirmationMail, initialState);
const [state, formAction] = useActionState(postResendConfirmationMail, initialState);

const resendForm = () => {
return (
Expand Down
5 changes: 2 additions & 3 deletions app/(account)/reset-password/[token]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@


import {useParams} from "next/navigation";
import React from "react";
import React, {useActionState} from "react";
import FormContainer from "../../../common/uiLibrary/Layouters/formContainer";
import TextField from "../../../common/uiLibrary/forms/textField";
import Button from "../../../common/uiLibrary/Button";
import {useFormState} from "react-dom";
import {postPasswordReset, ResetPasswordStep2Response} from "./actions";
import {isFieldError} from "../../../../lib/auth/guards";
import FullPage from "../../../common/uiLibrary/Layouters/fullPage";
Expand All @@ -18,7 +17,7 @@ const ResetPasswordPageStep2 = () => {
error: undefined
}

const [state, formAction] = useFormState(postPasswordReset, initialState);
const [state, formAction] = useActionState(postPasswordReset, initialState);

const successMessage = () => (
<div className='flex flex-col gap-4'>
Expand Down
5 changes: 2 additions & 3 deletions app/(account)/reset-password/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
'use client'

import Button from "../../common/uiLibrary/Button";
import React from "react";
import React, {useActionState} from "react";
import FormContainer from "../../common/uiLibrary/Layouters/formContainer";
import TextField from "../../common/uiLibrary/forms/textField";
import {requestAPasswordReset, ResetPassowrdStep1} from "./actions";
import {useFormState} from "react-dom";
import ContactInformation from "../../(home)/contactInformation";

const initialState: ResetPassowrdStep1 = {
Expand All @@ -15,7 +14,7 @@ const initialState: ResetPassowrdStep1 = {
};

const ResetPasswordPage = () => {
const [state, formAction] = useFormState(requestAPasswordReset, initialState);
const [state, formAction] = useActionState(requestAPasswordReset, initialState);

const successMessage = () => (
<div className='flex flex-col gap-4'>
Expand Down
67 changes: 0 additions & 67 deletions app/(home)/HeroRandomImageClient.tsx

This file was deleted.

9 changes: 0 additions & 9 deletions app/(home)/HomeBannerClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@ const images: string[] = [

let currentIndex = 0;

const shuffleImages = () => {
for (let i = images.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[images[i], images[j]] = [images[j], images[i]];
}
};

const getNextImage = () => {
currentIndex = (currentIndex + 1) % images.length;
return images[currentIndex];
Expand All @@ -33,8 +26,6 @@ const getNextImage = () => {
const HomeBannerClient = (props: layoutChildren) => {
const {children} = props;

shuffleImages();

const [image1, setImage1] = useState<string>(getNextImage());
const [image2, setImage2] = useState<string>(getNextImage());
const [showImage1, setShowImage1] = useState<boolean>(true);
Expand Down
2 changes: 2 additions & 0 deletions app/(home)/latestNews.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import classNames from "classnames";
import Container from "../common/uiLibrary/container";
import PageSectionTitle from "../common/uiLibrary/pageSectionTitle";
import LinkButton from "../common/uiLibrary/linkButton";
import Image from "next/image";

interface PostPreviewCardProps {
post: BlogPost,
Expand Down Expand Up @@ -30,6 +31,7 @@ const PostPreviewImage = ({post, isMain = false, className}: PostPreviewCardProp
return (
<div className={classNames(outerContainerStyles, {className})}>
<div className={innerContainerStyles}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={post.socials_image}
alt={post.title}
Expand Down
6 changes: 3 additions & 3 deletions app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import LatestNews from "./latestNews";
import ContactInformation from "./contactInformation";
import React from "react";
import dynamic from 'next/dynamic';
import HomeBannerClient from "./HomeBannerClient";

const mainText = "Welcome to Unitystation!";
const secondaryText = "Free and open-source remake of the cult classic Space Station 13, made in Unity Engine.";
Expand All @@ -20,17 +21,16 @@ const fetchLatestBlogPost = async (): Promise<BlogPost[]> => {

const HomePage = async () => {
const latestBlogPosts: BlogPost[] = await fetchLatestBlogPost();
const NoSsrHomebannerClient = dynamic(() => import('./HomeBannerClient'), { ssr: false });

return (
<>
<div className="flex flex-col justify-center gap-6">
<div className="flex-[1]">
<NoSsrHomebannerClient>
<HomeBannerClient>
<LandingText mainText={mainText} secondaryText={secondaryText}/>
<DownloadButtonClient/>
<LandingButtonsServer/>
</NoSsrHomebannerClient>
</HomeBannerClient>
</div>
<div className="flex-[1]">
<LatestNews posts={latestBlogPosts}/>
Expand Down
2 changes: 1 addition & 1 deletion app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const setMetadata = (post: BlogPost) => {

const PostPage = async (query: PageParams) => {

const {slug} = query.params;
const {slug} = await query.params;
const post: BlogPost = await fetchPost(slug as string);
setMetadata(post);

Expand Down
2 changes: 1 addition & 1 deletion app/blog/[slug]/post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const colourByType: Dict<string> = {

const textByType: Dict<string> = {
'announcement': 'Announcement',
'weekly': 'Weekly Update',
'weekly': 'Progress Update',
'community': 'Community Highlight',
}

Expand Down
77 changes: 74 additions & 3 deletions app/changelog/buildComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import Build from "../../types/build";
import Change from "../../types/change";
import ChangeComponent from "./changeComponent";
import React from "react";
import React, {useEffect, useRef, useState} from "react";
import Panel from "../common/uiLibrary/panel";
import Button from "../common/uiLibrary/Button";
import {BiSolidChevronDown} from "react-icons/bi";
import classNames from "classnames";

function populateChangeList(changes: Change[]) {
let changesList;
Expand Down Expand Up @@ -35,13 +38,78 @@ interface BuildProps {
build: Build
}

//TODO: make this component a general dropdown instead and move it to commons
const DownloadBuildDropdown = (props: { version: string }) => {
'use client'

const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);

const platforms = [
"linuxserver",
"StandaloneLinux64",
"StandaloneOSX",
"StandaloneWindows64"
];

const listClasses = classNames(
'absolute top-full mt-2 w-56 rounded-md shadow-lg bg-slate-600 ring-1 ring-black ring-opacity-5 transition-opacity transition-transform duration-500 ease-out',
{
'opacity-100 translate-y-0': isOpen,
'opacity-0 -translate-y-4 pointer-events-none': !isOpen
}
);

const handleClick = () => {
setIsOpen(!isOpen);
}

const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
};

useEffect(() => {
if (isOpen) {
document.addEventListener('mousedown', handleClickOutside);
} else {
document.removeEventListener('mousedown', handleClickOutside);
}
return () => document.removeEventListener('mousedown', handleClickOutside);
}, [isOpen]);

return (
<div className="relative" ref={dropdownRef}>
<Button upperCase={false} iconRight={BiSolidChevronDown} onClick={handleClick}>
Download
</Button>
<div className={listClasses}>
<div className="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
{platforms.map((platform) => (
<a
key={platform}
href={`https://unitystationfile.b-cdn.net/UnityStationDevelop/${platform}/${props.version}.zip`}
className="block px-4 py-2 text-sm text-blue-50 hover:bg-gray-100 hover:text-gray-900"
role="menuitem"
onClick={handleClick}
>
{platform}
</a>
))}
</div>
</div>
</div>
);
}

const BuildComponent = (props: BuildProps) => {
const {version_number, date_created, changes} = props.build;
const { version_number, date_created, changes } = props.build;
const changesList = populateChangeList(changes);

return (
<Panel>
<div className={'flex justify-between'}>
<div className='flex justify-between'>
<h5 className="lg:text-xl font-bold leading-none text-white">
Build: {version_number}
</h5>
Expand All @@ -54,6 +122,9 @@ const BuildComponent = (props: BuildProps) => {
{changesList}
</ul>
</div>
<div className='relative mt-2 flex justify-end'>
<DownloadBuildDropdown version={version_number} />
</div>
</Panel>
)
}
Expand Down
Loading