mirror of
https://git.sanhost.net/sanasol/hytale-f2p
synced 2026-03-01 00:21:46 -03:00
- Fix auto-update popup: indeterminate progress fallback when no download events, show 100% on complete - Remove macOS auto-update warning (app is now signed) - Disable update popup pulse animation - Remove news tab and news section from home screen - Center play section vertically, add community links with colored icons - Add game version + branch display on play page (from manifest) - Add last played timestamp tracking - Version badge links to git.sanhost.net releases - Profiles now store version_branch and version_client per-configuration - Profile switch restores branch/version and refreshes settings UI - DevTools enabled in dev mode (electron . --dev) - Reorder community links: Chat, Discord, TG Channel, TG Group, Source Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
231 lines
6.3 KiB
JavaScript
231 lines
6.3 KiB
JavaScript
const path = require('path');
|
|
const fs = require('fs');
|
|
const { v4: uuidv4 } = require('uuid');
|
|
const {
|
|
loadConfig,
|
|
saveConfig,
|
|
getModsPath,
|
|
loadVersionBranch,
|
|
saveVersionBranch,
|
|
loadVersionClient,
|
|
saveVersionClient
|
|
} = require('../core/config');
|
|
|
|
// Lazy-load modManager to avoid circular deps, or keep imports structured.
|
|
// For now, access mod paths directly or use helper helpers.
|
|
|
|
class ProfileManager {
|
|
constructor() {
|
|
this.initialized = false;
|
|
}
|
|
|
|
init() {
|
|
if (this.initialized) return;
|
|
|
|
const config = loadConfig();
|
|
|
|
// Migration: specific check to see if we have profiles yet
|
|
if (!config.profiles || Object.keys(config.profiles).length === 0) {
|
|
this.migrateLegacyConfig(config);
|
|
}
|
|
|
|
this.initialized = true;
|
|
console.log('[ProfileManager] Initialized');
|
|
}
|
|
|
|
migrateLegacyConfig(config) {
|
|
console.log('[ProfileManager] Migrating legacy config to profile system...');
|
|
|
|
// Create a default profile with current settings
|
|
const defaultProfileId = 'default';
|
|
const defaultProfile = {
|
|
id: defaultProfileId,
|
|
name: 'Default',
|
|
created: new Date().toISOString(),
|
|
lastUsed: new Date().toISOString(),
|
|
|
|
// settings specific to this profile
|
|
// If global settings existed, we copy them here
|
|
mods: config.installedMods || [], // Legacy mods are now part of default profile
|
|
javaPath: config.javaPath || '',
|
|
versionBranch: config.version_branch || 'release',
|
|
versionClient: config.version_client || null,
|
|
gameOptions: {
|
|
minMemory: '1G',
|
|
maxMemory: '4G',
|
|
args: []
|
|
}
|
|
};
|
|
|
|
const updates = {
|
|
profiles: {
|
|
[defaultProfileId]: defaultProfile
|
|
},
|
|
activeProfileId: defaultProfileId,
|
|
// Mods are currently treated as files on disk.
|
|
// The profile's `mods` array is the source of truth for enabled/known mods per profile.
|
|
|
|
};
|
|
|
|
saveConfig(updates);
|
|
console.log('[ProfileManager] Migration complete. Created Default profile.');
|
|
}
|
|
|
|
createProfile(name) {
|
|
if (!name || typeof name !== 'string') {
|
|
throw new Error('Invalid profile name');
|
|
}
|
|
|
|
const config = loadConfig();
|
|
const id = uuidv4();
|
|
|
|
// New profiles inherit the current branch/version
|
|
const newProfile = {
|
|
id,
|
|
name: name.trim(),
|
|
created: new Date().toISOString(),
|
|
lastUsed: null,
|
|
mods: [], // Start with no mods enabled
|
|
javaPath: '',
|
|
versionBranch: loadVersionBranch(),
|
|
versionClient: loadVersionClient(),
|
|
gameOptions: {
|
|
minMemory: '1G',
|
|
maxMemory: '4G',
|
|
args: []
|
|
}
|
|
};
|
|
|
|
const profiles = config.profiles || {};
|
|
profiles[id] = newProfile;
|
|
|
|
saveConfig({ profiles });
|
|
|
|
console.log(`[ProfileManager] Created new profile: "${name}" (${id})`);
|
|
return newProfile;
|
|
}
|
|
|
|
getProfiles() {
|
|
const config = loadConfig();
|
|
return Object.values(config.profiles || {});
|
|
}
|
|
|
|
getProfile(id) {
|
|
const config = loadConfig();
|
|
return (config.profiles && config.profiles[id]) || null;
|
|
}
|
|
|
|
getActiveProfile() {
|
|
const config = loadConfig();
|
|
const activeId = config.activeProfileId;
|
|
if (!activeId || !config.profiles || !config.profiles[activeId]) {
|
|
// Fallback if something is corrupted
|
|
return this.getProfiles()[0] || null;
|
|
}
|
|
return config.profiles[activeId];
|
|
}
|
|
|
|
async activateProfile(id) {
|
|
const config = loadConfig();
|
|
if (!config.profiles || !config.profiles[id]) {
|
|
throw new Error(`Profile not found: ${id}`);
|
|
}
|
|
|
|
if (config.activeProfileId === id) {
|
|
console.log(`[ProfileManager] Profile ${id} is already active.`);
|
|
return config.profiles[id];
|
|
}
|
|
|
|
console.log(`[ProfileManager] Switching to profile: ${config.profiles[id].name} (${id})`);
|
|
|
|
// Save current branch/version to the outgoing profile
|
|
const oldId = config.activeProfileId;
|
|
if (oldId && config.profiles[oldId]) {
|
|
config.profiles[oldId].versionBranch = loadVersionBranch();
|
|
config.profiles[oldId].versionClient = loadVersionClient();
|
|
}
|
|
|
|
// 1. Update config
|
|
config.profiles[id].lastUsed = new Date().toISOString();
|
|
saveConfig({
|
|
activeProfileId: id,
|
|
profiles: config.profiles
|
|
});
|
|
|
|
// 2. Restore branch/version from the new profile
|
|
const newProfile = config.profiles[id];
|
|
if (newProfile.versionBranch) {
|
|
saveVersionBranch(newProfile.versionBranch);
|
|
}
|
|
if (newProfile.versionClient !== undefined) {
|
|
saveVersionClient(newProfile.versionClient);
|
|
}
|
|
|
|
// 3. Trigger Mod Sync
|
|
const { syncModsForCurrentProfile } = require('./modManager');
|
|
await syncModsForCurrentProfile();
|
|
|
|
return newProfile;
|
|
}
|
|
|
|
deleteProfile(id) {
|
|
const config = loadConfig();
|
|
const profiles = config.profiles || {};
|
|
|
|
if (!profiles[id]) {
|
|
throw new Error('Profile not found');
|
|
}
|
|
|
|
if (config.activeProfileId === id) {
|
|
throw new Error('Cannot delete the active profile');
|
|
}
|
|
|
|
// Don't allow deleting the last profile
|
|
if (Object.keys(profiles).length <= 1) {
|
|
throw new Error('Cannot delete the only remaining profile');
|
|
}
|
|
|
|
delete profiles[id];
|
|
saveConfig({ profiles });
|
|
console.log(`[ProfileManager] Deleted profile: ${id}`);
|
|
|
|
return true;
|
|
}
|
|
|
|
updateProfile(id, updates) {
|
|
const config = loadConfig();
|
|
const profiles = config.profiles || {};
|
|
|
|
if (!profiles[id]) {
|
|
throw new Error('Profile not found');
|
|
}
|
|
|
|
// Safety checks on updates
|
|
const allowedFields = ['name', 'javaPath', 'gameOptions', 'mods', 'versionBranch', 'versionClient'];
|
|
const sanitizedUpdates = {};
|
|
|
|
Object.keys(updates).forEach(key => {
|
|
if (allowedFields.includes(key)) {
|
|
sanitizedUpdates[key] = updates[key];
|
|
}
|
|
});
|
|
|
|
profiles[id] = { ...profiles[id], ...sanitizedUpdates };
|
|
|
|
saveConfig({ profiles });
|
|
console.log(`[ProfileManager] Updated profile: ${id}`);
|
|
|
|
// If we updated mods for the *active* profile, we might need to sync immediately
|
|
if (config.activeProfileId === id && updates.mods) {
|
|
// Optionally trigger sync?
|
|
// Sync is usually triggered when toggling a single mod.
|
|
// For bulk updates, the caller should decide when to sync.
|
|
|
|
}
|
|
|
|
return profiles[id];
|
|
}
|
|
}
|
|
|
|
module.exports = new ProfileManager();
|