Skip to content

Commit f1759cd

Browse files
committed
Big updates
too many things
1 parent 68a6d99 commit f1759cd

18 files changed

Lines changed: 443 additions & 1815 deletions

gifs/Hazel.gif

32.5 KB
Loading

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@
403403
</style>
404404
</head>
405405
<body>
406+
<script src="/js/page-loader.js"></script>
406407
<main class="shell">
407408
<section class="gate-card">
408409
<div class="brand-mark">Noctive</div>

js/admin-config.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
export const ADMIN_CONFIG = {
2+
uids: [
3+
"TljwjuBuKvd6VG9e0Mz81y7ZRgi1",
4+
"G6RyacKuSUTLXniBWRC1WsAm4Rq2"
5+
],
6+
emails: [
7+
"noctivehq@gmail.com"
8+
],
9+
usernames: [
10+
"venus"
11+
]
12+
};
13+
14+
export function normalizeAdminValue(value) {
15+
return String(value || "").trim().toLowerCase();
16+
}
17+
18+
export function isAdminIdentity(identity = {}) {
19+
const uid = String(identity.uid || "").trim();
20+
const email = normalizeAdminValue(identity.email);
21+
const username = normalizeAdminValue(identity.username);
22+
const displayName = normalizeAdminValue(identity.displayName);
23+
24+
if (uid && ADMIN_CONFIG.uids.includes(uid)) {
25+
return true;
26+
}
27+
28+
if (email && ADMIN_CONFIG.emails.map(normalizeAdminValue).includes(email)) {
29+
return true;
30+
}
31+
32+
const adminUsernames = ADMIN_CONFIG.usernames.map(normalizeAdminValue);
33+
return adminUsernames.includes(username) || adminUsernames.includes(displayName);
34+
}

js/main.js

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
getAuth,
1616
onAuthStateChanged
1717
} from "https://www.gstatic.com/firebasejs/10.12.2/firebase-auth.js";
18+
import { isAdminIdentity } from "./admin-config.js";
1819

1920
console.log("main.js loaded");
2021

@@ -28,19 +29,6 @@ const BIO_MAX_LENGTH = 180;
2829
const ACCESS_MODE_SESSION_KEY = "noctive_access_mode";
2930
const GUEST_PREVIEW_MODE = "guest";
3031

