Skip to content

Commit 006f0ca

Browse files
committed
Improve homepage
1 parent 5cedf86 commit 006f0ca

5 files changed

Lines changed: 337 additions & 178 deletions

File tree

src/components/schema/ClassTree.tsx

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { useContext, useMemo } from "react";
22
import { Link } from "../Link";
33
import { styled } from "@linaria/react";
4-
import { Declaration, SchemaClass } from "../../data/types";
4+
import { Declaration, SchemaClass, SchemaEnum } from "../../data/types";
55
import { DeclarationsContext, declarationKey, schemaPath } from "./DeclarationsContext";
6+
import { CardBlock } from "./styles";
7+
import { ICONS_URL } from "../kind-icon/KindIcon";
68

79
interface TreeNode {
810
cls: SchemaClass;
@@ -84,19 +86,36 @@ const RootList = styled.ul`
8486
`;
8587

8688
const TreeHeading = styled.h1`
89+
display: flex;
90+
align-items: center;
91+
gap: 6px;
8792
margin: 0 0 8px;
8893
font-size: 18px;
8994
font-weight: 600;
9095
color: var(--text);
96+
97+
a {
98+
display: flex;
99+
}
100+
101+
svg {
102+
width: 24px;
103+
height: 24px;
104+
border-radius: 3px;
105+
}
91106
`;
92107

93-
const TreeContainer = styled.div`
94-
max-width: 560px;
95-
margin: 16px auto 0;
96-
padding: 16px 20px;
97-
background: var(--group);
98-
border: 1px solid var(--group-border);
99-
border-radius: 10px;
108+
const EnumsHeading = styled.h2`
109+
font-size: 14px;
110+
font-weight: 600;
111+
text-transform: uppercase;
112+
letter-spacing: 0.04em;
113+
color: var(--text-dim);
114+
margin: 12px 0 6px;
115+
`;
116+
117+
const TreeContainer = styled(CardBlock)`
118+
margin-top: 32px;
100119
overflow: hidden;
101120
`;
102121

@@ -127,23 +146,33 @@ function TreeNodeView({ node, game }: { node: TreeNode; game: string }) {
127146
export function ClassTree({ module }: { module?: string }) {
128147
const { declarations, game } = useContext(DeclarationsContext);
129148

130-
const classes = useMemo(() => {
131-
const result = new Map<string, SchemaClass>();
149+
const { classes, enums } = useMemo(() => {
150+
const classes = new Map<string, SchemaClass>();
151+
const enums: SchemaEnum[] = [];
132152
const modules = module ? [declarations.get(module)] : declarations.values();
133153
for (const moduleMap of modules) {
134154
if (!moduleMap) continue;
135155
for (const d of moduleMap.values()) {
136-
if (d.kind === "class") result.set(declarationKey(d.module, d.name), d);
156+
if (d.kind === "class") classes.set(declarationKey(d.module, d.name), d);
157+
else enums.push(d);
137158
}
138159
}
139-
return result;
160+
enums.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
161+
return { classes, enums };
140162
}, [declarations, module]);
141163

142164
const roots = useMemo(() => buildTree(classes, declarations), [classes, declarations]);
143165

144166
return (
145167
<TreeContainer>
146-
<TreeHeading>{module}</TreeHeading>
168+
<TreeHeading>
169+
<Link to={schemaPath(game)}>
170+
<svg width="24" height="24">
171+
<use href={`${ICONS_URL}#game-${game}`} />
172+
</svg>
173+
</Link>
174+
{module}
175+
</TreeHeading>
147176
<RootList>
148177
{roots.map((node) => (
149178
<TreeNodeView
@@ -153,6 +182,20 @@ export function ClassTree({ module }: { module?: string }) {
153182
/>
154183
))}
155184
</RootList>
185+
{enums.length > 0 && (
186+
<>
187+
<EnumsHeading>Enums</EnumsHeading>
188+
<RootList>
189+
{enums.map((e) => (
190+
<li key={declarationKey(e.module, e.name)}>
191+
<ClassLink to={schemaPath(game, e.module, e.name)} title={`enum in ${e.module}`}>
192+
{e.name}
193+
</ClassLink>
194+
</li>
195+
))}
196+
</RootList>
197+
</>
198+
)}
156199
</TreeContainer>
157200
);
158201
}

