namespace StudySystemClient { public class ActivitiesView : CardArea, IRefreshable { private const uint REFRESH_PERIOD_MS = 30000; private Client client; private Refresher refresher; private bool pending_sort; public ActivitiesView(Client client) { this.client = client; refresher = new Refresher(this, REFRESH_PERIOD_MS); pending_sort = false; this.map.connect(() => { refresher.start(); refresh.begin(); }); } private async void refresh() { if (!client.connected) return; try { var activities = yield client.list_activities(); update_cards(activities); } catch (ClientError e) { stderr.printf("Error refreshing activities: %s\n", e.message); } } private async void log_session(string subject, ActivityType type, int minutes) { try { yield client.log_session(subject, type, minutes); yield refresh(); } catch (ClientError e) { stderr.printf("Error logging session: %s\n", e.message); } } private void handle_pending_sort() { if (pending_sort) { container.sort(compare_cards); pending_sort = false; } } private void update_cards(Array activities) { update_existing_cards(activities); for (uint i = 0; i < activities.length; ++i) create_card(activities.index(i)); if (log_in_progress()) pending_sort = true; else container.sort(compare_cards); } private void update_existing_cards(Array activities) { var to_remove = new List(); foreach (var card in container) { if (!update_existing_card(card, activities)) to_remove.append(card); } foreach (var card in to_remove) container.remove(card); } private bool update_existing_card(ActivityCard card, Array activities) { var activity_index = find_activity(card, activities); if (activity_index == null) return false; var priority = activities.index(activity_index).priority; card.update_priority(priority); activities._remove_index_fast(activity_index); return true; } private uint? find_activity(ActivityCard card, Array activities) { for (uint i = 0; i < activities.length; ++i) { if (activities.index(i).subject == card.activity.subject && activities.index(i).type == card.activity.type) return i; } return null; } private void create_card(Activity activity) { var card = new ActivityCard(activity); card.session_logged.connect(log_session); card.log_closed.connect(handle_pending_sort); container.append(card); } private bool log_in_progress() { foreach (var card in container) { if (card.logging) return true; } return false; } private static int compare_cards(ActivityCard card1, ActivityCard card2) { if (card1.activity.priority < card2.activity.priority) return -1; else if (card1.activity.priority > card2.activity.priority) return 1; else return 0; } } }