Login
1 branch 0 tags
Ben (Desktop/Arch) Improved podcast episode list e9e6fb4 29 days ago 81 Commits
moon / src / screens / podcast_sync_screen.c
#include "podcast_sync_screen.h"
#include <stdio.h>
#include <stdlib.h>
#include "../podcast_sync.h"
#include "../topbar.h"

static void cancel_event_cb(lv_event_t* e) {
	(void)e;
	podcast_sync_cancel();
	navigate_back(SCREEN_PODCASTS);
}

static void back_event_cb(lv_event_t* e) {
	if (lv_event_get_code(e) == LV_EVENT_CLICKED) {
		cancel_event_cb(e);
	}
}

ui_state_t setup_podcast_sync_screen(lv_obj_t* parent) {
	podcast_sync_screen_state_t* state =
	    calloc(1, sizeof(podcast_sync_screen_state_t));

	topbar_set_title("Syncing");

	// Create container for vertical layout
	lv_obj_t* cont = lv_obj_create(parent);
	lv_obj_set_size(cont, SCREEN_WIDTH, SCREEN_HEIGHT - TOPBAR_H);
	lv_obj_align(cont, LV_ALIGN_TOP_LEFT, 0, TOPBAR_H);
	lv_obj_set_style_bg_opa(cont, LV_OPA_TRANSP, 0);
	lv_obj_set_style_border_width(cont, 0, 0);
	lv_obj_set_style_pad_all(cont, 8, 0);
	lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
	lv_obj_set_flex_align(cont, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER,
	                      LV_FLEX_ALIGN_CENTER);
	lv_obj_set_style_pad_row(cont, 8, 0);

	// Status label
	state->label = lv_label_create(cont);
	lv_label_set_text(state->label, "Starting sync...");
	lv_obj_set_width(state->label, SCREEN_WIDTH - 16);
	lv_label_set_long_mode(state->label, LV_LABEL_LONG_SCROLL_CIRCULAR);

	// Progress bar
	state->bar = lv_bar_create(cont);
	lv_obj_set_size(state->bar, SCREEN_WIDTH - 16, 10);
	lv_bar_set_range(state->bar, 0, 100);
	lv_bar_set_value(state->bar, 0, LV_ANIM_OFF);

	// Back/Cancel button
	state->back_btn = lv_btn_create(cont);
	lv_obj_set_size(state->back_btn, SCREEN_WIDTH - 16, 28);
	lv_obj_t* btn_label = lv_label_create(state->back_btn);
	lv_label_set_text(btn_label, "Cancel");
	lv_obj_center(btn_label);

	lv_obj_add_event_cb(state->back_btn, back_event_cb, LV_EVENT_CLICKED, NULL);
	lv_obj_add_event_cb(state->back_btn, cancel_event_cb, LV_EVENT_CANCEL,
	                    NULL);
	lv_group_add_obj(lv_group_get_default(), state->back_btn);
	lv_group_focus_obj(state->back_btn);

	// Start sync — single feed if podcast_url is set, otherwise all
	if (app_state.podcast_url[0]) {
		podcast_sync_start_single(app_state.podcast_title,
		                          app_state.podcast_url);
		app_state.podcast_url[0] = '\0';
	} else {
		podcast_sync_start();
	}
	state->sync_active = true;

	return (ui_state_t){.type = SCREEN_PODCAST_SYNC, .podcast_sync = state};
}

void free_podcast_sync_screen(podcast_sync_screen_state_t* state) {
	if (!state) {
		return;
	}
	free(state);
}

void update_podcast_sync_screen(podcast_sync_screen_state_t* state) {
	if (!state || !state->sync_active) {
		return;
	}

	bool more = podcast_sync_step();
	const podcast_sync_status_t* st = podcast_sync_get_status();

	// Update progress
	int progress = 0;
	if (st->total_feeds > 0) {
		// Weight: feed downloads are ~10%, episode downloads are ~90%
		int feed_progress = st->current_feed * 100 / st->total_feeds;
		if (st->total_episodes > 0) {
			int ep_progress = st->current_episode * 100 / st->total_episodes;
			progress = (feed_progress * 10 + ep_progress * 90) / 100;
		} else {
			progress = feed_progress;
		}
	}

	lv_bar_set_value(state->bar, progress, LV_ANIM_OFF);

	// Update label
	if (st->current_action) {
		char buf[128];
		if (st->total_episodes > 0) {
			snprintf(buf, sizeof(buf), "[%d/%d] %s", st->current_episode,
			         st->total_episodes, st->current_action);
		} else if (st->total_feeds > 0) {
			snprintf(buf, sizeof(buf), "Feed %d/%d: %s", st->current_feed + 1,
			         st->total_feeds, st->current_action);
		} else {
			snprintf(buf, sizeof(buf), "%s", st->current_action);
		}
		lv_label_set_text(state->label, buf);
	}

	if (!more) {
		state->sync_active = false;
		lv_bar_set_value(state->bar, 100, LV_ANIM_OFF);

		char buf[256];
		if (st->errors > 0 && st->last_error[0]) {
			if (st->errors == 1) {
				snprintf(buf, sizeof(buf), "Error: %s", st->last_error);
			} else {
				snprintf(buf, sizeof(buf), "%d errors, last: %s", st->errors,
				         st->last_error);
			}
		} else {
			snprintf(buf, sizeof(buf), "Done. %d error%s", st->errors,
			         st->errors == 1 ? "" : "s");
		}
		lv_label_set_text(state->label, buf);

		topbar_set_title("Sync Done");

		// Change button text to "Back"
		lv_obj_t* btn_label = lv_obj_get_child(state->back_btn, 0);
		if (btn_label) {
			lv_label_set_text(btn_label, "Back");
		}
	}
}