-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextensions.js
More file actions
161 lines (125 loc) · 4.2 KB
/
extensions.js
File metadata and controls
161 lines (125 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Load and display all extensions
async function loadExtensions() {
const response = await fetch("extensions.json");
const data = await response.json();
const gallery = document.getElementById("gallery");
gallery.innerHTML = "";
let foundAny = false;
for (const key in data) {
foundAny = true;
const ext = data[key];
gallery.appendChild(createCard(ext));
}
if (!foundAny) {
gallery.innerHTML = "<p>No extensions found.</p>";
}
}
// Create a card element for an extension
function createCard(ext) {
const card = document.createElement("div");
card.className = "card";
const banner = document.createElement("img");
banner.className = "banner";
banner.src = ext.banner;
card.appendChild(banner);
const content = document.createElement("div");
content.className = "cardContent";
const title = document.createElement("h2");
title.textContent = ext.name;
content.appendChild(title);
const dates = document.createElement("p");
dates.textContent = `Created: ${ext.created_at} • Updated: ${ext.updated_at}`;
content.appendChild(dates);
const button = document.createElement("button");
button.textContent = "Install";
button.onclick = () => installExtension(ext.file);
content.appendChild(button);
card.appendChild(content);
return card;
}
// Install extension by injecting its script
function installExtension(url) {
const script = document.createElement("script");
script.src = url;
document.body.appendChild(script);
alert("Extension installed!");
}
// Main search logic
async function runSearch() {
const searchBar = document.getElementById("searchBar");
const query = searchBar.value.toLowerCase().trim();
const gallery = document.getElementById("gallery");
// If query is empty → show "No Extensions yet"
if (query === "") {
gallery.innerHTML = "<p>No Extensions yet</p>";
// Update URL to ?q=
const newUrl = `${window.location.pathname}?q=`;
window.history.replaceState(null, "", newUrl);
return;
}
// Update URL to ?q=query
const newUrl = `${window.location.pathname}?q=${encodeURIComponent(query)}`;
window.history.replaceState(null, "", newUrl);
const response = await fetch("extensions.json");
const data = await response.json();
gallery.innerHTML = "";
let found = false;
for (const key in data) {
const ext = data[key];
if (ext.name.toLowerCase().includes(query)) {
found = true;
gallery.appendChild(createCard(ext));
}
}
if (!found) {
gallery.innerHTML = `<p>No extensions found for '${query}'</p>`;
}
}
// Android-safe trigger wrapper
function triggerSearchAndroidSafe() {
// Android sometimes updates the input value AFTER the event
setTimeout(runSearch, 1);
}
const searchBar = document.getElementById("searchBar");
// 1. Normal typing
searchBar.addEventListener("input", triggerSearchAndroidSafe);
// 2. Backspace on Android keyboards
searchBar.addEventListener("keyup", triggerSearchAndroidSafe);
// 3. Beforeinput (if Family Link allows it)
searchBar.addEventListener("beforeinput", triggerSearchAndroidSafe);
// 4. Keydown (for held Backspace)
searchBar.addEventListener("keydown", (event) => {
// Enter key still works
if (event.key === "Enter") {
event.preventDefault();
runSearch();
return;
}
// For Backspace, Android updates value AFTER keydown
if (event.key === "Backspace") {
triggerSearchAndroidSafe();
}
});
// 5. MutationObserver fallback (for supervised accounts)
const observer = new MutationObserver(() => triggerSearchAndroidSafe());
observer.observe(searchBar, { attributes: true, characterData: true, subtree: true });
// Load query from URL on page load
function loadQueryFromURL() {
const params = new URLSearchParams(window.location.search);
const q = params.get("q");
const gallery = document.getElementById("gallery");
// If ?q= exists but is empty → show "No Extensions yet"
if (params.has("q") && (!q || q.trim() === "")) {
gallery.innerHTML = "<p>No Extensions yet</p>";
return;
}
// If ?q=something → run search
if (q) {
document.getElementById("searchBar").value = q;
runSearch();
return;
}
// No ?q at all → load everything normally
loadExtensions();
}
loadQueryFromURL();