- iOS: Add BackgroundSyncService, SyncScheduler, SyncWorker, BookmarkViewModel, FeedViewModel - iOS: Add BackgroundSyncService, SyncScheduler, SyncWorker services - Linux: Add settings-store.vala, State.vala signals, view widgets (FeedList, FeedDetail, AddFeed, Search, Settings, Bookmark) - Linux: Add bookmark-store.vala, bookmark vala model, search-service.vala - Android: Add NotificationService, NotificationManager, NotificationPreferencesStore - Android: Add BookmarkDao, BookmarkRepository, SettingsStore - Add unit tests for iOS, Android, Linux - Add integration tests - Add performance benchmarks - Update tasks and documentation Co-Authored-By: Paperclip <noreply@paperclip.ing>
129 lines
4.0 KiB
Vala
129 lines
4.0 KiB
Vala
/*
|
|
* Search.vala
|
|
*
|
|
* Widget for searching feed items
|
|
*/
|
|
|
|
namespace RSSuper {
|
|
|
|
using Gtk;
|
|
|
|
/**
|
|
* Search - Widget for searching feed items
|
|
*/
|
|
public class Search : WidgetBase {
|
|
private SearchService search_service;
|
|
private Entry search_entry;
|
|
private Button search_button;
|
|
private Label status_label;
|
|
private ListView results_view;
|
|
private ListStore results_store;
|
|
private ScrolledWindow scrolled_window;
|
|
|
|
public Search(SearchService search_service) {
|
|
this.search_service = search_service;
|
|
|
|
set_orientation(Orientation.VERTICAL);
|
|
set_spacing(12);
|
|
set_margin(20);
|
|
|
|
var title_label = new Label("Search");
|
|
title_label.add_css_class("heading");
|
|
append(title_label);
|
|
|
|
var search_box = new Box(Orientation.HORIZONTAL, 6);
|
|
search_box.set_hexpand(true);
|
|
|
|
search_entry = new Entry();
|
|
search_entry.set_placeholder_text("Search feeds...");
|
|
search_entry.set_hexpand(true);
|
|
search_entry.activate += on_search;
|
|
search_box.append(search_entry);
|
|
|
|
search_button = new Button.with_label("Search");
|
|
search_button.clicked += on_search;
|
|
search_box.append(search_button);
|
|
|
|
append(search_box);
|
|
|
|
status_label = new Label(null);
|
|
status_label.set_xalign(0);
|
|
status_label.set_wrap(true);
|
|
append(status_label);
|
|
|
|
scrolled_window = new ScrolledWindow();
|
|
scrolled_window.set_hexpand(true);
|
|
scrolled_window.set_vexpand(true);
|
|
|
|
results_store = new ListStore(1, typeof(string));
|
|
results_view = new ListView(results_store);
|
|
|
|
var factory = SignalListItemFactory.new();
|
|
factory.setup += on_setup;
|
|
factory.bind += on_bind;
|
|
factory.unset += on_unset;
|
|
results_view.set_factory(factory);
|
|
|
|
scrolled_window.set_child(results_view);
|
|
append(scrolled_window);
|
|
}
|
|
|
|
public override void initialize() {
|
|
// Initialize with default state
|
|
}
|
|
|
|
protected override void update_from_state() {
|
|
// Update from state if needed
|
|
}
|
|
|
|
private void on_search() {
|
|
var query = search_entry.get_text();
|
|
|
|
if (query.is_empty()) {
|
|
status_label.set_text("Please enter a search query");
|
|
return;
|
|
}
|
|
|
|
search_button.set_sensitive(false);
|
|
status_label.set_text("Searching...");
|
|
|
|
search_service.search(query, (state) => {
|
|
if (state.is_success()) {
|
|
var results = state.get_data() as SearchResult[];
|
|
update_results(results);
|
|
status_label.set_text($"Found {results.length} results");
|
|
} else if (state.is_error()) {
|
|
status_label.set_text($"Error: {state.get_message()}");
|
|
}
|
|
|
|
search_button.set_sensitive(true);
|
|
});
|
|
}
|
|
|
|
private void on_setup(ListItem item) {
|
|
var label = new Label(null);
|
|
label.set_xalign(0);
|
|
label.set_wrap(true);
|
|
label.set_max_width_chars(80);
|
|
item.set_child(label);
|
|
}
|
|
|
|
private void on_bind(ListItem item) {
|
|
var label = item.get_child() as Label;
|
|
var result = item.get_item() as SearchResult;
|
|
|
|
if (result != null) {
|
|
label.set_text(result.title);
|
|
}
|
|
}
|
|
|
|
private void on_unset(ListItem item) {
|
|
item.set_child(null);
|
|
}
|
|
|
|
private void update_results(SearchResult[] results) {
|
|
results_store.splice(0, results_store.get_n_items(), results);
|
|
}
|
|
}
|
|
}
|