31-
const ADMIN_CONFIG = {
32-
uids: [
33-
"TljwjuBuKvd6VG9e0Mz81y7ZRgi1",
34-
"G6RyacKuSUTLXniBWRC1WsAm4Rq2"
35-
],
36-
emails: [
37-
"noctivehq@gmail.com"
38-
],
39-
usernames: [
40-
"venus"
41-
]
42-
};
43-
4432
function isGuestPreviewSession() {
4533
try {
4634
return window.sessionStorage.getItem(ACCESS_MODE_SESSION_KEY) === GUEST_PREVIEW_MODE;
@@ -50,28 +38,6 @@ function isGuestPreviewSession() {
5038
}
5139
}
5240

53-
function normalizeAdminValue(value) {
54-
return String(value || "").trim().toLowerCase();
55-
}
56-
57-
function isAdminIdentity(identity = {}) {
58-
const uid = String(identity.uid || "").trim();
59-
const email = normalizeAdminValue(identity.email);
60-
const username = normalizeAdminValue(identity.username);
61-
const displayName = normalizeAdminValue(identity.displayName);
62-
63-
if (uid && ADMIN_CONFIG.uids.includes(uid)) {
64-
return true;
65-
}
66-
67-
if (email && ADMIN_CONFIG.emails.map(normalizeAdminValue).includes(email)) {
68-
return true;
69-
}
70-
71-
const adminUsernames = ADMIN_CONFIG.usernames.map(normalizeAdminValue);
72-
return adminUsernames.includes(username) || adminUsernames.includes(displayName);
73-
}
74-
7541
function getSavedProfile(uid) {
7642
if (!uid) return null;
7743

@@ -138,6 +104,11 @@ function stripLegacyBio(value) {
138104
return bio;
139105
}
140106

107+
function getBannerHeadline(username, displayName = "Noctive User") {
108+
const safeDisplayName = String(displayName || "").trim() || "Noctive User";
109+
return `${safeDisplayName} is Alive After Dark`;
110+
}
111+
141112
function syncPublicProfileFromPost(uid, profile = {}) {
142113
const normalizedUid = normalizeUid(uid);
143114
if (!normalizedUid) return;
@@ -166,7 +137,7 @@ function syncPublicProfileFromPost(uid, profile = {}) {
166137
bio: stripLegacyBio(existing.bio || profile.bio || ""),
167138
theme: existing.theme || profile.theme || "default",
168139
avatar: existing.avatar ?? profile.avatar ?? "",
169-
bannerTitle: existing.bannerTitle || profile.bannerTitle || `${displayName} is on Noctive.`,
140+
bannerTitle: existing.bannerTitle || profile.bannerTitle || getBannerHeadline(username, displayName),
170141
bannerText:
171142
existing.bannerText ||
172143
profile.bannerText ||
@@ -355,9 +326,7 @@ function buildPostCard(doc) {
355326
bio: clampBio(postIsAdmin
356327
? `${resolvedProfile.displayName} is an official Noctive account.`
357328
: `${resolvedProfile.displayName} is active on Noctive.`),
358-
bannerTitle: postIsAdmin
359-
? `${resolvedProfile.displayName} is part of the official Noctive team.`
360-
: `${resolvedProfile.displayName} is on Noctive.`,
329+
bannerTitle: getBannerHeadline(resolvedProfile.username, resolvedProfile.displayName),
361330
bannerText: postIsAdmin
362331
? `${resolvedProfile.displayName} posts official updates and community notes on Noctive.`
363332
: "",

js/page-loader.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
(function () {
2+
if (window.__noctivePageLoaderBooted) return;
3+
window.__noctivePageLoaderBooted = true;
4+
5+
var startTime = Date.now();
6+
var minVisibleMs = 420;
7+
8+
var style = document.createElement("style");
9+
style.textContent = [
10+
"html.noctive-loader-active, body.noctive-loader-active { overflow: hidden !important; }",
11+
".noctive-loader-overlay { position: fixed; inset: 0; z-index: 9999; display: grid; place-items: center; background: radial-gradient(circle at 50% 30%, rgba(71, 66, 121, 0.26), rgba(11, 12, 25, 0.97) 62%), linear-gradient(180deg, #15142a 0%, #0b0b17 100%); opacity: 1; transition: opacity 220ms ease; }",
12+
".noctive-loader-overlay.is-exiting { opacity: 0; pointer-events: none; }",
13+
".noctive-loader-shell { display: grid; justify-items: center; gap: 18px; padding: 28px 30px 24px; border-radius: 28px; border: 1px solid rgba(255,255,255,0.08); background: linear-gradient(180deg, rgba(29, 28, 54, 0.96), rgba(17, 17, 31, 0.96)); box-shadow: 0 24px 80px rgba(0,0,0,0.42); }",
14+
".noctive-loader-cat-frame { width: 180px; height: 136px; display: grid; place-items: center; border-radius: 24px; background: linear-gradient(180deg, #fbfbff 0%, #eef0f8 100%); box-shadow: inset 0 0 0 1px rgba(19, 22, 41, 0.06); overflow: hidden; }",
15+
".noctive-loader-cat { width: 124px; height: 100px; transform-origin: center bottom; animation: noctiveLoaderBob 900ms ease-in-out infinite; image-rendering: pixelated; }",
16+
".noctive-loader-copy { font-family: 'Inter', system-ui, sans-serif; font-size: 0.95rem; letter-spacing: 0.08em; text-transform: uppercase; color: rgba(255,255,255,0.76); }",
17+
".noctive-loader-copy strong { color: #ffd763; font-weight: 700; }",
18+
"@keyframes noctiveLoaderBob { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-4px); } }"
19+
].join("");
20+
document.head.appendChild(style);
21+
22+
document.documentElement.classList.add("noctive-loader-active");
23+
document.body.classList.add("noctive-loader-active");
24+
25+
var overlay = document.createElement("div");
26+
overlay.className = "noctive-loader-overlay";
27+
overlay.setAttribute("aria-hidden", "true");
28+
overlay.innerHTML = [
29+
'<div class="noctive-loader-shell">',
30+
' <div class="noctive-loader-cat-frame">',
31+
' <svg class="noctive-loader-cat" viewBox="0 0 124 100" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">',
32+
' <rect width="124" height="100" fill="transparent"/>',
33+
' <rect x="18" y="54" width="18" height="28" fill="#3c4250"/>',
34+
' <rect x="22" y="50" width="10" height="8" fill="#3c4250"/>',
35+
' <rect x="24" y="46" width="6" height="6" fill="#3c4250"/>',
36+
' <rect x="14" y="58" width="6" height="18" fill="#596273"/>',
37+
' <rect x="28" y="58" width="6" height="20" fill="#596273"/>',
38+
' <rect x="40" y="28" width="40" height="38" fill="#70798b"/>',
39+
' <rect x="36" y="32" width="8" height="18" fill="#70798b"/>',
40+
' <rect x="80" y="32" width="8" height="18" fill="#70798b"/>',
41+
' <rect x="44" y="20" width="10" height="10" fill="#70798b"/>',
42+
' <rect x="70" y="20" width="10" height="10" fill="#70798b"/>',
43+
' <rect x="48" y="24" width="4" height="4" fill="#fbfbff"/>',
44+
' <rect x="72" y="24" width="4" height="4" fill="#fbfbff"/>',
45+
' <rect x="48" y="34" width="6" height="6" fill="#2b2f3a"/>',
46+
' <rect x="70" y="34" width="6" height="6" fill="#2b2f3a"/>',
47+
' <rect x="58" y="44" width="4" height="4" fill="#2b2f3a"/>',
48+
' <rect x="62" y="44" width="4" height="4" fill="#2b2f3a"/>',
49+
' <rect x="54" y="52" width="16" height="4" fill="#596273"/>',
50+
' <rect x="46" y="66" width="8" height="22" fill="#596273"/>',
51+
' <rect x="70" y="66" width="8" height="22" fill="#596273"/>',
52+
' <rect x="52" y="64" width="20" height="20" fill="#7d8698"/>',
53+
' <rect x="78" y="58" width="20" height="22" fill="#4a5161"/>',
54+
' <rect x="96" y="52" width="10" height="10" fill="#4a5161"/>',
55+
' <rect x="90" y="74" width="8" height="14" fill="#596273"/>',
56+
' <rect x="98" y="74" width="8" height="14" fill="#596273"/>',
57+
' </svg>',
58+
' </div>',
59+
' <div class="noctive-loader-copy"><strong>Noctive</strong> loading</div>',
60+
'</div>'
61+
].join("");
62+
63+
function mountOverlay() {
64+
if (!document.body.contains(overlay)) {
65+
document.body.appendChild(overlay);
66+
}
67+
}
68+
69+
function removeLoader() {
70+
var elapsed = Date.now() - startTime;
71+
var delay = Math.max(0, minVisibleMs - elapsed);
72+
window.setTimeout(function () {
73+
overlay.classList.add("is-exiting");
74+
document.documentElement.classList.remove("noctive-loader-active");
75+
document.body.classList.remove("noctive-loader-active");
76+
window.setTimeout(function () {
77+
overlay.remove();
78+
}, 240);
79+
}, delay);
80+
}
81+
82+
if (document.body) {
83+
mountOverlay();
84+
} else {
85+
document.addEventListener("DOMContentLoaded", mountOverlay, { once: true });
86+
}
87+
88+
if (document.readyState === "complete") {
89+
removeLoader();
90+
} else {
91+
window.addEventListener("load", removeLoader, { once: true });
92+
}
93+
})();

pages/edit-profile.html

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@
394394
</style>
395395
</head>
396396
<body>
397+
<script src="/js/page-loader.js"></script>
397398
<header class="topbar">
398399
<div class="topbar-inner">
399400
<a href="./home.html"><span class="brand-title">Noctive</span></a>
@@ -522,14 +523,14 @@ <h2 id="previewBannerTitle">Your Noctive profile starts here.</h2>
522523
import { getAuth, onAuthStateChanged, setPersistence, browserLocalPersistence } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js";
523524
import { getFirestore, doc, setDoc, serverTimestamp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js";
524525
import { getStorage, ref as storageRef, uploadBytes, getDownloadURL } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-storage.js";
526+
import { isAdminIdentity } from "../js/admin-config.js";
525527

526528
const ACCESS_SESSION_KEY = 'noctive_site_access';
527529
const GUEST_PROFILE_KEY = 'noctive_profile_guest';
528530
const MARKET_OWNED_STORAGE_KEY = 'noctive_night_market_owned';
529531
const GIF_PROFILE_COUPON_ID = 'upgrade-gif-profile';
530532
const PUBLIC_PROFILE_DIRECTORY_KEY = 'noctive_public_profile_directory';
531533
const BIO_MAX_LENGTH = 180;
532-
const ADMIN_UIDS = ['TljwjuBuKvd6VG9e0Mz81y7ZRgi1', 'G6RyacKuSUTLXniBWRC1WsAm4Rq2'];
533534
if (sessionStorage.getItem(ACCESS_SESSION_KEY) !== 'granted') {
534535
window.location.replace('../index.html');
535536
}
@@ -555,7 +556,7 @@ <h2 id="previewBannerTitle">Your Noctive profile starts here.</h2>
555556
avatarStoragePath: '',
556557
bannerImage: '',
557558
bannerStoragePath: '',
558-
bannerTitle: 'Your Noctive profile starts here.',
559+
bannerTitle: 'Guest is Alive After Dark',
559560
bannerText: '',
560561
bannerTags: ['Profile Preview', 'Default Theme'],
561562
games: [],
@@ -639,7 +640,12 @@ <h2 id="previewBannerTitle">Your Noctive profile starts here.</h2>
639640
function stripLegacyProfileCopy(profile) {
640641
const nextProfile = deepMerge(PROFILE_TEMPLATE, profile || {});
641642
const bio = String(nextProfile.bio || '').trim();
642-
if (nextProfile.bannerTitle === 'Noctive is alive after dark.') {
643+
if (
644+
nextProfile.bannerTitle === 'Noctive is alive after dark.'
645+
|| nextProfile.bannerTitle === 'Your Noctive profile starts here.'
646+
|| String(nextProfile.bannerTitle || '').includes('is on Noctive.')
647+
|| String(nextProfile.bannerTitle || '').includes('has not finished setting up their profile yet.')
648+
) {
643649
nextProfile.bannerTitle = '';
644650
}
645651
if (
@@ -697,6 +703,11 @@ <h2 id="previewBannerTitle">Your Noctive profile starts here.</h2>
697703
return 'Offline';
698704
}
699705

706+
function getBannerHeadline(username, displayName = 'Guest') {
707+
const safeDisplayName = String(displayName || '').trim() || 'Guest';
708+
return `${safeDisplayName} is Alive After Dark`;
709+
}
710+
700711
function createStarterProfile(user) {
701712
if (!user) return JSON.parse(JSON.stringify(PROFILE_TEMPLATE));
702713
const emailBase = user.email?.split('@')[0] || 'guest';
@@ -708,9 +719,9 @@ <h2 id="previewBannerTitle">Your Noctive profile starts here.</h2>
708719
title: 'Noctive Member',
709720
status: 'Online',
710721
bio: '',
711-
bannerTitle: `${safeName} is alive after dark.`,
722+
bannerTitle: getBannerHeadline(emailBase, safeName),
712723
bannerText: '',
713-
bannerTags: ['Alive After Dark', 'Profile Starter'],
724+
bannerTags: ['Alive After Dark'],
714725
pinnedPost: {
715726
...PROFILE_TEMPLATE.pinnedPost,
716727
text: `Hey, I'm ${safeName}. Still setting this up, but this is where my late-night internet identity goes.`
@@ -819,7 +830,12 @@ <h2 id="previewBannerTitle">Your Noctive profile starts here.</h2>
819830
}
820831

821832
function isAdminUser(user = currentAuthUser) {
822-
return ADMIN_UIDS.includes(String(user?.uid || '').trim());
833+
return isAdminIdentity({
834+
uid: user?.uid,
835+
email: user?.email,
836+
username: user?.email?.split('@')[0],
837+
displayName: user?.displayName
838+
});
823839
}
824840

825841
function canUseGifProfilePictures(user = currentAuthUser) {
@@ -1017,7 +1033,7 @@ <h2 id="previewBannerTitle">Your Noctive profile starts here.</h2>
10171033
previewBanner.style.backgroundImage = bannerImage ? `url("${bannerImage.replace(/"/g, '&quot;')}")` : '';
10181034
previewBanner.style.backgroundSize = bannerImage ? 'cover' : '';
10191035
previewBanner.style.backgroundPosition = bannerImage ? 'center' : '';
1020-
document.getElementById('previewBannerTitle').textContent = profile.bannerTitle || PROFILE_TEMPLATE.bannerTitle;
1036+
document.getElementById('previewBannerTitle').textContent = getBannerHeadline(username, displayName);
10211037
document.getElementById('previewBannerText').textContent = previewBannerText;
10221038
document.getElementById('previewName').textContent = displayName;
10231039
document.getElementById('previewTitle').textContent = title;

pages/explore.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,7 @@
651651
</style>
652652
</head>
653653
<body>
654+
<script src="/js/page-loader.js"></script>
654655
<header class="topbar">
655656
<div class="topbar-inner">
656657
<a href="./home.html"><span class="brand-title">Noctive</span></a>

pages/faq.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@
465465
</style>
466466
</head>
467467
<body>
468+
<script src="/js/page-loader.js"></script>
468469
<header class="topbar">
469470
<div class="topbar-inner">
470471
<a href="./home.html"><span class="brand-title">Noctive</span></a>

0 commit comments

Comments
 (0)