Added more social stuff like previewing gardens and stuff! Pretty

awesome.
This commit is contained in:
sarah committed 2026-09-07 18:40:32 +02:00
1 parent d1721517cc
commit 56d70e8c0c
9 files changed
+2623 -43

No files matched your search

File diff suppressed because it is too large. Load diff
+6 -6
View File
@@ -147,12 +147,12 @@ async function RenderLeaderboard(
Rank.textContent =
Player.Rank + ".";
Username.textContent =
Player.Username;
ApplyPlayerColour(
Username,
Player.Colour
Username.appendChild(
CreateGardenerIdentity(
Player.Username,
Player.Colour,
Player.ProfilePicture
)
);
Dew.textContent =
+312 -3
View File
@@ -1,5 +1,17 @@
let SocialCurrentUsername = null;
let GardenerSearchRequest = 0;
let GardenerSearchTimer = null;
async function StartSocial() {
let CurrentUsername = null;
try {
await LoadGameContent();
} catch (Error) {
console.error(
"Couldn't load Garden content for Social:",
Error
);
}
try {
const Profile = await GetProfile();
@@ -8,7 +20,7 @@ async function StartSocial() {
Profile.Success &&
Profile.Username !== null
) {
CurrentUsername =
SocialCurrentUsername =
Profile.Username;
}
} catch (Error) {
@@ -18,12 +30,309 @@ async function StartSocial() {
);
}
BindGardenerSearch();
await RenderLeaderboard(
CurrentUsername
SocialCurrentUsername
);
}
function BindGardenerSearch() {
const Form =
document.getElementById(
"GardenerSearchForm"
);
const Input =
document.getElementById(
"GardenerSearchInput"
);
if (
Form === null ||
Input === null
) {
return;
}
Form.addEventListener(
"submit",
Event => {
Event.preventDefault();
SearchGardeners(
Input.value
);
}
);
Input.addEventListener(
"input",
() => {
if (GardenerSearchTimer !== null) {
clearTimeout(
GardenerSearchTimer
);
}
const Search =
Input.value.trim();
if (Search.length === 0) {
ClearGardenerSearch();
return;
}
GardenerSearchTimer =
setTimeout(
() => {
SearchGardeners(
Search
);
},
250
);
}
);
const Query =
new URLSearchParams(
window.location.search
);
const InitialSearch =
Query.get("Search")?.trim() ?? "";
if (InitialSearch.length > 0) {
Input.value = InitialSearch;
SearchGardeners(
InitialSearch
);
}
}
function ClearGardenerSearch() {
GardenerSearchRequest++;
const Results =
document.getElementById(
"GardenerSearchResults"
);
Results?.replaceChildren();
SetGardenerSearchMessage(
"Search for a gardener by username."
);
}
async function SearchGardeners(
SearchValue
) {
const Search =
String(SearchValue ?? "")
.trim();
if (Search.length === 0) {
ClearGardenerSearch();
return;
}
const RequestId =
++GardenerSearchRequest;
SetGardenerSearchMessage(
"Searching..."
);
try {
const Query =
new URLSearchParams({
Search: Search
});
const Response = await fetch(
ApiUrl +
"/Gardeners.php?" +
Query.toString(),
{
cache: "no-store"
}
);
const Result =
await Response.json();
if (RequestId !== GardenerSearchRequest) {
return;
}
if (!Result.Success) {
throw new Error(
Result.Error ??
"Couldn't search gardeners."
);
}
RenderGardenerSearchResults(
Array.isArray(Result.Gardeners)
? Result.Gardeners
: []
);
} catch (Error) {
if (RequestId !== GardenerSearchRequest) {
return;
}
console.error(
"Couldn't search gardeners:",
Error
);
document.getElementById(
"GardenerSearchResults"
)?.replaceChildren();
SetGardenerSearchMessage(
"Couldn't search gardeners."
);
}
}
function RenderGardenerSearchResults(
Gardeners
) {
const Results =
document.getElementById(
"GardenerSearchResults"
);
if (Results === null) {
return;
}
Results.replaceChildren();
if (Gardeners.length === 0) {
SetGardenerSearchMessage(
"No gardeners matched that search."
);
return;
}
for (const Gardener of Gardeners) {
Results.appendChild(
CreateGardenerSearchResult(
Gardener
)
);
}
SetGardenerSearchMessage(
Gardeners.length === 1
? "1 gardener found."
: Gardeners.length
.toLocaleString() +
" gardeners found."
);
}
function CreateGardenerSearchResult(
Gardener
) {
const Link =
document.createElement(
"a"
);
Link.className =
"PlantTile GardenerSearchResult";
Link.href =
GetGardenerPageUrl(
Gardener.Username
);
const Avatar =
CreateGardenerAvatar(
Gardener.ProfilePicture,
Gardener.Username,
"GardenerAvatarSearch"
);
const Details =
document.createElement(
"span"
);
Details.className =
"GardenerSearchResultDetails";
const Name =
document.createElement(
"strong"
);
Name.className =
"GardenerSearchResultName";
Name.textContent =
Gardener.Username;
ApplyPlayerColour(
Name,
Gardener.Colour
);
const Description =
document.createElement(
"span"
);
Description.className =
"GardenerSearchResultDescription";
Description.textContent =
typeof Gardener.Description ===
"string" &&
Gardener.Description.length > 0
? Gardener.Description
: "No description.";
Details.append(
Name,
Description
);
Link.append(
Avatar,
Details
);
return Link;
}
function SetGardenerSearchMessage(
Text
) {
const Message =
document.getElementById(
"GardenerSearchMessage"
);
if (Message !== null) {
Message.textContent = Text;
}
}
document.addEventListener(
"DOMContentLoaded",
StartSocial
+213
View File
@@ -191,6 +191,219 @@ function ApplyPlayerColour(
}
function GetGardenerProfilePictureSource(
ProfilePicture
) {
if (
ProfilePicture === null ||
typeof ProfilePicture !== "object" ||
Array.isArray(ProfilePicture) ||
typeof ProfilePicture.PlantKey !==
"string" ||
!Number.isInteger(
Number(
ProfilePicture.GrowthStage
)
)
) {
return null;
}
if (
typeof Plants === "undefined" ||
typeof GetPlantImageSources !==
"function"
) {
return null;
}
const Plant =
Plants[
ProfilePicture.PlantKey
];
if (Plant === undefined) {
return null;
}
const Images =
GetPlantImageSources(
Plant
);
const GrowthStage = Number(
ProfilePicture.GrowthStage
);
const RequestedSource =
Images[GrowthStage - 1];
if (
typeof RequestedSource ===
"string" &&
RequestedSource.length > 0
) {
return RequestedSource;
}
for (
let Index = Images.length - 1;
Index >= 0;
Index--
) {
if (
typeof Images[Index] ===
"string" &&
Images[Index].length > 0
) {
return Images[Index];
}
}
return null;
}
function CreateGardenerAvatar(
ProfilePicture,
Username = "",
AdditionalClass = null
) {
const Avatar =
document.createElement(
"span"
);
Avatar.className =
"PlantTile GardenerAvatar";
if (
typeof AdditionalClass ===
"string" &&
AdditionalClass.length > 0
) {
Avatar.classList.add(
AdditionalClass
);
}
if (Username.length > 0) {
Avatar.title =
Username +
"'s profile picture";
}
const ImageSource =
GetGardenerProfilePictureSource(
ProfilePicture
);
if (ImageSource !== null) {
const Image =
document.createElement(
"img"
);
Image.className =
"PlantSprite";
Image.src = ImageSource;
Image.alt = "";
Image.draggable = false;
Avatar.appendChild(
Image
);
return Avatar;
}
const Placeholder =
document.createElement(
"span"
);
Placeholder.className =
"GardenerAvatarPlaceholder";
Placeholder.textContent = "□";
Avatar.appendChild(
Placeholder
);
return Avatar;
}
function GetGardenerPageUrl(
Username
) {
const Query =
new URLSearchParams({
Username: Username
});
return (
"/Pages/Gardener.html?" +
Query.toString()
);
}
function CreateGardenerIdentity(
Username,
Colour,
ProfilePicture,
LinkToGardener = true
) {
const Container =
document.createElement(
LinkToGardener
? "a"
: "span"
);
Container.className =
"GardenerIdentity";
if (LinkToGardener) {
Container.href =
GetGardenerPageUrl(
Username
);
}
const Avatar =
CreateGardenerAvatar(
ProfilePicture,
Username
);
const Name =
document.createElement(
"span"
);
Name.className =
"GardenerIdentityName";
Name.textContent = Username;
ApplyPlayerColour(
Name,
Colour
);
Container.append(
Avatar,
Name
);
return Container;
}
async function GetProfile() {
const Response = await fetch(
ApiUrl + "/Profile.php",