Skip to content

General improvements #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions electron/ConfigHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,23 +325,19 @@
// Make a simple API call to test the key
await openai.models.list();
return { valid: true };
} catch (error: any) {

Check failure on line 328 in electron/ConfigHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

Unexpected any. Specify a different type

Check failure on line 328 in electron/ConfigHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

Unexpected any. Specify a different type
console.error('OpenAI API key test failed:', error);

// Determine the specific error type for better error messages
let errorMessage = 'Unknown error validating OpenAI API key';

// Return error without showing dialog
if (error.status === 401) {
errorMessage = 'Invalid API key. Please check your OpenAI key and try again.';
return { valid: false, error: 'Invalid API key' };
} else if (error.status === 429) {
errorMessage = 'Rate limit exceeded. Your OpenAI API key has reached its request limit or has insufficient quota.';
return { valid: false, error: 'Rate limit exceeded' };
} else if (error.status === 500) {
errorMessage = 'OpenAI server error. Please try again later.';
} else if (error.message) {
errorMessage = `Error: ${error.message}`;
return { valid: false, error: 'OpenAI server error' };
} else {
return { valid: false, error: error.message || 'Unknown error' };
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are added to bypass the dialog box I believe? Could you explain the diff please?
I think we can make them more meaningful either way!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the app used to open a defauly error dialog box, like in windows, whenever it encountered error....i removed it

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That must be because of some error code - I don't think the removal you did is necessary

}

return { valid: false, error: errorMessage };
}
}

Expand All @@ -358,7 +354,7 @@
return { valid: true };
}
return { valid: false, error: 'Invalid Gemini API key format.' };
} catch (error: any) {

Check failure on line 357 in electron/ConfigHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

Unexpected any. Specify a different type

Check failure on line 357 in electron/ConfigHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

Unexpected any. Specify a different type
console.error('Gemini API key test failed:', error);
let errorMessage = 'Unknown error validating Gemini API key';

Expand All @@ -383,7 +379,7 @@
return { valid: true };
}
return { valid: false, error: 'Invalid Anthropic API key format.' };
} catch (error: any) {

Check failure on line 382 in electron/ConfigHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

Unexpected any. Specify a different type

Check failure on line 382 in electron/ConfigHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

Unexpected any. Specify a different type
console.error('Anthropic API key test failed:', error);
let errorMessage = 'Unknown error validating Anthropic API key';

Expand Down
120 changes: 85 additions & 35 deletions electron/ProcessingHelper.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// ProcessingHelper.ts
import fs from "node:fs"
import path from "node:path"

Check failure on line 3 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'path' is defined but never used

Check failure on line 3 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

'path' is defined but never used
import { ScreenshotHelper } from "./ScreenshotHelper"
import { IProcessingHelperDeps } from "./main"
import * as axios from "axios"
import { app, BrowserWindow, dialog } from "electron"

Check failure on line 7 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'dialog' is defined but never used

Check failure on line 7 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'app' is defined but never used

Check failure on line 7 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

'dialog' is defined but never used

Check failure on line 7 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

'app' is defined but never used
import { OpenAI } from "openai"
import { configHelper } from "./ConfigHelper"
import Anthropic from '@anthropic-ai/sdk';
Expand All @@ -31,7 +31,7 @@
finishReason: string;
}>;
}
interface AnthropicMessage {

Check failure on line 34 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'AnthropicMessage' is defined but never used

Check failure on line 34 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

'AnthropicMessage' is defined but never used
role: 'user' | 'assistant';
content: Array<{
type: 'text' | 'image';
Expand All @@ -56,7 +56,7 @@

constructor(deps: IProcessingHelperDeps) {
this.deps = deps
this.screenshotHelper = deps.getScreenshotHelper()

Check failure on line 59 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

Type 'ScreenshotHelper | null' is not assignable to type 'ScreenshotHelper'.

// Initialize AI client based on config
this.initializeAIClient();
Expand Down Expand Up @@ -188,11 +188,11 @@
}
}

// Default fallback
return "python";
// Default to auto instead of python
return "auto";
} catch (error) {
console.error("Error getting language:", error)
return "python"
return "auto"
}
}

Expand Down Expand Up @@ -286,7 +286,7 @@
throw new Error("Failed to load screenshot data");
}

const result = await this.processScreenshotsHelper(validScreenshots, signal)

Check failure on line 289 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

