init: first commit
This commit is contained in:
commit
1a3f0f4d1b
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
1797
Cargo.lock
generated
Normal file
1797
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
Cargo.toml
Normal file
29
Cargo.toml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
[package]
|
||||||
|
name = "peiji"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["macros", "gnome_42"]
|
||||||
|
libadwaita = ["adw"]
|
||||||
|
libpanel = ["panel"]
|
||||||
|
macros = ["relm4-macros"]
|
||||||
|
gnome_46 = ["gnome_45", "gtk/gnome_45", "adw/v1_5"]
|
||||||
|
gnome_45 = ["gnome_44", "gtk/gnome_45", "adw/v1_4"]
|
||||||
|
gnome_44 = ["gnome_43", "gtk/gnome_44", "adw/v1_3"]
|
||||||
|
gnome_43 = ["gnome_42", "gtk/gnome_43", "adw/v1_2"]
|
||||||
|
gnome_42 = ["gtk/gnome_42"]
|
||||||
|
|
||||||
|
# All features except docs. This is also used in the CI
|
||||||
|
all = ["macros", "libadwaita", "panel", "panel/v1_4"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
adw = { version = "0.6", optional = true, package = "libadwaita" }
|
||||||
|
epub = "2.1.1"
|
||||||
|
gtk = { version = "0.8.1", package = "gtk4" }
|
||||||
|
relm4 = "0.8.1"
|
||||||
|
scraper = "0.19.0"
|
||||||
|
panel = { version = "0.4", optional = true, package = "libpanel" }
|
||||||
|
relm4-macros = { version = "0.8.1", optional = true }
|
158
src/main.rs
Normal file
158
src/main.rs
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
use std::{env, path::Path, process::exit};
|
||||||
|
|
||||||
|
use epub::doc::EpubDoc;
|
||||||
|
use gtk::glib::clone;
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use relm4::prelude::*;
|
||||||
|
use scraper::{Html, Selector};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if args.len() < 2 {
|
||||||
|
println!("Please provide an ePub file to read. Usage: peiji <file.epub>");
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
let app = RelmApp::new("dev.ontake.peiji").with_args(vec![args[1].to_string()]);
|
||||||
|
|
||||||
|
app.run::<App>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct App {
|
||||||
|
page_num: u8,
|
||||||
|
page_string: String,
|
||||||
|
doc: EpubDoc<std::io::BufReader<std::fs::File>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Msg {
|
||||||
|
PageNext,
|
||||||
|
PagePrev,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AppWidgets {
|
||||||
|
// window: gtk::Window,
|
||||||
|
// vbox: gtk::Box,
|
||||||
|
// inc_button: gtk::Button,
|
||||||
|
// dec_button: gtk::Button,
|
||||||
|
page_num_lbl: gtk::Label,
|
||||||
|
text_buffer: gtk::TextBuffer,
|
||||||
|
page_string_textview: gtk::TextView,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimpleComponent for App {
|
||||||
|
type Init = u8;
|
||||||
|
type Input = Msg;
|
||||||
|
type Output = ();
|
||||||
|
type Widgets = AppWidgets;
|
||||||
|
type Root = gtk::Window;
|
||||||
|
|
||||||
|
fn init_root() -> Self::Root {
|
||||||
|
gtk::Window::builder()
|
||||||
|
.title("peiji")
|
||||||
|
.default_width(300)
|
||||||
|
.default_height(100)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the component.
|
||||||
|
fn init(
|
||||||
|
page_num: Self::Init,
|
||||||
|
window: Self::Root,
|
||||||
|
sender: ComponentSender<Self>,
|
||||||
|
) -> ComponentParts<Self> {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
let path = Path::new(&args[1]);
|
||||||
|
println!("{:#?}", path);
|
||||||
|
let doc = EpubDoc::new(path);
|
||||||
|
let doc = doc.unwrap();
|
||||||
|
let page_string = "".into();
|
||||||
|
let model = App {
|
||||||
|
page_num,
|
||||||
|
page_string,
|
||||||
|
doc,
|
||||||
|
};
|
||||||
|
|
||||||
|
let vbox = gtk::Box::builder()
|
||||||
|
.orientation(gtk::Orientation::Vertical)
|
||||||
|
.spacing(5)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let hbox = gtk::Box::builder()
|
||||||
|
.orientation(gtk::Orientation::Horizontal)
|
||||||
|
.spacing(5)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let inc_button = gtk::Button::with_label(">");
|
||||||
|
let dec_button = gtk::Button::with_label("<");
|
||||||
|
|
||||||
|
let page_num_lbl = gtk::Label::new(Some(&format!("Page {}", model.page_num)));
|
||||||
|
page_num_lbl.set_margin_all(5);
|
||||||
|
|
||||||
|
let text_buffer = gtk::TextBuffer::default();
|
||||||
|
text_buffer.set_text(&model.page_string);
|
||||||
|
|
||||||
|
let page_string_textview = gtk::TextView::with_buffer(&text_buffer);
|
||||||
|
page_string_textview.set_margin_all(5);
|
||||||
|
page_string_textview.set_wrap_mode(gtk::WrapMode::Word);
|
||||||
|
|
||||||
|
let scrolled_window = gtk::ScrolledWindow::default();
|
||||||
|
scrolled_window.set_child(Some(&vbox));
|
||||||
|
window.set_child(Some(&scrolled_window));
|
||||||
|
vbox.set_margin_all(5);
|
||||||
|
hbox.append(&dec_button);
|
||||||
|
hbox.append(&inc_button);
|
||||||
|
hbox.append(&page_num_lbl);
|
||||||
|
vbox.append(&hbox);
|
||||||
|
vbox.append(&page_string_textview);
|
||||||
|
|
||||||
|
vbox.set_hexpand(false);
|
||||||
|
vbox.set_vexpand(false);
|
||||||
|
|
||||||
|
inc_button.connect_clicked(clone!(@strong sender => move |_| {
|
||||||
|
sender.input(Msg::PageNext);
|
||||||
|
}));
|
||||||
|
|
||||||
|
dec_button.connect_clicked(clone!(@strong sender => move |_| {
|
||||||
|
sender.input(Msg::PagePrev);
|
||||||
|
}));
|
||||||
|
|
||||||
|
let widgets = AppWidgets {
|
||||||
|
page_num_lbl,
|
||||||
|
text_buffer,
|
||||||
|
page_string_textview,
|
||||||
|
};
|
||||||
|
|
||||||
|
ComponentParts { model, widgets }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {
|
||||||
|
match msg {
|
||||||
|
Msg::PageNext => {
|
||||||
|
self.page_num = self.page_num.wrapping_add(1);
|
||||||
|
}
|
||||||
|
Msg::PagePrev => {
|
||||||
|
self.page_num = self.page_num.wrapping_sub(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.doc.set_current_page(self.page_num.into());
|
||||||
|
let html = self.doc.get_current_str().unwrap().0;
|
||||||
|
let document = Html::parse_document(html.as_str());
|
||||||
|
let selector = Selector::parse("body").unwrap();
|
||||||
|
let body = document.select(&selector).next().unwrap();
|
||||||
|
let text = body.text().collect::<Vec<_>>();
|
||||||
|
let joined_text = text.join("\n");
|
||||||
|
println!("{}", joined_text);
|
||||||
|
self.page_string = joined_text;
|
||||||
|
}
|
||||||
|
// Update the view to represent the updated model.
|
||||||
|
fn update_view(&self, widgets: &mut Self::Widgets, _sender: ComponentSender<Self>) {
|
||||||
|
widgets
|
||||||
|
.page_num_lbl
|
||||||
|
.set_label(&format!("Page {}", self.page_num));
|
||||||
|
widgets.text_buffer.set_text(&self.page_string);
|
||||||
|
widgets
|
||||||
|
.page_string_textview
|
||||||
|
.set_buffer(Some(&widgets.text_buffer));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user