Files
Modus/utils/functions.py
T

175 lines
4.6 KiB
Python

import html
import json
import os
import threading
from typing import Dict, List, Optional
from loguru import logger
# Threading helper functions
def thread(target, *args, **kwargs) -> threading.Thread:
"""
Simply run the given function in a thread.
The provided args and kwargs will be passed to the function.
"""
th = threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True)
th.start()
return th
def run_in_thread(func):
"""
Decorator to run the decorated function in a thread.
"""
def wrapper(*args, **kwargs):
return thread(func, *args, **kwargs)
return wrapper
@run_in_thread
def write_json_file(data: Dict, path: str):
try:
with open(path, "w") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
except Exception as e:
logger.warning(f"Failed to write json: {e}")
def read_json_file(file_path: str) -> Optional[List]:
if not os.path.exists(file_path):
logger.error(f"JSON file {file_path} does not exist.")
return None
with open(file_path, "r") as file:
try:
return json.load(file)
except json.JSONDecodeError as e:
logger.error(f"Failed to read JSON file {file_path}: {e}")
return None
def get_wifi_icon_for_strength(strength: int) -> str:
"""
Get the appropriate WiFi icon based on signal strength.
Args:
strength: Signal strength from 0-100
Returns:
Absolute path to the appropriate WiFi icon
"""
# Get the current directory where this script is located
current_dir = os.path.dirname(os.path.abspath(__file__))
# Get the project root (parent of utils directory)
project_root = os.path.dirname(current_dir)
if strength >= 80:
icon_name = "network-wireless-100.svg"
elif strength >= 60:
icon_name = "network-wireless-80.svg"
elif strength >= 40:
icon_name = "network-wireless-60.svg"
elif strength >= 20:
icon_name = "network-wireless-40.svg"
elif strength > 0:
icon_name = "network-wireless-20.svg"
else:
icon_name = "network-wireless-0.svg"
return os.path.join(project_root, "config", "assets", "icons", "wifi", icon_name)
def get_wifi_connecting_icon() -> str:
"""
Get the WiFi connecting icon path.
Returns:
Absolute path to the WiFi connecting icon
"""
# Get the current directory where this script is located
current_dir = os.path.dirname(os.path.abspath(__file__))
# Get the project root (parent of utils directory)
project_root = os.path.dirname(current_dir)
return os.path.join(project_root, "config", "assets", "icons", "wifi", "wifi-connecting.svg")
def is_special_workspace_id(ws_id) -> bool:
"""
Check if a workspace ID represents a special workspace.
Args:
ws_id: Workspace ID (can be int, string, or other types)
Returns:
True if the workspace is special, False otherwise
"""
try:
# Convert to int if it's a string
workspace_id = int(ws_id)
# Special workspaces have negative IDs
return workspace_id < 0
except (ValueError, TypeError):
# If it's a string, check if it starts with "special:"
if isinstance(ws_id, str) and ws_id.startswith("special:"):
return True
return False
def is_special_workspace(client: dict) -> bool:
"""
Check if a client is in a special workspace.
Args:
client: Client data dictionary from Hyprland
Returns:
True if the client is in a special workspace, False otherwise
"""
if "workspace" not in client:
return False
workspace = client["workspace"]
# Check workspace name first
if "name" in workspace:
workspace_name = str(workspace["name"])
# Special workspaces typically start with "special:" or have negative IDs
if workspace_name.startswith("special:"):
return True
# Check workspace ID
if "id" in workspace:
workspace_id = workspace["id"]
# Special workspaces have negative IDs
if workspace_id < 0:
return True
return False
def escape_markup_text(text: str) -> str:
"""
Escape special characters in text to make it safe for Pango markup.
Args:
text: Raw text that may contain special characters
Returns:
Escaped text safe for use in Pango markup
"""
if not text or not isinstance(text, str):
return ""
# Use html.escape to escape XML/HTML special characters
# This handles &, <, >, and quotes
return html.escape(text)