src/components/schema/ContentList.tsx

Lines changed: 10 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,23 @@
11
import React, { useContext, useMemo } from "react";
22
import { useParams } from "react-router";
3-
import { Link } from "../Link";
43
import { styled } from "@linaria/react";
54
import { ContentWrapper, ListItem, TextMessage } from "../layout/Content";
65
import { LazyList, ScrollableList } from "../Lists";
76
import { useFilteredData, useParsedSearch, searchDeclarations } from "../../utils/filtering";
87
import { DeclarationBreadcrumb } from "./Breadcrumb";
98
import { SchemaClassView } from "./SchemaClass";
109
import { SchemaEnumView } from "./SchemaEnum";
11-
import { ClassTree } from "./ClassTree";
1210
import { Declaration } from "../../data/types";
1311
import { INTRINSIC_MODULE } from "../../data/intrinsics";
1412
import { DeclarationsContext, declarationKey, schemaPath } from "./DeclarationsContext";
15-
import { GAME_LIST, GameId, getGameDef } from "../../games-list";
16-
import { SEARCH_TAGS } from "../search/SearchBox";
17-
import { KindIcon, ICONS_URL } from "../kind-icon/KindIcon";
18-
import { SectionLink } from "./styles";
19-
20-
const CardBlock = styled.div`
21-
max-width: 560px;
22-
margin: 16px auto 0;
23-
padding: 16px 20px;
24-
background: var(--group);
25-
border: 1px solid var(--group-border);
26-
border-radius: 10px;
27-
color: var(--text-dim);
28-
font-size: 16px;
29-
line-height: 1.6;
30-
`;
31-
32-
const InfoBlock = styled(CardBlock)`
33-
margin-top: 24px;
34-
35-
p {
36-
margin: 0;
37-
}
38-
39-
p + p {
40-
margin-top: 8px;
41-
}
42-
`;
43-
44-
const GameChip = styled(Link)`
45-
display: inline-flex;
46-
align-items: center;
47-
gap: 4px;
48-
padding: 2px 8px;
49-
border-radius: 6px;
50-
background: var(--group-members);
51-
border: 1px solid var(--group-border);
52-
color: var(--text);
53-
text-decoration: none;
54-
vertical-align: middle;
55-
transition: border-color 0.1s;
56-
57-
&:hover {
58-
border-color: var(--highlight);
59-
}
60-
61-
svg {
62-
width: 18px;
63-
height: 18px;
64-
border-radius: 4px;
65-
}
66-
`;
67-
68-
function GameList() {
69-
return (
70-
<>
71-
{GAME_LIST.map((g, i) => (
72-
<React.Fragment key={g.id}>
73-
{i > 0 && " "}
74-
<GameChip to={schemaPath(g.id)}>
75-
<svg width="24" height="24">
76-
<use href={`${ICONS_URL}#game-${g.id}`} />
77-
</svg>{" "}
78-
{g.name}
79-
</GameChip>
80-
</React.Fragment>
81-
))}
82-
</>
83-
);
84-
}
85-
86-
const InfoLink = styled.a`
87-
color: var(--highlight);
88-
89-
&:hover {
90-
color: var(--text);
91-
}
92-
`;
93-
94-
const SearchFiltersBlock = styled(CardBlock)`
95-
dl {
96-
margin: 0;
97-
}
98-
99-
dt {
100-
font-weight: 600;
101-
color: var(--text);
102-
}
103-
104-
dd {
105-
margin: 0 0 8px 12px;
106-
}
107-
108-
dd:last-child {
109-
margin-bottom: 0;
110-
}
111-
112-
code {
113-
background: var(--group-members);
114-
padding: 1px 5px;
115-
border-radius: 4px;
116-
font-size: 15px;
117-
}
118-
`;
13+
import { GameId, getGameDef } from "../../games-list";
14+
import { ICONS_URL } from "../kind-icon/KindIcon";
15+
import { CardBlock, SectionLink } from "./styles";
16+
import { ClassTree } from "./ClassTree";
17+
import { SchemaHome } from "./SchemaHome";
11918

