refactor: move Python backend modules to project root
This commit is contained in:
+123
@@ -0,0 +1,123 @@
|
||||
"""
|
||||
Clipboard management with 60-second auto-clear.
|
||||
Uses xclip/xdotool for SteamOS (KDE Plasma).
|
||||
"""
|
||||
import asyncio
|
||||
import subprocess
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
# Clipboard state
|
||||
_clipboard_timers: dict = {}
|
||||
_clipboard_contents: dict = {}
|
||||
|
||||
|
||||
async def copy_to_clipboard(text: str, clear_after: int = 60, label: str = "default") -> dict:
|
||||
"""Copy text to clipboard with auto-clear after specified seconds."""
|
||||
global _clipboard_timers, _clipboard_contents
|
||||
|
||||
try:
|
||||
# Cancel any existing timer for this label
|
||||
if label in _clipboard_timers:
|
||||
_clipboard_timers[label].cancel()
|
||||
|
||||
# Store the text
|
||||
_clipboard_contents[label] = text
|
||||
|
||||
# Copy to clipboard using xclip
|
||||
process = await asyncio.create_subprocess_exec(
|
||||
"xclip", "-selection", "clipboard",
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
await process.communicate(input=text.encode("utf-8"))
|
||||
|
||||
if process.returncode != 0:
|
||||
# Fallback to xsel if xclip not available
|
||||
process = await asyncio.create_subprocess_exec(
|
||||
"xsel", "--clipboard", "--input",
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
await process.communicate(input=text.encode("utf-8"))
|
||||
|
||||
if process.returncode != 0:
|
||||
return {"success": False, "error": "No clipboard tool available (xclip or xsel)"}
|
||||
|
||||
# Set up auto-clear timer
|
||||
async def clear_clipboard():
|
||||
await asyncio.sleep(clear_after)
|
||||
await clear_clipboard_label(label)
|
||||
|
||||
timer = asyncio.create_task(clear_clipboard())
|
||||
_clipboard_timers[label] = timer
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"clear_after": clear_after,
|
||||
"expires_at": int(time.time()) + clear_after,
|
||||
}
|
||||
|
||||
except FileNotFoundError:
|
||||
return {"success": False, "error": "xclip/xsel not found. Install with: pacman -S xclip"}
|
||||
except Exception as e:
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
|
||||
async def clear_clipboard_label(label: str = "default") -> dict:
|
||||
"""Clear the clipboard for a specific label."""
|
||||
global _clipboard_timers, _clipboard_contents
|
||||
|
||||
# Cancel timer if exists
|
||||
if label in _clipboard_timers:
|
||||
_clipboard_timers[label].cancel()
|
||||
del _clipboard_timers[label]
|
||||
|
||||
# Clear clipboard content
|
||||
if label in _clipboard_contents:
|
||||
del _clipboard_contents[label]
|
||||
|
||||
# Clear the actual clipboard
|
||||
try:
|
||||
process = await asyncio.create_subprocess_exec(
|
||||
"xclip", "-selection", "clipboard",
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
await process.communicate(input=b"")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
return {"success": True}
|
||||
|
||||
|
||||
async def clear_all_clipboards() -> dict:
|
||||
"""Clear all clipboard contents and cancel all timers."""
|
||||
global _clipboard_timers, _clipboard_contents
|
||||
|
||||
for label in list(_clipboard_timers.keys()):
|
||||
_clipboard_timers[label].cancel()
|
||||
|
||||
_clipboard_timers.clear()
|
||||
_clipboard_contents.clear()
|
||||
|
||||
await clear_clipboard_label("default")
|
||||
|
||||
return {"success": True}
|
||||
|
||||
|
||||
def get_clipboard_status(label: str = "default") -> dict:
|
||||
"""Get the status of clipboard content for a label."""
|
||||
global _clipboard_contents, _clipboard_timers
|
||||
|
||||
if label not in _clipboard_contents:
|
||||
return {"has_content": False}
|
||||
|
||||
return {
|
||||
"has_content": True,
|
||||
"label": label,
|
||||
"has_timer": label in _clipboard_timers,
|
||||
}
|
||||
Reference in New Issue
Block a user