2025-07-22 17:32:48 -04:00
|
|
|
use crate::db::FeedItem;
|
2025-07-19 20:42:07 -04:00
|
|
|
use crate::widgets::content_view;
|
2025-07-23 12:38:05 -04:00
|
|
|
use crate::widgets::media_view;
|
2025-12-04 15:20:12 -05:00
|
|
|
use crate::widgets::navbar;
|
2025-07-19 20:42:07 -04:00
|
|
|
|
2025-07-03 11:25:23 -04:00
|
|
|
use super::db;
|
2025-07-03 20:57:37 -04:00
|
|
|
use super::widgets;
|
2025-07-04 11:38:49 -04:00
|
|
|
use iced::widget::row;
|
2025-07-03 20:57:37 -04:00
|
|
|
use iced::widget::scrollable;
|
2025-07-04 11:38:49 -04:00
|
|
|
use iced::widget::text_input;
|
2025-07-04 22:14:24 -04:00
|
|
|
use iced::Task;
|
2025-07-03 11:25:23 -04:00
|
|
|
use iced::{
|
|
|
|
|
widget::{button, column, container, text},
|
|
|
|
|
Element,
|
|
|
|
|
Length::Fill,
|
|
|
|
|
};
|
2025-07-22 17:32:48 -04:00
|
|
|
use rss_content::parse_content;
|
|
|
|
|
use rss_content::Content;
|
2025-12-04 15:20:12 -05:00
|
|
|
const ICON: &[u8] = include_bytes!("../assets/icon_placeholder.png");
|
2025-07-19 20:42:07 -04:00
|
|
|
|
2025-07-02 20:11:43 -04:00
|
|
|
pub fn user_interface() -> iced::Result {
|
2025-12-04 15:20:12 -05:00
|
|
|
//iced::run(update, view)
|
|
|
|
|
let icon = iced::window::icon::from_file_data(ICON, None).ok();
|
|
|
|
|
let app = iced::application(State::default,update,view)
|
|
|
|
|
.title("RSSCar")
|
|
|
|
|
.theme(iced::Theme::Dark)
|
|
|
|
|
.window(iced::window::Settings{
|
|
|
|
|
icon, ..Default::default()
|
|
|
|
|
});
|
|
|
|
|
app.run()
|
2025-07-02 20:11:43 -04:00
|
|
|
}
|
|
|
|
|
|
2025-12-04 22:36:36 -05:00
|
|
|
#[derive(Clone, Debug,PartialEq)]
|
2025-07-04 22:14:24 -04:00
|
|
|
pub enum Page {
|
|
|
|
|
Home,
|
|
|
|
|
FeedView,
|
|
|
|
|
AllItems,
|
|
|
|
|
ItemView,
|
2025-12-04 15:20:12 -05:00
|
|
|
CategoryView,
|
2025-07-04 22:14:24 -04:00
|
|
|
Testing,
|
2025-07-02 20:11:43 -04:00
|
|
|
}
|
|
|
|
|
|
2025-07-22 17:32:48 -04:00
|
|
|
pub struct State {
|
2025-12-04 22:36:36 -05:00
|
|
|
pub page: Page,
|
|
|
|
|
pub current_feed: usize,
|
2025-07-22 17:32:48 -04:00
|
|
|
pub current_item: Option<FeedItem>,
|
|
|
|
|
pub item_description: Vec<Content>,
|
|
|
|
|
pub item_content: Vec<Content>,
|
2025-12-04 22:36:36 -05:00
|
|
|
pub feed_input: String,
|
2025-07-03 11:25:23 -04:00
|
|
|
}
|
|
|
|
|
impl Default for State {
|
|
|
|
|
fn default() -> Self {
|
2025-07-22 17:32:48 -04:00
|
|
|
State {
|
2025-07-04 22:14:24 -04:00
|
|
|
page: Page::Home,
|
2025-07-04 11:38:49 -04:00
|
|
|
current_feed: 0,
|
2025-07-22 17:32:48 -04:00
|
|
|
current_item: None,
|
|
|
|
|
item_description: Vec::new(),
|
|
|
|
|
item_content: Vec::new(),
|
|
|
|
|
feed_input: String::from(""),
|
|
|
|
|
}
|
2025-07-03 11:25:23 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
2025-07-03 20:57:37 -04:00
|
|
|
pub enum Message {
|
|
|
|
|
ChangePage(Page),
|
|
|
|
|
LoadFeed(usize),
|
|
|
|
|
AddFeed(String),
|
2025-07-25 19:03:50 -04:00
|
|
|
RemoveFeed(usize),
|
2025-07-19 20:42:07 -04:00
|
|
|
LoadItem(usize),
|
2025-07-22 17:32:48 -04:00
|
|
|
FieldUpdated(AppField, String),
|
2025-12-04 15:20:12 -05:00
|
|
|
LinkClicked(String),
|
2025-07-04 22:14:24 -04:00
|
|
|
Done(String),
|
2025-07-22 17:32:48 -04:00
|
|
|
ResetDB,
|
2025-07-03 11:25:23 -04:00
|
|
|
}
|
|
|
|
|
|
2025-07-22 17:32:48 -04:00
|
|
|
#[derive(Debug, Clone)]
|
2025-07-04 22:14:24 -04:00
|
|
|
pub enum AppField {
|
2025-07-22 17:32:48 -04:00
|
|
|
FeedInput,
|
2025-07-04 11:38:49 -04:00
|
|
|
}
|
|
|
|
|
|
2025-07-04 22:14:24 -04:00
|
|
|
async fn add_feed_background(url: String) -> String {
|
|
|
|
|
println!("Adding feed!");
|
|
|
|
|
db::add_feed(&url);
|
|
|
|
|
"Done adding feed".to_string()
|
|
|
|
|
}
|
2025-07-25 19:03:50 -04:00
|
|
|
async fn remove_feed_background(id:usize) -> String {
|
|
|
|
|
println!("Removing feed");
|
|
|
|
|
db::remove_feed(id);
|
|
|
|
|
"Done removing feed".to_owned()
|
|
|
|
|
}
|
2025-07-04 22:14:24 -04:00
|
|
|
|
2025-07-22 17:32:48 -04:00
|
|
|
fn update(state: &mut State, mes: Message) -> Task<Message> {
|
2025-07-03 11:25:23 -04:00
|
|
|
match mes {
|
2025-07-04 22:14:24 -04:00
|
|
|
Message::ChangePage(p) => {
|
2025-07-22 17:32:48 -04:00
|
|
|
state.page = p;
|
2025-07-04 22:14:24 -04:00
|
|
|
Task::none()
|
2025-07-22 17:32:48 -04:00
|
|
|
}
|
2025-07-03 20:57:37 -04:00
|
|
|
Message::LoadFeed(feed_id) => {
|
|
|
|
|
state.current_feed = feed_id;
|
2025-07-22 17:32:48 -04:00
|
|
|
state.page = Page::FeedView;
|
2025-07-04 22:14:24 -04:00
|
|
|
Task::none()
|
2025-07-22 17:32:48 -04:00
|
|
|
}
|
2025-07-25 19:03:50 -04:00
|
|
|
|
2025-07-03 20:57:37 -04:00
|
|
|
Message::AddFeed(f) => {
|
2025-07-04 22:14:24 -04:00
|
|
|
state.feed_input = "".to_string();
|
2025-07-22 17:32:48 -04:00
|
|
|
Task::perform(add_feed_background(f.to_string()), Message::Done)
|
|
|
|
|
}
|
2025-07-25 19:03:50 -04:00
|
|
|
Message::RemoveFeed(id) => {
|
|
|
|
|
Task::perform(remove_feed_background(id), Message::Done)
|
|
|
|
|
}
|
2025-07-19 20:42:07 -04:00
|
|
|
Message::LinkClicked(l) => {
|
2025-07-22 17:32:48 -04:00
|
|
|
println!("Link clicked: {}", l);
|
|
|
|
|
|
2025-07-19 20:42:07 -04:00
|
|
|
Task::none()
|
|
|
|
|
}
|
|
|
|
|
Message::LoadItem(id) => {
|
2025-07-22 17:32:48 -04:00
|
|
|
let item = db::get_item(id);
|
|
|
|
|
state.item_description = match &item.description {
|
|
|
|
|
Some(d) => {
|
|
|
|
|
parse_content(&d)
|
|
|
|
|
}
|
|
|
|
|
None => Vec::new()
|
|
|
|
|
};
|
|
|
|
|
state.item_content = match &item.content{
|
|
|
|
|
Some(c) => {
|
|
|
|
|
parse_content(&c)
|
|
|
|
|
}
|
|
|
|
|
None => Vec::new()
|
|
|
|
|
};
|
|
|
|
|
state.current_item = Some(item);
|
2025-07-19 20:42:07 -04:00
|
|
|
state.page = Page::ItemView;
|
|
|
|
|
Task::none()
|
|
|
|
|
}
|
2025-07-22 17:32:48 -04:00
|
|
|
Message::Done(_) => Task::none(),
|
2025-07-04 11:38:49 -04:00
|
|
|
Message::FieldUpdated(field, value) => {
|
|
|
|
|
match field {
|
|
|
|
|
AppField::FeedInput => {
|
2025-07-22 17:32:48 -04:00
|
|
|
state.feed_input = value;
|
2025-07-04 11:38:49 -04:00
|
|
|
}
|
|
|
|
|
}
|
2025-07-04 22:14:24 -04:00
|
|
|
Task::none()
|
2025-07-22 17:32:48 -04:00
|
|
|
}
|
2025-07-03 20:57:37 -04:00
|
|
|
Message::ResetDB => {
|
|
|
|
|
db::reset();
|
2025-07-04 22:14:24 -04:00
|
|
|
Task::none()
|
2025-07-03 20:57:37 -04:00
|
|
|
}
|
2025-07-03 11:25:23 -04:00
|
|
|
}
|
2025-07-02 20:11:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn view(state: &State) -> Element<'_, Message> {
|
2025-07-03 11:25:23 -04:00
|
|
|
match state.page {
|
2025-07-04 22:14:24 -04:00
|
|
|
Page::Home => home(&state),
|
|
|
|
|
Page::FeedView => feed_layout(&state),
|
|
|
|
|
Page::AllItems => item_list(&state),
|
|
|
|
|
Page::ItemView => item_view(&state),
|
2025-12-04 15:20:12 -05:00
|
|
|
Page::CategoryView => category_view(&state),
|
2025-07-04 22:14:24 -04:00
|
|
|
Page::Testing => testing(&state),
|
2025-07-03 11:25:23 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-04 15:20:12 -05:00
|
|
|
fn home(state: &State) -> Element<'_, Message> {
|
2025-07-03 11:25:23 -04:00
|
|
|
container(column!(
|
2025-12-04 15:20:12 -05:00
|
|
|
widgets::navbar(state),
|
2025-07-22 17:32:48 -04:00
|
|
|
scrollable(widgets::list_feeds())
|
|
|
|
|
.width(iced::Fill)
|
|
|
|
|
.height(iced::Fill),
|
2025-07-04 22:14:24 -04:00
|
|
|
button("Go to test!").on_press(Message::ChangePage(Page::Testing))
|
2025-07-03 11:25:23 -04:00
|
|
|
))
|
2025-12-04 22:56:33 -05:00
|
|
|
.padding(0)
|
2025-07-03 11:25:23 -04:00
|
|
|
.height(Fill)
|
|
|
|
|
.width(Fill)
|
|
|
|
|
.into()
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-03 20:57:37 -04:00
|
|
|
fn feed_layout(state: &State) -> Element<'_, Message> {
|
2025-07-22 17:32:48 -04:00
|
|
|
container(column!(
|
2025-12-04 22:56:33 -05:00
|
|
|
widgets::navbar(state),
|
2025-07-22 17:32:48 -04:00
|
|
|
scrollable(widgets::list_items(state.current_feed))
|
|
|
|
|
.width(iced::Fill)
|
|
|
|
|
.height(iced::Fill),
|
|
|
|
|
))
|
|
|
|
|
.height(Fill)
|
|
|
|
|
.width(Fill)
|
|
|
|
|
.into()
|
2025-07-03 11:25:23 -04:00
|
|
|
}
|
|
|
|
|
|
2025-07-03 20:57:37 -04:00
|
|
|
fn item_view(state: &State) -> Element<'_, Message> {
|
2025-07-23 12:38:05 -04:00
|
|
|
let title = match state.current_item.clone() {
|
|
|
|
|
Some(i) => {i.title}
|
|
|
|
|
None => {"".to_owned()}
|
|
|
|
|
};
|
2025-07-22 17:32:48 -04:00
|
|
|
container(column!(
|
2025-12-04 22:56:33 -05:00
|
|
|
widgets::navbar(state),
|
2025-07-23 12:38:05 -04:00
|
|
|
media_view(state),
|
2025-07-22 17:32:48 -04:00
|
|
|
content_view(state),
|
|
|
|
|
))
|
|
|
|
|
.height(Fill)
|
|
|
|
|
.width(Fill)
|
|
|
|
|
.into()
|
2025-07-03 11:25:23 -04:00
|
|
|
}
|
|
|
|
|
|
2025-12-04 15:20:12 -05:00
|
|
|
fn item_list(state: &State) -> Element<'_, Message> {
|
|
|
|
|
container(
|
|
|
|
|
column!(
|
|
|
|
|
navbar(state),
|
|
|
|
|
scrollable(
|
|
|
|
|
column(
|
|
|
|
|
db::get_all_items().iter().map(|i|{
|
|
|
|
|
widgets::list_item(i.item_id, i.title.clone(), i.description.clone().unwrap_or("".to_owned()))
|
|
|
|
|
}).map(iced::Element::from)
|
|
|
|
|
).align_x(iced::Alignment::Center)).width(Fill).spacing(5)
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
).width(Fill).height(Fill).into()
|
2025-07-03 20:57:37 -04:00
|
|
|
}
|
2025-12-04 15:20:12 -05:00
|
|
|
|
|
|
|
|
fn category_view(state: &State) -> Element<'_,Message> {
|
|
|
|
|
column!(
|
|
|
|
|
navbar(state)
|
|
|
|
|
|
|
|
|
|
).spacing(5).into()
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-03 11:25:23 -04:00
|
|
|
fn testing(state: &State) -> Element<'_, Message> {
|
|
|
|
|
column!(
|
2025-12-04 22:56:33 -05:00
|
|
|
widgets::navbar(state),
|
2025-07-03 20:57:37 -04:00
|
|
|
text("Dev Panel"),
|
|
|
|
|
button("Add gabe.rocks").on_press(Message::AddFeed(String::from("https://gabe.rocks/rss"))),
|
2025-07-22 17:32:48 -04:00
|
|
|
button("Add LSN").on_press(Message::AddFeed(String::from(
|
2025-12-04 15:20:12 -05:00
|
|
|
"https://libresolutions.network/archive/index.xml"
|
2025-07-22 17:32:48 -04:00
|
|
|
))),
|
2025-07-04 11:38:49 -04:00
|
|
|
row!(
|
2025-07-22 17:32:48 -04:00
|
|
|
text_input("Add a feed", &state.feed_input)
|
|
|
|
|
.on_input(|val| Message::FieldUpdated(AppField::FeedInput, val))
|
|
|
|
|
.width(300),
|
2025-07-04 11:38:49 -04:00
|
|
|
button("Add feed!").on_press(Message::AddFeed(state.feed_input.clone()))
|
2025-07-22 17:32:48 -04:00
|
|
|
)
|
|
|
|
|
.spacing(5)
|
|
|
|
|
.padding(10),
|
2025-07-03 20:57:37 -04:00
|
|
|
button("Wipe DB").on_press(Message::ResetDB),
|
2025-07-04 22:14:24 -04:00
|
|
|
button("go back!").on_press(Message::ChangePage(Page::Home))
|
2025-07-03 11:25:23 -04:00
|
|
|
)
|
|
|
|
|
.spacing(5)
|
|
|
|
|
.into()
|
|
|
|
|
}
|