import time import tkinter as tk from tkinter import ttk from tkinter.ttk import Notebook from tkinter import Tk import requests from app.widgets.abc import ThreadedTab class ChatTab(ThreadedTab): def __init__(self, root: Notebook | Tk, chat_server_url: str, sender_name: str, **kwargs): self.chat_server_url = chat_server_url self.sender_name = sender_name self.conn = False self.last_msg = 0 super().__init__(root, **kwargs) def task(self): try: self.get_messages() if not self.conn: self.connected() self.conn = True except requests.ConnectionError: self.disconnected() time.sleep(1) def build(self): # Create the main frame for the chat interface self.chat_frame = tk.Frame(self) self.chat_frame.pack(fill="both", expand=True) # Create the status label self.status_label = tk.Label(self.chat_frame, text="", font=("Helvetica", 16)) self.status_label.pack(fill="x") # Create the history frame with a scrollbar self.history_frame = tk.Frame(self.chat_frame) self.history_frame.pack(fill="both", expand=True) self.history_canvas = tk.Canvas(self.history_frame) self.history_canvas.pack(side="left", fill="both", expand=True) self.scrollbar = ttk.Scrollbar(self.history_frame, orient="vertical", command=self.history_canvas.yview) self.scrollbar.pack(side="right", fill="y") self.history_canvas.configure(yscrollcommand=self.scrollbar.set) self.history_canvas.bind('', lambda e: self.history_canvas.configure(scrollregion=self.history_canvas.bbox("all"))) self.history_container = tk.Frame(self.history_canvas) self.history_container.bind("", self.on_frame_configure) self.history_canvas.create_window((0, 0), window=self.history_container, anchor="nw") # Create the input frame at the bottom self.input_frame = tk.Frame(self.chat_frame) self.input_frame.pack(fill="x") self.message_entry = tk.Entry(self.input_frame) self.message_entry.pack(side="left", fill="x", expand=True, padx=5, pady=5) self.message_entry.bind("", lambda event: self.send_message()) # Bind Enter key to send_message self.send_button = tk.Button(self.input_frame, text="Send", command=self.send_message) self.send_button.pack(side="right", padx=5, pady=5) def on_frame_configure(self, event): self.history_canvas.configure(scrollregion=self.history_canvas.bbox("all")) def send_message(self): message = self.message_entry.get() if message and self.conn: response = requests.post(f"{self.chat_server_url}/send_message", json={"content": message, "sender": self.sender_name}) self.last_msg = response.json().get("id") self.display_message(self.sender_name, message) self.message_entry.delete(0, tk.END) def display_message(self, sender, message): message_frame = tk.Frame(self.history_container, bg="lightgray", pady=5) message_frame.pack(fill="x", padx=5, pady=5) message_label = tk.Label(message_frame, text=f"{sender}: {message}", anchor="w", justify="left", wraplength=300) message_label.pack(fill="x") self.history_canvas.update_idletasks() self.history_canvas.yview_moveto(1) def get_messages(self): response = requests.post(f"{self.chat_server_url}/get_messages", json={"last_id": self.last_msg}) messages = response.json().get("messages") for message in messages: self.display_message(message["sender"], message["content"]) self.last_msg = messages[-1]["id"] if messages else self.last_msg def connected(self): self.conn = True self.status_label.config(text="Connected to chat", fg="green") self.send_button.config(state="normal") def disconnected(self): self.conn = False self.status_label.config(text="Disconnected from Chat", fg="red") self.send_button.config(state="disabled") def change_sender_name(self, new_name: str): self.sender_name = new_name def change_server_url(self, new_url: str): self.chat_server_url = new_url