mirror of
https://git.srhtnin.garden/sarah/srhtnin.github.io.git
synced 2026-10-14 18:58:11 +02:00
Added more social stuff like previewing gardens and stuff! Pretty
awesome.
This commit is contained in:
1 parent
d1721517cc
commit
56d70e8c0c
9 files changed
+2623
-43
No files matched your search
@@ -0,0 +1,228 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$PageTitle = "Gardener";
|
||||||
|
$PageSection = "Social";
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en" data-palette="CatppuccinMocha">
|
||||||
|
<?php require __DIR__ . "/Bits/Head.php"; ?>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<?php require __DIR__ . "/Bits/Navbar.php"; ?>
|
||||||
|
|
||||||
|
<main class="MainContainer">
|
||||||
|
<p class="GardenerBackLink">
|
||||||
|
<a href="/Pages/Social.html">Back to Social</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="GardenerHero">
|
||||||
|
<div id="GardenerAvatar"></div>
|
||||||
|
|
||||||
|
<div class="GardenerHeroText">
|
||||||
|
<h1 id="GardenerName">Gardener</h1>
|
||||||
|
|
||||||
|
<p id="GardenerDescription">
|
||||||
|
Loading gardener...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p
|
||||||
|
id="GardenerPageMessage"
|
||||||
|
class="PageMessage"
|
||||||
|
aria-live="polite"
|
||||||
|
>
|
||||||
|
Loading gardener...
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<section
|
||||||
|
id="GardenerStatsSection"
|
||||||
|
class="Panel SocialSection"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
<h2 class="PanelHeader PanelHeaderInset">Statistics</h2>
|
||||||
|
|
||||||
|
<div class="ProfileStatistics">
|
||||||
|
<div class="ProfileStatistic">
|
||||||
|
<span class="ProfileStatisticName">Current Dew</span>
|
||||||
|
<strong id="GardenerCurrentDew">0</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ProfileStatistic">
|
||||||
|
<span class="ProfileStatisticName">Lifetime Dew</span>
|
||||||
|
<strong id="GardenerLifetimeDew">0</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ProfileStatistic">
|
||||||
|
<span class="ProfileStatisticName">Plants discovered</span>
|
||||||
|
<strong id="GardenerPlantsDiscovered">0</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ProfileStatistic">
|
||||||
|
<span class="ProfileStatisticName">Mutations discovered</span>
|
||||||
|
<strong id="GardenerMutationsDiscovered">0</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ProfileStatistic">
|
||||||
|
<span class="ProfileStatisticName">Gardens owned</span>
|
||||||
|
<strong id="GardenerGardensOwned">0</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ProfileStatistic">
|
||||||
|
<span class="ProfileStatisticName">Active Garden size</span>
|
||||||
|
<strong id="GardenerActiveGardenSize">0×0</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p
|
||||||
|
id="GardenerStatsPrivateMessage"
|
||||||
|
class="ProfileMessage"
|
||||||
|
hidden
|
||||||
|
></p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
id="GardenerGardensSection"
|
||||||
|
class="Panel SocialSection"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
<div class="PanelHeader PanelHeaderInset GardenerSectionHeader">
|
||||||
|
<h2>Gardens</h2>
|
||||||
|
<span id="GardenerGardenPosition"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="GardenerGardenControls"
|
||||||
|
class="GardenerGardenControls"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
id="PreviousGardenerGardenButton"
|
||||||
|
class="ActionButton"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="GardenerGardenTitle">
|
||||||
|
<strong id="GardenerGardenName">Garden</strong>
|
||||||
|
<span id="GardenerGardenSize">0×0</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
id="NextGardenerGardenButton"
|
||||||
|
class="ActionButton"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="GardenGridViewport">
|
||||||
|
<div
|
||||||
|
id="GardenerGardenGrid"
|
||||||
|
class="GardenGrid GardenerGardenGrid"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p
|
||||||
|
id="GardenerGardensMessage"
|
||||||
|
class="ProfileMessage"
|
||||||
|
></p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
id="GardenerDonationSection"
|
||||||
|
class="Panel SocialSection InteractivePanel"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
<h2 class="PanelHeader PanelHeaderInset">Dew donation</h2>
|
||||||
|
|
||||||
|
<p id="GardenerDonationBalance"></p>
|
||||||
|
|
||||||
|
<form
|
||||||
|
id="GardenerDonationForm"
|
||||||
|
class="FormRow"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
id="GardenerDonationAmount"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
step="1"
|
||||||
|
inputmode="numeric"
|
||||||
|
placeholder="Dew amount"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
|
||||||
|
<button type="submit">
|
||||||
|
Donate Dew
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p
|
||||||
|
id="GardenerDonationMessage"
|
||||||
|
class="ProfileMessage"
|
||||||
|
aria-live="polite"
|
||||||
|
></p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
id="GardenerCommentsSection"
|
||||||
|
class="Panel SocialSection InteractivePanel"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
<h2 class="PanelHeader PanelHeaderInset">Comments</h2>
|
||||||
|
|
||||||
|
<form id="GardenerCommentForm">
|
||||||
|
<label for="GardenerCommentInput">
|
||||||
|
Leave a comment
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<textarea
|
||||||
|
id="GardenerCommentInput"
|
||||||
|
rows="3"
|
||||||
|
maxlength="1000"
|
||||||
|
placeholder="Write a comment..."
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
|
||||||
|
<div class="FormRow">
|
||||||
|
<button type="submit">
|
||||||
|
Leave comment
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p
|
||||||
|
id="GardenerCommentMessage"
|
||||||
|
class="ProfileMessage"
|
||||||
|
aria-live="polite"
|
||||||
|
></p>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="GardenerCommentList"
|
||||||
|
class="GardenerCommentList"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
id="LoadMoreGardenerCommentsButton"
|
||||||
|
class="ActionButton GardenerLoadMoreButton"
|
||||||
|
type="button"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
Load more comments
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script src="/Scripts/Garden/PlantImages.js"></script>
|
||||||
|
<script src="/Scripts/Garden/Plants.js"></script>
|
||||||
|
<script src="/Scripts/Garden/Mutations.js"></script>
|
||||||
|
<script src="/Scripts/Garden/Save.js"></script>
|
||||||
|
<script src="/Scripts/Garden/Content.js"></script>
|
||||||
|
<script src="/Scripts/Garden/Users.js"></script>
|
||||||
|
<script src="/Scripts/Garden/Gardener.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+42
-8
@@ -312,11 +312,12 @@ $PageSection = "Guide";
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
Your <a href="/Pages/Profile.html">Profile</a>
|
Your <a href="/Pages/Profile.html">Profile</a>
|
||||||
contains your username, colour, Garden display settings,
|
contains your username, colour, Gardener description,
|
||||||
statistics, and Account Key. Garden saves can sync through
|
plant profile picture, privacy settings, Garden display
|
||||||
the API, while the Account Key lets you use the same Garden
|
settings, statistics, and Account Key. Garden saves can
|
||||||
in another browser or on another device. It's basically
|
sync through the API, while the Account Key lets you use
|
||||||
just like logging into an account.
|
the same Garden in another browser or on another device.
|
||||||
|
It's basically just like logging into an account.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@@ -325,6 +326,36 @@ $PageSection = "Guide";
|
|||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
id="Social"
|
||||||
|
class="GuideSection"
|
||||||
|
>
|
||||||
|
<h2>Social and Gardener profiles</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <a href="/Pages/Social.html">Social</a> page lets
|
||||||
|
you search for other gardeners by username and open their
|
||||||
|
public Gardener page. Gardener profile pictures use a plant
|
||||||
|
and growth stage the player has discovered.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Gardener pages can show statistics and read-only previews
|
||||||
|
of every Garden the player owns. Players can independently
|
||||||
|
disable Garden previews, comments, Dew donations, and
|
||||||
|
public statistics from their Profile. Disabling public
|
||||||
|
statistics also hides the player from the Dew leaderboard.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Comments are simple messages left on a Gardener page. A
|
||||||
|
comment can be deleted by its author or by the owner of the
|
||||||
|
Gardener page. Dew donations transfer spendable Dew between
|
||||||
|
accounts, but donated Dew does not increase the recipient's
|
||||||
|
Lifetime Dew.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section
|
<section
|
||||||
id="Privacy"
|
id="Privacy"
|
||||||
class="GuideSection"
|
class="GuideSection"
|
||||||
@@ -343,9 +374,12 @@ $PageSection = "Guide";
|
|||||||
<p>
|
<p>
|
||||||
This browser stores your Account Key and a local copy
|
This browser stores your Account Key and a local copy
|
||||||
of your Garden save so the same account can keep working
|
of your Garden save so the same account can keep working
|
||||||
between visits. If you set a username, some profile
|
between visits. If you set a username, your Gardener can
|
||||||
information and statistics can also appear on the
|
be found through Social. Your username, profile colour,
|
||||||
public leaderboard.
|
description, and selected plant profile picture form the
|
||||||
|
basic public Gardener profile; the separate privacy
|
||||||
|
settings control Garden previews, comments, Dew donations,
|
||||||
|
and public statistics.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
+9
-7
@@ -25,7 +25,7 @@ $PageTitle = "Profile";
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
id="Player"
|
id="Player"
|
||||||
class="Panel ProfileSection"
|
class="Panel ProfileSection InteractivePanel"
|
||||||
>
|
>
|
||||||
<h2 class="PanelHeader PanelHeaderInset">Player</h2>
|
<h2 class="PanelHeader PanelHeaderInset">Player</h2>
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ $PageTitle = "Profile";
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
id="GardenerProfile"
|
id="GardenerProfile"
|
||||||
class="Panel ProfileSection"
|
class="Panel ProfileSection InteractivePanel"
|
||||||
>
|
>
|
||||||
<h2 class="PanelHeader PanelHeaderInset">Gardener profile</h2>
|
<h2 class="PanelHeader PanelHeaderInset">Gardener profile</h2>
|
||||||
|
|
||||||
@@ -226,6 +226,8 @@ $PageTitle = "Profile";
|
|||||||
<p>
|
<p>
|
||||||
Choose which parts of your Gardener profile
|
Choose which parts of your Gardener profile
|
||||||
other players will be able to use or view.
|
other players will be able to use or view.
|
||||||
|
Hiding statistics also removes you from the
|
||||||
|
public Dew leaderboard.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="ProfileButtonRow">
|
<div class="ProfileButtonRow">
|
||||||
@@ -267,7 +269,7 @@ $PageTitle = "Profile";
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
id="GardenDisplay"
|
id="GardenDisplay"
|
||||||
class="Panel ProfileSection"
|
class="Panel ProfileSection InteractivePanel"
|
||||||
>
|
>
|
||||||
<h2 class="PanelHeader PanelHeaderInset">Garden display</h2>
|
<h2 class="PanelHeader PanelHeaderInset">Garden display</h2>
|
||||||
|
|
||||||
@@ -411,7 +413,7 @@ $PageTitle = "Profile";
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
id="Statistics"
|
id="Statistics"
|
||||||
class="Panel ProfileSection"
|
class="Panel ProfileSection InteractivePanel"
|
||||||
>
|
>
|
||||||
<h3 class="PanelHeader PanelHeaderInset">Statistics</h3>
|
<h3 class="PanelHeader PanelHeaderInset">Statistics</h3>
|
||||||
|
|
||||||
@@ -481,7 +483,7 @@ $PageTitle = "Profile";
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
id="Contact"
|
id="Contact"
|
||||||
class="Panel ProfileSection"
|
class="Panel ProfileSection InteractivePanel"
|
||||||
>
|
>
|
||||||
<h2 class="PanelHeader PanelHeaderInset">Contact</h2>
|
<h2 class="PanelHeader PanelHeaderInset">Contact</h2>
|
||||||
|
|
||||||
@@ -501,7 +503,7 @@ $PageTitle = "Profile";
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
id="Account"
|
id="Account"
|
||||||
class="Panel ProfileSection"
|
class="Panel ProfileSection InteractivePanel"
|
||||||
>
|
>
|
||||||
<h2 class="PanelHeader PanelHeaderInset">Account</h2>
|
<h2 class="PanelHeader PanelHeaderInset">Account</h2>
|
||||||
|
|
||||||
@@ -610,7 +612,7 @@ $PageTitle = "Profile";
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
id="Import"
|
id="Import"
|
||||||
class="Panel ProfileSection"
|
class="Panel ProfileSection InteractivePanel"
|
||||||
>
|
>
|
||||||
<h3 class="PanelHeader PanelHeaderInset">Import Account</h3>
|
<h3 class="PanelHeader PanelHeaderInset">Import Account</h3>
|
||||||
|
|
||||||
|
|||||||
+53
-1
@@ -16,6 +16,54 @@ $PageSection = "Social";
|
|||||||
<main class="MainContainer">
|
<main class="MainContainer">
|
||||||
<h1>Social</h1>
|
<h1>Social</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Find other gardeners, visit their public profiles,
|
||||||
|
preview their Gardens, leave comments, and donate Dew
|
||||||
|
when they allow it.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<section
|
||||||
|
id="GardenerSearch"
|
||||||
|
class="Panel SocialSection"
|
||||||
|
>
|
||||||
|
<h2 class="PanelHeader PanelHeaderInset">Find gardeners</h2>
|
||||||
|
|
||||||
|
<form
|
||||||
|
id="GardenerSearchForm"
|
||||||
|
class="CatalogueControls"
|
||||||
|
role="search"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
id="GardenerSearchInput"
|
||||||
|
type="search"
|
||||||
|
maxlength="64"
|
||||||
|
placeholder="Search usernames..."
|
||||||
|
aria-label="Search gardeners by username"
|
||||||
|
autocomplete="off"
|
||||||
|
>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="ActionButton"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Search
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="GardenerSearchResults"
|
||||||
|
class="GardenerSearchResults"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<p
|
||||||
|
id="GardenerSearchMessage"
|
||||||
|
class="PageMessage"
|
||||||
|
aria-live="polite"
|
||||||
|
>
|
||||||
|
Search for a gardener by username.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section
|
<section
|
||||||
id="Leaderboard"
|
id="Leaderboard"
|
||||||
class="Panel Leaderboard"
|
class="Panel Leaderboard"
|
||||||
@@ -31,7 +79,7 @@ $PageSection = "Social";
|
|||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Username
|
Gardener
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th class="LeaderboardDewColumn">
|
<th class="LeaderboardDewColumn">
|
||||||
@@ -46,7 +94,11 @@ $PageSection = "Social";
|
|||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<script src="/Scripts/Garden/PlantImages.js"></script>
|
||||||
|
<script src="/Scripts/Garden/Plants.js"></script>
|
||||||
|
<script src="/Scripts/Garden/Mutations.js"></script>
|
||||||
<script src="/Scripts/Garden/Save.js"></script>
|
<script src="/Scripts/Garden/Save.js"></script>
|
||||||
|
<script src="/Scripts/Garden/Content.js"></script>
|
||||||
<script src="/Scripts/Garden/Users.js"></script>
|
<script src="/Scripts/Garden/Users.js"></script>
|
||||||
<script src="/Scripts/Garden/Leaderboard.js"></script>
|
<script src="/Scripts/Garden/Leaderboard.js"></script>
|
||||||
<script src="/Scripts/Garden/Social.js"></script>
|
<script src="/Scripts/Garden/Social.js"></script>
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -147,12 +147,12 @@ async function RenderLeaderboard(
|
|||||||
Rank.textContent =
|
Rank.textContent =
|
||||||
Player.Rank + ".";
|
Player.Rank + ".";
|
||||||
|
|
||||||
Username.textContent =
|
Username.appendChild(
|
||||||
Player.Username;
|
CreateGardenerIdentity(
|
||||||
|
Player.Username,
|
||||||
ApplyPlayerColour(
|
Player.Colour,
|
||||||
Username,
|
Player.ProfilePicture
|
||||||
Player.Colour
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
Dew.textContent =
|
Dew.textContent =
|
||||||
|
|||||||
+312
-3
@@ -1,5 +1,17 @@
|
|||||||
|
let SocialCurrentUsername = null;
|
||||||
|
let GardenerSearchRequest = 0;
|
||||||
|
let GardenerSearchTimer = null;
|
||||||
|
|
||||||
|
|
||||||
async function StartSocial() {
|
async function StartSocial() {
|
||||||
let CurrentUsername = null;
|
try {
|
||||||
|
await LoadGameContent();
|
||||||
|
} catch (Error) {
|
||||||
|
console.error(
|
||||||
|
"Couldn't load Garden content for Social:",
|
||||||
|
Error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const Profile = await GetProfile();
|
const Profile = await GetProfile();
|
||||||
@@ -8,7 +20,7 @@ async function StartSocial() {
|
|||||||
Profile.Success &&
|
Profile.Success &&
|
||||||
Profile.Username !== null
|
Profile.Username !== null
|
||||||
) {
|
) {
|
||||||
CurrentUsername =
|
SocialCurrentUsername =
|
||||||
Profile.Username;
|
Profile.Username;
|
||||||
}
|
}
|
||||||
} catch (Error) {
|
} catch (Error) {
|
||||||
@@ -18,12 +30,309 @@ async function StartSocial() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BindGardenerSearch();
|
||||||
|
|
||||||
await RenderLeaderboard(
|
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(
|
document.addEventListener(
|
||||||
"DOMContentLoaded",
|
"DOMContentLoaded",
|
||||||
StartSocial
|
StartSocial
|
||||||
|
|||||||
@@ -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() {
|
async function GetProfile() {
|
||||||
const Response = await fetch(
|
const Response = await fetch(
|
||||||
ApiUrl + "/Profile.php",
|
ApiUrl + "/Profile.php",
|
||||||
|
|||||||
+276
-18
@@ -1020,7 +1020,7 @@ input, button, textarea, select {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection {
|
.ProfileSection, .SocialSection {
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
}
|
}
|
||||||
@@ -1029,7 +1029,7 @@ input, button, textarea, select {
|
|||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileFormRow, .ProfileButtonRow {
|
.FormRow, .ProfileFormRow, .ProfileButtonRow {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
@@ -1040,13 +1040,13 @@ input, button, textarea, select {
|
|||||||
margin-top: 0.75rem;
|
margin-top: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection label {
|
.InteractivePanel label {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
color: var(--Blue);
|
color: var(--Blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection input, .ProfileSection textarea, .ProfileSection select, .ProfileSection button {
|
.InteractivePanel input, .InteractivePanel textarea, .InteractivePanel select, .InteractivePanel button {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: var(--Text);
|
color: var(--Text);
|
||||||
background-color: var(--Surface0);
|
background-color: var(--Surface0);
|
||||||
@@ -1055,46 +1055,46 @@ input, button, textarea, select {
|
|||||||
appearance: none;
|
appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection input, .ProfileSection textarea, .ProfileSection select {
|
.InteractivePanel input, .InteractivePanel textarea, .InteractivePanel select {
|
||||||
padding: 0.6rem;
|
padding: 0.6rem;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection input {
|
.InteractivePanel input {
|
||||||
min-width: 12rem;
|
min-width: 12rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection select {
|
.InteractivePanel select {
|
||||||
appearance: auto;
|
appearance: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection textarea {
|
.InteractivePanel textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 24rem;
|
max-width: 24rem;
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection input::placeholder, .ProfileSection textarea::placeholder {
|
.InteractivePanel input::placeholder, .InteractivePanel textarea::placeholder {
|
||||||
color: var(--Overlay1);
|
color: var(--Overlay1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection input:hover, .ProfileSection textarea:hover, .ProfileSection select:hover {
|
.InteractivePanel input:hover, .InteractivePanel textarea:hover, .InteractivePanel select:hover {
|
||||||
background-color: var(--Surface1);
|
background-color: var(--Surface1);
|
||||||
border-color: var(--Overlay2);
|
border-color: var(--Overlay2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection input:focus, .ProfileSection textarea:focus, .ProfileSection select:focus {
|
.InteractivePanel input:focus, .InteractivePanel textarea:focus, .InteractivePanel select:focus {
|
||||||
background-color: var(--Surface1);
|
background-color: var(--Surface1);
|
||||||
border-color: var(--Sky);
|
border-color: var(--Sky);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection button {
|
.InteractivePanel button {
|
||||||
padding: 0.6rem 0.8rem;
|
padding: 0.6rem 0.8rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 3px 3px 0 var(--Crust);
|
box-shadow: 3px 3px 0 var(--Crust);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection button:hover {
|
.InteractivePanel button:hover:not(:disabled) {
|
||||||
color: var(--Sky);
|
color: var(--Sky);
|
||||||
background-color: var(--Surface1);
|
background-color: var(--Surface1);
|
||||||
border-color: var(--Sky);
|
border-color: var(--Sky);
|
||||||
@@ -1102,7 +1102,7 @@ input, button, textarea, select {
|
|||||||
box-shadow: 2px 2px 0 var(--Crust);
|
box-shadow: 2px 2px 0 var(--Crust);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection button:disabled {
|
.InteractivePanel button:disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
color: var(--Overlay1);
|
color: var(--Overlay1);
|
||||||
background-color: var(--Surface0);
|
background-color: var(--Surface0);
|
||||||
@@ -1110,7 +1110,7 @@ input, button, textarea, select {
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection button:active {
|
.InteractivePanel button:active:not(:disabled) {
|
||||||
color: var(--Green);
|
color: var(--Green);
|
||||||
background-color: var(--Surface2);
|
background-color: var(--Surface2);
|
||||||
border-color: var(--Green);
|
border-color: var(--Green);
|
||||||
@@ -1118,7 +1118,7 @@ input, button, textarea, select {
|
|||||||
box-shadow: 1px 1px 0 var(--Crust);
|
box-shadow: 1px 1px 0 var(--Crust);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection button:focus-visible, .ProfileSection summary:focus-visible {
|
.InteractivePanel button:focus-visible, .InteractivePanel summary:focus-visible {
|
||||||
outline: 3px solid var(--Yellow);
|
outline: 3px solid var(--Yellow);
|
||||||
outline-offset: 3px;
|
outline-offset: 3px;
|
||||||
}
|
}
|
||||||
@@ -1259,12 +1259,12 @@ input, button, textarea, select {
|
|||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileFormRow, .ProfileButtonRow {
|
.FormRow, .ProfileFormRow, .ProfileButtonRow {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileSection input, .ProfileSection textarea, .ProfileSection select, .ProfileSection button {
|
.InteractivePanel input, .InteractivePanel textarea, .InteractivePanel select, .InteractivePanel button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1609,6 +1609,264 @@ input, button, textarea, select {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* * Garden social */
|
||||||
|
|
||||||
|
.GardenerAvatar {
|
||||||
|
display: flex;
|
||||||
|
width: 3rem;
|
||||||
|
height: 3rem;
|
||||||
|
flex: 0 0 3rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerAvatarPlaceholder {
|
||||||
|
color: var(--Overlay1);
|
||||||
|
font-size: 1.75rem;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerIdentity {
|
||||||
|
display: inline-flex;
|
||||||
|
min-width: 0;
|
||||||
|
gap: 0.65rem;
|
||||||
|
align-items: center;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerIdentityName {
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerIdentity:hover .GardenerIdentityName {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerSearchResults {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerSearchResult {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto minmax(0, 1fr);
|
||||||
|
gap: 0.85rem;
|
||||||
|
padding: 0.75rem;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--Text);
|
||||||
|
text-decoration: none;
|
||||||
|
box-shadow: 3px 3px 0 var(--Crust);
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerSearchResult:hover {
|
||||||
|
color: var(--Text);
|
||||||
|
background-color: var(--Surface1);
|
||||||
|
border-color: var(--Sky);
|
||||||
|
transform: translate(1px, 1px);
|
||||||
|
box-shadow: 2px 2px 0 var(--Crust);
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerAvatarSearch {
|
||||||
|
width: 4.25rem;
|
||||||
|
height: 4.25rem;
|
||||||
|
flex-basis: 4.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerSearchResultDetails {
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerSearchResultName {
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 1.35rem;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerSearchResultDescription {
|
||||||
|
display: -webkit-box;
|
||||||
|
overflow: hidden;
|
||||||
|
color: var(--Subtext1);
|
||||||
|
line-height: 1.35;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerBackLink {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerHero {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto minmax(0, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerHeroText {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerHeroText h1 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerHeroText p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerAvatarHero {
|
||||||
|
width: 7rem;
|
||||||
|
height: 7rem;
|
||||||
|
flex-basis: 7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerSectionHeader {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerGardenControls {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(7rem, auto) minmax(0, 1fr) minmax(7rem, auto);
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerGardenTitle {
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.2rem;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerGardenTitle strong {
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerGardenTitle span,
|
||||||
|
.GardenerSectionHeader span {
|
||||||
|
color: var(--Subtext1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenPlotReadOnly,
|
||||||
|
.GardenPlotReadOnly:hover {
|
||||||
|
cursor: default;
|
||||||
|
transform: none;
|
||||||
|
box-shadow: 3px 3px 0 var(--Crust);
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenPlotReadOnly:hover {
|
||||||
|
--TileBackground: var(--Surface0);
|
||||||
|
--PlotBorderColour: var(--Surface2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenPlotReadOnly.GardenPlotEmpty:hover {
|
||||||
|
--TileBackground: var(--Mantle);
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenPlotReadOnly.GardenPlotMature:hover {
|
||||||
|
--GrowthColour: var(--Green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerCommentList {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerComment {
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerCommentHeader {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.75rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerCommentTime {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
color: var(--Overlay1);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerCommentText {
|
||||||
|
margin: 0.75rem 0 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.InteractivePanel .GardenerCommentDelete {
|
||||||
|
width: auto;
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerCommentsEmpty {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--Subtext1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerLoadMoreButton {
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.LeaderboardTable {
|
||||||
|
font-size: 1.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.LeaderboardUsername .GardenerAvatar {
|
||||||
|
width: 3.25rem;
|
||||||
|
height: 3.25rem;
|
||||||
|
flex-basis: 3.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.LeaderboardUsername .GardenerIdentity {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.GardenerAvatarHero {
|
||||||
|
width: 5.5rem;
|
||||||
|
height: 5.5rem;
|
||||||
|
flex-basis: 5.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerGardenControls {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerGardenTitle {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
grid-row: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerCommentHeader {
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GardenerCommentTime {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* * Garden guide */
|
/* * Garden guide */
|
||||||
|
|
||||||
.GuideSection {
|
.GuideSection {
|
||||||
|
|||||||
Reference in new issue
Block a user