feat: implement cross-platform features and UI integration
- 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>
This commit is contained in:
127
linux/src/view/feed-detail.vala
Normal file
127
linux/src/view/feed-detail.vala
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* FeedDetail.vala
|
||||
*
|
||||
* Widget for displaying feed details
|
||||
*/
|
||||
|
||||
namespace RSSuper {
|
||||
|
||||
using Gtk;
|
||||
|
||||
/**
|
||||
* FeedDetail - Displays details of a selected feed
|
||||
*/
|
||||
public class FeedDetail : WidgetBase {
|
||||
private FeedViewModel view_model;
|
||||
private Label title_label;
|
||||
private Label author_label;
|
||||
private Label published_label;
|
||||
private Label content_label;
|
||||
private ScrolledWindow scrolled_window;
|
||||
private Box content_box;
|
||||
private Button mark_read_button;
|
||||
private Button star_button;
|
||||
|
||||
public FeedDetail(FeedViewModel view_model) {
|
||||
this.view_model = view_model;
|
||||
|
||||
scrolled_window = new ScrolledWindow();
|
||||
scrolled_window.set_hexpand(true);
|
||||
scrolled_window.set_vexpand(true);
|
||||
|
||||
content_box = new Box(Orientation.VERTICAL, 12);
|
||||
content_box.set_margin(20);
|
||||
|
||||
title_label = new Label(null);
|
||||
title_label.set_wrap(true);
|
||||
title_label.set_xalign(0);
|
||||
title_label.add_css_class("title");
|
||||
content_box.append(title_label);
|
||||
|
||||
var metadata_box = new Box(Orientation.HORIZONTAL, 12);
|
||||
author_label = new Label(null);
|
||||
author_label.add_css_class("dim-label");
|
||||
metadata_box.append(author_label);
|
||||
|
||||
published_label = new Label(null);
|
||||
published_label.add_css_class("dim-label");
|
||||
metadata_box.append(published_label);
|
||||
|
||||
content_box.append(metadata_box);
|
||||
|
||||
content_label = new Label(null);
|
||||
content_label.set_wrap(true);
|
||||
content_label.set_xalign(0);
|
||||
content_label.set_max_width_chars(80);
|
||||
content_box.append(content_label);
|
||||
|
||||
mark_read_button = new Button.with_label("Mark as Read");
|
||||
mark_read_button.clicked += on_mark_read;
|
||||
content_box.append(mark_read_button);
|
||||
|
||||
star_button = new Button.with_label("Star");
|
||||
star_button.clicked += on_star;
|
||||
content_box.append(star_button);
|
||||
|
||||
scrolled_window.set_child(content_box);
|
||||
append(scrolled_window);
|
||||
|
||||
view_model.feed_state.state_changed += on_state_changed;
|
||||
}
|
||||
|
||||
public override void initialize() {
|
||||
// Initialize with default state
|
||||
update_from_state();
|
||||
}
|
||||
|
||||
public void set_feed_item(FeedItem item) {
|
||||
title_label.set_text(item.title);
|
||||
author_label.set_text(item.author ?? "Unknown");
|
||||
published_label.set_text(item.published.to_string());
|
||||
content_label.set_text(item.content);
|
||||
|
||||
mark_read_button.set_visible(!item.read);
|
||||
mark_read_button.set_label(item.read ? "Mark as Unread" : "Mark as Read");
|
||||
|
||||
star_button.set_label(item.starred ? "Unstar" : "Star");
|
||||
}
|
||||
|
||||
private void on_state_changed() {
|
||||
update_from_state();
|
||||
}
|
||||
|
||||
protected override void update_from_state() {
|
||||
var state = view_model.get_feed_state();
|
||||
|
||||
if (state.is_error()) {
|
||||
content_box.set_sensitive(false);
|
||||
content_label.set_text($"Error: {state.get_message()}");
|
||||
} else {
|
||||
content_box.set_sensitive(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_mark_read() {
|
||||
// Get selected item from FeedList and mark as read
|
||||
// This requires integrating with FeedList selection
|
||||
// For now, mark current item as read
|
||||
var state = view_model.get_feed_state();
|
||||
if (state.is_success()) {
|
||||
var items = state.get_data() as FeedItem[];
|
||||
foreach (var item in items) {
|
||||
view_model.mark_as_read(item.id, !item.read);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void on_star() {
|
||||
var state = view_model.get_feed_state();
|
||||
if (state.is_success()) {
|
||||
var items = state.get_data() as FeedItem[];
|
||||
foreach (var item in items) {
|
||||
view_model.mark_as_starred(item.id, !item.starred);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user