Files
RSSuper/native-route/linux/src/models/search-result.vala
Michael Freno f0922e3c03 Implement Linux data models (C/Vala)
- Add FeedItem, Feed, FeedSubscription models
- Add SearchResult, SearchFilters, SearchQuery models
- Add NotificationPreferences, ReadingPreferences models
- Implement JSON serialization/deserialization for all models
- Add equality comparison methods
- Following GNOME HIG naming conventions
- Build system configured with Meson/Ninja
2026-03-29 17:40:59 -04:00

209 lines
5.9 KiB
Vala

/*
* SearchResult.vala
*
* Represents a search result item from the feed database.
* Following GNOME HIG naming conventions and Vala/GObject patterns.
*/
/**
* SearchResultType - Type of search result
*/
public enum RSSuper.SearchResultType {
ARTICLE,
FEED
}
/**
* SearchResult - Represents a single search result
*/
public class RSSuper.SearchResult : Object {
public string id { get; set; }
public SearchResultType result_type { get; set; }
public string title { get; set; }
public string? snippet { get; set; }
public string? link { get; set; }
public string? feed_title { get; set; }
public string? published { get; set; }
public double score { get; set; }
/**
* Default constructor
*/
public SearchResult() {
this.id = "";
this.result_type = SearchResultType.ARTICLE;
this.title = "";
this.score = 0.0;
}
/**
* Constructor with initial values
*/
public SearchResult.with_values(string id, SearchResultType type, string title,
string? snippet = null, string? link = null,
string? feed_title = null, string? published = null,
double score = 0.0) {
this.id = id;
this.result_type = type;
this.title = title;
this.snippet = snippet;
this.link = link;
this.feed_title = feed_title;
this.published = published;
this.score = score;
}
/**
* Get type as string
*/
public string get_type_string() {
switch (this.result_type) {
case SearchResultType.ARTICLE:
return "article";
case SearchResultType.FEED:
return "feed";
default:
return "unknown";
}
}
/**
* Parse type from string
*/
public static SearchResultType type_from_string(string str) {
switch (str) {
case "article":
return SearchResultType.ARTICLE;
case "feed":
return SearchResultType.FEED;
default:
return SearchResultType.ARTICLE;
}
}
/**
* Serialize to JSON string
*/
public string to_json_string() {
var sb = new StringBuilder();
sb.append("{");
sb.append("\"id\":\"");
sb.append(this.id);
sb.append("\",\"type\":\"");
sb.append(this.get_type_string());
sb.append("\",\"title\":\"");
sb.append(this.title);
sb.append("\"");
if (this.snippet != null) {
sb.append(",\"snippet\":\"");
sb.append(this.snippet);
sb.append("\"");
}
if (this.link != null) {
sb.append(",\"link\":\"");
sb.append(this.link);
sb.append("\"");
}
if (this.feed_title != null) {
sb.append(",\"feedTitle\":\"");
sb.append(this.feed_title);
sb.append("\"");
}
if (this.published != null) {
sb.append(",\"published\":\"");
sb.append(this.published);
sb.append("\"");
}
if (this.score != 0.0) {
sb.append(",\"score\":%f".printf(this.score));
}
sb.append("}");
return sb.str;
}
/**
* Deserialize from JSON string
*/
public static SearchResult? from_json_string(string json_string) {
var parser = new Json.Parser();
try {
if (!parser.load_from_data(json_string)) {
return null;
}
} catch (Error e) {
warning("Failed to parse JSON: %s", e.message);
return null;
}
return from_json_node(parser.get_root());
}
/**
* Deserialize from Json.Node
*/
public static SearchResult? from_json_node(Json.Node node) {
if (node.get_node_type() != Json.NodeType.OBJECT) {
return null;
}
var obj = node.get_object();
if (!obj.has_member("id") || !obj.has_member("type") || !obj.has_member("title")) {
return null;
}
var result = new SearchResult();
result.id = obj.get_string_member("id");
result.result_type = SearchResult.type_from_string(obj.get_string_member("type"));
result.title = obj.get_string_member("title");
if (obj.has_member("snippet")) {
result.snippet = obj.get_string_member("snippet");
}
if (obj.has_member("link")) {
result.link = obj.get_string_member("link");
}
if (obj.has_member("feedTitle")) {
result.feed_title = obj.get_string_member("feedTitle");
}
if (obj.has_member("published")) {
result.published = obj.get_string_member("published");
}
if (obj.has_member("score")) {
result.score = obj.get_double_member("score");
}
return result;
}
/**
* Equality comparison
*/
public bool equals(SearchResult? other) {
if (other == null) {
return false;
}
return this.id == other.id &&
this.result_type == other.result_type &&
this.title == other.title &&
this.snippet == other.snippet &&
this.link == other.link &&
this.feed_title == other.feed_title &&
this.published == other.published &&
this.score == other.score;
}
/**
* Get a human-readable summary
*/
public string get_summary() {
if (this.feed_title != null) {
return "[%s] %s - %s".printf(this.get_type_string(), this.feed_title, this.title);
}
return "[%s] %s".printf(this.get_type_string(), this.title);
}
}