i apologize if this isn't the right place for this or if i made a mistake. but i need help with my python desktop app, the issue is that i have setup the clipboard_button from the main.py to trigger the send_message_test function in the Server class, the function is being ran clearely because the two print functions ("[server] ran send_message_test" and "[server] done running send_message_test") (the self.connected_sid is valid and correct) however the self.sio.emit("test", "test", room=self.connected_sid) doesn't seem to do anything, the connection is valid and the file-ack emit works just fine! i already searched everywhere for a solution and tried many different ways but none seemed to help. main.py: import sys import threading import time import json import qrcode import pyperclip from PIL.ImageQt import ImageQt from PySide6.QtCore import ( Qt, Property, QEasingCurve, QPropertyAnimation, Signal, QSize ) from PySide6.QtGui import QCursor, QColor, QEnterEvent, QFont, QFontDatabase, QIcon, QPixmap from PySide6.QtWidgets import ( QApplication, QWidget, QPushButton, QLabel, QHBoxLayout, QVBoxLayout ) from server import Server from win10toast import ToastNotifier from PySide6.QtWidgets import QLabel toaster = ToastNotifier() class AnimatedButton(QPushButton): def __init__(self, text): super().__init__(text) self._color = QColor("#4C4C4C") self.setStyleSheet(f"background-color: {self._color.name()}") self.animation = QPropertyAnimation(self, b"bgColor") self.animation.setDuration(140) self.animation.setEasingCurve(QEasingCurve.InOutQuad) def enterEvent(self, event: QEnterEvent): self.animate_to(QColor("#2D2D2D")) super().enterEvent(event) def leaveEvent(self, event): self.animate_to(QColor("#4C4C4C")) super().leaveEvent(event) def animate_to(self, color): self.animation.stop() self.animation.setStartValue(self._color) self.animation.setEndValue(color) self.animation.start() def get_bg_color(self): return self._color def set_bg_color(self, color): self._color = color self.setStyleSheet(f"background-color: {color.name()};") bgColor = Property(QColor, get_bg_color, set_bg_color) class MainWindow(QWidget): file_received_signal = Signal(dict) clipboard_received_signal = Signal(str) text_received_signal = Signal(str) test_button_clicked_signal = Signal(any) def __init__(self): super().__init__() self.server = server self.setWindowTitle("Connection Button") self.setFixedSize(846, 520) # Status bar unfinished # self.status_bar = QWidget() # self.status_bar.setObjectName("status_bar") # self.status_bar.setFixedSize(758, 112) # self.status_bar_layout = QHBoxLayout(self.status_bar) # self.status_label = QLabel("Status: Waiting...") # self.status_label.setAlignment(Qt.AlignCenter) # self.status_bar_layout.addWidget(self.status_label) # Clipboard button self.clipboard_button = AnimatedButton("Clipboard") self.clipboard_button.setObjectName("clipboardButton") self.clipboard_button.setFixedSize(352, 112) self.clipboard_button.setCursor(QCursor(Qt.PointingHandCursor)) self.clipboard_button.setIcon(QIcon("assets/icons/Paperclip.svg")) self.clipboard_button.setIconSize(QSize(32, 32)) self.clipboard_button.setLayoutDirection(Qt.RightToLeft) # Filesharing button self.filesharing_button = AnimatedButton("Filesharing") self.filesharing_button.setObjectName("filesharingButton") self.filesharing_button.setFixedSize(352, 112) self.filesharing_button.setCursor(QCursor(Qt.PointingHandCursor)) self.filesharing_button.setIcon(QIcon("assets/icons/file.svg")) self.filesharing_button.setIconSize(QSize(32, 32)) self.filesharing_button.setLayoutDirection(Qt.RightToLeft) # Share text button self.text_button = AnimatedButton("Share text") self.text_button.setObjectName("textButton") self.text_button.setFixedSize(352, 112) self.text_button.setCursor(QCursor(Qt.PointingHandCursor)) self.text_button.setIcon(QIcon("assets/icons/placeholder.svg")) self.text_button.setIconSize(QSize(32, 32)) self.text_button.setLayoutDirection(Qt.RightToLeft) # QR box self.qrbox = QWidget() self.qrbox.setObjectName("box") self.qrbox.setFixedSize(382, 382) self.qrbox_layout = QVBoxLayout(self.qrbox) # Layout buttons_layout = QVBoxLayout() buttons_layout.addWidget(self.clipboard_button) buttons_layout.addWidget(self.filesharing_button) buttons_layout.addWidget(self.text_button) buttons_layout.setSpacing(24) button_box_layout = QHBoxLayout() button_box_layout.addWidget(self.qrbox) button_box_layout.addLayout(buttons_layout) button_box_layout.setSpacing(24) button_box_layout.setAlignment(Qt.AlignCenter) layout = QVBoxLayout(self) # layout.addWidget(self.status_bar) layout.setAlignment(Qt.AlignCenter) layout.addSpacing(24) layout.addLayout(button_box_layout) #signals self.file_received_signal.connect(self.handle_file) self.clipboard_received_signal.connect(self.handle_clipboard) self.text_received_signal.connect(self.handle_text) self.test_button_clicked_signal.connect(self.server.send_message_test) self.clipboard_button.clicked.connect(self.test_button_clicked_signal) # self.clipboard_button.clicked.connect(self.text_received_signal) def send_clipboard_to_phone(self): text = pyperclip.paste() if text: # self.server.send_clipboard(text=text) pass else: print("clipboard is empty") def handle_callback(self, msg_type, content): if msg_type == "file": self.file_received_signal.emit(content) elif msg_type == "clipboard": self.clipboard_received_signal.emit(content) elif msg_type == "text": self.text_received_signal.emit(content) else: print(f"Unknown type: {msg_type}") def handle_file(self, file_info): fname = file_info.get("filename", "unknown") ftype = file_info.get("filetype", "unknown") toaster.show_toast(f"Received {ftype}", fname) def handle_clipboard(self, text): pyperclip.copy(text) toaster.show_toast("Copied to clipboard", text) while toaster.notification_active(): time.sleep(0.1) def handle_text(self, text): print(f"UI: Text received - {text}") def update_qr(self, data: dict, fill_color: str = "#000", back_color: str = "#000"): for i in reversed(range(self.qrbox_layout.count())): w = self.qrbox_layout.itemAt(i).widget() if w: w.setParent(None) payload = json.dumps(data, separators=(',', ':')) qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=4 ) qr.add_data(payload) qr.make(fit=True) pil_img = qr.make_image(fill_color=fill_color, back_color=back_color).convert("RGB") qt_img = ImageQt(pil_img) pix = QPixmap.fromImage(qt_img) lbl = QLabel(alignment=Qt.AlignCenter) lbl.setPixmap(pix.scaled(400, 400, Qt.KeepAspectRatio)) lbl.setStyleSheet("background: transparent;") self.qrbox_layout.addWidget(lbl) if __name__ == "__main__": server = Server() app = QApplication(sys.argv) font_id = QFontDatabase.addApplicationFont("assets/fonts/poppins-v23-latin-700.ttf") if font_id != -1: app.setFont(QFontDatabase.applicationFontFamilies(font_id)[0]) with open("styles/theme.qss", "r") as f: app.setStyleSheet(f.read()) win = MainWindow() win.update_qr({"ip": server.ip_address, "port": server.port, "authToken": server.token, "name": "pc"}, fill_color="#2D2D2D", back_color="#D3D3D3") print(server.ip_address) server.start() server.register_callback('file', win.handle_file) server.register_callback('message', win.handle_callback) win.show() sys.exit(app.exec()) server.py: import eventlet from eventlet import wsgi from urllib.parse import parse_qs import socket import socketio import threading import json import base64 import random class Server: def __init__(self): # core socket.io server self.sio = socketio.Server(cors_allowed_origins='*') self.app = socketio.WSGIApp(self.sio) # track exactly one connected client self.connected_sid = None # auth token, IP, port self.token = self.generate_token() self.ip_address = self.get_local_ip() self.port = 5000 # GUI callbacks (for file/text), registered later self._callbacks = { 'message': None, 'file': None, } # ——— event handlers ——— @self.sio.event def connect(sid, environ): print(f"[CONNECT] raw sid = {sid}, qs = {environ.get('QUERY_STRING')}") query = parse_qs(environ.get('QUERY_STRING', '')) token = query.get('token', [None])[0] self.sio.emit("test", {}, room=sid) if token == self.token: self.connected_sid = sid print(f"✅ Client {sid} connected with valid token.") self.sio.emit("message", {}) self.sio.emit("wtv", "wtv", room=sid) self.sio.emit("test", {}, room=sid) else: print(f"❌ Client {sid} invalid token: {token}") raise socketio.exceptions.ConnectionRefusedError('Unauthorized') self.sio.emit("test", {}, room=sid) @self.sio.event def disconnect(sid): print(f"[DISCONNECT] sid = {sid}") if sid == self.connected_sid: self.connected_sid = None print("→ Cleared connected_sid") @self.sio.event def file(sid, data): print(f"[FILE] from {sid}") try: filename = data.get("name") filetype = data.get("type", "application/octet-stream") b64 = data.get("data", "") content = base64.b64decode(b64) with open(filename, "wb") as f: f.write(content) print(f"Saved file: {filename}") if self._callbacks['file']: self._callbacks['file']({ "filename": filename, "filetype": filetype, }) self.sio.emit( "file-ack", {"status": "received", "filename": filename}, room=sid ) except Exception as e: print("Error in file handler:", e) @self.sio.event def message(sid, data): print(f"[MESSAGE] raw data from {sid}:", data) try: if isinstance(data, str): data = json.loads(data) msg_type = data.get("type", "text") content = data.get("content", "") if self._callbacks['message']: self._callbacks['message'](msg_type, content) except Exception as e: print("Error in message handler:", e) def generate_token(self): return str(random.randint(1000, 9999)) def send_message_test(self): print("[server] ran send_message_test") print(f"[server] self: {self.connected_sid}") self.sio.emit("test", "test", room=self.connected_sid) print("[server] done running send_message_test") def get_local_ip(self): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(('8.8.8.8', 80)) return s.getsockname()[0] except: return '127.0.0.1' finally: s.close() def start(self): threading.Thread( target=lambda: wsgi.server( eventlet.listen(('0.0.0.0', self.port)), self.app ), daemon=True ).start() print(f"Server started on {self.ip_address}:{self.port}") print(f"Auth token = {self.token}") print(f"[server] {self}") def register_callback(self, event_name, callback): if event_name in self._callbacks: self._callbacks[event_name] = callback else: raise ValueError(f"Unknown event '{event_name}'") if __name__ == "__main__": server = Server() server.start() i'm using expo react native to connect: main.tsx: //#region // main.tsx import * as Clipboard from 'expo-clipboard'; import * as DocumentPicker from 'expo-document-picker'; import * as FileSystem from 'expo-file-system'; import React, { useEffect, useRef, useState } from 'react'; import { Alert, Platform, Pressable, StyleSheet, Text, View } from 'react-native'; import 'react-native-url-polyfill/auto'; import { Socket } from 'socket.io-client'; import Fileicon from '../../assets/images/file.svg'; import ClipboardIcon from '../../assets/images/Paperclip.svg'; import PlaceHolderIcon from '../../assets/images/placeholder.svg'; import WifiIcon from '../../assets/images/wifi.svg'; import { useConnection } from '../(tabs)/test'; export default function MainScreen() { const { activeConnection } = useConnection(); const [message, setMessage] = useState(''); const socketRef = useRef<Socket | null>(null); const [isConnected, setIsConnected] = useState(false); useEffect(() => { if (!activeConnection || !activeConnection.socket) { socketRef.current?.disconnect(); socketRef.current = null; setIsConnected(false); return; } const socket = activeConnection.socket; socketRef.current = socket; socket.onAny((event, ...args) => { console.log(` [onAny] event=’${event}’, args=`, args); console.error(event, args); }); socket.on('connect', () => { console.log('Socket connected'); setIsConnected(true); }); socket.on('disconnect', () => { console.log('Socket disconnected dnwd'); setIsConnected(false); }); socket.on('connect_error', (err) => { console.log('Socket connect error:', err); setIsConnected(false); }); socket.on('message', (data: string) => { console.log('Received message:', data); }); socket.on('test', ()=>{ console.log("test"); Alert.alert("test"); }); socket.on('clipboard', (data) => { console.log(' Received clipboard event with content:', data); if (data && data.content) { Alert.alert('Clipboard updated', `Clipboard content: ${data.content}`); } else { Alert.alert('Clipboard updated', 'Clipboard event received but content empty'); } }); socket.on('file-ack', (data: { status: string; filename: string }) => { console.log('File ACK:', data); if (data.status === 'received') { Alert.alert('File Uploaded', `${data.filename} was saved on the server.`); } else { Alert.alert('Upload Failed', `Server responded with status: ${data.status}`); } }); return () => { // socket.off('connect'); // socket.off('disconnect'); // socket.off('connect_error'); // socket.off('message'); // socket.off('file-ack'); // socket.off('clipboard') // socket.off('test') socket.disconnect(); socketRef.current = null; setIsConnected(false); }; }, [activeConnection]); const sendMessage = () => { if (!message.trim()) { return Alert.alert('Error', 'Please enter a message'); } if (!socketRef.current?.connected) { return Alert.alert('Error', 'Not connected to any server'); } socketRef.current.emit('message', message); setMessage(''); }; const sendClipboard = async () => { if (!activeConnection) { return Alert.alert('Error', 'Not connected to any server'); } if (!socketRef.current?.connected) { return Alert.alert('Error', 'Not connected to any server'); } const clipboardContent = await Clipboard.getStringAsync(); if (!clipboardContent) { return Alert.alert('Clipboard', 'Clipboard is empty'); } socketRef.current.emit( 'message', { type: 'clipboard', content: clipboardContent }, Alert.alert('clipboard sent successfully') ); }; async function pickAndSendFile() { if (Platform.OS === 'web') { return Alert.alert("File picking isn't available on web."); } try { const result = await DocumentPicker.getDocumentAsync({ type: '*/*', copyToCacheDirectory: true, }); // If user cancelled if (result.canceled === true) { return; } // Ensure assets array exists if (!Array.isArray(result.assets) || result.assets.length === 0) { return Alert.alert('Error', 'No file selected.'); } const asset = result.assets[0]; const { uri, name, mimeType } = asset; if (typeof uri !== 'string' || typeof name !== 'string') { return Alert.alert('Error', 'Invalid file data.'); } await sendFile(uri, name, mimeType ?? 'application/octet-stream'); } catch (error: any) { Alert.alert('Error', 'Failed to pick/send file: ' + error.message); } } async function sendFile(uri: string, filename: string, mimeType: string) { if (!socketRef.current?.connected) { return Alert.alert('Error', 'Not connected to any server'); } try { const base64 = await FileSystem.readAsStringAsync(uri, { encoding: FileSystem.EncodingType.Base64, }); socketRef.current.emit('file', { name: filename, type: mimeType, data: base64, }); } catch (error: any) { Alert.alert('Error', 'Failed to read and send file: ' + error.message); } } return ( <View style={styles.container}> {/* Connection Status */} <Pressable style={[styles.cardBase, activeConnection ? styles.connectionCard : styles.disconnectedCard]}> <View style={styles.cardRow}> <View> <Text style={styles.cardTitle}> {activeConnection ? `Connected to ${activeConnection.name}` : 'Not Connected'} </Text> <View style={styles.cardDetails}> <Text style={styles.cardSub}> {activeConnection ? activeConnection.ip : 'XXX.XXX.XX.XXX'} </Text> <Text style={styles.cardSub}> {new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit', })} </Text> </View> </View> <WifiIcon width={28} height={28} /> </View> </Pressable> {/* Clipboard */} <Pressable onPress={sendClipboard} style={[styles.cardBase, styles.actionCard]}> <View style={styles.iconRow}> <Text style={styles.buttonText}>Send Clipboard</Text> <ClipboardIcon width={28} height={28} /> </View> </Pressable> {/* File */} <Pressable onPress={pickAndSendFile} style={[styles.cardBase, styles.actionCard]}> <View style={styles.iconRow}> <Text style={styles.buttonText}>Send File</Text> <Fileicon width={28} height={28} /> </View> </Pressable> {/* Message */} <Pressable onPress={sendMessage} style={[styles.cardBase, styles.actionCard]}> <View style={styles.iconRow}> <Text style={styles.buttonText}>Send Message</Text> <PlaceHolderIcon width={28} height={28} /> </View> </Pressable> <Text>{activeConnection?.ip}</Text> </View> ); } //#region Styles const styles = StyleSheet.create({ container: { flex: 1, padding: 20, paddingTop: 150, backgroundColor: '#fff', alignItems: 'center', fontFamily: 'poppins-regular', }, cardBase: { width: '100%', borderRadius: 16, padding: 16, marginBottom: 16, height: 112, justifyContent: 'center', }, connectionCard: { backgroundColor: '#49944E', }, disconnectedCard: { backgroundColor: '#D95353', }, cardRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 8, width: '100%', }, cardTitle: { color: '#fff', fontSize: 16, marginBottom: 6, fontFamily: 'poppins-500', }, cardDetails: { flexDirection: 'row', gap: 16, }, cardSub: { color: '#fff', fontSize: 12, opacity: 0.8, }, actionCard: { backgroundColor: '#4C4C4C', }, iconRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', width: '100%', height: '100%', paddingHorizontal: 8, }, buttonText: { color: '#fff', fontSize: 18, fontFamily: 'poppins-500', }, response: { marginTop: 20, fontSize: 16, color: '#333', }, }); //#endregion this works just fine besides not recieving said emit, this is a very debug version. again i'm very sorry if this question dosn't make sense, maybe i'm just an idiot Continue reading...