import flet as ft import pyperclip import time import threading import os def main(page: ft.Page): # --- 1. Window Configuration --- page.title = "PathWarp" page.theme_mode = ft.ThemeMode.DARK page.window.width = 320 page.window.height = 360 page.window.resizable = False page.window.always_on_top = True page.padding = 10 page.spacing = 10 # Center the window on startup page.window.center() # Set Window Icon if os.path.exists("logo.ico"): page.window.icon = "logo.ico" # --- 2. Path Conversion Logic --- def do_convert(win_path): if not win_path: return None p = win_path.strip().strip('"').strip("'") if p.lower().startswith("w:"): rel = p[2:].lstrip("\\") # Your Samba mapping: W:\ -> /home/rongye/ProgramFiles/ return f"/home/rongye/ProgramFiles/{rel.replace('\\', '/')}" return None # --- 3. UI Components --- input_field = ft.TextField( label="Windows Path", hint_text=r"e.g. W:\Project\Main", text_size=12, height=45, border_color=ft.Colors.CYAN_800, prefix_icon=ft.Icons.FOLDER_OPEN, content_padding=10, ) result_field = ft.TextField( label="Ubuntu Path", read_only=True, text_size=12, height=45, color=ft.Colors.GREEN_400, border_color=ft.Colors.GREEN_900, prefix_icon=ft.Icons.TERMINAL, content_padding=10, ) status_text = ft.Text("Ready", size=10, color=ft.Colors.GREY_600) def convert_click(e): res = do_convert(input_field.value) if res: result_field.value = res pyperclip.copy(res) status_text.value = f"Copied: {time.strftime('%H:%M:%S')}" status_text.color = ft.Colors.GREEN_400 else: status_text.value = "Error: Invalid Path" status_text.color = ft.Colors.RED_400 page.update() # --- 4. Background Clipboard Monitor --- stop_listen = threading.Event() def listen_clip(): last_clip = "" while not stop_listen.is_set(): try: curr = pyperclip.paste().strip().strip('"') if curr != last_clip and curr.lower().startswith("w:"): conv = do_convert(curr) if conv: pyperclip.copy(conv) input_field.value = curr result_field.value = conv status_text.value = "Auto-Warped" status_text.color = ft.Colors.CYAN_400 last_clip = conv page.update() except: pass time.sleep(0.5) def toggle_listen(e): if listen_switch.value: stop_listen.clear() threading.Thread(target=listen_clip, daemon=True).start() status_text.value = "Monitoring..." else: stop_listen.set() status_text.value = "Stopped" page.update() listen_switch = ft.Switch(label="Auto Monitor", value=False, on_change=toggle_listen, scale=0.7) # --- 5. Compact Layout --- page.add( ft.Column([ ft.Row([ ft.Icon(ft.Icons.BOLT, color=ft.Colors.CYAN_400, size=18), ft.Text("PathWarp", size=16, weight=ft.FontWeight.BOLD), ], alignment=ft.MainAxisAlignment.CENTER), input_field, ft.FilledButton( "Convert & Copy", on_click=convert_click, width=320, height=40, style=ft.ButtonStyle(shape=ft.RoundedRectangleBorder(radius=6)), ), result_field, ft.Container( content=ft.Row([listen_switch, status_text], alignment=ft.MainAxisAlignment.SPACE_BETWEEN), padding=ft.padding.only(left=5, right=10), bgcolor=ft.Colors.BLACK12, border_radius=5, ) ], spacing=8) ) if __name__ == "__main__": ft.app(target=main)