12019
const ModuleChipsBlock = styled(CardBlock)`
20+
margin-top: 32px;
12121
display: flex;
12222
flex-wrap: wrap;
12323
gap: 5px;
@@ -172,7 +72,7 @@ function OtherGamesResults() {
17272
<OtherGameHeader>
17373
<svg width="24" height="24">
17474
<use href={`${ICONS_URL}#game-${gameId}`} />
175-
</svg>{" "}
75+
</svg>
17676
{gameInfo?.name}
17777
</OtherGameHeader>
17878
<DeclarationsContext.Provider value={{ ...ctx, game: gameId }}>
@@ -223,7 +123,7 @@ const renderSearchResult = (declaration: Declaration) => renderItem(declaration,
223123
export function ContentList() {
224124
const { declarations, metadata, error } = useContext(DeclarationsContext);
225125
const { data, isSearching } = useFilteredData(declarations);
226-
const { module } = useParams();
126+
const { game: gameParam, module } = useParams();
227127

228128
return (
229129
<ContentWrapper>
@@ -242,47 +142,8 @@ export function ContentList() {
242142
<TextMessage>{error}</TextMessage>
243143
) : (
244144
<>
245-
<TextMessage>Choose a class or enum from the sidebar, or use search...</TextMessage>
246-
<InfoBlock>
247-
<p>
248-
Source 2 includes a schema system that describes the engine's classes, fields, and
249-
enumerations along with their types, offsets, and metadata. These schemas
250-
comprehensively map engine internals, making them useful for modding and reverse
251-
engineering.
252-
</p>
253-
<p>
254-
Currently tracking: <GameList />
255-
</p>
256-
<p>
257-
The schemas displayed here are generated by{" "}
258-
<InfoLink href="https://github.com/ValveResourceFormat/DumpSource2">
259-
DumpSource2
260-
</InfoLink>{" "}
261-
and automatically updated by{" "}
262-
<InfoLink href="https://github.com/SteamTracking/GameTracking">GameTracking</InfoLink>
263-
. The code for this site is on{" "}
264-
<InfoLink href="https://github.com/ValveResourceFormat/SchemaExplorer">
265-
GitHub
266-
</InfoLink>
267-
.
268-
</p>
269-
</InfoBlock>
270-
<SearchFiltersBlock>
271-
<dl>
272-
<dt>Search by name, filters can be combined</dt>
273-
<dd>Type any text to match class, field, or enum names.</dd>
274-
{SEARCH_TAGS.map((t) => (
275-
<React.Fragment key={t.tag}>
276-
<dt>
277-
<KindIcon kind={t.icon} size="small" /> <code>{t.tag}</code>{" "}
278-
{t.description.toLowerCase()}
279-
</dt>
280-
<dd>{t.example}</dd>
281-
</React.Fragment>
282-
))}
283-
</dl>
284-
</SearchFiltersBlock>
285-
{module ? <ClassTree module={module} /> : <ModuleList />}
145+
<SchemaHome isRoot={!gameParam} />
146+
{module ? <ClassTree module={module} /> : gameParam && <ModuleList />}
286147
</>
287148
)}
288149
{data.length > 0 && metadata.revision > 0 && module !== INTRINSIC_MODULE && (

src/components/schema/CrossGameRefs.tsx

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,6 @@ const GameLink = styled(SectionLink)`
2424
}
2525
`;
2626

27-
const GameIconWrapper = styled.span`
28-
display: flex;
29-
flex-shrink: 0;
30-
31-
> svg {
32-
width: 18px;
33-
height: 18px;
34-
border-radius: 3px;
35-
}
36-
`;
37-
3827
const ModuleIconWrapper = styled.span`
3928
display: flex;
4029
flex-shrink: 0;
@@ -171,11 +160,9 @@ export function CrossGameRefs({ declaration }: { declaration: Declaration }) {
171160
: "Differs"
172161
}
173162
>
174-
<GameIconWrapper>
175-
<svg width="24" height="24">
176-
<use href={`${ICONS_URL}#game-${gameId}`} />
177-
</svg>
178-
</GameIconWrapper>
163+
<svg width="24" height="24">
164+
<use href={`${ICONS_URL}#game-${gameId}`} />
165+
</svg>
179166
{gameName}
180167
</GameLink>
181168
))}

0 commit comments

Comments
 (0)