Skip to content

Commit 37c3094

Browse files
committed
refactor: deduplicate code to reuse logic & add title on login screen
1 parent a876c51 commit 37c3094

79 files changed

Lines changed: 1003 additions & 1241 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

webos-desktop/public/app-list.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@
209209
"raft",
210210
"redball4",
211211
"remotehostapp",
212-
"replitapp",
213212
"repo",
214213
"rhythmsapp",
215214
"roads",
@@ -266,7 +265,6 @@
266265
"swordssouls",
267266
"systemappsapp",
268267
"tabs",
269-
"talkingben",
270268
"tanktrouble",
271269
"taskmanagerapp",
272270
"tattletail",

webos-desktop/src/3d/GameCaseManager.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ export class GameCaseManager {
590590
}
591591

592592
startGameMode(gameState) {
593+
const THREE = this.THREE;
593594
this.setGameMode(true, gameState);
594595
for (const gameCase of this.gameCases) {
595596
if (gameCase.shelved) {

webos-desktop/src/3d/RoomRenderer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,7 @@ export class RoomRenderer {
13941394
}
13951395

13961396
setQuality(level) {
1397+
const THREE = this.THREE;
13971398
const isUltra = level === "ultra";
13981399
const isHigh = level === "high" || isUltra;
13991400
const isLow = level === "low";

webos-desktop/src/3d/editor/SceneSerializer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { os } from "../../os/index.js";
1+
import { os, StorageKeys } from "../../framework.js";
22

3-
const STORAGE_KEY = "rm3d_roomLayout";
3+
const STORAGE_KEY = StorageKeys.room3dRoomLayout;
44

55
export class SceneSerializer {
66
serialize(furnitureManager, decorManager) {

webos-desktop/src/SessionManager.js

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import { YUKIOS_VERSION } from "./apps/about.js";
77
import { resolveAvatarUrl } from "./shared/avatarResolver.js";
88
import { $ } from "./shared/domUtils.js";
99
import { renderLiveStats } from "./shared/liveStats.js";
10-
import { resolveAppId } from "./utils/utils.js";
11-
import { StorageKeys, os, brand } from "./framework.js";
10+
import { resolveAppId, generateUUID, timeAgo } from "./utils/utils.js";
11+
import { StorageKeys, os, brand, wasRandomYuriTrigger } from "./framework.js";
1212
import { KeybindManager } from "./keybindManager.js";
1313
import { applyTheme } from "./settings/settingsApply.js";
1414
import { taskbarPositionManager } from "./desktopui/taskbarPositionManager.js";
@@ -22,13 +22,6 @@ import { applyTilingSettings, disableTilingSettings } from "./modes/tiling/sessi
2222
import { applyChromeOsSettings, disableChromeOsSettings } from "./modes/chromeos/session.js";
2323
import { showDonationPopup } from "./donationPopup.js";
2424
import { getRecentNews } from "./apps/news.js";
25-
function generateUUID() {
26-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
27-
const r = (Math.random() * 16) | 0;
28-
const v = c === "x" ? r : (r & 0x3) | 0x8;
29-
return v.toString(16);
30-
});
31-
}
3225

3326
export class SessionManager {
3427
constructor(os) {
@@ -215,6 +208,7 @@ export class SessionManager {
215208
<div class="session-wallpaper"></div>
216209
<div class="session-background"></div>
217210
<div class="session-content${state === "locked" ? "" : " extra-hidden"}">
211+
<div class="session-brand">${brand("YukiOS")}</div>
218212
<div class="session-time">${timeStr}</div>
219213
<div class="session-date">${dateStr}</div>
220214
@@ -523,17 +517,7 @@ export class SessionManager {
523517
}
524518

525519
formatTimeAgo(date) {
526-
const now = new Date();
527-
const diffMs = now - date;
528-
const diffMins = Math.floor(diffMs / 60000);
529-
const diffHours = Math.floor(diffMs / 3600000);
530-
const diffDays = Math.floor(diffMs / 86400000);
531-
532-
if (diffMins < 1) return "Just now";
533-
if (diffMins < 60) return `${diffMins}m ago`;
534-
if (diffHours < 24) return `${diffHours}h ago`;
535-
if (diffDays < 7) return `${diffDays}d ago`;
536-
return date.toLocaleDateString();
520+
return timeAgo(date);
537521
}
538522

539523
async applySessionWallpaper(container) {
@@ -1078,6 +1062,13 @@ export class SessionManager {
10781062
}
10791063

10801064
os.events.emit(BusEvents.SESSION_INITIALIZED, this.currentSession);
1065+
if (wasRandomYuriTrigger()) {
1066+
os.notify.send("YuriOS", "Random chance triggered YuriOS! Pink mode has appeared.", {
1067+
type: "info",
1068+
duration: 6000,
1069+
icon: "fas fa-heart"
1070+
});
1071+
}
10811072
liveActivityManager.init();
10821073

10831074
if (this.selectedSession === "Yuki Mac Desktop") {

webos-desktop/src/StorageKeys.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,5 +247,16 @@ export const StorageKeys = {
247247
chromeOsShelfPosition: "yukiOS_chrome_os_shelf_position",
248248
chromeOsShelfAutoHide: "yukiOS_chrome_os_shelf_autohide",
249249
chromeOsClock24h: "yukiOS_chrome_os_clock_24h",
250-
chromeOsShelfPinnedItems: "yukiOS_chrome_os_shelf_pinned_items"
250+
chromeOsShelfPinnedItems: "yukiOS_chrome_os_shelf_pinned_items",
251+
aiMemory: "yuki_ai_memory",
252+
aiChatHistory: "yuki_ai_chathistory",
253+
aiPreferences: "yuki_ai_preferences",
254+
weatherUserLocation: "wx_user_location",
255+
weatherCachePrefix: "yukiOS_weather_",
256+
analyticsQueue: "yuki_analytics_queue",
257+
robloxSettings: "roblox_settings",
258+
settingsDisplayName: "settings:displayName",
259+
room3dStoragePrefix: "rm3d_",
260+
room3dAchievements: "rm3d_achievements",
261+
room3dRoomLayout: "rm3d_roomLayout"
251262
};

webos-desktop/src/achievements.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -653,24 +653,30 @@ export class AchievementsApp extends BaseApp {
653653

654654
document.body.appendChild(popup);
655655

656-
popup.addEventListener("click", () => os.app.launch("achievementsApp"));
656+
const dismissPopup = () => {
657+
if (!popup.isConnected) return;
658+
popup.remove();
659+
this.isShowingAchievement = false;
660+
this.processQueue();
661+
};
662+
663+
let hideTimer;
664+
popup.addEventListener("click", () => {
665+
clearTimeout(hideTimer);
666+
dismissPopup();
667+
os.app.launch("achievementsApp");
668+
});
657669

658670
setTimeout(() => popup.classList.add("achievement-popup--show"), 10);
659671

660672
const displayDuration = 4000;
661-
const delayBetween = 500;
662673

663-
setTimeout(() => {
674+
hideTimer = setTimeout(() => {
664675
popup.classList.remove("achievement-popup--show");
665676
popup.classList.add("achievement-popup--hide");
666677

667678
setTimeout(() => {
668-
popup.remove();
669-
670-
setTimeout(() => {
671-
this.isShowingAchievement = false;
672-
this.processQueue();
673-
}, delayBetween);
679+
dismissPopup();
674680
}, 600);
675681
}, displayDuration);
676682
}

webos-desktop/src/analytics.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { os, $ } from "./framework.js";
22
import { StorageKeys } from "./StorageKeys.js";
33

4-
const ANALYTICS_QUEUE_KEY = "yuki_analytics_queue";
4+
const ANALYTICS_QUEUE_KEY = StorageKeys.analyticsQueue;
55
import { parseBool } from "./utils/utils.js";
66

77
const ENDPOINT_BASE = "https://analytics.liventcord-a60.workers.dev";

webos-desktop/src/appLauncher.js

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { initializeAppGrid, tryGetIcon, trackRecentlyUsed } from "./desktopui/st
77
const IFRAME_ATTRS =
88
'style="width:100%;height:100%;border:none;" allow="autoplay; fullscreen; clipboard-write; encrypted-media; picture-in-picture" sandbox="allow-forms allow-downloads allow-modals allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation-by-user-activation"';
99
import { getLibraryUrl } from "./shared/cdnConfig.js";
10-
import { StorageKeys, os, brand } from "./framework.js";
10+
import { StorageKeys, os, brand, yuriPageTitle } from "./framework.js";
1111
import { parseBool } from "./utils/utils.js";
1212
import {
1313
fetchHtmlAsBlobUrl,
@@ -551,12 +551,10 @@ player.load("${swfPath}");
551551
const isGame = this.isTransparencyBlocked(appId, { type });
552552
const gameIcon = this.appMap[appId]?.icon || "fas fa-gamepad";
553553
const resolvedGameIcon = resolveIconUrl(gameIcon);
554-
const gameIconHtml =
555-
resolvedGameIcon.startsWith("fas ") ||
556-
resolvedGameIcon.startsWith("fab ") ||
557-
resolvedGameIcon.startsWith("far ")
558-
? `<i class="${resolvedGameIcon}" style="margin-right:6px;font-size:16px;vertical-align:middle;"></i>`
559-
: `<img src="${resolvedGameIcon}" style="width:20px;height:20px;margin-right:6px;vertical-align:middle;object-fit:contain;">`;
554+
const gameIconHtml = this.buildWindowIconHtml(resolvedGameIcon, {
555+
margin: "6px",
556+
iconVerticalAlign: true
557+
});
560558

561559
if (window.electronAPI) {
562560
let nativeWidth = 1280;
@@ -609,13 +607,12 @@ player.load("${swfPath}");
609607
: "";
610608

611609
win.innerHTML = `
612-
<div class="window-header">
613-
<span>${gameIconHtml}${displayTitle}</span>
614-
<div class="window-header-actions">
615-
${overlayBtnHtml}
616-
${os.window.getWindowControls(resolvedSource, true)}
617-
</div>
618-
</div>
610+
${this.buildWindowHeaderMarkup(
611+
gameIconHtml,
612+
displayTitle,
613+
overlayBtnHtml,
614+
os.window.getWindowControls(resolvedSource, true)
615+
)}
619616
<div class="window-content" style="width:100%; height:100%; overflow:hidden; display:flex; align-items:center; justify-content:center; background:#1a1a1a;">
620617
<div class="modern-loader">
621618
<div class="loader-dots">
@@ -702,10 +699,32 @@ player.load("${swfPath}");
702699
return !(appMeta.type === "system" || this.TRANSPARENCY_ALLOWED_APP_IDS.has(appId));
703700
}
704701

702+
buildWindowIconHtml(resolvedIcon, options = {}) {
703+
const { margin = "8px", iconVerticalAlign = false } = options;
704+
const isFontIcon =
705+
resolvedIcon.startsWith("fas ") || resolvedIcon.startsWith("fab ") || resolvedIcon.startsWith("far ");
706+
const vertAlignStyle = iconVerticalAlign ? "vertical-align:middle;" : "";
707+
return isFontIcon
708+
? `<i class="${resolvedIcon}" style="margin-right:${margin};font-size:16px;${vertAlignStyle}"></i>`
709+
: `<img src="${resolvedIcon}" style="width:20px;height:20px;margin-right:${margin};vertical-align:middle;object-fit:contain;">`;
710+
}
711+
712+
buildWindowHeaderMarkup(iconHtml, title, overlayBtnHtml, controlsHtml) {
713+
return `
714+
<div class="window-header">
715+
<span>${iconHtml}${title}</span>
716+
<div class="window-header-actions">
717+
${overlayBtnHtml}
718+
${controlsHtml}
719+
</div>
720+
</div>
721+
`;
722+
}
723+
705724
createWindow(id, title, contentHtml, externalUrl = null, appId = null, appMeta = {}) {
706725
const urlParams = new URLSearchParams(window.location.search);
707726
if (urlParams.has("game") && appId) {
708-
document.title = sanitizeTitle(title);
727+
document.title = yuriPageTitle() || sanitizeTitle(title);
709728
document.head.insertAdjacentHTML(
710729
"beforeend",
711730
`<style>
@@ -751,23 +770,14 @@ player.load("${swfPath}");
751770
});
752771

753772
const resolvedIcon = resolveIconUrl(icon);
754-
const iconHtml =
755-
resolvedIcon.startsWith("fas ") || resolvedIcon.startsWith("fab ") || resolvedIcon.startsWith("far ")
756-
? `<i class="${resolvedIcon}" style="margin-right:8px;font-size:16px;"></i>`
757-
: `<img src="${resolvedIcon}" style="width:20px;height:20px;margin-right:8px;vertical-align:middle;object-fit:contain;">`;
773+
const iconHtml = this.buildWindowIconHtml(resolvedIcon, { margin: "8px" });
758774

759775
const overlayBtnHtml = isGame
760776
? `<button class="overlay-open-btn" title="Steam Overlay (Shift+Tab)"><i class="fab fa-steam"></i></button>`
761777
: "";
762778

763779
win.innerHTML = `
764-
<div class="window-header">
765-
<span>${iconHtml}${title}</span>
766-
<div class="window-header-actions">
767-
${overlayBtnHtml}
768-
${os.window.getWindowControls(externalUrl, true)}
769-
</div>
770-
</div>
780+
${this.buildWindowHeaderMarkup(iconHtml, title, overlayBtnHtml, os.window.getWindowControls(externalUrl, true))}
771781
<div class="window-content" style="width:100%; height:100%; overflow:hidden;">${contentHtml}</div>
772782
`;
773783

webos-desktop/src/apps/RemoteHostApp.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const SIGNALING_BASE = "wss://yukios-remote-signaling.liventcord-a60.workers.dev
1010
export class RemoteHostApp extends BaseApp {
1111
constructor(services) {
1212
super(services);
13-
this.openWindows = new Set();
1413
this.hostStreaming = false;
1514
this.hostRoomCode = null;
1615
this.hostConnState = "idle";
@@ -20,7 +19,7 @@ export class RemoteHostApp extends BaseApp {
2019

2120
async open(opts = {}) {
2221
const winId = "remote-host";
23-
if (this.openWindows.has(winId)) return;
22+
if (this.hasOpenWindow(winId)) return;
2423

2524
const isElectron = typeof window.electronAPI !== "undefined";
2625

@@ -165,7 +164,7 @@ export class RemoteHostApp extends BaseApp {
165164
</div>
166165
`;
167166

168-
this.openWindows.add(winId);
167+
this.trackWindow(winId, win);
169168
this.win = win;
170169
this.winId = winId;
171170

@@ -609,7 +608,7 @@ export class RemoteHostApp extends BaseApp {
609608
}
610609

611610
onClose(winId) {
612-
this.openWindows.delete(winId);
611+
this.untrackWindow(winId);
613612
if (this.hostStatusInterval) {
614613
clearInterval(this.hostStatusInterval);
615614
this.hostStatusInterval = null;

0 commit comments

Comments
 (0)