Compare commits
2 Commits
b2f5288c4b
...
e81a47d83f
Author | SHA1 | Date | |
---|---|---|---|
e81a47d83f | |||
5697cf0652 |
@ -1,38 +1,52 @@
|
|||||||
namespace StudySystemClient {
|
namespace StudySystemClient {
|
||||||
public class ActivitiesView : CardArea<ActivityCard>, IRefreshable {
|
public class ActivitiesView : ListView<ActivityCard> {
|
||||||
private const uint REFRESH_PERIOD_MS = 30000;
|
private const uint REFRESH_PERIOD_MS = 30000;
|
||||||
|
|
||||||
private Client client;
|
private Client client;
|
||||||
|
private Updater updater;
|
||||||
private Refresher refresher;
|
private Refresher refresher;
|
||||||
private bool pending_sort;
|
private bool pending_sort;
|
||||||
|
|
||||||
public ActivitiesView(Client client) {
|
public ActivitiesView(Client client) {
|
||||||
|
base();
|
||||||
|
add_css_class("card-container");
|
||||||
this.client = client;
|
this.client = client;
|
||||||
refresher = new Refresher(this, REFRESH_PERIOD_MS);
|
updater = new Updater(this, client);
|
||||||
|
refresher = new Refresher(updater, REFRESH_PERIOD_MS);
|
||||||
pending_sort = false;
|
pending_sort = false;
|
||||||
this.map.connect(() => {
|
this.map.connect(() => {
|
||||||
|
updater.refresh.begin();
|
||||||
refresher.start();
|
refresher.start();
|
||||||
refresh.begin();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void refresh() {
|
internal IterableBox.Iterator<Type, ActivityCard> iterator() {
|
||||||
if (!client.connected)
|
return container.iterator();
|
||||||
return;
|
|
||||||
try {
|
|
||||||
var activities = yield client.list_activities();
|
|
||||||
update_cards(activities);
|
|
||||||
} catch (ClientError e) {
|
|
||||||
stderr.printf("Error refreshing activities: %s\n",
|
|
||||||
e.message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void new_card(Activity activity) {
|
||||||
|
var card = new ActivityCard(activity);
|
||||||
|
card.session_logged.connect(log_session);
|
||||||
|
card.log_closed.connect(handle_pending_sort);
|
||||||
|
container.append(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void remove_card(ActivityCard card) {
|
||||||
|
container.remove(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void sort() {
|
||||||
|
if (log_in_progress())
|
||||||
|
pending_sort = true;
|
||||||
|
else
|
||||||
|
container.sort(compare_cards);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void log_session(string subject, ActivityType type,
|
private async void log_session(string subject, ActivityType type,
|
||||||
int minutes) {
|
int minutes) {
|
||||||
try {
|
try {
|
||||||
yield client.log_session(subject, type, minutes);
|
yield client.log_session(subject, type, minutes);
|
||||||
yield refresh();
|
yield updater.refresh();
|
||||||
} catch (ClientError e) {
|
} catch (ClientError e) {
|
||||||
stderr.printf("Error logging session: %s\n", e.message);
|
stderr.printf("Error logging session: %s\n", e.message);
|
||||||
}
|
}
|
||||||
@ -45,54 +59,6 @@ namespace StudySystemClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update_cards(Array<Activity> 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<Activity> activities) {
|
|
||||||
var to_remove = new List<ActivityCard>();
|
|
||||||
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<Activity> 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<Activity> 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() {
|
private bool log_in_progress() {
|
||||||
foreach (var card in container) {
|
foreach (var card in container) {
|
||||||
if (card.logging)
|
if (card.logging)
|
||||||
@ -111,4 +77,64 @@ namespace StudySystemClient {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class Updater : IRefreshable {
|
||||||
|
private weak ActivitiesView target;
|
||||||
|
private Client client;
|
||||||
|
|
||||||
|
public Updater(ActivitiesView target, Client client) {
|
||||||
|
this.target = target;
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void refresh() {
|
||||||
|
if (!client.connected || target == null)
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
var activities = yield client.list_activities();
|
||||||
|
apply_update(activities);
|
||||||
|
target.sort();
|
||||||
|
} catch (ClientError e) {
|
||||||
|
stderr.printf("Error refreshing activities: %s\n",
|
||||||
|
e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void apply_update(Array<Activity> activities) {
|
||||||
|
update_existing(activities);
|
||||||
|
for (uint i = 0; i < activities.length; ++i)
|
||||||
|
target.new_card(activities.index(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update_existing(Array<Activity> activities) {
|
||||||
|
var to_remove = new List<ActivityCard>();
|
||||||
|
foreach (var card in target) {
|
||||||
|
if (!update_card(card, activities))
|
||||||
|
to_remove.append(card);
|
||||||
|
}
|
||||||
|
foreach (var card in to_remove)
|
||||||
|
target.remove_card(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool update_card(ActivityCard card,
|
||||||
|
Array<Activity> 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 static uint? find_activity(ActivityCard card,
|
||||||
|
Array<Activity> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
namespace StudySystemClient {
|
namespace StudySystemClient {
|
||||||
public class ActivityCard : Card {
|
public class ActivityCard : Gtk.Frame {
|
||||||
public signal void session_logged(string subject, ActivityType type,
|
public signal void session_logged(string subject, ActivityType type,
|
||||||
int minutes);
|
int minutes);
|
||||||
public signal void log_closed();
|
public signal void log_closed();
|
||||||
@ -10,7 +10,8 @@ namespace StudySystemClient {
|
|||||||
private Gtk.Label priority_label;
|
private Gtk.Label priority_label;
|
||||||
|
|
||||||
public ActivityCard(Activity activity) {
|
public ActivityCard(Activity activity) {
|
||||||
base();
|
hexpand = true;
|
||||||
|
add_css_class("card");
|
||||||
|
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
logging = false;
|
logging = false;
|
||||||
|
@ -1,15 +1,8 @@
|
|||||||
namespace StudySystemClient {
|
namespace StudySystemClient {
|
||||||
public class Card : Gtk.Frame {
|
public class ListView<T> : Gtk.Box {
|
||||||
public Card() {
|
|
||||||
hexpand = true;
|
|
||||||
add_css_class("card");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CardArea<T> : Gtk.Box {
|
|
||||||
protected IterableBox<T> container;
|
protected IterableBox<T> container;
|
||||||
|
|
||||||
public CardArea() {
|
public ListView() {
|
||||||
hexpand = vexpand = true;
|
hexpand = vexpand = true;
|
||||||
margin_top = margin_bottom = margin_start = margin_end = 0;
|
margin_top = margin_bottom = margin_start = margin_end = 0;
|
||||||
|
|
||||||
@ -19,7 +12,6 @@ namespace StudySystemClient {
|
|||||||
var scrolled_window = new Gtk.ScrolledWindow();
|
var scrolled_window = new Gtk.ScrolledWindow();
|
||||||
scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER;
|
scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER;
|
||||||
scrolled_window.hexpand = scrolled_window.vexpand = true;
|
scrolled_window.hexpand = scrolled_window.vexpand = true;
|
||||||
scrolled_window.add_css_class("card-container");
|
|
||||||
scrolled_window.set_child(container);
|
scrolled_window.set_child(container);
|
||||||
|
|
||||||
append(scrolled_window);
|
append(scrolled_window);
|
@ -13,11 +13,11 @@ lib = library(
|
|||||||
'activities_view.vala',
|
'activities_view.vala',
|
||||||
'activity.vala',
|
'activity.vala',
|
||||||
'activity_card.vala',
|
'activity_card.vala',
|
||||||
'card.vala',
|
|
||||||
'client.vala',
|
'client.vala',
|
||||||
'connection.vala',
|
'connection.vala',
|
||||||
'der.vala',
|
'der.vala',
|
||||||
'iterable_box.vala',
|
'iterable_box.vala',
|
||||||
|
'list_view.vala',
|
||||||
'main_window.vala',
|
'main_window.vala',
|
||||||
'periodic.vala',
|
'periodic.vala',
|
||||||
'refresher.vala',
|
'refresher.vala',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user