mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-22 05:19:17 +00:00
Gm handbook lmao (#2149)
* Fix font issue * Fix avatars * Fix text overflow in commands * Fix virtualized lists and items page 😭😭 * magix why 💀 * use hover style in all minicards * button * remove console.log * lint * Add icons * magix asked * Fix overflow padding issue * Fix achievement text overflow * remove icons from repo * Change command icon * Add the wiki page as a submodule * total magix moment * fix text overflow in commands * Fix discord button * Make text scale on Minicard * import icons and font from another source * Add hover effects to siebar buttons * move font and readme to submodule repo * Make data folder a submodule * import icons and font from data submodule * Update README.md * total magix moment * magix moment v2 * submodule change * Import `.webp` files * Resize `HomeButton` * Fix 'Copy Command' reappearing after changing pages --------- Co-authored-by: KingRainbow44 <kobedo11@gmail.com>
This commit is contained in:
parent
964cc8143b
commit
4647d528e2
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
|||||||
[submodule "docs/wiki"]
|
[submodule "docs/wiki"]
|
||||||
path = docs/wiki
|
path = docs/wiki
|
||||||
url = https://github.com/Grasscutters/Grasscutter.wiki.git
|
url = https://github.com/Grasscutters/Grasscutter.wiki.git
|
||||||
|
[submodule "src/handbook/data/assets"]
|
||||||
|
path = src/handbook/data/assets
|
||||||
|
url = https://github.com/genshitters/gm-handbook-assets.git
|
||||||
|
@ -80,7 +80,7 @@ Grasscutter uses Gradle to handle dependencies & building.
|
|||||||
##### Windows
|
##### Windows
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git clone https://github.com/Grasscutters/Grasscutter.git
|
git clone --recurse-submodules -b unstable https://github.com/Grasscutters/Grasscutter.git
|
||||||
cd Grasscutter
|
cd Grasscutter
|
||||||
.\gradlew.bat # Setting up environments
|
.\gradlew.bat # Setting up environments
|
||||||
.\gradlew jar # Compile
|
.\gradlew jar # Compile
|
||||||
@ -89,7 +89,7 @@ cd Grasscutter
|
|||||||
##### Linux (GNU)
|
##### Linux (GNU)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/Grasscutters/Grasscutter.git
|
git clone --recurse-submodules -b unstable https://github.com/Grasscutters/Grasscutter.git
|
||||||
cd Grasscutter
|
cd Grasscutter
|
||||||
chmod +x gradlew
|
chmod +x gradlew
|
||||||
./gradlew jar # Compile
|
./gradlew jar # Compile
|
||||||
|
1
src/handbook/data/assets
Submodule
1
src/handbook/data/assets
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 4b823697f5a31312a03e20eb057a1a58e374df78
|
5
src/handbook/src/backend/files.d.ts
vendored
5
src/handbook/src/backend/files.d.ts
vendored
@ -2,6 +2,11 @@ declare module "*.svg" {
|
|||||||
export const ReactComponent: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
|
export const ReactComponent: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module "*.webp" {
|
||||||
|
const ref: string;
|
||||||
|
export default ref;
|
||||||
|
}
|
||||||
|
|
||||||
declare module "*.csv" {
|
declare module "*.csv" {
|
||||||
const content: any[];
|
const content: any[];
|
||||||
export default content;
|
export default content;
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Poppins';
|
||||||
|
src: url('/data/assets/Poppins-Regular.ttf')
|
||||||
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
--background-color: #346b77;
|
--background-color: #346b77;
|
||||||
--secondary-color: #418493;
|
--secondary-color: #418493;
|
||||||
@ -17,6 +22,7 @@ body {
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background-color: var(--background-color);
|
||||||
|
|
||||||
#root {
|
#root {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
.AvatarsPage {
|
.AvatarsPage {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
width: calc(100% - 352px);
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
|
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.AvatarsPage_Title {
|
.AvatarsPage_Title {
|
||||||
@ -21,13 +22,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.AvatarsPage_List {
|
.AvatarsPage_List {
|
||||||
display: grid;
|
display: flex;
|
||||||
gap: 15px 15px;
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 15px;
|
||||||
|
|
||||||
max-width: 90%;
|
max-width: 90%;
|
||||||
|
|
||||||
grid-template-columns: repeat(12, 100px);
|
|
||||||
|
|
||||||
margin-bottom: 28px;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
.HomePage {
|
.HomePage {
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
overflow-y: scroll;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
background-color: var(--background-color);
|
display:flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
gap: 50px;
|
||||||
|
|
||||||
|
background-color: var(--background-color);
|
||||||
|
|
||||||
div {
|
div {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -15,7 +19,6 @@
|
|||||||
.HomePage_Top {
|
.HomePage_Top {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 80%;
|
|
||||||
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -30,10 +33,8 @@
|
|||||||
|
|
||||||
.HomePage_Buttons {
|
.HomePage_Buttons {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 40%;
|
|
||||||
|
|
||||||
max-width: 1376px;
|
max-width: 1376px;
|
||||||
max-height: 256px;
|
|
||||||
|
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -42,11 +43,9 @@
|
|||||||
|
|
||||||
.HomePage_Bottom {
|
.HomePage_Bottom {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
height: 50%;
|
|
||||||
max-height: 125px;
|
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
margin-bottom: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.HomePage_Box {
|
.HomePage_Box {
|
||||||
@ -57,13 +56,11 @@
|
|||||||
.HomePage_Disclaimer {
|
.HomePage_Disclaimer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
gap: 30px;
|
||||||
background-color: var(--secondary-color);
|
background-color: var(--secondary-color);
|
||||||
|
|
||||||
width: 50%;
|
height: 100px;
|
||||||
height: 100%;
|
align-self: end;
|
||||||
max-width: 630px;
|
|
||||||
max-height: 93px;
|
|
||||||
|
|
||||||
margin: 0 0 0 60px;
|
margin: 0 0 0 60px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@ -71,29 +68,15 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 11px;
|
padding: 11px;
|
||||||
|
|
||||||
:nth-child(1) {
|
|
||||||
font-size: 24px;
|
|
||||||
max-height: 30px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-size: 18px;
|
font-size: 16px;
|
||||||
max-height: 40px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.HomePage_Discord {
|
.HomePage_Discord {
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
border-radius: 10px;
|
|
||||||
|
|
||||||
max-height: 40px;
|
|
||||||
max-width: 150px;
|
max-width: 150px;
|
||||||
height: 100%;
|
padding: 10px;
|
||||||
width: 100%;
|
border-radius: 10px;
|
||||||
|
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
@ -104,34 +87,26 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
max-width: 44px;
|
max-width: 44px;
|
||||||
max-height: 30px;
|
max-height: 30px;
|
||||||
|
|
||||||
fill: #5865F2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
max-width: 90px;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.HomePage_Discord:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
align-items: center;
|
background-color: #5865F2;
|
||||||
justify-content: center;
|
box-shadow: 0 0 10px 0 rgba(0,0,0,0.75);
|
||||||
|
}
|
||||||
max-height: 50px;
|
|
||||||
max-width: 160px;
|
|
||||||
|
|
||||||
background-color: #5865F2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.HomePage_Text {
|
.HomePage_Text {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
background-color: var(--secondary-color);
|
background-color: var(--secondary-color);
|
||||||
|
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
max-height: 80px;
|
|
||||||
|
|
||||||
margin: 13px 60px 0 0;
|
margin: 13px 60px 0 0;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@ -145,9 +120,6 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
|
|
||||||
max-height: 18px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
|
|
||||||
:nth-child(1) {
|
:nth-child(1) {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@ -161,11 +133,15 @@
|
|||||||
|
|
||||||
.HomePage_Links {
|
.HomePage_Links {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-direction: column;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: var(--text-primary-color);
|
color: var(--text-primary-color);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,11 +72,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ItemsPage_List {
|
.ItemsPage_List {
|
||||||
display: grid;
|
|
||||||
gap: 15px 15px;
|
|
||||||
|
|
||||||
grid-template-columns: repeat(15, 100px);
|
|
||||||
|
|
||||||
margin-bottom: 28px;
|
margin-bottom: 28px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,14 @@
|
|||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
|
transition: 0.1s ease-in-out all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ScenesPage_Button:hover {
|
.ScenesPage_Button:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ScenesPage_Button:active {
|
||||||
|
scale: 0.9;
|
||||||
|
}
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
padding-left: 27px;
|
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 1510px;
|
max-width: 1510px;
|
||||||
max-height: 100px;
|
|
||||||
|
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
@ -42,9 +41,7 @@
|
|||||||
|
|
||||||
.Card_Description {
|
.Card_Description {
|
||||||
color: var(--text-primary-color);
|
color: var(--text-primary-color);
|
||||||
|
padding-bottom: 5px;
|
||||||
overflow-y: scroll;
|
|
||||||
max-height: 24px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.Card_Button {
|
.Card_Button {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
max-width: 96px;
|
max-width: 96px;
|
||||||
max-height: 125px;
|
max-height: 135px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -11,6 +11,12 @@
|
|||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.1s ease-in-out all;
|
||||||
|
box-shadow: 0 0 10px 5px var(--accent-color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Character :hover {
|
.Character :hover {
|
||||||
@ -18,11 +24,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.Character_Icon {
|
.Character_Icon {
|
||||||
width: 100%;
|
width: 96px;
|
||||||
height: 100%;
|
height: 96px;
|
||||||
|
|
||||||
max-width: 96px;
|
|
||||||
max-height: 96px;
|
|
||||||
|
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
@ -35,7 +38,7 @@
|
|||||||
background-color: var(--secondary-color);
|
background-color: var(--secondary-color);
|
||||||
|
|
||||||
max-width: 100px;
|
max-width: 100px;
|
||||||
height: 30px;
|
height: 40px;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
.HomeButton {
|
.HomeButton {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
width: 100%;
|
width: 196px;
|
||||||
height: 100%;
|
height: 196px;
|
||||||
max-width: 256px;
|
|
||||||
max-height: 256px;
|
|
||||||
|
|
||||||
background-color: var(--secondary-color);
|
background-color: var(--secondary-color);
|
||||||
|
|
||||||
@ -15,10 +14,24 @@
|
|||||||
|
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.1s ease-in-out all;
|
||||||
|
box-shadow: 0 0 10px 5px var(--accent-color);
|
||||||
|
scale: 1.01;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.HomeButton:hover {
|
.HomeButton:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: 0.1s ease-in-out all;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 0 10px 5px var(--accent-color);
|
||||||
|
scale: 1.01;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.HomeButton_Icon {
|
.HomeButton_Icon {
|
||||||
@ -27,8 +40,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.HomeButton_Label {
|
.HomeButton_Label {
|
||||||
font-size: 34px;
|
font-size: 30px;
|
||||||
line-height: 44px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-style: normal;
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,13 @@
|
|||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
transition: 0.1s ease-in-out all;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
filter: brightness(0.9);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.MiniCard_Background {
|
.MiniCard_Background {
|
||||||
|
@ -147,8 +147,14 @@
|
|||||||
background-color: var(--secondary-color);
|
background-color: var(--secondary-color);
|
||||||
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
transition: 0.1s ease-in-out all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ObjectCard_Submit:hover {
|
.ObjectCard_Submit:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
scale: 1.05;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ObjectCard_Submit:active {
|
||||||
|
scale: 0.9;
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,17 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
|
padding-left: 27px;
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 64px;
|
height: 64px;
|
||||||
max-width: 300px;
|
|
||||||
max-height: 64px;
|
|
||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.1s ease-in-out all;
|
||||||
|
backdrop-filter: brightness(0.9);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.SideBarButton_Icon {
|
.SideBarButton_Icon {
|
||||||
|
@ -3,6 +3,7 @@ import React from "react";
|
|||||||
import emitter from "@backend/events";
|
import emitter from "@backend/events";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
|
initial: boolean;
|
||||||
event: string;
|
event: string;
|
||||||
text1: string;
|
text1: string;
|
||||||
text2: string;
|
text2: string;
|
||||||
|
@ -21,6 +21,7 @@ interface IProps<T> {
|
|||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
scrollTop: number;
|
scrollTop: number;
|
||||||
|
itemsPerRow: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
class VirtualizedGrid<T> extends React.Component<IProps<T>, IState> {
|
class VirtualizedGrid<T> extends React.Component<IProps<T>, IState> {
|
||||||
@ -28,7 +29,8 @@ class VirtualizedGrid<T> extends React.Component<IProps<T>, IState> {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
scrollTop: 0
|
scrollTop: 0,
|
||||||
|
itemsPerRow: 10
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ class VirtualizedGrid<T> extends React.Component<IProps<T>, IState> {
|
|||||||
const items: React.ReactNode[] = [];
|
const items: React.ReactNode[] = [];
|
||||||
|
|
||||||
// Calculate the items to render.
|
// Calculate the items to render.
|
||||||
const perRow = this.props.itemsPerRow ?? 10;
|
const perRow = this.state.itemsPerRow ?? 10;
|
||||||
for (let i = 0; i < perRow; i++) {
|
for (let i = 0; i < perRow; i++) {
|
||||||
const itemIndex = props.index * perRow + i;
|
const itemIndex = props.index * perRow + i;
|
||||||
if (itemIndex < this.props.list.length) {
|
if (itemIndex < this.props.list.length) {
|
||||||
@ -64,8 +66,20 @@ class VirtualizedGrid<T> extends React.Component<IProps<T>, IState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setState({
|
||||||
|
itemsPerRow: Math.floor((window.innerWidth - 650) / (this.props.itemHeight + (this.props.gap ?? 0)))
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("resize", () => {
|
||||||
|
this.setState({
|
||||||
|
itemsPerRow: Math.floor((window.innerWidth - 650) / (this.props.itemHeight + (this.props.gap ?? 0)))
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { list, itemHeight, itemsPerRow } = this.props;
|
const { list, itemHeight } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AutoSizer>
|
<AutoSizer>
|
||||||
@ -74,7 +88,7 @@ class VirtualizedGrid<T> extends React.Component<IProps<T>, IState> {
|
|||||||
height={height - 150}
|
height={height - 150}
|
||||||
width={width}
|
width={width}
|
||||||
rowHeight={itemHeight + (this.props.gap ?? 0)}
|
rowHeight={itemHeight + (this.props.gap ?? 0)}
|
||||||
rowCount={Math.ceil(list.length / (itemsPerRow ?? 10))}
|
rowCount={Math.ceil(list.length / (this.state.itemsPerRow ?? 10))}
|
||||||
rowRenderer={this.rowRender.bind(this)}
|
rowRenderer={this.rowRender.bind(this)}
|
||||||
scrollTop={this.state.scrollTop}
|
scrollTop={this.state.scrollTop}
|
||||||
onScroll={(e) => this.setState({ scrollTop: e.scrollTop })}
|
onScroll={(e) => this.setState({ scrollTop: e.scrollTop })}
|
||||||
|
@ -21,7 +21,6 @@ class CommandsPage extends React.PureComponent {
|
|||||||
command.name.length == 1 ? undefined : `(aka /${command.name.slice(1).join(", /")})`
|
command.name.length == 1 ? undefined : `(aka /${command.name.slice(1).join(", /")})`
|
||||||
}
|
}
|
||||||
description={command.description}
|
description={command.description}
|
||||||
height={75}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,6 +4,14 @@ import HomeButton from "@widgets/HomeButton";
|
|||||||
|
|
||||||
import { ReactComponent as DiscordLogo } from "@icons/discord.svg";
|
import { ReactComponent as DiscordLogo } from "@icons/discord.svg";
|
||||||
|
|
||||||
|
import Icon_Version_Highlights from "@assets/Icon_Version_Highlights.webp";
|
||||||
|
import Icon_Character_Lumine from "@assets/Icon_Character_Lumine.webp";
|
||||||
|
import Icon_Inventory from "@assets/Icon_Inventory.webp";
|
||||||
|
import Icon_Tutorial_Monster from "@assets/Icon_Tutorial_Monster.webp";
|
||||||
|
import Icon_Map from "@assets/Icon_Map.webp";
|
||||||
|
import Icon_Quests from "@assets/Icon_Quests.webp";
|
||||||
|
import Icon_Achievements from "@assets/Icon_Achievements.webp";
|
||||||
|
|
||||||
import { openUrl } from "@app/utils";
|
import { openUrl } from "@app/utils";
|
||||||
|
|
||||||
import "@css/pages/HomePage.scss";
|
import "@css/pages/HomePage.scss";
|
||||||
@ -20,26 +28,25 @@ class HomePage extends React.Component<any, any> {
|
|||||||
<h1 className={"HomePage_Title"}>Welcome back, Traveler~</h1>
|
<h1 className={"HomePage_Title"}>Welcome back, Traveler~</h1>
|
||||||
|
|
||||||
<div className={"HomePage_Buttons"}>
|
<div className={"HomePage_Buttons"}>
|
||||||
<HomeButton name={"Commands"} anchor={"Commands"} />
|
<HomeButton name={"Commands"} anchor={"Commands"} icon={Icon_Version_Highlights} />
|
||||||
<HomeButton name={"Characters"} anchor={"Avatars"} />
|
<HomeButton name={"Characters"} anchor={"Avatars"} icon={Icon_Character_Lumine} />
|
||||||
<HomeButton name={"Items"} anchor={"Items"} />
|
<HomeButton name={"Items"} anchor={"Items"} icon={Icon_Inventory} />
|
||||||
<HomeButton name={"Entities"} anchor={"Entities"} />
|
<HomeButton name={"Entities"} anchor={"Entities"} icon={Icon_Tutorial_Monster} />
|
||||||
<HomeButton name={"Scenes"} anchor={"Scenes"} />
|
<HomeButton name={"Scenes"} anchor={"Scenes"} icon={Icon_Map} />
|
||||||
</div>
|
<HomeButton name={"Quests"} anchor={"Home"} icon={Icon_Quests} />
|
||||||
|
<HomeButton name={"Achievements"} anchor={"Home"} icon={Icon_Achievements} />
|
||||||
<div className={"HomePage_Buttons"}>
|
|
||||||
<HomeButton name={"Quests"} anchor={"Home"} />
|
|
||||||
<HomeButton name={"Achievements"} anchor={"Home"} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={"HomePage_Bottom"}>
|
<div className={"HomePage_Bottom"}>
|
||||||
<div className={"HomePage_Box HomePage_Disclaimer"}>
|
<div className={"HomePage_Box HomePage_Disclaimer"}>
|
||||||
<div>
|
<p>
|
||||||
<p>This tool is not affiliated with HoYoverse.</p>
|
<b>This tool is not affiliated with HoYoverse.</b>
|
||||||
<p>Genshin Impact, game content and materials are</p>
|
<br />
|
||||||
<p>trademarks and copyrights of HoYoverse.</p>
|
Genshin Impact, game content and materials are
|
||||||
</div>
|
<br />
|
||||||
|
trademarks and copyrights of HoYoverse.
|
||||||
|
</p>
|
||||||
|
|
||||||
<div className={"HomePage_Discord"} onClick={() => openUrl("https://discord.gg/grasscutter")}>
|
<div className={"HomePage_Discord"} onClick={() => openUrl("https://discord.gg/grasscutter")}>
|
||||||
<DiscordLogo />
|
<DiscordLogo />
|
||||||
|
@ -2,10 +2,18 @@ import React, { ChangeEvent } from "react";
|
|||||||
|
|
||||||
import SideBarButton from "@app/ui/widgets/SideBarButton";
|
import SideBarButton from "@app/ui/widgets/SideBarButton";
|
||||||
|
|
||||||
import { navigate } from "@app/backend/events";
|
import Icon_Version_Highlights from "@assets/Icon_Version_Highlights.webp";
|
||||||
|
import Icon_Character_Lumine from "@assets/Icon_Character_Lumine.webp";
|
||||||
|
import Icon_Inventory from "@assets/Icon_Inventory.webp";
|
||||||
|
import Icon_Tutorial_Monster from "@assets/Icon_Tutorial_Monster.webp";
|
||||||
|
import Icon_Map from "@assets/Icon_Map.webp";
|
||||||
|
import Icon_Quests from "@assets/Icon_Quests.webp";
|
||||||
|
import Icon_Achievements from "@assets/Icon_Achievements.webp";
|
||||||
|
|
||||||
|
import { navigate } from "@backend/events";
|
||||||
|
import { setTargetPlayer } from "@backend/server";
|
||||||
|
|
||||||
import "@css/views/SideBar.scss";
|
import "@css/views/SideBar.scss";
|
||||||
import { setTargetPlayer } from "@backend/server";
|
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
uid: string | null;
|
uid: string | null;
|
||||||
@ -51,13 +59,13 @@ class SideBar extends React.Component<{}, IState> {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={"SideBar_Buttons"}>
|
<div className={"SideBar_Buttons"}>
|
||||||
<SideBarButton name={"Commands"} anchor={"Commands"} />
|
<SideBarButton name={"Commands"} anchor={"Commands"} icon={Icon_Version_Highlights} />
|
||||||
<SideBarButton name={"Characters"} anchor={"Avatars"} />
|
<SideBarButton name={"Characters"} anchor={"Avatars"} icon={Icon_Character_Lumine} />
|
||||||
<SideBarButton name={"Items"} anchor={"Items"} />
|
<SideBarButton name={"Items"} anchor={"Items"} icon={Icon_Inventory} />
|
||||||
<SideBarButton name={"Entities"} anchor={"Entities"} />
|
<SideBarButton name={"Entities"} anchor={"Entities"} icon={Icon_Tutorial_Monster} />
|
||||||
<SideBarButton name={"Scenes"} anchor={"Scenes"} />
|
<SideBarButton name={"Scenes"} anchor={"Scenes"} icon={Icon_Map} />
|
||||||
<SideBarButton name={"Quests"} anchor={"Home"} />
|
<SideBarButton name={"Quests"} anchor={"Home"} icon={Icon_Quests} />
|
||||||
<SideBarButton name={"Achievements"} anchor={"Home"} />
|
<SideBarButton name={"Achievements"} anchor={"Home"} icon={Icon_Achievements} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={"SideBar_Enter"}>
|
<div className={"SideBar_Enter"}>
|
||||||
|
@ -28,7 +28,10 @@ class Card extends React.PureComponent<IProps> {
|
|||||||
onClick={this.props.onClick}
|
onClick={this.props.onClick}
|
||||||
onMouseOver={this.props.onOver}
|
onMouseOver={this.props.onOver}
|
||||||
onMouseOut={this.props.onOut}
|
onMouseOut={this.props.onOut}
|
||||||
style={{ height: this.props.height }}
|
style={{
|
||||||
|
height: this.props.height,
|
||||||
|
cursor: this.props.onClick ? "pointer" : undefined
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className={"Card_Content"}>
|
<div className={"Card_Content"}>
|
||||||
<div className={"Card_Header"}>
|
<div className={"Card_Header"}>
|
||||||
|
@ -49,7 +49,7 @@ class Character extends React.PureComponent<IProps> {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={"Character_Label"}>
|
<div className={"Character_Label"}>
|
||||||
<p style={{ fontSize: characterName.length >= 12 ? 13 : 17 }}>{characterName}</p>
|
<p style={{ fontSize: characterName.length >= 10 ? 13 : 17 }}>{characterName}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -7,6 +7,7 @@ import "@css/widgets/HomeButton.scss";
|
|||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
name: string;
|
name: string;
|
||||||
|
icon: string;
|
||||||
anchor: Page;
|
anchor: Page;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ class HomeButton extends React.PureComponent<IProps> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className={"HomeButton"} onClick={() => this.redirect()}>
|
<div className={"HomeButton"} onClick={() => this.redirect()}>
|
||||||
<img className={"HomeButton_Icon"} src={"https://dummyimage.com/128x128"} alt={this.props.name} />
|
<img className={"HomeButton_Icon"} src={this.props.icon} alt={this.props.name} />
|
||||||
|
|
||||||
<p className={"HomeButton_Label"}>{this.props.name}</p>
|
<p className={"HomeButton_Label"}>{this.props.name}</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -163,7 +163,7 @@ class ItemCard extends React.Component<IProps, IState> {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button className={"ObjectCard_Submit"} onClick={this.addToInventory.bind(this)}>
|
<button className={"ObjectCard_Submit"} onClick={this.addToInventory.bind(this)}>
|
||||||
<TextState event={"connected"} text1={"Copy Command"} text2={"Add to Inventory"} />
|
<TextState initial={connected} event={"connected"} text1={"Copy Command"} text2={"Add to Inventory"} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -20,6 +20,9 @@ interface IState {
|
|||||||
class MiniCard extends React.Component<IProps, IState> {
|
class MiniCard extends React.Component<IProps, IState> {
|
||||||
loading: number | any;
|
loading: number | any;
|
||||||
|
|
||||||
|
containerRef: React.RefObject<HTMLDivElement>;
|
||||||
|
textRef: React.RefObject<HTMLDivElement>;
|
||||||
|
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@ -28,6 +31,9 @@ class MiniCard extends React.Component<IProps, IState> {
|
|||||||
icon: true,
|
icon: true,
|
||||||
loaded: false
|
loaded: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.containerRef = React.createRef();
|
||||||
|
this.textRef = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,8 +48,34 @@ class MiniCard extends React.Component<IProps, IState> {
|
|||||||
if (!this.state.loaded) this.replaceIcon();
|
if (!this.state.loaded) this.replaceIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the font size of the text to fit the container.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private adjustFontSize() {
|
||||||
|
const container = this.containerRef.current;
|
||||||
|
const text = this.textRef.current;
|
||||||
|
|
||||||
|
if (!container || !text) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const containerWidth = container.offsetWidth;
|
||||||
|
const textWidth = text.scrollWidth;
|
||||||
|
|
||||||
|
const fontSize = parseFloat(window.getComputedStyle(text).fontSize);
|
||||||
|
const availableWidth = containerWidth - 10;
|
||||||
|
const scaleFactor = availableWidth / textWidth;
|
||||||
|
|
||||||
|
if (scaleFactor < 1) {
|
||||||
|
const newFontSize = fontSize * scaleFactor;
|
||||||
|
text.style.fontSize = newFontSize + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.loading = setTimeout(this.forceReplace.bind(this), 1e3);
|
this.loading = setTimeout(this.forceReplace.bind(this), 1e3);
|
||||||
|
this.adjustFontSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
@ -54,7 +86,7 @@ class MiniCard extends React.Component<IProps, IState> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className={"MiniCard"} onClick={this.props.onClick}>
|
<div className={"MiniCard"} onClick={this.props.onClick}>
|
||||||
<div className={"MiniCard_Background"}>
|
<div className={"MiniCard_Background"} ref={this.containerRef}>
|
||||||
{this.state.icon && (
|
{this.state.icon && (
|
||||||
<img
|
<img
|
||||||
className={"MiniCard_Icon"}
|
className={"MiniCard_Icon"}
|
||||||
@ -66,7 +98,7 @@ class MiniCard extends React.Component<IProps, IState> {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{(!this.state.loaded || !this.state.icon) && (
|
{(!this.state.loaded || !this.state.icon) && (
|
||||||
<p className={"MiniCard_Label"}>{this.props.data.name}</p>
|
<p className={"MiniCard_Label"} ref={this.textRef}>{this.props.data.name}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,6 +7,7 @@ import "@css/widgets/SideBarButton.scss";
|
|||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
name: string;
|
name: string;
|
||||||
|
icon: string;
|
||||||
anchor: Page;
|
anchor: Page;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ class SideBarButton extends React.PureComponent<IProps> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className={"SideBarButton"} onClick={() => this.redirect()}>
|
<div className={"SideBarButton"} onClick={() => this.redirect()}>
|
||||||
<img className={"SideBarButton_Icon"} src={"https://dummyimage.com/128x128"} alt={this.props.name} />
|
<img className={"SideBarButton_Icon"} src={this.props.icon} alt={this.props.name} />
|
||||||
|
|
||||||
<p className={"SideBarButton_Label"}>{this.props.name}</p>
|
<p className={"SideBarButton_Label"}>{this.props.name}</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,8 @@
|
|||||||
"@pages/*": ["src/ui/pages/*"],
|
"@pages/*": ["src/ui/pages/*"],
|
||||||
"@widgets/*": ["src/ui/widgets/*"],
|
"@widgets/*": ["src/ui/widgets/*"],
|
||||||
"@components/*": ["src/ui/components/*"],
|
"@components/*": ["src/ui/components/*"],
|
||||||
"@data/*": ["data/*"]
|
"@data/*": ["data/*"],
|
||||||
|
"@assets/*": ["data/assets/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
|
Loading…
Reference in New Issue
Block a user