0
1
mirror of https://github.com/radio95-rnt/RadioPlayer.git synced 2026-02-27 06:03:52 +01:00

this should be better

This commit is contained in:
Kuba
2025-06-22 12:23:29 +02:00
committed by GitHub
parent 84a4919c56
commit 2fc5c1657a

View File

@@ -41,7 +41,19 @@ def get_char() -> str:
return ch return ch
def clear_screen() -> None: def clear_screen() -> None:
print("\033c", end="") print("\033[2J\033[H", end="", flush=True)
def move_cursor(row, col=1):
print(f"\033[{row};{col}H", end="", flush=True)
def clear_line():
print("\033[2K", end="", flush=True)
def hide_cursor():
print("\033[?25l", end="", flush=True)
def show_cursor():
print("\033[?25h", end="", flush=True)
def get_terminal_size() -> os.terminal_size: def get_terminal_size() -> os.terminal_size:
return shutil.get_terminal_size() return shutil.get_terminal_size()
@@ -190,23 +202,18 @@ def copy_current_file_to_all(playlists: dict, source_day: str, days: list[str],
return playlists, True return playlists, True
def draw_interface(audio_files: list, playlists: dict, selected_idx: int, current_day_idx: int, scroll_offset: int, terminal_size_cache: libcache.Cache, message=None): class InterfaceState:
clear_screen() def __init__(self):
term_width, term_height = terminal_size_cache.getElement("width", False), terminal_size_cache.getElement("height", False) self.last_header = None
if term_width is None or term_height is None: self.last_files_display = None
term_width, term_height = get_terminal_size() self.last_selected_idx = -1
terminal_size_cache.saveElement("width", term_width, 5, False, True) self.last_current_day_idx = -1
terminal_size_cache.saveElement("height", term_height, 5, False, True) self.last_scroll_offset = -1
days = get_days_of_week() self.last_message = None
current_day = days[current_day_idx]
def draw_header(playlists: dict, current_day: str, current_day_idx: int, days: list[str], term_width: int, force_redraw=False, state=None):
percentages, polskie_percentages, total_pl = calculate_category_percentages(playlists, current_day) or ({}, {}, 0) percentages, polskie_percentages, total_pl = calculate_category_percentages(playlists, current_day) or ({}, {}, 0)
available_lines = term_height - 6
start_idx = max(0, min(scroll_offset, len(audio_files) - available_lines))
end_idx = min(start_idx + available_lines, len(audio_files))
print("\033[1;37mCategory Distribution:\033[0m".center(term_width))
category_bar = "" category_bar = ""
for category in ['late_night', 'morning', 'day', 'night']: for category in ['late_night', 'morning', 'day', 'night']:
percent = percentages.get(category, 0) percent = percentages.get(category, 0)
@@ -220,7 +227,7 @@ def draw_interface(audio_files: list, playlists: dict, selected_idx: int, curren
for category in categories: for category in categories:
assigned_files.update(playlists[day][category]) assigned_files.update(playlists[day][category])
total_files = len(audio_files) total_files = len(get_audio_files(files_dir))
assigned_count = len(assigned_files) assigned_count = len(assigned_files)
unassigned = ((total_files - assigned_count) / total_files) * 100 if total_files > 0 else 0 unassigned = ((total_files - assigned_count) / total_files) * 100 if total_files > 0 else 0
@@ -228,7 +235,6 @@ def draw_interface(audio_files: list, playlists: dict, selected_idx: int, curren
if len(category_bar) > term_width - 2: if len(category_bar) > term_width - 2:
category_bar = category_bar[:term_width - 5] + "..." category_bar = category_bar[:term_width - 5] + "..."
print(category_bar.center(term_width))
day_bar = "" day_bar = ""
for i, day in enumerate(days): for i, day in enumerate(days):
@@ -236,9 +242,41 @@ def draw_interface(audio_files: list, playlists: dict, selected_idx: int, curren
day_bar += f"\033[1;44m[{day}]\033[0m " day_bar += f"\033[1;44m[{day}]\033[0m "
else: else:
day_bar += f"[{day}] " day_bar += f"[{day}] "
print(day_bar.strip())
print("UP/DOWN: Navigate | D/N/L: Toggle | C: Copy day to all | F: Copy file to all | Q: Quit") header_content = (category_bar, day_bar.strip())
if force_redraw or (state and state.last_header != header_content):
move_cursor(1)
clear_line()
print("\033[1;37mCategory Distribution:\033[0m".center(term_width), end="", flush=True)
move_cursor(2)
clear_line()
print(category_bar.center(term_width), end="", flush=True)
move_cursor(3)
clear_line()
print(day_bar.strip(), end="", flush=True)
if state:
state.last_header = header_content
def draw_files_section(audio_files: list, playlists: dict, selected_idx: int, current_day: str,
scroll_offset: int, term_width: int, term_height: int, force_redraw=False, state=None):
available_lines = term_height - 6
start_idx = max(0, min(scroll_offset, len(audio_files) - available_lines))
end_idx = min(start_idx + available_lines, len(audio_files))
files_display_state = (start_idx, end_idx, selected_idx, current_day)
if force_redraw or (state and (state.last_files_display != files_display_state or
state.last_selected_idx != selected_idx or
state.last_current_day_idx != current_day)):
# Update position info line
move_cursor(5)
clear_line()
if start_idx > 0: if start_idx > 0:
print("", end="") print("", end="")
@@ -250,17 +288,14 @@ def draw_interface(audio_files: list, playlists: dict, selected_idx: int, curren
print(position_info.center(padding), end="") print(position_info.center(padding), end="")
if end_idx < len(audio_files): if end_idx < len(audio_files):
print("") print("", end="", flush=True)
else: else:
print(" ") print(" ", end="", flush=True)
if message: # Update file list
print(f"\033[1;32m{message}\033[0m") for display_row, idx in enumerate(range(start_idx, end_idx)):
else:
print()
for idx in range(start_idx, end_idx):
file = audio_files[idx] file = audio_files[idx]
line_row = 7 + display_row # Start after header lines
in_late_night = file in playlists[current_day]['late_night'] in_late_night = file in playlists[current_day]['late_night']
in_morning = file in playlists[current_day]['morning'] in_morning = file in playlists[current_day]['morning']
@@ -278,10 +313,60 @@ def draw_interface(audio_files: list, playlists: dict, selected_idx: int, curren
row_highlight = "" row_highlight = ""
max_filename_length = term_width - 15 max_filename_length = term_width - 15
display_file = file
if len(file) > max_filename_length: if len(file) > max_filename_length:
file = file[:max_filename_length-3] + "..." display_file = file[:max_filename_length-3] + "..."
print(f"{row_highlight}[{l_color}L\033[0m{row_highlight}] [{m_color}M\033[0m{row_highlight}] [{d_color}D\033[0m{row_highlight}] [{n_color}N\033[0m{row_highlight}] {file}\033[0m") move_cursor(line_row)
clear_line()
print(f"{row_highlight}[{l_color}L\033[0m{row_highlight}] [{m_color}M\033[0m{row_highlight}] [{d_color}D\033[0m{row_highlight}] [{n_color}N\033[0m{row_highlight}] {display_file}\033[0m", end="", flush=True)
# Clear any remaining lines if we're showing fewer files
for clear_row in range(7 + (end_idx - start_idx), term_height):
move_cursor(clear_row)
clear_line()
if state:
state.last_files_display = files_display_state
state.last_selected_idx = selected_idx
def draw_interface(audio_files: list, playlists: dict, selected_idx: int, current_day_idx: int,
scroll_offset: int, terminal_size_cache: libcache.Cache, message=None,
force_redraw=False, state=None):
term_width, term_height = terminal_size_cache.getElement("width", False), terminal_size_cache.getElement("height", False)
if term_width is None or term_height is None:
term_width, term_height = get_terminal_size()
terminal_size_cache.saveElement("width", term_width, 5, False, True)
terminal_size_cache.saveElement("height", term_height, 5, False, True)
force_redraw = True
days = get_days_of_week()
current_day = days[current_day_idx]
if force_redraw:
clear_screen()
hide_cursor()
# Draw static elements
move_cursor(4)
print("UP/DOWN: Navigate | D/N/L: Toggle | C: Copy day to all | F: Copy file to all | Q: Quit", end="", flush=True)
# Draw header (only if changed)
draw_header(playlists, current_day, current_day_idx, days, term_width, force_redraw, state)
# Draw files section (only if changed)
draw_files_section(audio_files, playlists, selected_idx, current_day, scroll_offset,
term_width, term_height, force_redraw, state)
# Handle message display
if message != (state.last_message if state else None):
move_cursor(6)
clear_line()
if message:
print(f"\033[1;32m{message}\033[0m", end="", flush=True)
if state:
state.last_message = message
def main(): def main():
audio_files = get_audio_files(files_dir) audio_files = get_audio_files(files_dir)
@@ -300,13 +385,20 @@ def main():
message_timer = 0 message_timer = 0
def signal_handler(sig, frame): def signal_handler(sig, frame):
show_cursor()
clear_screen() clear_screen()
sys.exit(0) sys.exit(0)
signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGINT, signal_handler)
terminal_size_cache = libcache.Cache() terminal_size_cache = libcache.Cache()
interface_state = InterfaceState()
# Initial full draw
draw_interface(audio_files, playlists, selected_idx, current_day_idx, scroll_offset,
terminal_size_cache, flash_message, force_redraw=True, state=interface_state)
try:
while True: while True:
term_width, term_height = terminal_size_cache.getElement("width", False), terminal_size_cache.getElement("height", False) term_width, term_height = terminal_size_cache.getElement("width", False), terminal_size_cache.getElement("height", False)
if term_width is None or term_height is None: if term_width is None or term_height is None:
@@ -320,7 +412,17 @@ def main():
elif selected_idx >= scroll_offset + visible_lines: elif selected_idx >= scroll_offset + visible_lines:
scroll_offset = selected_idx - visible_lines + 1 scroll_offset = selected_idx - visible_lines + 1
draw_interface(audio_files, playlists, selected_idx, current_day_idx, scroll_offset, terminal_size_cache, flash_message) # Only redraw if something changed
needs_redraw = (interface_state.last_selected_idx != selected_idx or
interface_state.last_current_day_idx != current_day_idx or
interface_state.last_scroll_offset != scroll_offset or
flash_message != interface_state.last_message)
if needs_redraw:
draw_interface(audio_files, playlists, selected_idx, current_day_idx, scroll_offset,
terminal_size_cache, flash_message, state=interface_state)
interface_state.last_current_day_idx = current_day_idx
interface_state.last_scroll_offset = scroll_offset
if flash_message: if flash_message:
message_timer += 1 message_timer += 1
@@ -331,7 +433,6 @@ def main():
key = get_char() key = get_char()
if key == 'q': if key == 'q':
clear_screen()
break break
elif key == '\x1b': elif key == '\x1b':
next_key = get_char() next_key = get_char()
@@ -444,6 +545,11 @@ def main():
break break
if found_idx != -1: if found_idx != -1:
selected_idx = found_idx selected_idx = found_idx
finally:
show_cursor()
clear_screen()
return 0 return 0
if __name__ == "__main__": if __name__ == "__main__":