mirror of
https://github.com/jwinterm/grim.git
synced 2026-10-22 07:58:31 +02:00
android: pick file
This commit is contained in:
+42
-21
@@ -18,12 +18,14 @@ use std::{fs, thread};
|
||||
use parking_lot::RwLock;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::FILE_ARROW_UP;
|
||||
use crate::gui::icons::ARCHIVE_BOX;
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::View;
|
||||
|
||||
/// Button to pick file and parse its data into text.
|
||||
pub struct FilePickButton {
|
||||
/// Flag to check if file is picking.
|
||||
pub file_picking: Arc<AtomicBool>,
|
||||
/// Flag to check if file is parsing.
|
||||
pub file_parsing: Arc<AtomicBool>,
|
||||
/// File parsing result.
|
||||
@@ -33,6 +35,7 @@ pub struct FilePickButton {
|
||||
impl Default for FilePickButton {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
file_picking: Arc::new(AtomicBool::new(false)),
|
||||
file_parsing: Arc::new(AtomicBool::new(false)),
|
||||
file_parsing_result: Arc::new(RwLock::new(None))
|
||||
}
|
||||
@@ -45,8 +48,16 @@ impl FilePickButton {
|
||||
ui: &mut egui::Ui,
|
||||
cb: &dyn PlatformCallbacks,
|
||||
on_result: impl FnOnce(String)) {
|
||||
if self.file_parsing.load(Ordering::Relaxed) {
|
||||
// Draw loading spinner on file parsing.
|
||||
if self.file_picking.load(Ordering::Relaxed) {
|
||||
View::small_loading_spinner(ui);
|
||||
// Check file pick result.
|
||||
if let Some(path) = cb.picked_file() {
|
||||
self.file_picking.store(false, Ordering::Relaxed);
|
||||
if !path.is_empty() {
|
||||
self.on_file_pick(path);
|
||||
}
|
||||
}
|
||||
} else if self.file_parsing.load(Ordering::Relaxed) {
|
||||
View::small_loading_spinner(ui);
|
||||
// Check file parsing result.
|
||||
let has_result = {
|
||||
@@ -67,29 +78,39 @@ impl FilePickButton {
|
||||
}
|
||||
} else {
|
||||
// Draw button to pick file.
|
||||
let file_text = format!("{} {}", FILE_ARROW_UP, t!("choose_file"));
|
||||
let file_text = format!("{} {}", ARCHIVE_BOX, t!("choose_file"));
|
||||
View::colored_text_button(ui, file_text, Colors::blue(), Colors::button(), || {
|
||||
if let Some(path) = cb.pick_file() {
|
||||
// Parse file at new thread.
|
||||
self.file_parsing.store(true, Ordering::Relaxed);
|
||||
let result = self.file_parsing_result.clone();
|
||||
thread::spawn(move || {
|
||||
if path.ends_with(".gif") {
|
||||
//TODO: Detect QR codes on GIF file.
|
||||
} else if path.ends_with(".jpeg") || path.ends_with(".jpg") ||
|
||||
path.ends_with(".png") {
|
||||
//TODO: Detect QR codes on image files.
|
||||
} else {
|
||||
// Parse file as plain text.
|
||||
if let Ok(text) = fs::read_to_string(path) {
|
||||
let mut w_res = result.write();
|
||||
*w_res = Some(text);
|
||||
}
|
||||
}
|
||||
});
|
||||
self.on_file_pick(path);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle picked file path.
|
||||
fn on_file_pick(&self, path: String) {
|
||||
// Wait for asynchronous file pick result if path is empty.
|
||||
if path.is_empty() {
|
||||
self.file_picking.store(true, Ordering::Relaxed);
|
||||
return;
|
||||
}
|
||||
self.file_parsing.store(true, Ordering::Relaxed);
|
||||
let result = self.file_parsing_result.clone();
|
||||
thread::spawn(move || {
|
||||
if path.ends_with(".gif") {
|
||||
//TODO: Detect QR codes on GIF file.
|
||||
} else if path.ends_with(".jpeg") || path.ends_with(".jpg") ||
|
||||
path.ends_with(".png") {
|
||||
//TODO: Detect QR codes on image files.
|
||||
} else {
|
||||
// Parse file as plain text.
|
||||
let mut w_res = result.write();
|
||||
if let Ok(text) = fs::read_to_string(path) {
|
||||
*w_res = Some(text);
|
||||
} else {
|
||||
*w_res = Some("".to_string());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+46
-45
@@ -73,50 +73,6 @@ impl QrCodeContent {
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw QR code image content.
|
||||
fn qr_image_ui(&mut self, svg: Vec<u8>, ui: &mut egui::Ui) {
|
||||
let mut rect = ui.available_rect_before_wrap();
|
||||
rect.min += egui::emath::vec2(10.0, 0.0);
|
||||
rect.max -= egui::emath::vec2(10.0, 0.0);
|
||||
|
||||
// Create background shape.
|
||||
let mut bg_shape = egui::epaint::RectShape {
|
||||
rect,
|
||||
rounding: egui::Rounding::default(),
|
||||
fill: egui::Color32::WHITE,
|
||||
stroke: egui::Stroke::NONE,
|
||||
fill_texture_id: Default::default(),
|
||||
uv: egui::Rect::ZERO
|
||||
};
|
||||
let bg_idx = ui.painter().add(bg_shape);
|
||||
|
||||
// Draw QR code image content.
|
||||
let mut content_rect = ui.allocate_ui_at_rect(rect, |ui| {
|
||||
ui.add_space(10.0);
|
||||
let size = SizeHint::Size(ui.available_width() as u32, ui.available_width() as u32);
|
||||
let color_img = load_svg_bytes_with_size(svg.as_slice(), Some(size)).unwrap();
|
||||
// Create image texture.
|
||||
let texture_handle = ui.ctx().load_texture("qr_code",
|
||||
color_img.clone(),
|
||||
TextureOptions::default());
|
||||
self.texture_handle = Some(texture_handle.clone());
|
||||
let img_size = egui::emath::vec2(color_img.width() as f32,
|
||||
color_img.height() as f32);
|
||||
let sized_img = SizedTexture::new(texture_handle.id(), img_size);
|
||||
// Add image to content.
|
||||
ui.add(egui::Image::from_texture(sized_img)
|
||||
.max_height(ui.available_width())
|
||||
.fit_to_original_size(1.0));
|
||||
ui.add_space(10.0);
|
||||
}).response.rect;
|
||||
|
||||
// Setup background shape to be painted behind content.
|
||||
content_rect.min -= egui::emath::vec2(10.0, 0.0);
|
||||
content_rect.max += egui::emath::vec2(10.0, 0.0);
|
||||
bg_shape.rect = content_rect;
|
||||
ui.painter().set(bg_idx, bg_shape);
|
||||
}
|
||||
|
||||
/// Draw animated QR code content.
|
||||
fn animated_ui(&mut self, ui: &mut egui::Ui, text: String, cb: &dyn PlatformCallbacks) {
|
||||
if !self.has_image() {
|
||||
@@ -180,8 +136,9 @@ impl QrCodeContent {
|
||||
});
|
||||
} else {
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.add_space(8.0);
|
||||
ui.add_space(2.0);
|
||||
View::small_loading_spinner(ui);
|
||||
ui.add_space(1.0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -271,6 +228,50 @@ impl QrCodeContent {
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw QR code image content.
|
||||
fn qr_image_ui(&mut self, svg: Vec<u8>, ui: &mut egui::Ui) {
|
||||
let mut rect = ui.available_rect_before_wrap();
|
||||
rect.min += egui::emath::vec2(10.0, 0.0);
|
||||
rect.max -= egui::emath::vec2(10.0, 0.0);
|
||||
|
||||
// Create background shape.
|
||||
let mut bg_shape = egui::epaint::RectShape {
|
||||
rect,
|
||||
rounding: egui::Rounding::default(),
|
||||
fill: egui::Color32::WHITE,
|
||||
stroke: egui::Stroke::NONE,
|
||||
fill_texture_id: Default::default(),
|
||||
uv: egui::Rect::ZERO
|
||||
};
|
||||
let bg_idx = ui.painter().add(bg_shape);
|
||||
|
||||
// Draw QR code image content.
|
||||
let mut content_rect = ui.allocate_ui_at_rect(rect, |ui| {
|
||||
ui.add_space(10.0);
|
||||
let size = SizeHint::Size(ui.available_width() as u32, ui.available_width() as u32);
|
||||
let color_img = load_svg_bytes_with_size(svg.as_slice(), Some(size)).unwrap();
|
||||
// Create image texture.
|
||||
let texture_handle = ui.ctx().load_texture("qr_code",
|
||||
color_img.clone(),
|
||||
TextureOptions::default());
|
||||
self.texture_handle = Some(texture_handle.clone());
|
||||
let img_size = egui::emath::vec2(color_img.width() as f32,
|
||||
color_img.height() as f32);
|
||||
let sized_img = SizedTexture::new(texture_handle.id(), img_size);
|
||||
// Add image to content.
|
||||
ui.add(egui::Image::from_texture(sized_img)
|
||||
.max_height(ui.available_width())
|
||||
.fit_to_original_size(1.0));
|
||||
ui.add_space(10.0);
|
||||
}).response.rect;
|
||||
|
||||
// Setup background shape to be painted behind content.
|
||||
content_rect.min -= egui::emath::vec2(10.0, 0.0);
|
||||
content_rect.max += egui::emath::vec2(10.0, 0.0);
|
||||
bg_shape.rect = content_rect;
|
||||
ui.painter().set(bg_idx, bg_shape);
|
||||
}
|
||||
|
||||
/// Check if QR code is loading.
|
||||
fn loading(&self) -> bool {
|
||||
let r_state = self.qr_image_state.read();
|
||||
|
||||
Reference in New Issue
Block a user