Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 77 additions & 72 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ <h2 id="history-date"></h2>
<img src="banner-transparent.png" alt="Virtual Clicker Banner">
<span class="version" id="version-string"></span>
<button data-modal-view="settings/code">Seat Code</button>
<button data-modal-view="settings/theme">Theme</button>
<button data-modal-view="store">Theme Store</button>
<button data-modal-view="settings/keybinds">Keyboard Shortcuts</button>
<button data-modal-view="settings/makeup">Make Up Clicks</button>
<button data-modal-view="settings/reset">Reset</button>
Expand Down Expand Up @@ -309,77 +309,6 @@ <h2 id="history-date"></h2>
<div id="seat-grid"></div>
</div>
</div>
<div data-modal-page="theme" data-page-title="Theme">
<div id="theme-preview">
<h1 class="text-placeholder">000</h1>
<p class="text-placeholder">Question</p>
<div class="control-placeholder"></div>
<p class="text-placeholder">Answer</p>
<div class="control-placeholder"></div>
<div class="control-placeholder pill"></div>
</div>
<div id="theme-selector">
<button data-modal-view="settings/theme/editor">Custom</button>
</div>
<div data-modal-actions>
<button id="theme-reset">Reset</button>
<button id="theme-apply">Apply</button>
</div>
<div data-modal-page="editor" data-page-title="Custom Theme">
<div id="editor-preview">
<h1 class="text-placeholder">000</h1>
<p class="text-placeholder">Question</p>
<div class="control-placeholder"></div>
<p class="text-placeholder">Answer</p>
<div class="control-placeholder"></div>
<div class="control-placeholder pill"></div>
</div>
<div id="theme-editor">
<label>
Color Scheme
<select name="color-scheme">
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label>
<label>
Text
<div data-color-input="text-color"></div>
</label>
<label>
Background
<div data-color-input="background-color"></div>
</label>
<label>
Surface
<div data-color-input="surface-color"></div>
</label>
<label>
Accent
<div data-color-input="accent-color"></div>
</label>
<label>
Accent Text
<div data-color-input="accent-text-color"></div>
</label>
<label>
Error
<div data-color-input="error-color"></div>
</label>
</div>
<label>
Theme Code
<input type="text" id="theme-code" />
</label>
<div data-modal-actions>
<button data-suggest-theme>Suggest Theme</button>
</div>
<div data-modal-actions>
<button id="editor-reset">Reset</button>
<button id="editor-apply">Apply</button>
</div>
</div>
</div>
<div data-modal-page="keybinds" data-page-title="Keyboard Shortcuts">
<p><kbd>Ctrl</kbd> + <kbd>Enter</kbd> Submit click</p>
<p><kbd>Alt</kbd> + <kbd>1-9</kbd> Insert nth symbol</p>
Expand Down Expand Up @@ -461,6 +390,82 @@ <h1 class="text-placeholder">000</h1>
The Virtual Clicker is undergoing maintenance. Please try again later.
</p>
</dialog>
<!-- Theme Store -->
<dialog data-modal-page="store" data-page-title="Theme Store">
<div data-modal-page="theme" data-page-title="Your Themes">
<div id="theme-preview">
<h1 class="text-placeholder">000</h1>
<p class="text-placeholder">Question</p>
<div class="control-placeholder"></div>
<div class="control-placeholder"></div>
<p class="text-placeholder">Answer</p>
<div class="control-placeholder"></div>
<div class="control-placeholder pill"></div>
</div>
<div id="theme-selector">
<button data-modal-view="settings/store/editor">Custom</button>
</div>
<div data-modal-actions>
<button id="theme-reset">Reset</button>
<button id="theme-apply">Apply</button>
</div>
</div>
<div data-modal-page="editor" data-page-title="Custom Theme">
<div id="editor-preview">
<h1 class="text-placeholder">000</h1>
<p class="text-placeholder">Question</p>
<div class="control-placeholder"></div>
<div class="control-placeholder"></div>
<p class="text-placeholder">Answer</p>
<div class="control-placeholder"></div>
<div class="control-placeholder pill"></div>
</div>
<div id="theme-editor">
<label>
Color Scheme
<select name="color-scheme">
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label>
<label>
Text
<div data-color-input="text-color"></div>
</label>
<label>
Background
<div data-color-input="background-color"></div>
</label>
<label>
Surface
<div data-color-input="surface-color"></div>
</label>
<label>
Accent
<div data-color-input="accent-color"></div>
</label>
<label>
Accent Text
<div data-color-input="accent-text-color"></div>
</label>
<label>
Error
<div data-color-input="error-color"></div>
</label>
</div>
<label>
Theme Code
<input type="text" id="theme-code" />
</label>
<div data-modal-actions>
<button data-suggest-theme>Suggest Theme</button>
</div>
<div data-modal-actions>
<button id="editor-reset">Reset</button>
<button id="editor-apply">Apply</button>
</div>
</div>
</dialog>
<dialog data-modal-page="menu" data-page-title="Virtual Clicker">
<div class="menu-icons">
<a href="https://check.vssfalcons.com/" tooltip="Virtual Checker">
Expand Down
Binary file added public/store/backdrop/aeroplane.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/black-sand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/blizzard-pro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/galaxy-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/galaxy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/jellyfish-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/jellyfish-pro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/jellyfish.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/lavender-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/lavender-pro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/milky-way.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/northern-lights.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/rainy-day.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/rose-pro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/sage-pro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/sandy-beach.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/shells.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/snow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/stealth-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/synthwave-pro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/backdrop/tides.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/thumb/aeroplane.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/thumb/black-sand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/thumb/blizzard-pro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/thumb/butterfly.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/store/thumb/galaxy-2.png
Binary file added public/store/thumb/galaxy.png
Binary file added public/store/thumb/jellyfish-2.png
Binary file added public/store/thumb/jellyfish-pro.png
Binary file added public/store/thumb/jellyfish.png
Binary file added public/store/thumb/lavender-2.png
Binary file added public/store/thumb/lavender-pro.png
Binary file added public/store/thumb/milky-way.png
Binary file added public/store/thumb/northern-lights.png
Binary file added public/store/thumb/rainy-day.png
Binary file added public/store/thumb/rose-pro.png
Binary file added public/store/thumb/sage-pro.png
Binary file added public/store/thumb/sandy-beach.png
Binary file added public/store/thumb/shells.png
Binary file added public/store/thumb/snow.png
Binary file added public/store/thumb/stealth-2.png
Binary file added public/store/thumb/synthwave-pro.png
Binary file added public/store/thumb/tides.png
3 changes: 3 additions & 0 deletions src/clicker/clicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import * as ui from "/src/modules/ui.js";
import storage from "/src/modules/storage.js";
import * as auth from "/src/modules/auth.js";
import * as themes from "/src/themes/themes.js";

