summary refs log tree commit diff
path: root/contexts.c
diff options
context:
space:
mode:
Diffstat (limited to 'contexts.c')
-rw-r--r--contexts.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/contexts.c b/contexts.c
index d432cb1..bf5811f 100644
--- a/contexts.c
+++ b/contexts.c
@@ -22,10 +22,27 @@
 #include "server.h"
 
 const char *ContextsQuery = SQL(
-	SELECT name
-	FROM contexts
-	WHERE network = :network AND coalesce(query = :query, true)
-	ORDER BY query, name;
+	WITH recentEvents AS (
+		SELECT time, context
+		FROM events
+		ORDER BY event DESC
+		LIMIT 500 // TODO: Configurable.
+	), activeContexts AS (
+		SELECT name, query
+		FROM contexts
+		JOIN recentEvents USING (context)
+		WHERE network = :network AND coalesce(query = :query, true)
+		GROUP BY context
+		ORDER BY max(time) DESC
+	), allContexts AS (
+		SELECT name, query
+		FROM contexts
+		WHERE network = :network AND coalesce(query = :query, true)
+		ORDER BY query, name
+	)
+	SELECT name, query, 1 FROM activeContexts
+	UNION ALL
+	SELECT name, query, 0 FROM allContexts;
 );
 
 enum kcgi_err pageContexts(struct kreq *req) {
@@ -41,16 +58,38 @@ enum kcgi_err pageContexts(struct kreq *req) {
 		|| khtml_open(&html, req, KHTML_PRETTY)
 		|| htmlHead(&html, network)
 		|| htmlNav(&html, network, NULL)
-		|| htmlSearch(&html, network, NULL)
-		|| khtml_elem(&html, KELEM_UL);
+		|| htmlSearch(&html, network, NULL);
 	if (error) return error;
 
 	dbBindText(stmt.contexts, ":network", network);
 	if (pagePublic) dbBindInt(stmt.contexts, ":query", false);
 
+	enum State {
+		None,
+		Active,
+		Channels,
+		Queries,
+	} state = None;
+	const char *Headings[] = { NULL, "Active", "Channels", "Queries" };
+
 	int result;
 	while (SQLITE_ROW == (result = sqlite3_step(stmt.contexts))) {
 		const char *context = (const char *)sqlite3_column_text(stmt.contexts, 0);
+		bool query = sqlite3_column_int(stmt.contexts, 1);
+		bool active = sqlite3_column_int(stmt.contexts, 2);
+
+		enum State prev = state;
+		state = (active ? Active : (query ? Queries : Channels));
+		if (state != prev) {
+			error = 0
+				|| khtml_closeelem(&html, 1)
+				|| khtml_elem(&html, KELEM_H2)
+				|| khtml_puts(&html, Headings[state])
+				|| khtml_closeelem(&html, 1)
+				|| khtml_elem(&html, KELEM_UL);
+			if (error) return error;
+		}
+
 		char *href = khttp_urlpart(
 			NULL, NULL, Pages[Events],
 			Keys[Network].name, network,
@@ -58,7 +97,6 @@ enum kcgi_err pageContexts(struct kreq *req) {
 			NULL
 		);
 		if (!href) err(EX_OSERR, "khttp_urlpart");
-
 		error = 0
 			|| khtml_elem(&html, KELEM_LI)
 			|| khtml_attr(&html, KELEM_A, KATTR_HREF, href, KATTR__MAX)