Rename project from "Cheating Daddy" to "Mastermind" across all files, update version to 0.6.0, and implement migration functionality for users with existing configurations. Enhance onboarding experience with migration options and update relevant documentation.
Build and Release / build (x64, ubuntu-latest, linux) (push) Has been skipped
Build and Release / build (arm64, macos-latest, darwin) (push) Has been cancelled
Build and Release / build (x64, macos-latest, darwin) (push) Has been cancelled
Build and Release / build (x64, windows-latest, win32) (push) Has been cancelled
Build and Release / release (push) Has been cancelled
Build and Release / build (x64, ubuntu-latest, linux) (push) Has been skipped
Build and Release / build (arm64, macos-latest, darwin) (push) Has been cancelled
Build and Release / build (x64, macos-latest, darwin) (push) Has been cancelled
Build and Release / build (x64, windows-latest, win32) (push) Has been cancelled
Build and Release / release (push) Has been cancelled
This commit is contained in:
@@ -1,640 +0,0 @@
|
||||
import { html, css, LitElement } from '../../assets/lit-core-2.7.4.min.js';
|
||||
import { AppHeader } from './AppHeader.js';
|
||||
import { MainView } from '../views/MainView.js';
|
||||
import { CustomizeView } from '../views/CustomizeView.js';
|
||||
import { HelpView } from '../views/HelpView.js';
|
||||
import { HistoryView } from '../views/HistoryView.js';
|
||||
import { AssistantView } from '../views/AssistantView.js';
|
||||
import { OnboardingView } from '../views/OnboardingView.js';
|
||||
import { ScreenPickerDialog } from '../views/ScreenPickerDialog.js';
|
||||
|
||||
export class CheatingDaddyApp extends LitElement {
|
||||
static styles = css`
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
font-family:
|
||||
'Inter',
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
sans-serif;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: var(--background-transparent);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.window-container {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: var(--bg-primary);
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
padding: var(--main-content-padding);
|
||||
overflow-y: auto;
|
||||
background: var(--main-content-background);
|
||||
}
|
||||
|
||||
.main-content.with-border {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.main-content.assistant-view {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.main-content.onboarding-view {
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.main-content.settings-view,
|
||||
.main-content.help-view,
|
||||
.main-content.history-view {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.view-container {
|
||||
opacity: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.view-container.entering {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--scrollbar-thumb);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--scrollbar-thumb-hover);
|
||||
}
|
||||
`;
|
||||
|
||||
static properties = {
|
||||
currentView: { type: String },
|
||||
statusText: { type: String },
|
||||
startTime: { type: Number },
|
||||
isRecording: { type: Boolean },
|
||||
sessionActive: { type: Boolean },
|
||||
selectedProfile: { type: String },
|
||||
selectedLanguage: { type: String },
|
||||
responses: { type: Array },
|
||||
currentResponseIndex: { type: Number },
|
||||
selectedScreenshotInterval: { type: String },
|
||||
selectedImageQuality: { type: String },
|
||||
layoutMode: { type: String },
|
||||
_viewInstances: { type: Object, state: true },
|
||||
_isClickThrough: { state: true },
|
||||
_awaitingNewResponse: { state: true },
|
||||
shouldAnimateResponse: { type: Boolean },
|
||||
_storageLoaded: { state: true },
|
||||
aiProvider: { type: String },
|
||||
modelInfo: { type: Object },
|
||||
showScreenPicker: { type: Boolean },
|
||||
screenSources: { type: Array },
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
// Set defaults - will be overwritten by storage
|
||||
this.currentView = 'main'; // Will check onboarding after storage loads
|
||||
this.statusText = '';
|
||||
this.startTime = null;
|
||||
this.isRecording = false;
|
||||
this.sessionActive = false;
|
||||
this.selectedProfile = 'interview';
|
||||
this.selectedLanguage = 'en-US';
|
||||
this.selectedScreenshotInterval = '5';
|
||||
this.selectedImageQuality = 'medium';
|
||||
this.layoutMode = 'normal';
|
||||
this.responses = [];
|
||||
this.currentResponseIndex = -1;
|
||||
this._viewInstances = new Map();
|
||||
this._isClickThrough = false;
|
||||
this._awaitingNewResponse = false;
|
||||
this._currentResponseIsComplete = true;
|
||||
this.shouldAnimateResponse = false;
|
||||
this._storageLoaded = false;
|
||||
this.aiProvider = 'gemini';
|
||||
this.modelInfo = { model: '', visionModel: '', whisperModel: '' };
|
||||
this.showScreenPicker = false;
|
||||
this.screenSources = [];
|
||||
|
||||
// Load from storage
|
||||
this._loadFromStorage();
|
||||
}
|
||||
|
||||
async _loadFromStorage() {
|
||||
try {
|
||||
const [config, prefs, openaiSdkCreds] = await Promise.all([
|
||||
cheatingDaddy.storage.getConfig(),
|
||||
cheatingDaddy.storage.getPreferences(),
|
||||
cheatingDaddy.storage.getOpenAISDKCredentials(),
|
||||
]);
|
||||
|
||||
// Check onboarding status
|
||||
this.currentView = config.onboarded ? 'main' : 'onboarding';
|
||||
|
||||
// Apply background appearance (color + transparency)
|
||||
this.applyBackgroundAppearance(prefs.backgroundColor ?? '#1e1e1e', prefs.backgroundTransparency ?? 0.8);
|
||||
|
||||
// Load preferences
|
||||
this.selectedProfile = prefs.selectedProfile || 'interview';
|
||||
this.selectedLanguage = prefs.selectedLanguage || 'en-US';
|
||||
this.selectedScreenshotInterval = prefs.selectedScreenshotInterval || '5';
|
||||
this.selectedImageQuality = prefs.selectedImageQuality || 'medium';
|
||||
this.layoutMode = config.layout || 'normal';
|
||||
|
||||
// Load AI provider and model info
|
||||
this.aiProvider = prefs.aiProvider || 'gemini';
|
||||
this.modelInfo = {
|
||||
model: openaiSdkCreds.model || 'gpt-4o',
|
||||
visionModel: openaiSdkCreds.visionModel || 'gpt-4o',
|
||||
whisperModel: openaiSdkCreds.whisperModel || 'whisper-1',
|
||||
};
|
||||
|
||||
this._storageLoaded = true;
|
||||
this.updateLayoutMode();
|
||||
this.requestUpdate();
|
||||
} catch (error) {
|
||||
console.error('Error loading from storage:', error);
|
||||
this._storageLoaded = true;
|
||||
this.requestUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
hexToRgb(hex) {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result
|
||||
? {
|
||||
r: parseInt(result[1], 16),
|
||||
g: parseInt(result[2], 16),
|
||||
b: parseInt(result[3], 16),
|
||||
}
|
||||
: { r: 30, g: 30, b: 30 };
|
||||
}
|
||||
|
||||
lightenColor(rgb, amount) {
|
||||
return {
|
||||
r: Math.min(255, rgb.r + amount),
|
||||
g: Math.min(255, rgb.g + amount),
|
||||
b: Math.min(255, rgb.b + amount),
|
||||
};
|
||||
}
|
||||
|
||||
applyBackgroundAppearance(backgroundColor, alpha) {
|
||||
const root = document.documentElement;
|
||||
const baseRgb = this.hexToRgb(backgroundColor);
|
||||
|
||||
// Generate color variants based on the base color
|
||||
const secondary = this.lightenColor(baseRgb, 7);
|
||||
const tertiary = this.lightenColor(baseRgb, 15);
|
||||
const hover = this.lightenColor(baseRgb, 20);
|
||||
|
||||
root.style.setProperty('--header-background', `rgba(${baseRgb.r}, ${baseRgb.g}, ${baseRgb.b}, ${alpha})`);
|
||||
root.style.setProperty('--main-content-background', `rgba(${baseRgb.r}, ${baseRgb.g}, ${baseRgb.b}, ${alpha})`);
|
||||
root.style.setProperty('--bg-primary', `rgba(${baseRgb.r}, ${baseRgb.g}, ${baseRgb.b}, ${alpha})`);
|
||||
root.style.setProperty('--bg-secondary', `rgba(${secondary.r}, ${secondary.g}, ${secondary.b}, ${alpha})`);
|
||||
root.style.setProperty('--bg-tertiary', `rgba(${tertiary.r}, ${tertiary.g}, ${tertiary.b}, ${alpha})`);
|
||||
root.style.setProperty('--bg-hover', `rgba(${hover.r}, ${hover.g}, ${hover.b}, ${alpha})`);
|
||||
root.style.setProperty('--input-background', `rgba(${tertiary.r}, ${tertiary.g}, ${tertiary.b}, ${alpha})`);
|
||||
root.style.setProperty('--input-focus-background', `rgba(${tertiary.r}, ${tertiary.g}, ${tertiary.b}, ${alpha})`);
|
||||
root.style.setProperty('--hover-background', `rgba(${hover.r}, ${hover.g}, ${hover.b}, ${alpha})`);
|
||||
root.style.setProperty('--scrollbar-background', `rgba(${baseRgb.r}, ${baseRgb.g}, ${baseRgb.b}, ${alpha})`);
|
||||
}
|
||||
|
||||
// Keep old function name for backwards compatibility
|
||||
applyBackgroundTransparency(alpha) {
|
||||
this.applyBackgroundAppearance('#1e1e1e', alpha);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
// Apply layout mode to document root
|
||||
this.updateLayoutMode();
|
||||
|
||||
// Set up IPC listeners if needed
|
||||
if (window.require) {
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
ipcRenderer.on('new-response', (_, response) => {
|
||||
this.addNewResponse(response);
|
||||
});
|
||||
ipcRenderer.on('update-response', (_, response) => {
|
||||
this.updateCurrentResponse(response);
|
||||
});
|
||||
ipcRenderer.on('update-status', (_, status) => {
|
||||
this.setStatus(status);
|
||||
});
|
||||
ipcRenderer.on('click-through-toggled', (_, isEnabled) => {
|
||||
this._isClickThrough = isEnabled;
|
||||
});
|
||||
ipcRenderer.on('reconnect-failed', (_, data) => {
|
||||
this.addNewResponse(data.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
if (window.require) {
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
ipcRenderer.removeAllListeners('new-response');
|
||||
ipcRenderer.removeAllListeners('update-response');
|
||||
ipcRenderer.removeAllListeners('update-status');
|
||||
ipcRenderer.removeAllListeners('click-through-toggled');
|
||||
ipcRenderer.removeAllListeners('reconnect-failed');
|
||||
}
|
||||
}
|
||||
|
||||
setStatus(text) {
|
||||
this.statusText = text;
|
||||
|
||||
// Mark response as complete when we get certain status messages
|
||||
if (text.includes('Ready') || text.includes('Listening') || text.includes('Error')) {
|
||||
this._currentResponseIsComplete = true;
|
||||
console.log('[setStatus] Marked current response as complete');
|
||||
}
|
||||
}
|
||||
|
||||
addNewResponse(response) {
|
||||
// Add a new response entry (first word of a new AI response)
|
||||
this.responses = [...this.responses, response];
|
||||
this.currentResponseIndex = this.responses.length - 1;
|
||||
this._awaitingNewResponse = false;
|
||||
console.log('[addNewResponse] Added:', response);
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
updateCurrentResponse(response) {
|
||||
// Update the current response in place (streaming subsequent words)
|
||||
if (this.responses.length > 0) {
|
||||
this.responses = [...this.responses.slice(0, -1), response];
|
||||
console.log('[updateCurrentResponse] Updated to:', response);
|
||||
} else {
|
||||
// Fallback: if no responses exist, add as new
|
||||
this.addNewResponse(response);
|
||||
}
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
// Header event handlers
|
||||
handleCustomizeClick() {
|
||||
this.currentView = 'customize';
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
handleHelpClick() {
|
||||
this.currentView = 'help';
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
handleHistoryClick() {
|
||||
this.currentView = 'history';
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
async handleClose() {
|
||||
if (this.currentView === 'customize' || this.currentView === 'help' || this.currentView === 'history') {
|
||||
this.currentView = 'main';
|
||||
} else if (this.currentView === 'assistant') {
|
||||
cheatingDaddy.stopCapture();
|
||||
|
||||
// Close the session
|
||||
if (window.require) {
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
await ipcRenderer.invoke('close-session');
|
||||
}
|
||||
this.sessionActive = false;
|
||||
this.currentView = 'main';
|
||||
console.log('Session closed');
|
||||
} else {
|
||||
// Quit the entire application
|
||||
if (window.require) {
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
await ipcRenderer.invoke('quit-application');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async handleHideToggle() {
|
||||
if (window.require) {
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
await ipcRenderer.invoke('toggle-window-visibility');
|
||||
}
|
||||
}
|
||||
|
||||
// Main view event handlers
|
||||
async handleStart() {
|
||||
// check if api key is empty do nothing
|
||||
const apiKey = await cheatingDaddy.storage.getApiKey();
|
||||
if (!apiKey || apiKey === '') {
|
||||
// Trigger the red blink animation on the API key input
|
||||
const mainView = this.shadowRoot.querySelector('main-view');
|
||||
if (mainView && mainView.triggerApiKeyError) {
|
||||
mainView.triggerApiKeyError();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
await cheatingDaddy.initializeGemini(this.selectedProfile, this.selectedLanguage);
|
||||
// Pass the screenshot interval as string (including 'manual' option)
|
||||
cheatingDaddy.startCapture(this.selectedScreenshotInterval, this.selectedImageQuality);
|
||||
this.responses = [];
|
||||
this.currentResponseIndex = -1;
|
||||
this.startTime = Date.now();
|
||||
this.currentView = 'assistant';
|
||||
}
|
||||
|
||||
async handleAPIKeyHelp() {
|
||||
if (window.require) {
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
await ipcRenderer.invoke('open-external', 'https://cheatingdaddy.com/help/api-key');
|
||||
}
|
||||
}
|
||||
|
||||
// Customize view event handlers
|
||||
async handleProfileChange(profile) {
|
||||
this.selectedProfile = profile;
|
||||
await cheatingDaddy.storage.updatePreference('selectedProfile', profile);
|
||||
}
|
||||
|
||||
async handleLanguageChange(language) {
|
||||
this.selectedLanguage = language;
|
||||
await cheatingDaddy.storage.updatePreference('selectedLanguage', language);
|
||||
}
|
||||
|
||||
async handleScreenshotIntervalChange(interval) {
|
||||
this.selectedScreenshotInterval = interval;
|
||||
await cheatingDaddy.storage.updatePreference('selectedScreenshotInterval', interval);
|
||||
}
|
||||
|
||||
async handleImageQualityChange(quality) {
|
||||
this.selectedImageQuality = quality;
|
||||
await cheatingDaddy.storage.updatePreference('selectedImageQuality', quality);
|
||||
}
|
||||
|
||||
handleBackClick() {
|
||||
this.currentView = 'main';
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
// Help view event handlers
|
||||
async handleExternalLinkClick(url) {
|
||||
if (window.require) {
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
await ipcRenderer.invoke('open-external', url);
|
||||
}
|
||||
}
|
||||
|
||||
// Assistant view event handlers
|
||||
async handleSendText(message) {
|
||||
const result = await window.cheatingDaddy.sendTextMessage(message);
|
||||
|
||||
if (!result.success) {
|
||||
console.error('Failed to send message:', result.error);
|
||||
this.setStatus('Error sending message: ' + result.error);
|
||||
} else {
|
||||
this.setStatus('Message sent...');
|
||||
this._awaitingNewResponse = true;
|
||||
}
|
||||
}
|
||||
|
||||
handleResponseIndexChanged(e) {
|
||||
this.currentResponseIndex = e.detail.index;
|
||||
this.shouldAnimateResponse = false;
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
// Onboarding event handlers
|
||||
handleOnboardingComplete() {
|
||||
this.currentView = 'main';
|
||||
}
|
||||
|
||||
updated(changedProperties) {
|
||||
super.updated(changedProperties);
|
||||
|
||||
// Only notify main process of view change if the view actually changed
|
||||
if (changedProperties.has('currentView') && window.require) {
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
ipcRenderer.send('view-changed', this.currentView);
|
||||
|
||||
// Add a small delay to smooth out the transition
|
||||
const viewContainer = this.shadowRoot?.querySelector('.view-container');
|
||||
if (viewContainer) {
|
||||
viewContainer.classList.add('entering');
|
||||
requestAnimationFrame(() => {
|
||||
viewContainer.classList.remove('entering');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (changedProperties.has('layoutMode')) {
|
||||
this.updateLayoutMode();
|
||||
}
|
||||
}
|
||||
|
||||
renderCurrentView() {
|
||||
// Only re-render the view if it hasn't been cached or if critical properties changed
|
||||
const viewKey = `${this.currentView}-${this.selectedProfile}-${this.selectedLanguage}`;
|
||||
|
||||
switch (this.currentView) {
|
||||
case 'onboarding':
|
||||
return html`
|
||||
<onboarding-view .onComplete=${() => this.handleOnboardingComplete()} .onClose=${() => this.handleClose()}></onboarding-view>
|
||||
`;
|
||||
|
||||
case 'main':
|
||||
return html`
|
||||
<main-view
|
||||
.onStart=${() => this.handleStart()}
|
||||
.onAPIKeyHelp=${() => this.handleAPIKeyHelp()}
|
||||
.onLayoutModeChange=${layoutMode => this.handleLayoutModeChange(layoutMode)}
|
||||
></main-view>
|
||||
`;
|
||||
|
||||
case 'customize':
|
||||
return html`
|
||||
<customize-view
|
||||
.selectedProfile=${this.selectedProfile}
|
||||
.selectedLanguage=${this.selectedLanguage}
|
||||
.selectedScreenshotInterval=${this.selectedScreenshotInterval}
|
||||
.selectedImageQuality=${this.selectedImageQuality}
|
||||
.layoutMode=${this.layoutMode}
|
||||
.onProfileChange=${profile => this.handleProfileChange(profile)}
|
||||
.onLanguageChange=${language => this.handleLanguageChange(language)}
|
||||
.onScreenshotIntervalChange=${interval => this.handleScreenshotIntervalChange(interval)}
|
||||
.onImageQualityChange=${quality => this.handleImageQualityChange(quality)}
|
||||
.onLayoutModeChange=${layoutMode => this.handleLayoutModeChange(layoutMode)}
|
||||
></customize-view>
|
||||
`;
|
||||
|
||||
case 'help':
|
||||
return html` <help-view .onExternalLinkClick=${url => this.handleExternalLinkClick(url)}></help-view> `;
|
||||
|
||||
case 'history':
|
||||
return html` <history-view></history-view> `;
|
||||
|
||||
case 'assistant':
|
||||
return html`
|
||||
<assistant-view
|
||||
.responses=${this.responses}
|
||||
.currentResponseIndex=${this.currentResponseIndex}
|
||||
.selectedProfile=${this.selectedProfile}
|
||||
.aiProvider=${this.aiProvider}
|
||||
.onSendText=${message => this.handleSendText(message)}
|
||||
.shouldAnimateResponse=${this.shouldAnimateResponse}
|
||||
@response-index-changed=${this.handleResponseIndexChanged}
|
||||
@response-animation-complete=${() => {
|
||||
this.shouldAnimateResponse = false;
|
||||
this._currentResponseIsComplete = true;
|
||||
console.log('[response-animation-complete] Marked current response as complete');
|
||||
this.requestUpdate();
|
||||
}}
|
||||
></assistant-view>
|
||||
`;
|
||||
|
||||
default:
|
||||
return html`<div>Unknown view: ${this.currentView}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const viewClassMap = {
|
||||
assistant: 'assistant-view',
|
||||
onboarding: 'onboarding-view',
|
||||
customize: 'settings-view',
|
||||
help: 'help-view',
|
||||
history: 'history-view',
|
||||
};
|
||||
const mainContentClass = `main-content ${viewClassMap[this.currentView] || 'with-border'}`;
|
||||
|
||||
return html`
|
||||
<div class="window-container">
|
||||
<div class="container">
|
||||
<app-header
|
||||
.currentView=${this.currentView}
|
||||
.statusText=${this.statusText}
|
||||
.startTime=${this.startTime}
|
||||
.aiProvider=${this.aiProvider}
|
||||
.modelInfo=${this.modelInfo}
|
||||
.onCustomizeClick=${() => this.handleCustomizeClick()}
|
||||
.onHelpClick=${() => this.handleHelpClick()}
|
||||
.onHistoryClick=${() => this.handleHistoryClick()}
|
||||
.onCloseClick=${() => this.handleClose()}
|
||||
.onBackClick=${() => this.handleBackClick()}
|
||||
.onHideToggleClick=${() => this.handleHideToggle()}
|
||||
?isClickThrough=${this._isClickThrough}
|
||||
></app-header>
|
||||
<div class="${mainContentClass}">
|
||||
<div class="view-container">${this.renderCurrentView()}</div>
|
||||
</div>
|
||||
</div>
|
||||
${this.showScreenPicker
|
||||
? html`
|
||||
<screen-picker-dialog
|
||||
?visible=${this.showScreenPicker}
|
||||
.sources=${this.screenSources}
|
||||
@source-selected=${this.handleSourceSelected}
|
||||
@cancelled=${this.handlePickerCancelled}
|
||||
></screen-picker-dialog>
|
||||
`
|
||||
: ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
updateLayoutMode() {
|
||||
// Apply or remove compact layout class to document root
|
||||
if (this.layoutMode === 'compact') {
|
||||
document.documentElement.classList.add('compact-layout');
|
||||
} else {
|
||||
document.documentElement.classList.remove('compact-layout');
|
||||
}
|
||||
}
|
||||
|
||||
async handleLayoutModeChange(layoutMode) {
|
||||
this.layoutMode = layoutMode;
|
||||
await cheatingDaddy.storage.updateConfig('layout', layoutMode);
|
||||
this.updateLayoutMode();
|
||||
|
||||
// Notify main process about layout change for window resizing
|
||||
if (window.require) {
|
||||
try {
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
await ipcRenderer.invoke('update-sizes');
|
||||
} catch (error) {
|
||||
console.error('Failed to update sizes in main process:', error);
|
||||
}
|
||||
}
|
||||
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
async showScreenPickerDialog() {
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
const result = await ipcRenderer.invoke('get-screen-sources');
|
||||
|
||||
if (result.success) {
|
||||
this.screenSources = result.sources;
|
||||
this.showScreenPicker = true;
|
||||
return new Promise(resolve => {
|
||||
this._screenPickerResolve = resolve;
|
||||
});
|
||||
} else {
|
||||
console.error('Failed to get screen sources:', result.error);
|
||||
return { cancelled: true };
|
||||
}
|
||||
}
|
||||
|
||||
async handleSourceSelected(event) {
|
||||
const { source } = event.detail;
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
|
||||
// Tell main process which source was selected
|
||||
await ipcRenderer.invoke('set-selected-source', source.id);
|
||||
|
||||
this.showScreenPicker = false;
|
||||
if (this._screenPickerResolve) {
|
||||
this._screenPickerResolve({ source });
|
||||
this._screenPickerResolve = null;
|
||||
}
|
||||
}
|
||||
|
||||
handlePickerCancelled() {
|
||||
this.showScreenPicker = false;
|
||||
if (this._screenPickerResolve) {
|
||||
this._screenPickerResolve({ cancelled: true });
|
||||
this._screenPickerResolve = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('cheating-daddy-app', CheatingDaddyApp);
|
||||
Reference in New Issue
Block a user