import { autocomplete } from "/src/symbols/symbols.js";
import { unixToTimeString } from "/src/modules/time.js";
Expand Down Expand Up @@ -568,6 +569,8 @@ try {
},
]);
}
// Render Theme Store
themes.renderStore();
}

// Show multiple choice card
Expand Down
9 changes: 8 additions & 1 deletion src/design.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
}

::-webkit-scrollbar-track {
background-color: transparent;
background-color: var(--background-color);
}

::-webkit-scrollbar-thumb {
Expand All @@ -55,6 +55,13 @@ body {
gap: 50px !important;
}

body[data-theme] {
background-position: center !important;
background-size: cover !important;
background-attachment: fixed !important;
background-repeat: no-repeat !important;
}

body.enable-transitions {
--easing: cubic-bezier(0.32, 0, 0.67, 0);
}
Expand Down
76 changes: 56 additions & 20 deletions src/modules/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -598,29 +598,26 @@ export async function bulkLoad(fields = [], usr = null, pwd = null, isAdmin = fa
var updatedBulkLoad = {};
for (const table in fetchedBulkLoad) {
if (table === 'asOf' || table === 'syncDeleted') continue;
if (storage.get((isAdmin || isTA) ? "lastAdminBulkLoad" : "lastBulkLoad") || null) {
var deletedData;
var existingData;
var mergedData;
if (!Array.isArray(fetchedBulkLoad[table] || [])) {
updatedBulkLoad[table] = fetchedBulkLoad[table];
continue;
}
deletedData = fetchedBulkLoad.syncDeleted?.[table] || [];
const cacheObj = (await storage.idbGet((isAdmin || isTA) ? "adminCache" : "cache")) || storage.get((isAdmin || isTA) ? "adminCache" : "cache") || {};
existingData = (Array.isArray(cacheObj[table]) ? cacheObj[table] : []).filter(item => {
return !deletedData.includes(String(item.id || item.seatCode || item.period || item.key || item.username || 0));
const fetchedTableData = fetchedBulkLoad[table];
if (!Array.isArray(fetchedTableData) || (fetchedTableData.length > 0 && (typeof fetchedTableData[0] !== 'object' || Array.isArray(fetchedTableData[0])))) {
updatedBulkLoad[table] = fetchedTableData;
continue;
}
const currentCacheKey = (isAdmin || isTA) ? "adminCache" : "cache";
const lastBulkLoadKey = (isAdmin || isTA) ? "lastAdminBulkLoad" : "lastBulkLoad";
if (storage.get(lastBulkLoadKey)) {
let deletedData = fetchedBulkLoad.syncDeleted?.[table] || [];
const cacheObj = (await storage.idbGet(currentCacheKey)) || storage.get(currentCacheKey) || {};
const deletedSet = new Set(deletedData.map(item => String(item.id || item.seatCode || item.period || item.key || item.username || 0)));
const existingData = Array.isArray(cacheObj[table]) ? cacheObj[table].filter(item => !deletedSet.has(String(item.id || item.seatCode || item.period || item.key || item.username || 0))) : [];
const mergedMap = {};
existingData.forEach(item => {
mergedMap[String(item.id || item.seatCode || item.period || item.key || item.username || 0)] = item;
});
mergedData = [...existingData];
(fetchedBulkLoad[table] || []).forEach(newItem => {
const index = mergedData.findIndex(item => String(item.id || item.seatCode || item.period || item.key || item.username || 0) === String(newItem.id || newItem.seatCode || newItem.period || newItem.key || newItem.username || 0));
if (index !== -1) {
mergedData[index] = newItem;
} else {
mergedData.push(newItem);
}
mergedMap[String(newItem.id || newItem.seatCode || newItem.period || newItem.key || newItem.username || 0)] = newItem;
});
updatedBulkLoad[table] = mergedData;
updatedBulkLoad[table] = Object.values(mergedMap);
} else {
updatedBulkLoad[table] = fetchedBulkLoad[table];
}
Expand All @@ -643,4 +640,43 @@ export async function clearBulkLoad() {
await storage.idbDelete("adminCache").catch((e) => console.error('IDB delete failed', e));
storage.delete("lastAdminBulkLoad");
console.log('🟢 Bulk load cleared');
}

export async function buyTheme(theme = null, cost = 0) {
if (!theme || !cost || !storage.get("code")) return;
await fetch(domain + '/buy_theme', {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
"seatCode": storage.get("code"),
"password": storage.get("password"),
"theme": theme,
"cost": cost,
})
})
.then(async (r) => {
if (!r.ok) {
try {
var re = await r.json();
if (re.error || re.message) {
ui.toast(re.error || re.message, 5000, "error", "bi bi-exclamation-triangle-fill");
if ((re.error === "Access denied.") || (re.message === "Access denied.")) {
if (storage.get("password")) storage.delete("password");
}
throw new Error(re.error || re.message);
} else {
throw new Error("API error");
}
} catch (e) {
throw new Error(e.message || "API error");
}
}
return await r.json();
})
.catch((e) => {
console.error(e);
if (!e.message || (e.message && !e.message.includes("."))) ui.view("api-fail");
});
}
Loading