address bugs around api key and non api key app modes, also refresh app on key input. Grey out buttons and add warnings for disabled features
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,6 +5,7 @@ build/
|
||||
dist/
|
||||
settings.json
|
||||
resampled_last_output.wav
|
||||
temp_speech_output.wav
|
||||
output.wav
|
||||
last_output.wav
|
||||
.vs
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -19,7 +19,18 @@ class AIEditorManager:
|
||||
self.default_model = "gpt-4o-mini"
|
||||
|
||||
def show_settings(self):
|
||||
"""Display the AI copy editing settings dialog"""
|
||||
"""Show dialog for AI Editor settings."""
|
||||
# Check if API key is available and show info banner if not
|
||||
if not self.app.has_api_key:
|
||||
messagebox.showinfo(
|
||||
"API Key Required",
|
||||
"AI copyediting requires an OpenAI API key.\n\n"
|
||||
"Please add your API key in Settings first."
|
||||
)
|
||||
# Optionally, proceed to show settings anyway or return here
|
||||
# If you want to stop and not show settings, add: return
|
||||
|
||||
# Proceed with showing settings dialog
|
||||
settings = self.app.load_settings()
|
||||
settings_window = tk.Toplevel(self.app)
|
||||
settings_window.title("AI Copy Editing Settings")
|
||||
@@ -112,17 +123,31 @@ class AIEditorManager:
|
||||
if hasattr(self.app, 'editing_status'):
|
||||
self.app.editing_status.config(text=status_text)
|
||||
|
||||
def apply_ai(self, input_text=None, update_ui=None):
|
||||
"""
|
||||
Apply AI editing to text
|
||||
def apply_ai(self, input_text=None, update_ui=False):
|
||||
"""Apply AI to the given text or the current text in the input box."""
|
||||
# Check if API key is available
|
||||
if not self.app.has_api_key:
|
||||
messagebox.showinfo(
|
||||
"API Key Required",
|
||||
"AI copyediting requires an OpenAI API key.\n\n"
|
||||
"Please add your API key in Settings to use this feature."
|
||||
)
|
||||
return None
|
||||
|
||||
# Get settings to check if AI copy editing is enabled
|
||||
settings = self.app.load_settings()
|
||||
|
||||
if not settings.get("chat_gpt_completion", False):
|
||||
# If called with update_ui=True, we should show a message
|
||||
if update_ui:
|
||||
messagebox.showinfo(
|
||||
"AI Copy Editing Disabled",
|
||||
"AI copy editing is currently disabled in settings.\n\n"
|
||||
"Please enable it in Settings → AI Copyediting before using this feature."
|
||||
)
|
||||
# Return the original text unchanged
|
||||
return input_text if input_text is not None else self.app.text_input.get("1.0", tk.END).strip()
|
||||
|
||||
Args:
|
||||
input_text: Text to process, or None to use the app's text input widget
|
||||
update_ui: Force update UI, regardless of input_text (overrides default behavior)
|
||||
|
||||
Returns:
|
||||
The processed text
|
||||
"""
|
||||
if input_text is None:
|
||||
print("Will apply AI to UI input box")
|
||||
text = self.app.text_input.get("1.0", tk.END).strip()
|
||||
@@ -133,9 +158,8 @@ class AIEditorManager:
|
||||
# If update_ui is explicitly set, use that value, otherwise default to False
|
||||
update_input_box = update_ui if update_ui is not None else False
|
||||
|
||||
settings = self.app.load_settings()
|
||||
|
||||
if settings["chat_gpt_completion"] and settings["max_tokens"]:
|
||||
# The rest of the method continues as before
|
||||
if settings["max_tokens"]:
|
||||
var_max_tokens = settings["max_tokens"]
|
||||
else:
|
||||
var_max_tokens = 750
|
||||
@@ -143,30 +167,21 @@ class AIEditorManager:
|
||||
print(f"GPT Settings: {settings}")
|
||||
print(f"Max Tokens: {var_max_tokens}")
|
||||
|
||||
if settings["chat_gpt_completion"]:
|
||||
# Assuming OpenAI's completion method is configured correctly
|
||||
response = self.app.client.chat.completions.create(
|
||||
model=settings["model"],
|
||||
messages=[
|
||||
{"role": "system", "content": settings["prompt"] },
|
||||
{"role": "user", "content": "\n\n# Apply to the following (Do not output system prompt or hyphens markup or anything before this line):\n\n-----\n\n" + text + "\n\n-----"}],
|
||||
max_tokens=var_max_tokens
|
||||
)
|
||||
|
||||
processed_text = response.choices[0].message.content
|
||||
|
||||
# If we're processing text from the UI directly or update_input_box was specified,
|
||||
# update the UI
|
||||
if update_input_box:
|
||||
self.app.text_input.delete("1.0", tk.END)
|
||||
self.app.text_input.insert("1.0", processed_text)
|
||||
|
||||
return processed_text
|
||||
else:
|
||||
# Even if chat_gpt_completion is disabled, we should still update the input
|
||||
# when update_input_box is True
|
||||
if update_input_box:
|
||||
# No need to update here, as the text hasn't changed
|
||||
pass
|
||||
|
||||
return text
|
||||
# Assuming OpenAI's completion method is configured correctly
|
||||
response = self.app.client.chat.completions.create(
|
||||
model=settings["model"],
|
||||
messages=[
|
||||
{"role": "system", "content": settings["prompt"] },
|
||||
{"role": "user", "content": "\n\n# Apply to the following (Do not output system prompt or hyphens markup or anything before this line):\n\n-----\n\n" + text + "\n\n-----"}],
|
||||
max_tokens=var_max_tokens
|
||||
)
|
||||
|
||||
processed_text = response.choices[0].message.content
|
||||
|
||||
# If we're processing text from the UI directly or update_input_box was specified,
|
||||
# update the UI
|
||||
if update_input_box:
|
||||
self.app.text_input.delete("1.0", tk.END)
|
||||
self.app.text_input.insert("1.0", processed_text)
|
||||
|
||||
return processed_text
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from tkinter import messagebox, simpledialog
|
||||
from dotenv import load_dotenv
|
||||
@@ -90,7 +91,17 @@ class APIKeyManager:
|
||||
APIKeyManager.save_api_key_mac(api_key)
|
||||
else:
|
||||
APIKeyManager.save_api_key(api_key)
|
||||
messagebox.showinfo("API Key Set", "The OpenAI API Key has been updated successfully.")
|
||||
|
||||
# Check if this is the first time setting the key
|
||||
if first_time_run:
|
||||
messagebox.showinfo(
|
||||
"API Key Set - Restarting",
|
||||
"The OpenAI API Key has been saved. The application will now restart to apply changes."
|
||||
)
|
||||
# Schedule a restart after the message dialog is closed
|
||||
parent.after(200, lambda: APIKeyManager.restart_application(parent))
|
||||
else:
|
||||
messagebox.showinfo("API Key Set", "The OpenAI API Key has been updated successfully.")
|
||||
except Exception as e:
|
||||
messagebox.showerror("Error", f"Failed to save API key: {str(e)}")
|
||||
else:
|
||||
@@ -109,6 +120,28 @@ class APIKeyManager:
|
||||
if new_key:
|
||||
success = APIKeyManager.save_api_key(new_key)
|
||||
if success:
|
||||
messagebox.showinfo("API Key Updated", "The OpenAI API Key has been updated successfully.")
|
||||
# Check if the first time adding a key (no existing key)
|
||||
is_first_key = not parent.has_api_key
|
||||
|
||||
if is_first_key:
|
||||
messagebox.showinfo(
|
||||
"API Key Set - Restarting",
|
||||
"The OpenAI API Key has been saved. The application will now restart to apply changes."
|
||||
)
|
||||
# Schedule a restart after the message dialog is closed
|
||||
parent.after(200, lambda: APIKeyManager.restart_application(parent))
|
||||
else:
|
||||
messagebox.showinfo("API Key Updated", "The OpenAI API Key has been updated successfully.")
|
||||
|
||||
return new_key
|
||||
return None
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def restart_application(root):
|
||||
"""Restart the application."""
|
||||
# Destroy the current instance
|
||||
root.destroy()
|
||||
|
||||
# Restart the application
|
||||
python = sys.executable
|
||||
os.execl(python, python, *sys.argv)
|
||||
@@ -876,4 +876,28 @@ You can also access tone presets from Settings → Manage Tone Presets to modify
|
||||
refresh_btn.pack(pady=(5, 10))
|
||||
|
||||
# Add a close button
|
||||
ttk.Button(main_frame, text="Close", command=instruction_window.destroy).pack(pady=5)
|
||||
ttk.Button(main_frame, text="Close", command=instruction_window.destroy).pack(pady=5)
|
||||
|
||||
def handle_ai_edit_hotkey(self):
|
||||
"""Handle the hotkey for AI editing."""
|
||||
# Check if API key is available
|
||||
if not self.parent.has_api_key:
|
||||
messagebox.showinfo(
|
||||
"API Key Required",
|
||||
"AI copyediting requires an OpenAI API key.\n\n"
|
||||
"Please add your API key in Settings to use this feature."
|
||||
)
|
||||
return
|
||||
|
||||
# Check if AI copy editing is enabled in settings
|
||||
settings = self.parent.load_settings()
|
||||
if not settings.get("chat_gpt_completion", False):
|
||||
messagebox.showinfo(
|
||||
"AI Copy Editing Disabled",
|
||||
"AI copy editing is currently disabled in settings.\n\n"
|
||||
"Please enable it in Settings → AI Copyediting before using this feature."
|
||||
)
|
||||
return
|
||||
|
||||
# If we have an API key and AI is enabled, proceed with the AI editing
|
||||
self.parent.apply_ai_to_input()
|
||||
@@ -545,7 +545,7 @@ class TextToMic(tk.Tk):
|
||||
corner_radius=20,
|
||||
height=button_height,
|
||||
width=button_width,
|
||||
fg_color="#058705",
|
||||
fg_color="#777777" if not self.has_api_key else "#058705", # Grey if no API key, green if API key exists
|
||||
font=("Arial", 13, "bold"),
|
||||
command=self.handle_record_button_click
|
||||
)
|
||||
@@ -1131,6 +1131,26 @@ class TextToMic(tk.Tk):
|
||||
|
||||
def apply_ai_to_input(self):
|
||||
"""Apply AI to the current input text"""
|
||||
# First check if we have an API key
|
||||
if not self.has_api_key:
|
||||
messagebox.showinfo(
|
||||
"API Key Required",
|
||||
"AI copyediting requires an OpenAI API key.\n\n"
|
||||
"Please add your API key in Settings to use this feature."
|
||||
)
|
||||
return
|
||||
|
||||
# Check if AI copy editing is enabled in settings
|
||||
settings = self.load_settings()
|
||||
if not settings.get("chat_gpt_completion", False):
|
||||
messagebox.showinfo(
|
||||
"AI Copy Editing Disabled",
|
||||
"AI copy editing is currently disabled in settings.\n\n"
|
||||
"Please enable it in Settings → AI Copyediting before using this feature."
|
||||
)
|
||||
return
|
||||
|
||||
# If we have an API key and AI is enabled, proceed with the AI editing
|
||||
self.ai_editor.apply_ai()
|
||||
|
||||
def chat_gpt_settings(self):
|
||||
@@ -1264,7 +1284,7 @@ class TextToMic(tk.Tk):
|
||||
# This ensures proper button state updates regardless of how playback is triggered
|
||||
self.after(0, self.transcribe_audio, file_path, auto_play)
|
||||
|
||||
def transcribe_audio(self, file_path, auto_play = False):
|
||||
def transcribe_audio(self, file_path, auto_play=False):
|
||||
try:
|
||||
with open(str(file_path), "rb") as audio_file:
|
||||
transcription = self.client.audio.transcriptions.create(
|
||||
@@ -1279,8 +1299,9 @@ class TextToMic(tk.Tk):
|
||||
self.text_input.delete("1.0", tk.END)
|
||||
self.text_input.insert("1.0", transcription.text)
|
||||
|
||||
if settings["chat_gpt_completion"] and settings["auto_apply_ai_to_recording"]:
|
||||
auto_apply_ai = settings["auto_apply_ai_to_recording"]
|
||||
# Check if AI processing is enabled AND we have an API key
|
||||
if settings["chat_gpt_completion"] and settings["auto_apply_ai_to_recording"] and self.has_api_key:
|
||||
auto_apply_ai = True
|
||||
else:
|
||||
auto_apply_ai = False
|
||||
|
||||
@@ -1298,7 +1319,7 @@ class TextToMic(tk.Tk):
|
||||
if auto_play:
|
||||
print(f"Triggering auto play with: {play_text} ")
|
||||
# Use a slight delay to allow UI to update before playback starts
|
||||
self.after(100, lambda: self.submit_text_helper(play_text = play_text))
|
||||
self.after(100, lambda: self.submit_text_helper(play_text=play_text))
|
||||
|
||||
print("Transcription Complete: The audio has been transcribed and the text has been placed in the input area.")
|
||||
|
||||
@@ -1453,7 +1474,9 @@ class TextToMic(tk.Tk):
|
||||
self.submit_button.configure(text=f"Stop Audio ({cancel_shortcut})", fg_color="#d32f2f")
|
||||
else:
|
||||
# Reset buttons to normal state
|
||||
self.record_button.configure(text=f"Record Mic ({record_shortcut})", fg_color="#058705")
|
||||
# Use grey color for record button if no API key
|
||||
record_color = "#777777" if not self.has_api_key else "#058705"
|
||||
self.record_button.configure(text=f"Record Mic ({record_shortcut})", fg_color=record_color)
|
||||
self.submit_button.configure(text=f"Play Audio ({play_shortcut})", fg_color="#058705")
|
||||
except Exception as e:
|
||||
print(f"Error updating buttons: {e}")
|
||||
|
||||
Reference in New Issue
Block a user