Skip to content

Commit 1a6dd3a

Browse files
authored
Merge pull request #27 from Unity-Lab-AI/develop
Develop
2 parents 0ef4bcd + 1e72e1a commit 1a6dd3a

File tree

10 files changed

+2724
-1939
lines changed

10 files changed

+2724
-1939
lines changed

ai/chat-part1.js

Lines changed: 336 additions & 321 deletions
Large diffs are not rendered by default.

ai/chat-part2.js

Lines changed: 1002 additions & 218 deletions
Large diffs are not rendered by default.

ai/chat-part3.js

Lines changed: 416 additions & 528 deletions
Large diffs are not rendered by default.

ai/index.html

Lines changed: 134 additions & 379 deletions
Large diffs are not rendered by default.

ai/memory-api.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ document.addEventListener("DOMContentLoaded", () => {
8686
const updatedText = newText.trim();
8787

8888
try {
89-
memories[index] = updatedText;
90-
localStorage.setItem("pollinations_memory", JSON.stringify(memories));
89+
const currentMemories = this.getMemories();
90+
currentMemories[index] = updatedText;
91+
localStorage.setItem("pollinations_memory", JSON.stringify(currentMemories));
9192
console.log(`Memory at index ${index} updated to: ${updatedText}`);
9293
return true;
9394
} catch (err) {
@@ -113,4 +114,5 @@ document.addEventListener("DOMContentLoaded", () => {
113114
};
114115

115116
console.log("Memory API loaded and linked to Storage-based memory system.");
117+
116118
});

ai/screensaver.js

Lines changed: 57 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
// screensaver.js
2-
// Handles screensaver functionality with Pollinations API integration
3-
// Updated with safe=false for uncensored content and cross-browser/device support
4-
51
document.addEventListener("DOMContentLoaded", () => {
62
const screensaverContainer = document.getElementById("screensaver-container");
73
const toggleScreensaverButton = document.getElementById("toggle-screensaver");
@@ -24,7 +20,6 @@ document.addEventListener("DOMContentLoaded", () => {
2420
let paused = false;
2521
let isFullscreen = false;
2622

27-
// Set tooltips
2823
toggleScreensaverButton.title = "Toggle the screensaver on/off.";
2924
fullscreenButton.title = "Go full screen (or exit it).";
3025
stopButton.title = "Stop the screensaver.";
@@ -38,7 +33,6 @@ document.addEventListener("DOMContentLoaded", () => {
3833
enhanceCheckbox.title = "If enabled, the prompt is 'enhanced' via an LLM.";
3934
privateCheckbox.title = "If enabled, the image won't appear on the public feed.";
4035

41-
// Utility to detect browser for compatibility adjustments
4236
const getBrowserInfo = () => {
4337
const ua = navigator.userAgent.toLowerCase();
4438
return {
@@ -50,7 +44,6 @@ document.addEventListener("DOMContentLoaded", () => {
5044
};
5145
};
5246

53-
// Utility to create audio context for cross-browser support
5447
const createAudioContext = () => {
5548
const AudioContext = window.AudioContext || window.webkitAudioContext;
5649
if (!AudioContext) {
@@ -60,11 +53,10 @@ document.addEventListener("DOMContentLoaded", () => {
6053
return new AudioContext();
6154
};
6255

63-
// Utility to play audio with cross-browser compatibility
6456
const playAudio = (audioUrl) => {
6557
return new Promise((resolve, reject) => {
6658
const audio = new Audio(audioUrl);
67-
audio.crossOrigin = "anonymous"; // For CORS support
59+
audio.crossOrigin = "anonymous";
6860
audio.preload = "auto";
6961

7062
audio.play().catch((err) => {
@@ -91,7 +83,6 @@ document.addEventListener("DOMContentLoaded", () => {
9183
});
9284
};
9385

94-
// Save settings to localStorage
9586
function saveScreensaverSettings() {
9687
const settings = {
9788
prompt: promptInput.value,
@@ -104,7 +95,6 @@ document.addEventListener("DOMContentLoaded", () => {
10495
localStorage.setItem("screensaverSettings", JSON.stringify(settings));
10596
}
10697

107-
// Load settings from localStorage
10898
function loadScreensaverSettings() {
10999
const raw = localStorage.getItem("screensaverSettings");
110100
if (!raw) return;
@@ -123,17 +113,10 @@ document.addEventListener("DOMContentLoaded", () => {
123113

124114
loadScreensaverSettings();
125115

126-
// Generate a random seed
127116
function generateSeed() {
128-
const length = Math.floor(Math.random() * 8) + 1;
129-
let seed = "";
130-
for (let i = 0; i < length; i++) {
131-
seed += Math.floor(Math.random() * 10);
132-
}
133-
return seed;
117+
return Math.floor(Math.random() * 1000000).toString();
134118
}
135119

136-
// Get dimensions based on aspect ratio
137120
function getDimensions(aspect) {
138121
switch (aspect) {
139122
case "widescreen": return { width: 1280, height: 720 };
@@ -143,17 +126,14 @@ document.addEventListener("DOMContentLoaded", () => {
143126
}
144127
}
145128

146-
// FIXED: Fetch a new image from Pollinations API with nolog parameter
147129
function fetchNewImage() {
148130
saveScreensaverSettings();
149131
let prompt = promptInput.value || "random artistic scene, high quality, detailed";
150132

151-
// Keep the prompt concise and clean
152133
if (prompt.length > 100) {
153134
prompt = prompt.substring(0, 100);
154135
}
155136

156-
// Add quality terms
157137
prompt += ", high resolution, detailed";
158138

159139
const { width, height } = getDimensions(aspectSelect.value);
@@ -162,19 +142,15 @@ document.addEventListener("DOMContentLoaded", () => {
162142
const enhance = enhanceCheckbox.checked;
163143
const priv = privateCheckbox.checked;
164144

165-
// Use global config if available, otherwise hardcode safe=false
166-
const safeParam = window._pollinationsAPIConfig ? `safe=${window._pollinationsAPIConfig.safe}` : "safe=false";
167-
168-
// Add nolog=true parameter to prevent unwanted URL parameters
169-
const url = `https://image.pollinations.ai/prompt/${encodeURIComponent(prompt)}?width=${width}&height=${height}&seed=${seed}&model=${model}&nologo=true&private=${priv}&enhance=${enhance}&${safeParam}&nolog=true`;
145+
const url = `https://image.pollinations.ai/prompt/${encodeURIComponent(prompt)}?width=${width}&height=${height}&seed=${seed}&model=${model}&nologo=true&private=${priv}&enhance=${enhance}&safe=false&nolog=true`;
170146

171147
screensaverImage.style.opacity = "0.5";
172-
screensaverImage.crossOrigin = "anonymous"; // Enable CORS for cross-browser support
148+
screensaverImage.crossOrigin = "anonymous";
173149
screensaverImage.onload = () => {
174150
screensaverImage.style.opacity = "1";
175151
const browserInfo = getBrowserInfo();
176152
if (browserInfo.isSafari) {
177-
screensaverImage.style.webkitMaskImage = "none"; // Fix Safari rendering
153+
screensaverImage.style.webkitMaskImage = "none";
178154
}
179155
};
180156
screensaverImage.onerror = () => {
@@ -185,7 +161,6 @@ document.addEventListener("DOMContentLoaded", () => {
185161
screensaverImage.src = url;
186162
}
187163

188-
// Set or reset the image interval
189164
function setOrResetInterval() {
190165
clearInterval(imageInterval);
191166
const intervalSeconds = parseInt(timerInput.value) || 30;
@@ -195,7 +170,6 @@ document.addEventListener("DOMContentLoaded", () => {
195170
window.imageInterval = imageInterval;
196171
}
197172

198-
// Start the screensaver
199173
function startScreensaver() {
200174
screensaverActive = true;
201175
paused = false;
@@ -221,12 +195,10 @@ document.addEventListener("DOMContentLoaded", () => {
221195
document.body.style.overflow = "hidden";
222196
window.screensaverActive = true;
223197

224-
// Optional audio cue for screensaver start (placeholder)
225-
const audioUrl = "https://example.com/audio/start.mp3"; // Replace with actual audio API
198+
const audioUrl = "https://example.com/audio/start.mp3";
226199
playAudio(audioUrl).catch(err => console.warn("Audio cue failed:", err));
227200
}
228201

229-
// Stop the screensaver
230202
function stopScreensaver() {
231203
screensaverActive = false;
232204
paused = false;
@@ -251,7 +223,6 @@ document.addEventListener("DOMContentLoaded", () => {
251223
}
252224
}
253225

254-
// Toggle pause state
255226
function togglePause() {
256227
paused = !paused;
257228
playPauseButton.innerHTML = paused ? "▶️" : "⏸️";
@@ -260,89 +231,70 @@ document.addEventListener("DOMContentLoaded", () => {
260231
window.showToast(paused ? "Screensaver paused" : "Screensaver resumed");
261232
}
262233

263-
// Save the current image
264234
function saveImage() {
265235
if (!screensaverImage.src) {
266236
window.showToast("No image to save");
267237
return;
268238
}
269-
fetch(screensaverImage.src)
270-
.then(response => response.ok ? response.blob() : Promise.reject("Fetch failed"))
239+
fetch(screensaverImage.src, { mode: "cors" })
240+
.then(response => {
241+
if (!response.ok) throw new Error("Network response was not ok");
242+
return response.blob();
243+
})
271244
.then(blob => {
272-
const blobUrl = URL.createObjectURL(blob);
273-
const link = document.createElement("a");
274-
link.href = blobUrl;
275-
link.download = "screensaver-image.png";
276-
document.body.appendChild(link);
277-
link.click();
278-
document.body.removeChild(link);
279-
URL.revokeObjectURL(blobUrl);
280-
window.showToast("Image saved!");
245+
const url = URL.createObjectURL(blob);
246+
const a = document.createElement("a");
247+
a.href = url;
248+
a.download = `screensaver-image-${Date.now()}.png`;
249+
document.body.appendChild(a);
250+
a.click();
251+
document.body.removeChild(a);
252+
URL.revokeObjectURL(url);
253+
window.showToast("Image download initiated");
281254
})
282255
.catch(err => {
283256
console.error("Error saving image:", err);
284257
window.showToast("Failed to save image");
285258
});
286259
}
287260

288-
// Copy the current image to clipboard
289261
function copyImage() {
290262
if (!screensaverImage.src) {
291263
window.showToast("No image to copy");
292264
return;
293265
}
266+
if (!screensaverImage.complete || screensaverImage.naturalWidth === 0) {
267+
window.showToast("Image not fully loaded yet. Please try again.");
268+
return;
269+
}
294270
copyButton.textContent = "Copying...";
295271
const canvas = document.createElement("canvas");
296272
const ctx = canvas.getContext("2d");
297-
298-
if (screensaverImage.complete && screensaverImage.naturalWidth > 0) {
299-
canvas.width = screensaverImage.naturalWidth;
300-
canvas.height = screensaverImage.naturalHeight;
301-
ctx.drawImage(screensaverImage, 0, 0);
302-
canvas.toBlob(blob => {
303-
navigator.clipboard.write([new ClipboardItem({ "image/png": blob })])
304-
.then(() => {
305-
copyButton.textContent = "✅ Copied!";
306-
window.showToast("Image copied!");
307-
setTimeout(() => copyButton.textContent = "Copy Image", 1500);
308-
})
309-
.catch(err => {
310-
copyButton.textContent = "❌ Failed";
311-
window.showToast("Copy failed");
312-
setTimeout(() => copyButton.textContent = "Copy Image", 1500);
313-
});
314-
}, "image/png", 1.0);
315-
} else {
316-
const tempImg = new Image();
317-
tempImg.crossOrigin = "anonymous";
318-
tempImg.onload = () => {
319-
canvas.width = tempImg.naturalWidth;
320-
canvas.height = tempImg.naturalHeight;
321-
ctx.drawImage(tempImg, 0, 0);
322-
canvas.toBlob(blob => {
323-
navigator.clipboard.write([new ClipboardItem({ "image/png": blob })])
324-
.then(() => {
325-
copyButton.textContent = "✅ Copied!";
326-
window.showToast("Image copied!");
327-
setTimeout(() => copyButton.textContent = "Copy Image", 1500);
328-
})
329-
.catch(() => {
330-
copyButton.textContent = "❌ Failed";
331-
window.showToast("Copy failed");
332-
setTimeout(() => copyButton.textContent = "Copy Image", 1500);
333-
});
334-
}, "image/png", 1.0);
335-
};
336-
tempImg.onerror = () => {
337-
copyButton.textContent = "❌ Failed";
338-
window.showToast("Failed to load image");
339-
setTimeout(() => copyButton.textContent = "Copy Image", 1500);
340-
};
341-
tempImg.src = screensaverImage.src;
342-
}
273+
canvas.width = screensaverImage.naturalWidth;
274+
canvas.height = screensaverImage.naturalHeight;
275+
ctx.drawImage(screensaverImage, 0, 0);
276+
canvas.toBlob(blob => {
277+
if (!blob) {
278+
copyButton.textContent = "Copy Image";
279+
window.showToast("Failed to copy image: Unable to create blob.");
280+
return;
281+
}
282+
navigator.clipboard.write([new ClipboardItem({ "image/png": blob })])
283+
.then(() => {
284+
const dataURL = canvas.toDataURL("image/png");
285+
localStorage.setItem("lastCopiedImage", dataURL);
286+
copyButton.textContent = "✅ Copied!";
287+
window.showToast("Image copied to clipboard and saved to local storage");
288+
setTimeout(() => copyButton.textContent = "Copy Image", 1500);
289+
})
290+
.catch(err => {
291+
copyButton.textContent = "❌ Failed";
292+
window.showToast("Copy failed: " + err.message);
293+
setTimeout(() => copyButton.textContent = "Copy Image", 1500);
294+
});
295+
}, "image/png");
343296
}
344297

345-
// Toggle fullscreen mode
346298
function toggleFullscreen() {
347299
if (!screensaverActive) {
348300
window.showToast("Start the screensaver first!");
@@ -367,7 +319,6 @@ document.addEventListener("DOMContentLoaded", () => {
367319
}
368320
}
369321

370-
// Event listeners
371322
toggleScreensaverButton.addEventListener("click", () => {
372323
screensaverActive ? stopScreensaver() : startScreensaver();
373324
});
@@ -417,13 +368,21 @@ document.addEventListener("DOMContentLoaded", () => {
417368
}
418369
});
419370

420-
// Cross-browser toast notification
421371
window.showToast = function(message, duration = 3000) {
422372
let toast = document.getElementById("toast-notification");
423373
if (!toast) {
424374
toast = document.createElement("div");
425375
toast.id = "toast-notification";
426-
toast.style.cssText = "position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background-color:rgba(0,0,0,0.7);color:white;padding:10px 20px;border-radius:5px;z-index:9999;transition:opacity 0.3s;";
376+
toast.style.position = "fixed";
377+
toast.style.top = "5%";
378+
toast.style.left = "50%";
379+
toast.style.transform = "translateX(-50%)";
380+
toast.style.backgroundColor = "rgba(0,0,0,0.7)";
381+
toast.style.color = "white";
382+
toast.style.padding = "10px 20px";
383+
toast.style.borderRadius = "5px";
384+
toast.style.zIndex = "9999";
385+
toast.style.transition = "opacity 0.3s";
427386
document.body.appendChild(toast);
428387
}
429388
toast.textContent = message;
@@ -432,7 +391,6 @@ document.addEventListener("DOMContentLoaded", () => {
432391
toast.timeout = setTimeout(() => toast.style.opacity = "0", duration);
433392
};
434393

435-
// Expose functions globally
436394
window.startScreensaver = startScreensaver;
437395
window.stopScreensaver = stopScreensaver;
438396
window.togglePause = togglePause;

0 commit comments

Comments
 (0)