|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { api } from '../../shared/js/core/api-client.js';
|
|
|
import { LayoutManager } from '../../shared/js/core/layout-manager.js';
|
|
|
import { Toast } from '../../shared/js/components/toast.js';
|
|
|
|
|
|
|
|
|
const DEFAULT_SETTINGS = {
|
|
|
tokens: {
|
|
|
hfToken: '',
|
|
|
coingeckoKey: '',
|
|
|
cmcKey: '',
|
|
|
etherscanKey: '',
|
|
|
cryptocompareKey: '',
|
|
|
},
|
|
|
telegram: {
|
|
|
botToken: '',
|
|
|
chatId: '',
|
|
|
enabled: true,
|
|
|
silent: false,
|
|
|
includeCharts: true,
|
|
|
},
|
|
|
signals: {
|
|
|
bullish: true,
|
|
|
bearish: true,
|
|
|
whale: true,
|
|
|
news: false,
|
|
|
sentiment: true,
|
|
|
price: true,
|
|
|
confidenceThreshold: 70,
|
|
|
priceChangeThreshold: 5,
|
|
|
whaleThreshold: 100000,
|
|
|
watchedCoins: 'BTC, ETH, SOL',
|
|
|
},
|
|
|
scheduling: {
|
|
|
autoRefreshEnabled: true,
|
|
|
intervalMarket: 30,
|
|
|
intervalNews: 120,
|
|
|
intervalSentiment: 300,
|
|
|
intervalWhale: 60,
|
|
|
intervalBlockchain: 300,
|
|
|
intervalModels: 600,
|
|
|
quietHoursEnabled: false,
|
|
|
quietStart: '22:00',
|
|
|
quietEnd: '08:00',
|
|
|
},
|
|
|
notifications: {
|
|
|
browser: true,
|
|
|
sound: true,
|
|
|
toast: true,
|
|
|
soundType: 'default',
|
|
|
volume: 50,
|
|
|
},
|
|
|
appearance: {
|
|
|
theme: 'dark',
|
|
|
compactMode: false,
|
|
|
showAnimations: true,
|
|
|
showBgEffects: true,
|
|
|
},
|
|
|
};
|
|
|
|
|
|
const STORAGE_KEY = 'crypto_monitor_settings';
|
|
|
|
|
|
class SettingsPage {
|
|
|
constructor() {
|
|
|
this.settings = this.loadSettings();
|
|
|
this.activeSection = 'api-tokens';
|
|
|
}
|
|
|
|
|
|
async init() {
|
|
|
try {
|
|
|
await LayoutManager.injectLayouts();
|
|
|
LayoutManager.setActiveNav('settings');
|
|
|
|
|
|
this.bindEvents();
|
|
|
this.populateForm();
|
|
|
this.applySettings();
|
|
|
} catch (error) {
|
|
|
console.error('[Settings] Init error:', error);
|
|
|
Toast.error('Failed to initialize settings page');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
loadSettings() {
|
|
|
try {
|
|
|
const saved = localStorage.getItem(STORAGE_KEY);
|
|
|
if (saved) {
|
|
|
const parsed = JSON.parse(saved);
|
|
|
|
|
|
return this.deepMerge(DEFAULT_SETTINGS, parsed);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.warn('[Settings] Could not load settings:', error);
|
|
|
}
|
|
|
return { ...DEFAULT_SETTINGS };
|
|
|
}
|
|
|
|
|
|
saveSettings() {
|
|
|
try {
|
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.settings));
|
|
|
return true;
|
|
|
} catch (error) {
|
|
|
console.error('[Settings] Could not save settings:', error);
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
deepMerge(target, source) {
|
|
|
const result = { ...target };
|
|
|
for (const key in source) {
|
|
|
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
|
|
result[key] = this.deepMerge(target[key] || {}, source[key]);
|
|
|
} else {
|
|
|
result[key] = source[key];
|
|
|
}
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
bindEvents() {
|
|
|
|
|
|
document.querySelectorAll('.settings-nav-btn').forEach(btn => {
|
|
|
btn.addEventListener('click', (e) => this.switchSection(e.target.closest('.settings-nav-btn').dataset.section));
|
|
|
});
|
|
|
|
|
|
|
|
|
document.getElementById('save-all-btn')?.addEventListener('click', () => this.saveAllSettings());
|
|
|
|
|
|
|
|
|
document.getElementById('reset-btn')?.addEventListener('click', () => this.resetSettings());
|
|
|
|
|
|
|
|
|
document.querySelectorAll('.toggle-visibility').forEach(btn => {
|
|
|
btn.addEventListener('click', (e) => {
|
|
|
const targetId = e.target.closest('.toggle-visibility').dataset.target;
|
|
|
this.togglePasswordVisibility(targetId);
|
|
|
});
|
|
|
});
|
|
|
|
|
|
|
|
|
this.bindRangeInput('signal-confidence', 'confidence-value', '%');
|
|
|
this.bindRangeInput('price-change-threshold', 'price-threshold-value', '%');
|
|
|
this.bindRangeInput('notif-volume', 'volume-value', '%');
|
|
|
|
|
|
|
|
|
document.getElementById('save-tokens-btn')?.addEventListener('click', () => this.saveTokens());
|
|
|
document.getElementById('test-tokens-btn')?.addEventListener('click', () => this.testTokens());
|
|
|
document.getElementById('save-telegram-btn')?.addEventListener('click', () => this.saveTelegram());
|
|
|
document.getElementById('test-telegram-btn')?.addEventListener('click', () => this.testTelegram());
|
|
|
document.getElementById('save-signals-btn')?.addEventListener('click', () => this.saveSignals());
|
|
|
document.getElementById('save-scheduling-btn')?.addEventListener('click', () => this.saveScheduling());
|
|
|
document.getElementById('save-notif-btn')?.addEventListener('click', () => this.saveNotifications());
|
|
|
document.getElementById('test-notif-btn')?.addEventListener('click', () => this.testNotification());
|
|
|
document.getElementById('save-appearance-btn')?.addEventListener('click', () => this.saveAppearance());
|
|
|
|
|
|
|
|
|
document.querySelectorAll('input[name="theme"]').forEach(radio => {
|
|
|
radio.addEventListener('change', (e) => {
|
|
|
this.settings.appearance.theme = e.target.value;
|
|
|
this.applyTheme();
|
|
|
});
|
|
|
});
|
|
|
|
|
|
|
|
|
document.querySelectorAll('.toggle-switch input').forEach(toggle => {
|
|
|
toggle.addEventListener('change', () => this.handleToggleChange(toggle));
|
|
|
});
|
|
|
}
|
|
|
|
|
|
bindRangeInput(rangeId, valueId, suffix = '') {
|
|
|
const range = document.getElementById(rangeId);
|
|
|
const valueEl = document.getElementById(valueId);
|
|
|
if (range && valueEl) {
|
|
|
range.addEventListener('input', () => {
|
|
|
valueEl.textContent = `${range.value}${suffix}`;
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
switchSection(sectionId) {
|
|
|
|
|
|
document.querySelectorAll('.settings-nav-btn').forEach(btn => {
|
|
|
btn.classList.toggle('active', btn.dataset.section === sectionId);
|
|
|
});
|
|
|
|
|
|
|
|
|
document.querySelectorAll('.settings-section').forEach(section => {
|
|
|
section.classList.toggle('active', section.id === `section-${sectionId}`);
|
|
|
});
|
|
|
|
|
|
this.activeSection = sectionId;
|
|
|
}
|
|
|
|
|
|
populateForm() {
|
|
|
|
|
|
this.setInputValue('hf-token', this.settings.tokens.hfToken);
|
|
|
this.setInputValue('coingecko-key', this.settings.tokens.coingeckoKey);
|
|
|
this.setInputValue('cmc-key', this.settings.tokens.cmcKey);
|
|
|
this.setInputValue('etherscan-key', this.settings.tokens.etherscanKey);
|
|
|
this.setInputValue('cryptocompare-key', this.settings.tokens.cryptocompareKey);
|
|
|
|
|
|
|
|
|
this.setInputValue('telegram-bot-token', this.settings.telegram.botToken);
|
|
|
this.setInputValue('telegram-chat-id', this.settings.telegram.chatId);
|
|
|
this.setCheckbox('telegram-enabled', this.settings.telegram.enabled);
|
|
|
this.setCheckbox('telegram-silent', this.settings.telegram.silent);
|
|
|
this.setCheckbox('telegram-charts', this.settings.telegram.includeCharts);
|
|
|
|
|
|
|
|
|
this.setCheckbox('signal-bullish', this.settings.signals.bullish);
|
|
|
this.setCheckbox('signal-bearish', this.settings.signals.bearish);
|
|
|
this.setCheckbox('signal-whale', this.settings.signals.whale);
|
|
|
this.setCheckbox('signal-news', this.settings.signals.news);
|
|
|
this.setCheckbox('signal-sentiment', this.settings.signals.sentiment);
|
|
|
this.setCheckbox('signal-price', this.settings.signals.price);
|
|
|
this.setRangeValue('signal-confidence', this.settings.signals.confidenceThreshold, 'confidence-value', '%');
|
|
|
this.setRangeValue('price-change-threshold', this.settings.signals.priceChangeThreshold, 'price-threshold-value', '%');
|
|
|
this.setInputValue('whale-threshold', this.settings.signals.whaleThreshold);
|
|
|
this.setInputValue('watched-coins', this.settings.signals.watchedCoins);
|
|
|
|
|
|
|
|
|
this.setCheckbox('auto-refresh-enabled', this.settings.scheduling.autoRefreshEnabled);
|
|
|
this.setSelectValue('interval-market', this.settings.scheduling.intervalMarket);
|
|
|
this.setSelectValue('interval-news', this.settings.scheduling.intervalNews);
|
|
|
this.setSelectValue('interval-sentiment', this.settings.scheduling.intervalSentiment);
|
|
|
this.setSelectValue('interval-whale', this.settings.scheduling.intervalWhale);
|
|
|
this.setSelectValue('interval-blockchain', this.settings.scheduling.intervalBlockchain);
|
|
|
this.setSelectValue('interval-models', this.settings.scheduling.intervalModels);
|
|
|
this.setCheckbox('quiet-hours-enabled', this.settings.scheduling.quietHoursEnabled);
|
|
|
this.setInputValue('quiet-start', this.settings.scheduling.quietStart);
|
|
|
this.setInputValue('quiet-end', this.settings.scheduling.quietEnd);
|
|
|
|
|
|
|
|
|
this.setCheckbox('notif-browser', this.settings.notifications.browser);
|
|
|
this.setCheckbox('notif-sound', this.settings.notifications.sound);
|
|
|
this.setCheckbox('notif-toast', this.settings.notifications.toast);
|
|
|
this.setSelectValue('notif-sound-type', this.settings.notifications.soundType);
|
|
|
this.setRangeValue('notif-volume', this.settings.notifications.volume, 'volume-value', '%');
|
|
|
|
|
|
|
|
|
this.setRadioValue('theme', this.settings.appearance.theme);
|
|
|
this.setCheckbox('compact-mode', this.settings.appearance.compactMode);
|
|
|
this.setCheckbox('show-animations', this.settings.appearance.showAnimations);
|
|
|
this.setCheckbox('show-bg-effects', this.settings.appearance.showBgEffects);
|
|
|
}
|
|
|
|
|
|
|
|
|
setInputValue(id, value) {
|
|
|
const el = document.getElementById(id);
|
|
|
if (el) el.value = value || '';
|
|
|
}
|
|
|
|
|
|
setCheckbox(id, checked) {
|
|
|
const el = document.getElementById(id);
|
|
|
if (el) el.checked = checked;
|
|
|
}
|
|
|
|
|
|
setSelectValue(id, value) {
|
|
|
const el = document.getElementById(id);
|
|
|
if (el) el.value = value;
|
|
|
}
|
|
|
|
|
|
setRadioValue(name, value) {
|
|
|
const radio = document.querySelector(`input[name="${name}"][value="${value}"]`);
|
|
|
if (radio) radio.checked = true;
|
|
|
}
|
|
|
|
|
|
setRangeValue(id, value, valueDisplayId, suffix = '') {
|
|
|
const range = document.getElementById(id);
|
|
|
const valueDisplay = document.getElementById(valueDisplayId);
|
|
|
if (range) range.value = value;
|
|
|
if (valueDisplay) valueDisplay.textContent = `${value}${suffix}`;
|
|
|
}
|
|
|
|
|
|
togglePasswordVisibility(inputId) {
|
|
|
const input = document.getElementById(inputId);
|
|
|
if (input) {
|
|
|
input.type = input.type === 'password' ? 'text' : 'password';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
handleToggleChange(toggle) {
|
|
|
|
|
|
if (toggle.id === 'show-animations') {
|
|
|
this.applyAnimations(toggle.checked);
|
|
|
} else if (toggle.id === 'show-bg-effects') {
|
|
|
this.applyBgEffects(toggle.checked);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
saveTokens() {
|
|
|
this.settings.tokens = {
|
|
|
hfToken: document.getElementById('hf-token')?.value || '',
|
|
|
coingeckoKey: document.getElementById('coingecko-key')?.value || '',
|
|
|
cmcKey: document.getElementById('cmc-key')?.value || '',
|
|
|
etherscanKey: document.getElementById('etherscan-key')?.value || '',
|
|
|
cryptocompareKey: document.getElementById('cryptocompare-key')?.value || '',
|
|
|
};
|
|
|
|
|
|
if (this.saveSettings()) {
|
|
|
Toast.success('API tokens saved successfully');
|
|
|
this.sendTokensToBackend();
|
|
|
} else {
|
|
|
Toast.error('Failed to save tokens');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
async sendTokensToBackend() {
|
|
|
try {
|
|
|
await api.post('/settings/tokens', this.settings.tokens);
|
|
|
} catch (error) {
|
|
|
console.warn('[Settings] Could not sync tokens with backend:', error);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
async testTokens() {
|
|
|
Toast.info('Testing API tokens...');
|
|
|
|
|
|
const results = [];
|
|
|
|
|
|
|
|
|
if (this.settings.tokens.hfToken) {
|
|
|
try {
|
|
|
const response = await fetch('https://huggingface.co/api/whoami-v2', {
|
|
|
headers: { 'Authorization': `Bearer ${this.settings.tokens.hfToken}` }
|
|
|
});
|
|
|
results.push({ name: 'HuggingFace', ok: response.ok });
|
|
|
} catch {
|
|
|
results.push({ name: 'HuggingFace', ok: false });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
if (this.settings.tokens.coingeckoKey) {
|
|
|
try {
|
|
|
const response = await fetch(`https://api.coingecko.com/api/v3/ping?x_cg_demo_api_key=${this.settings.tokens.coingeckoKey}`);
|
|
|
results.push({ name: 'CoinGecko', ok: response.ok });
|
|
|
} catch {
|
|
|
results.push({ name: 'CoinGecko', ok: false });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
const passed = results.filter(r => r.ok).length;
|
|
|
const total = results.length;
|
|
|
|
|
|
if (total === 0) {
|
|
|
Toast.warning('No tokens configured to test');
|
|
|
} else if (passed === total) {
|
|
|
Toast.success(`All ${total} tokens verified successfully`);
|
|
|
} else {
|
|
|
Toast.warning(`${passed}/${total} tokens verified`);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
saveTelegram() {
|
|
|
this.settings.telegram = {
|
|
|
botToken: document.getElementById('telegram-bot-token')?.value || '',
|
|
|
chatId: document.getElementById('telegram-chat-id')?.value || '',
|
|
|
enabled: document.getElementById('telegram-enabled')?.checked || false,
|
|
|
silent: document.getElementById('telegram-silent')?.checked || false,
|
|
|
includeCharts: document.getElementById('telegram-charts')?.checked || false,
|
|
|
};
|
|
|
|
|
|
if (this.saveSettings()) {
|
|
|
Toast.success('Telegram settings saved');
|
|
|
this.sendTelegramToBackend();
|
|
|
} else {
|
|
|
Toast.error('Failed to save Telegram settings');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
async sendTelegramToBackend() {
|
|
|
try {
|
|
|
await api.post('/settings/telegram', this.settings.telegram);
|
|
|
} catch (error) {
|
|
|
console.warn('[Settings] Could not sync Telegram settings with backend:', error);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
async testTelegram() {
|
|
|
const botToken = document.getElementById('telegram-bot-token')?.value;
|
|
|
const chatId = document.getElementById('telegram-chat-id')?.value;
|
|
|
|
|
|
if (!botToken || !chatId) {
|
|
|
Toast.warning('Please enter both bot token and chat ID');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
Toast.info('Sending test message...');
|
|
|
|
|
|
try {
|
|
|
const message = `🚀 *Crypto Monitor ULTIMATE*\n\nTest message sent successfully!\n\n_Time: ${new Date().toLocaleString()}_`;
|
|
|
|
|
|
const response = await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, {
|
|
|
method: 'POST',
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
body: JSON.stringify({
|
|
|
chat_id: chatId,
|
|
|
text: message,
|
|
|
parse_mode: 'Markdown',
|
|
|
disable_notification: document.getElementById('telegram-silent')?.checked || false,
|
|
|
}),
|
|
|
});
|
|
|
|
|
|
const data = await response.json();
|
|
|
|
|
|
if (data.ok) {
|
|
|
Toast.success('Test message sent successfully! Check your Telegram.');
|
|
|
} else {
|
|
|
Toast.error(`Telegram error: ${data.description}`);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
Toast.error(`Failed to send test message: ${error.message}`);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
saveSignals() {
|
|
|
this.settings.signals = {
|
|
|
bullish: document.getElementById('signal-bullish')?.checked || false,
|
|
|
bearish: document.getElementById('signal-bearish')?.checked || false,
|
|
|
whale: document.getElementById('signal-whale')?.checked || false,
|
|
|
news: document.getElementById('signal-news')?.checked || false,
|
|
|
sentiment: document.getElementById('signal-sentiment')?.checked || false,
|
|
|
price: document.getElementById('signal-price')?.checked || false,
|
|
|
confidenceThreshold: parseInt(document.getElementById('signal-confidence')?.value) || 70,
|
|
|
priceChangeThreshold: parseInt(document.getElementById('price-change-threshold')?.value) || 5,
|
|
|
whaleThreshold: parseInt(document.getElementById('whale-threshold')?.value) || 100000,
|
|
|
watchedCoins: document.getElementById('watched-coins')?.value || 'BTC, ETH, SOL',
|
|
|
};
|
|
|
|
|
|
if (this.saveSettings()) {
|
|
|
Toast.success('Signal settings saved');
|
|
|
this.sendSignalsToBackend();
|
|
|
} else {
|
|
|
Toast.error('Failed to save signal settings');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
async sendSignalsToBackend() {
|
|
|
try {
|
|
|
await api.post('/settings/signals', this.settings.signals);
|
|
|
} catch (error) {
|
|
|
console.warn('[Settings] Could not sync signal settings with backend:', error);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
saveScheduling() {
|
|
|
this.settings.scheduling = {
|
|
|
autoRefreshEnabled: document.getElementById('auto-refresh-enabled')?.checked || false,
|
|
|
intervalMarket: parseInt(document.getElementById('interval-market')?.value) || 30,
|
|
|
intervalNews: parseInt(document.getElementById('interval-news')?.value) || 120,
|
|
|
intervalSentiment: parseInt(document.getElementById('interval-sentiment')?.value) || 300,
|
|
|
intervalWhale: parseInt(document.getElementById('interval-whale')?.value) || 60,
|
|
|
intervalBlockchain: parseInt(document.getElementById('interval-blockchain')?.value) || 300,
|
|
|
intervalModels: parseInt(document.getElementById('interval-models')?.value) || 600,
|
|
|
quietHoursEnabled: document.getElementById('quiet-hours-enabled')?.checked || false,
|
|
|
quietStart: document.getElementById('quiet-start')?.value || '22:00',
|
|
|
quietEnd: document.getElementById('quiet-end')?.value || '08:00',
|
|
|
};
|
|
|
|
|
|
if (this.saveSettings()) {
|
|
|
Toast.success('Schedule settings saved');
|
|
|
this.applyScheduling();
|
|
|
} else {
|
|
|
Toast.error('Failed to save schedule settings');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
applyScheduling() {
|
|
|
|
|
|
window.dispatchEvent(new CustomEvent('settingsChanged', {
|
|
|
detail: { scheduling: this.settings.scheduling }
|
|
|
}));
|
|
|
}
|
|
|
|
|
|
saveNotifications() {
|
|
|
this.settings.notifications = {
|
|
|
browser: document.getElementById('notif-browser')?.checked || false,
|
|
|
sound: document.getElementById('notif-sound')?.checked || false,
|
|
|
toast: document.getElementById('notif-toast')?.checked || false,
|
|
|
soundType: document.getElementById('notif-sound-type')?.value || 'default',
|
|
|
volume: parseInt(document.getElementById('notif-volume')?.value) || 50,
|
|
|
};
|
|
|
|
|
|
if (this.saveSettings()) {
|
|
|
Toast.success('Notification settings saved');
|
|
|
} else {
|
|
|
Toast.error('Failed to save notification settings');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
testNotification() {
|
|
|
|
|
|
if (this.settings.notifications.browser && 'Notification' in window) {
|
|
|
if (Notification.permission === 'granted') {
|
|
|
new Notification('Crypto Monitor ULTIMATE', {
|
|
|
body: 'Test notification! Your settings are working.',
|
|
|
icon: '/static/assets/icons/favicon.svg'
|
|
|
});
|
|
|
} else if (Notification.permission !== 'denied') {
|
|
|
Notification.requestPermission().then(permission => {
|
|
|
if (permission === 'granted') {
|
|
|
new Notification('Crypto Monitor ULTIMATE', {
|
|
|
body: 'Notifications enabled successfully!',
|
|
|
icon: '/static/assets/icons/favicon.svg'
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
if (this.settings.notifications.toast) {
|
|
|
Toast.info('Test notification! Your settings are working.');
|
|
|
}
|
|
|
|
|
|
|
|
|
if (this.settings.notifications.sound) {
|
|
|
console.log('[Settings] Would play sound:', this.settings.notifications.soundType);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
saveAppearance() {
|
|
|
this.settings.appearance = {
|
|
|
theme: document.querySelector('input[name="theme"]:checked')?.value || 'dark',
|
|
|
compactMode: document.getElementById('compact-mode')?.checked || false,
|
|
|
showAnimations: document.getElementById('show-animations')?.checked || true,
|
|
|
showBgEffects: document.getElementById('show-bg-effects')?.checked || true,
|
|
|
};
|
|
|
|
|
|
if (this.saveSettings()) {
|
|
|
Toast.success('Appearance settings saved');
|
|
|
this.applySettings();
|
|
|
} else {
|
|
|
Toast.error('Failed to save appearance settings');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
applySettings() {
|
|
|
this.applyTheme();
|
|
|
this.applyAnimations(this.settings.appearance.showAnimations);
|
|
|
this.applyBgEffects(this.settings.appearance.showBgEffects);
|
|
|
this.applyCompactMode(this.settings.appearance.compactMode);
|
|
|
}
|
|
|
|
|
|
applyTheme() {
|
|
|
const theme = this.settings.appearance.theme;
|
|
|
if (theme === 'system') {
|
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
|
document.documentElement.setAttribute('data-theme', prefersDark ? 'dark' : 'light');
|
|
|
} else {
|
|
|
document.documentElement.setAttribute('data-theme', theme);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
applyAnimations(enabled) {
|
|
|
document.body.classList.toggle('no-animations', !enabled);
|
|
|
}
|
|
|
|
|
|
applyBgEffects(enabled) {
|
|
|
const bgEffects = document.querySelector('.background-effects');
|
|
|
if (bgEffects) {
|
|
|
bgEffects.style.display = enabled ? 'block' : 'none';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
applyCompactMode(enabled) {
|
|
|
document.body.classList.toggle('compact-mode', enabled);
|
|
|
}
|
|
|
|
|
|
saveAllSettings() {
|
|
|
this.saveTokens();
|
|
|
this.saveTelegram();
|
|
|
this.saveSignals();
|
|
|
this.saveScheduling();
|
|
|
this.saveNotifications();
|
|
|
this.saveAppearance();
|
|
|
Toast.success('All settings saved successfully!');
|
|
|
}
|
|
|
|
|
|
resetSettings() {
|
|
|
if (confirm('Are you sure you want to reset all settings to defaults? This cannot be undone.')) {
|
|
|
this.settings = { ...DEFAULT_SETTINGS };
|
|
|
this.saveSettings();
|
|
|
this.populateForm();
|
|
|
this.applySettings();
|
|
|
Toast.info('Settings reset to defaults');
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
const page = new SettingsPage();
|
|
|
window.settingsPage = page;
|
|
|
|
|
|
|
|
|
export function getSettings() {
|
|
|
return page.settings;
|
|
|
}
|
|
|
|
|
|
if (document.readyState === 'loading') {
|
|
|
document.addEventListener('DOMContentLoaded', () => page.init());
|
|
|
} else {
|
|
|
page.init();
|
|
|
}
|
|
|
|
|
|
|