Starting to support fancier elements...

This commit is contained in:
Gabriel 2025-07-22 17:32:48 -04:00
parent 56a62e96fd
commit a4756b8ec4
2 changed files with 109 additions and 81 deletions

135
src/ui.rs
View file

@ -1,17 +1,20 @@
use crate::db::FeedItem;
use crate::widgets::content_view;
use super::db;
use super::widgets;
use iced::widget::markdown::Url;
use iced::widget::row;
use iced::widget::scrollable;
use iced::widget::text_input;
use iced::widget::markdown::Url;
use iced::Task;
use iced::{
widget::{button, column, container, text},
Element,
Length::Fill,
};
use rss_content::parse_content;
use rss_content::Content;
pub fn user_interface() -> iced::Result {
iced::run(update, view)
@ -26,20 +29,24 @@ pub enum Page {
Testing,
}
struct State {
pub struct State {
page: Page,
current_feed: usize,
current_item: usize,
feed_input: String
pub current_item: Option<FeedItem>,
pub item_description: Vec<Content>,
pub item_content: Vec<Content>,
feed_input: String,
}
impl Default for State {
fn default() -> Self {
State {
State {
page: Page::Home,
current_feed: 0,
current_item: 0,
feed_input: String::from("")
}
current_item: None,
item_description: Vec::new(),
item_content: Vec::new(),
feed_input: String::from(""),
}
}
}
@ -49,15 +56,15 @@ pub enum Message {
LoadFeed(usize),
AddFeed(String),
LoadItem(usize),
FieldUpdated(AppField,String),
FieldUpdated(AppField, String),
LinkClicked(Url),
Done(String),
ResetDB
ResetDB,
}
#[derive(Debug,Clone)]
#[derive(Debug, Clone)]
pub enum AppField {
FeedInput
FeedInput,
}
async fn add_feed_background(url: String) -> String {
@ -66,51 +73,58 @@ async fn add_feed_background(url: String) -> String {
"Done adding feed".to_string()
}
fn update(state: &mut State, mes: Message) -> Task<Message>{
fn update(state: &mut State, mes: Message) -> Task<Message> {
match mes {
Message::ChangePage(p) => {
state.page=p;
state.page = p;
Task::none()
},
}
Message::LoadFeed(feed_id) => {
state.current_feed = feed_id;
state.page=Page::FeedView;
state.page = Page::FeedView;
Task::none()
},
}
Message::AddFeed(f) => {
state.feed_input = "".to_string();
Task::perform(
add_feed_background(f.to_string()),
Message::Done
)
},
Task::perform(add_feed_background(f.to_string()), Message::Done)
}
Message::LinkClicked(l) => {
println!("Link clicked: {}",l);
println!("Link clicked: {}", l);
Task::none()
}
Message::LoadItem(id) => {
state.current_item = id;
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);
state.page = Page::ItemView;
Task::none()
}
Message::Done(_) => {Task::none()},
Message::Done(_) => Task::none(),
Message::FieldUpdated(field, value) => {
match field {
AppField::FeedInput => {
state.feed_input=value;
state.feed_input = value;
}
}
Task::none()
},
}
Message::ResetDB => {
db::reset();
Task::none()
}
}
}
fn view(state: &State) -> Element<'_, Message> {
@ -125,7 +139,9 @@ fn view(state: &State) -> Element<'_, Message> {
fn home(_state: &State) -> Element<'_, Message> {
container(column!(
scrollable(widgets::list_feeds()).width(iced::Fill).height(iced::Fill),
scrollable(widgets::list_feeds())
.width(iced::Fill)
.height(iced::Fill),
button("Go to test!").on_press(Message::ChangePage(Page::Testing))
))
.padding(15)
@ -134,47 +150,50 @@ fn home(_state: &State) -> Element<'_, Message> {
.into()
}
fn feed_layout(state: &State) -> Element<'_, Message> {
container(
column!(
button(text("Home")).on_press(Message::ChangePage(Page::Home)),
scrollable(widgets::list_items(state.current_feed)).width(iced::Fill).height(iced::Fill),
)
)
.height(Fill)
.width(Fill)
.into()
container(column!(
button(text("Home")).on_press(Message::ChangePage(Page::Home)),
scrollable(widgets::list_items(state.current_feed))
.width(iced::Fill)
.height(iced::Fill),
))
.height(Fill)
.width(Fill)
.into()
}
fn item_view(state: &State) -> Element<'_, Message> {
let item = db::get_item(state.current_item);
container(
column!(
row!(
button(text("Home")).on_press(Message::ChangePage(Page::Home)),
button(text("Feed")).on_press(Message::ChangePage(Page::FeedView))
).spacing(10),
content_view(item),
container(column!(
row!(
button(text("Home")).on_press(Message::ChangePage(Page::Home)),
button(text("Feed")).on_press(Message::ChangePage(Page::FeedView))
)
)
.height(Fill)
.width(Fill)
.into()
.spacing(10),
content_view(state),
))
.height(Fill)
.width(Fill)
.into()
}
fn item_list(_: &State) -> Element<'_,Message>{
fn item_list(_: &State) -> Element<'_, Message> {
todo!()
}
fn testing(state: &State) -> Element<'_, Message> {
column!(
text("Dev Panel"),
button("Add gabe.rocks").on_press(Message::AddFeed(String::from("https://gabe.rocks/rss"))),
button("Add LSN").on_press(Message::AddFeed(String::from("https://libresolutions.network/rss"))),
button("Add LSN").on_press(Message::AddFeed(String::from(
"https://libresolutions.network/rss"
))),
row!(
text_input("Add a feed",&state.feed_input).on_input(|val| Message::FieldUpdated(AppField::FeedInput,val)).width(300),
text_input("Add a feed", &state.feed_input)
.on_input(|val| Message::FieldUpdated(AppField::FeedInput, val))
.width(300),
button("Add feed!").on_press(Message::AddFeed(state.feed_input.clone()))
).spacing(5).padding(10),
)
.spacing(5)
.padding(10),
button("Wipe DB").on_press(Message::ResetDB),
button("go back!").on_press(Message::ChangePage(Page::Home))
)