Argument of type '({ path: string; preview: string; data: string; } | null)[]' is not assignable to parameter of type '{ path: string; data: string; }[]'.

if (!result.success) {
console.log("Processing failed:", result.error)
Expand All @@ -313,7 +313,7 @@
result.data
)
this.deps.setView("solutions")
} catch (error: any) {

Check failure on line 316 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

Unexpected any. Specify a different type

Check failure on line 316 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

Unexpected any. Specify a different type
mainWindow.webContents.send(
this.deps.PROCESSING_EVENTS.INITIAL_SOLUTION_ERROR,
error
Expand Down Expand Up @@ -346,7 +346,6 @@
if (!extraScreenshotQueue || extraScreenshotQueue.length === 0) {
console.log("No extra screenshots found in queue");
mainWindow.webContents.send(this.deps.PROCESSING_EVENTS.NO_SCREENSHOTS);

return;
}

Expand Down Expand Up @@ -400,11 +399,11 @@

console.log(
"Combined screenshots for processing:",
validScreenshots.map((s) => s.path)

Check failure on line 402 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

's' is possibly 'null'.
)

const result = await this.processExtraScreenshotsHelper(
validScreenshots,

Check failure on line 406 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

Argument of type '({ path: string; preview: string; data: string; } | null)[]' is not assignable to parameter of type '{ path: string; data: string; }[]'.
signal
)

Expand All @@ -420,7 +419,7 @@
result.error
)
}
} catch (error: any) {

Check failure on line 422 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

Unexpected any. Specify a different type

Check failure on line 422 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

Unexpected any. Specify a different type
if (axios.isCancel(error)) {
mainWindow.webContents.send(
this.deps.PROCESSING_EVENTS.DEBUG_ERROR,
Expand All @@ -443,48 +442,47 @@
signal: AbortSignal
) {
try {
const config = configHelper.loadConfig();
const language = await this.getLanguage();
const config = configHelper.loadConfig();
const mainWindow = this.deps.getMainWindow();

// Step 1: Extract problem info using AI Vision API (OpenAI or Gemini)
const imageDataList = screenshots.map(screenshot => screenshot.data);

// Update the user on progress
// Create base64 image data array
const imageDataList = screenshots.map(s => s.data);

if (mainWindow) {
mainWindow.webContents.send("processing-status", {
message: "Analyzing problem from screenshots...",
progress: 20
message: "Analyzing screenshots...",
progress: 30
});
}

let problemInfo;
let responseContent;

if (config.apiProvider === "openai") {
// Verify OpenAI client
// OpenAI processing
if (!this.openaiClient) {
this.initializeAIClient(); // Try to reinitialize

if (!this.openaiClient) {
return {
success: false,
error: "OpenAI API key not configured or invalid. Please check your settings."
};
}
return {
success: false,
error: "OpenAI API key not configured. Please check your settings."
};
}

// Use OpenAI for processing
// Create OpenAI message structure
const messages = [
{
role: "system" as const,
content: "You are a coding challenge interpreter. Analyze the screenshot of the coding problem and extract all relevant information. Return the information in JSON format with these fields: problem_statement, constraints, example_input, example_output. Just return the structured JSON without any other text."
role: "system" as const,
content: language === 'auto' ?
"You are a coding challenge interpreter. Analyze the screenshots of the coding problem, identify the programming language being used, and extract all relevant information. Return the information in JSON format with these fields: problem_statement (which must include the identified programming language), constraints, example_input, example_output. Just return the structured JSON without any other text." :
"You are a coding challenge interpreter. Analyze the screenshots of the coding problem and extract all relevant information. Return the information in JSON format with these fields: problem_statement, constraints, example_input, example_output. Just return the structured JSON without any other text."
},
{
role: "user" as const,
content: [
{
type: "text" as const,
text: `Extract the coding problem details from these screenshots. Return in JSON format. Preferred coding language we gonna use for this problem is ${language}.`
type: "text" as const,
text: language === 'auto' ?
"Analyze the screenshots, identify the programming language being used or required, and extract all relevant information. Make sure to include the identified programming language in the problem statement." :
`Preferred coding language we gonna use for this problem is ${language}.`
},
...imageDataList.map(data => ({
type: "image_url" as const,
Expand All @@ -506,8 +504,8 @@
try {
const responseText = extractionResponse.choices[0].message.content;
// Handle when OpenAI might wrap the JSON in markdown code blocks
const jsonText = responseText.replace(/```json|```/g, '').trim();

Check failure on line 507 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

'responseText' is possibly 'null'.
problemInfo = JSON.parse(jsonText);
responseContent = JSON.parse(jsonText);
} catch (error) {
console.error("Error parsing OpenAI response:", error);
return {
Expand All @@ -531,7 +529,9 @@
role: "user",
parts: [
{
text: `You are a coding challenge interpreter. Analyze the screenshots of the coding problem and extract all relevant information. Return the information in JSON format with these fields: problem_statement, constraints, example_input, example_output. Just return the structured JSON without any other text. Preferred coding language we gonna use for this problem is ${language}.`
text: language === 'auto' ?
"You are a coding challenge interpreter. Analyze the screenshots of the coding problem, identify the programming language being used, and extract all relevant information. Return the information in JSON format with these fields: problem_statement (which must include the identified programming language), constraints, example_input, example_output. Just return the structured JSON without any other text." :
`You are a coding challenge interpreter. Analyze the screenshots of the coding problem and extract all relevant information. Return the information in JSON format with these fields: problem_statement, constraints, example_input, example_output. Just return the structured JSON without any other text. Preferred coding language we gonna use for this problem is ${language}.`
},
...imageDataList.map(data => ({
inlineData: {
Expand Down Expand Up @@ -566,7 +566,7 @@

// Handle when Gemini might wrap the JSON in markdown code blocks
const jsonText = responseText.replace(/```json|```/g, '').trim();
problemInfo = JSON.parse(jsonText);
responseContent = JSON.parse(jsonText);
} catch (error) {
console.error("Error using Gemini API:", error);
return {
Expand Down Expand Up @@ -612,7 +612,7 @@

const responseText = (response.content[0] as { type: 'text', text: string }).text;
const jsonText = responseText.replace(/```json|```/g, '').trim();
problemInfo = JSON.parse(jsonText);

Check failure on line 615 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

Cannot find name 'problemInfo'.

Check failure on line 615 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'problemInfo' is not defined

Check failure on line 615 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

Cannot find name 'problemInfo'.

Check failure on line 615 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

Cannot find name 'problemInfo'.

Check failure on line 615 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

'problemInfo' is not defined
} catch (error: any) {
console.error("Error using Anthropic API:", error);

Expand Down Expand Up @@ -645,13 +645,13 @@
}

// Store problem info in AppState
this.deps.setProblemInfo(problemInfo);
this.deps.setProblemInfo(responseContent);

// Send first success event
if (mainWindow) {
mainWindow.webContents.send(
this.deps.PROCESSING_EVENTS.PROBLEM_EXTRACTED,
problemInfo
responseContent
);

// Generate solutions after successful extraction
Expand Down Expand Up @@ -734,7 +734,31 @@
}

// Create prompt for solution generation
const promptText = `
const promptText = language === 'auto' ? `
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ornithopter-pilot Need a deep review on this since it is the heart of the code

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ornithopter-pilot Need a deep review on this since it is the heart of the code

@bhaumikmaan, thanks for the heads-up! I don't have enough time to do a deep dive today, but I'll definitely check it out later. In the meantime, if you get a chance, feel free to give it a look yourself and share any insights. You know what they say ...two pairs of eyes are better than one! 😄

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ornithopter-pilot Need a deep review on this since it is the heart of the code

@bhaumikmaan, thanks for the heads-up! I don't have enough time to do a deep dive today, but I'll definitely check it out later. In the meantime, if you get a chance, feel free to give it a look yourself and share any insights. You know what they say ...two pairs of eyes are better than one! 😄

any update? if this pull would be merged or not codebase seems solid to me except the mouse Handeling thing we need to come up with the different approach to make sure mouse tracking doesn't happen when cursor leaves the browser which is happening currently

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not tracking what you are referring to here. Is it a new issue, if so please make an issue for it. If it is for this PR, it still needs changes

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is for settings where llms are instructed to detect which language the solution has to be given based on the screenshot. For eg. one question maybe in Js other SQL. if you set to auto. it will instruct the llm to detect the language and provide soluition in that prgramming language

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense however you shouldn't default to said auto
The reason is because what about the case where a language can't be detected - there should be some reasonable fallback which was python that you changed

https://github.com/Ornithopter-pilot/interview-coder-withoupaywall-opensource/blob/6ee79cad0c5de888bf3d0404d053fca9d5ca0fa2/electron/ProcessingHelper.ts#L191-L195

Generate a detailed solution for the following coding problem. First analyze the problem statement, constraints, and examples to identify the most appropriate programming language, then provide the solution in that language:

PROBLEM STATEMENT:
${problemInfo.problem_statement}

CONSTRAINTS:
${problemInfo.constraints || "No specific constraints provided."}

EXAMPLE INPUT:
${problemInfo.example_input || "No example input provided."}

EXAMPLE OUTPUT:
${problemInfo.example_output || "No example output provided."}

I need the response in the following format:
1. Code: A clean, optimized implementation in the most appropriate programming language (based on the problem and examples)
2. Your Thoughts: A list of key insights and reasoning behind your approach
3. Time complexity: O(X) with a detailed explanation (at least 2 sentences)
4. Space complexity: O(X) with a detailed explanation (at least 2 sentences)

For complexity explanations, please be thorough. For example: "Time complexity: O(n) because we iterate through the array only once. This is optimal as we need to examine each element at least once to find the solution." or "Space complexity: O(n) because in the worst case, we store all elements in the hashmap. The additional space scales linearly with the input size."

Your solution should be efficient, well-commented, and handle edge cases.
` : `
Generate a detailed solution for the following coding problem:

PROBLEM STATEMENT:
Expand Down Expand Up @@ -889,12 +913,12 @@
}

// Extract parts from the response
const codeMatch = responseContent.match(/```(?:\w+)?\s*([\s\S]*?)```/);

Check failure on line 916 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

'responseContent' is possibly 'null' or 'undefined'.
const code = codeMatch ? codeMatch[1].trim() : responseContent;

// Extract thoughts, looking for bullet points or numbered lists
const thoughtsRegex = /(?:Thoughts:|Key Insights:|Reasoning:|Approach:)([\s\S]*?)(?:Time complexity:|$)/i;
const thoughtsMatch = responseContent.match(thoughtsRegex);

Check failure on line 921 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

'responseContent' is possibly 'null' or 'undefined'.
let thoughts: string[] = [];

if (thoughtsMatch && thoughtsMatch[1]) {
Expand All @@ -919,7 +943,7 @@
let timeComplexity = "O(n) - Linear time complexity because we only iterate through the array once. Each element is processed exactly one time, and the hashmap lookups are O(1) operations.";
let spaceComplexity = "O(n) - Linear space complexity because we store elements in the hashmap. In the worst case, we might need to store all elements before finding the solution pair.";

const timeMatch = responseContent.match(timeComplexityPattern);

Check failure on line 946 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

'responseContent' is possibly 'null' or 'undefined'.
if (timeMatch && timeMatch[1]) {
timeComplexity = timeMatch[1].trim();
if (!timeComplexity.match(/O\([^)]+\)/i)) {
Expand All @@ -934,7 +958,7 @@
}
}

const spaceMatch = responseContent.match(spaceComplexityPattern);

Check failure on line 961 in electron/ProcessingHelper.ts

View workflow job for this annotation

GitHub Actions / Build and Test on ubuntu-latest

'responseContent' is possibly 'null' or 'undefined'.
if (spaceMatch && spaceMatch[1]) {
spaceComplexity = spaceMatch[1].trim();
if (!spaceComplexity.match(/O\([^)]+\)/i)) {
Expand Down Expand Up @@ -1020,7 +1044,27 @@
const messages = [
{
role: "system" as const,
content: `You are a coding interview assistant helping debug and improve solutions. Analyze these screenshots which include either error messages, incorrect outputs, or test cases, and provide detailed debugging help.
content: language === 'auto' ?
`You are a coding interview assistant helping debug and improve solutions. Analyze these screenshots which include either error messages, incorrect outputs, or test cases. First identify the programming language from the code, then provide detailed debugging help in that language.

Your response MUST follow this exact structure with these section headers (use ### for headers):
### Issues Identified
- List each issue as a bullet point with clear explanation

### Specific Improvements and Corrections
- List specific code changes needed as bullet points

### Optimizations
- List any performance optimizations if applicable

### Explanation of Changes Needed
Here provide a clear explanation of why the changes are needed

### Key Points
- Summary bullet points of the most important takeaways

If you include code examples, use proper markdown code blocks with the appropriate language specification.` :
`You are a coding interview assistant helping debug and improve solutions. Analyze these screenshots which include either error messages, incorrect outputs, or test cases, and provide detailed debugging help.

Your response MUST follow this exact structure with these section headers (use ### for headers):
### Issues Identified
Expand All @@ -1045,11 +1089,17 @@
content: [
{
type: "text" as const,
text: `I'm solving this coding problem: "${problemInfo.problem_statement}" in ${language}. I need help with debugging or improving my solution. Here are screenshots of my code, the errors or test cases. Please provide a detailed analysis with:
text: language === 'auto' ?
`I'm solving this coding problem: "${problemInfo.problem_statement}". Analyze my code to identify the programming language being used, then help me debug or improve my solution. Here are screenshots of my code, the errors or test cases. Please provide a detailed analysis with:
1. What issues you found in my code
2. Specific improvements and corrections
3. Any optimizations that would make the solution better
4. A clear explanation of the changes needed` :
`I'm solving this coding problem: "${problemInfo.problem_statement}" in ${language}. I need help with debugging or improving my solution. Here are screenshots of my code, the errors or test cases. Please provide a detailed analysis with:
1. What issues you found in my code
2. Specific improvements and corrections
3. Any optimizations that would make the solution better
4. A clear explanation of the changes needed`
4. A clear explanation of the changes needed`
},
...imageDataList.map(data => ({
type: "image_url" as const,
Expand Down
2 changes: 1 addition & 1 deletion electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
const indexPath = path.join(__dirname, "../dist/index.html")
console.log("Falling back to:", indexPath)
if (fs.existsSync(indexPath)) {
state.mainWindow.loadFile(indexPath)

Check failure on line 272 in electron/main.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'state.mainWindow' is possibly 'null'.
} else {
console.error("Could not find index.html in dist folder")
}
Expand Down Expand Up @@ -390,11 +390,11 @@
// Window visibility functions
function hideMainWindow(): void {
if (!state.mainWindow?.isDestroyed()) {
const bounds = state.mainWindow.getBounds();

Check failure on line 393 in electron/main.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'state.mainWindow' is possibly 'null'.
state.windowPosition = { x: bounds.x, y: bounds.y };
state.windowSize = { width: bounds.width, height: bounds.height };
state.mainWindow.setIgnoreMouseEvents(true, { forward: true });

Check failure on line 396 in electron/main.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'state.mainWindow' is possibly 'null'.
state.mainWindow.setOpacity(0);

Check failure on line 397 in electron/main.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'state.mainWindow' is possibly 'null'.
state.isWindowVisible = false;
console.log('Window hidden, opacity set to 0');
}
Expand All @@ -403,17 +403,17 @@
function showMainWindow(): void {
if (!state.mainWindow?.isDestroyed()) {
if (state.windowPosition && state.windowSize) {
state.mainWindow.setBounds({

Check failure on line 406 in electron/main.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'state.mainWindow' is possibly 'null'.
...state.windowPosition,
...state.windowSize
});
}
state.mainWindow.setIgnoreMouseEvents(false);
state.mainWindow.setIgnoreMouseEvents(true, { forward: true });

Check failure on line 411 in electron/main.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'state.mainWindow' is possibly 'null'.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will prevent the user from interacting with the initial config screen (for example, setting the API key). If you already had the API key saved locally before this change, it's easy to overlook

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can interact it for the when you start... you will not be able interact it after you hide once and show it...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's a good user experience.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on the other hand i think it is better..when you startm it is ineteractable...but after hiding and showing again it is not which will help you interact with other apps.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is more complicated than I thought, but Is it possible to have a different behavior for each screen? Interact with the settings screen/button but ignore the mouse for the rest?

state.mainWindow.setAlwaysOnTop(true, "screen-saver", 1);

Check failure on line 412 in electron/main.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'state.mainWindow' is possibly 'null'.
state.mainWindow.setVisibleOnAllWorkspaces(true, {

Check failure on line 413 in electron/main.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'state.mainWindow' is possibly 'null'.
visibleOnFullScreen: true
});
state.mainWindow.setContentProtection(true);

Check failure on line 416 in electron/main.ts

View workflow job for this annotation

GitHub Actions / Build and Test on macos-latest

'state.mainWindow' is possibly 'null'.
state.mainWindow.setOpacity(0); // Set opacity to 0 before showing
state.mainWindow.showInactive(); // Use showInactive instead of show+focus
state.mainWindow.setOpacity(1); // Then set opacity to 1 after showing
Expand Down
8 changes: 2 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,8 @@ function App() {
try {
const hasKey = await window.electronAPI.checkApiKey()
setHasApiKey(hasKey)

// If no API key is found, show the settings dialog after a short delay
if (!hasKey) {
setTimeout(() => {
setIsSettingsOpen(true)
}, 1000)
showToast("API Key Required", "Please set up your API key in settings to use the application.", "neutral")
}
} catch (error) {
console.error("Failed to check API key:", error)
Expand All @@ -104,7 +100,7 @@ function App() {
if (isInitialized) {
checkApiKey()
}
}, [isInitialized])
}, [isInitialized, showToast])

// Initialize dropdown handler
useEffect(() => {
Expand Down
2 changes: 2 additions & 0 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ interface HeaderProps {
const LANGUAGES = [
{ value: 'python', label: 'Python' },
{ value: 'javascript', label: 'JavaScript' },
{ value: 'react', label: 'React.js' },
{ value: 'auto', label: 'Auto (Detect from Screen)' },
{ value: 'java', label: 'Java' },
{ value: 'cpp', label: 'C++' },
{ value: 'csharp', label: 'C#' },
Expand Down
3 changes: 3 additions & 0 deletions src/components/Settings/SettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ export function SettingsDialog({ open: externalOpen, onOpenChange }: SettingsDia
window.electronAPI.openLink(url);
};

// Return null if not explicitly opened
if (!open) return null;

return (
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent
Expand Down
65 changes: 12 additions & 53 deletions src/components/UpdateNotification.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React, { useEffect, useState } from "react"
import { Dialog, DialogContent } from "./ui/dialog"
import { Button } from "./ui/button"
import { useToast } from "../contexts/toast"

interface UpdateInfo {
version: string;
releaseNotes?: string;
}

export const UpdateNotification: React.FC = () => {
const [updateAvailable, setUpdateAvailable] = useState(false)
const [updateDownloaded, setUpdateDownloaded] = useState(false)
Expand All @@ -13,17 +16,19 @@ export const UpdateNotification: React.FC = () => {
console.log("UpdateNotification: Setting up event listeners")

const unsubscribeAvailable = window.electronAPI.onUpdateAvailable(
(info) => {
(info: UpdateInfo) => {
console.log("UpdateNotification: Update available received", info)
setUpdateAvailable(true)
showToast("Update Available", "A new version is available. The app will update on next restart.", "neutral")
}
)

const unsubscribeDownloaded = window.electronAPI.onUpdateDownloaded(
(info) => {
(info: UpdateInfo) => {
console.log("UpdateNotification: Update downloaded received", info)
setUpdateDownloaded(true)
setIsDownloading(false)
showToast("Update Ready", "Update downloaded. The app will update on next restart.", "neutral")
}
)

Expand All @@ -32,7 +37,7 @@ export const UpdateNotification: React.FC = () => {
unsubscribeAvailable()
unsubscribeDownloaded()
}
}, [])
}, [showToast])

const handleStartUpdate = async () => {
console.log("UpdateNotification: Starting update download")
Expand All @@ -50,52 +55,6 @@ export const UpdateNotification: React.FC = () => {
window.electronAPI.installUpdate()
}

console.log("UpdateNotification: Render state", {
updateAvailable,
updateDownloaded,
isDownloading
})
if (!updateAvailable && !updateDownloaded) return null

return (
<Dialog open={true}>
<DialogContent
className="bg-black/90 text-white border-white/20"
onPointerDownOutside={(e) => e.preventDefault()}
>
<div className="p-4">
<h2 className="text-lg font-semibold mb-4">
{updateDownloaded
? "Update Ready to Install"
: "A New Version is Available"}
</h2>
<p className="text-sm text-white/70 mb-6">
{updateDownloaded
? "The update has been downloaded and will be installed when you restart the app."
: "A new version of Interview Coder is available. Please update to continue using the app."}
</p>
<div className="flex justify-end gap-2">
{updateDownloaded ? (
<Button
variant="outline"
onClick={handleInstallUpdate}
className="border-white/20 hover:bg-white/10"
>
Restart and Install
</Button>
) : (
<Button
variant="outline"
onClick={handleStartUpdate}
disabled={isDownloading}
className="border-white/20 hover:bg-white/10"
>
{isDownloading ? "Downloading..." : "Download Update"}
</Button>
)}
</div>
</div>
</DialogContent>
</Dialog>
)
// Return null to prevent any UI from showing
return null
}
Loading
Loading