View file

@ -1,8 +1,9 @@
use crate::db::FeedItem;
use super::db;
use super::ui;
use iced::widget::markdown;
use iced::widget::scrollable;
use iced::widget::Column;
use iced::Theme;
use rss_content::Content;
use ui::Message;
use rss_content;
@ -40,44 +41,52 @@ pub fn list_items(feed_id: usize) -> iced::widget::Column<'static,Message> {
.padding(15)
}
pub fn content_area(cnt: String) -> iced::widget::Container<'static,Message>{
let content = rss_content::parse_content(&cnt);
container(
column(
content.into_iter().map(|c: Content|{
match c {
Content::Markdown(md) => {
text(md)
},
Content::Image(_) => {text("Image goes here")},
Content::Audio(_) => {text("Audio widget here")},
Content::Video(_) => {text("video player here")},
_ => {text("")}
pub fn content_area(content: &Vec<Content>) -> iced::widget::Container<Message> {
let mut children: Vec<Element<Message>> = Vec::new();
for c in content {
match c {
Content::MarkdownParsed(p) => {
children.push(
markdown(p, Theme::Dark).map(Message::LinkClicked)
);
}
Content::Image(_) => {children.push(text("<Image goes here>")
.size(32)
.into());},
Content::Audio(_) => {children.push(text("<Audio widget here>")
.size(32)
.into());},
Content::Video(_) => {children.push(text("<Video goes here>")
.size(32)
.into());},
_ => {}
}
}).map(Element::from)
)
}
container(
Column::with_children(children)
)
}
pub fn content_view(item: FeedItem) -> iced::widget::Scrollable<'static, Message> {
pub fn content_view(state: &super::ui::State) -> iced::widget::Scrollable<Message> {
let item = state.current_item.clone().unwrap();
scrollable(
column!(
text(item.title).size(34),
match item.description {
Some(d) => {
content_area(d)
Some(_d) => {
content_area(&state.item_description)
},
None => {container(text("No description found"))}
},
match item.content {
Some(c) => {
content_area(c)
Some(_c) => {
content_area(&state.item_content)
}
None => {container(text("No content found"))}
}
)
)
).width(iced::Fill)
}