mirror of
https://github.com/jwinterm/grim.git
synced 2026-10-19 06:48:33 +02:00
platform: android file opening, better exit
This commit is contained in:
+1
-1
@@ -110,7 +110,7 @@ impl<Platform: PlatformCallbacks> App<Platform> {
|
||||
}
|
||||
|
||||
// Provide incoming data to wallets.
|
||||
if let Some(data) = crate::consume_passed_data() {
|
||||
if let Some(data) = crate::consume_incoming_data() {
|
||||
if !data.is_empty() {
|
||||
self.content.wallets.on_data(ui, Some(data), &self.platform);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,10 @@ impl PlatformCallbacks for Android {
|
||||
*w_ctx = Some(ctx.clone());
|
||||
}
|
||||
|
||||
fn exit(&self) {
|
||||
self.call_java_method("exit", "()V", &[]).unwrap();
|
||||
}
|
||||
|
||||
fn show_keyboard(&self) {
|
||||
// Disable NDK soft input show call before fix for egui.
|
||||
// self.android_app.show_soft_input(false);
|
||||
@@ -137,20 +141,18 @@ impl PlatformCallbacks for Android {
|
||||
fn share_data(&self, name: String, data: Vec<u8>) -> Result<(), std::io::Error> {
|
||||
// Create file at cache dir.
|
||||
let default_cache = OsString::from(dirs::cache_dir().unwrap());
|
||||
let mut cache = PathBuf::from(env::var_os("XDG_CACHE_HOME").unwrap_or(default_cache));
|
||||
cache.push("images");
|
||||
std::fs::create_dir_all(cache.to_str().unwrap())?;
|
||||
cache.push(name);
|
||||
if cache.exists() {
|
||||
std::fs::remove_file(cache.clone())?;
|
||||
let mut file = PathBuf::from(env::var_os("XDG_CACHE_HOME").unwrap_or(default_cache));
|
||||
file.push(name);
|
||||
if file.exists() {
|
||||
std::fs::remove_file(file.clone())?;
|
||||
}
|
||||
let mut image = File::create_new(cache.clone())?;
|
||||
let mut image = File::create_new(file.clone())?;
|
||||
image.write_all(data.as_slice())?;
|
||||
image.sync_all()?;
|
||||
// Call share modal at system.
|
||||
let vm = unsafe { jni::JavaVM::from_raw(self.android_app.vm_as_ptr() as _) }.unwrap();
|
||||
let env = vm.attach_current_thread().unwrap();
|
||||
let arg_value = env.new_string(cache.to_str().unwrap()).unwrap();
|
||||
let arg_value = env.new_string(file.to_str().unwrap()).unwrap();
|
||||
self.call_java_method("shareImage",
|
||||
"(Ljava/lang/String;)V",
|
||||
&[JValue::Object(&JObject::from(arg_value))]).unwrap();
|
||||
|
||||
@@ -43,6 +43,14 @@ impl PlatformCallbacks for Desktop {
|
||||
*w_ctx = Some(ctx.clone());
|
||||
}
|
||||
|
||||
fn exit(&self) {
|
||||
let r_ctx = self.ctx.read();
|
||||
if r_ctx.is_some() {
|
||||
let ctx = r_ctx.as_ref().unwrap();
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
}
|
||||
}
|
||||
|
||||
fn show_keyboard(&self) {}
|
||||
|
||||
fn hide_keyboard(&self) {}
|
||||
|
||||
@@ -23,6 +23,7 @@ pub mod platform;
|
||||
|
||||
pub trait PlatformCallbacks {
|
||||
fn set_context(&mut self, ctx: &egui::Context);
|
||||
fn exit(&self);
|
||||
fn show_keyboard(&self);
|
||||
fn hide_keyboard(&self);
|
||||
fn copy_string_to_buffer(&self, data: String);
|
||||
|
||||
@@ -40,8 +40,8 @@ pub struct Content {
|
||||
/// Central panel [`WalletsContent`] content.
|
||||
pub wallets: WalletsContent,
|
||||
|
||||
/// Check if app exit is allowed on close event of [`eframe::App`] implementation.
|
||||
pub(crate) exit_allowed: bool,
|
||||
/// Check if app exit is allowed on Desktop close event.
|
||||
pub exit_allowed: bool,
|
||||
/// Flag to show exit progress at [`Modal`].
|
||||
show_exit_progress: bool,
|
||||
|
||||
@@ -83,7 +83,7 @@ impl ModalContainer for Content {
|
||||
modal: &Modal,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
match modal.id {
|
||||
Self::EXIT_CONFIRMATION_MODAL => self.exit_modal_content(ui, modal),
|
||||
Self::EXIT_CONFIRMATION_MODAL => self.exit_modal_content(ui, modal, cb),
|
||||
Self::SETTINGS_MODAL => self.settings_modal_ui(ui, modal),
|
||||
Self::ANDROID_INTEGRATED_NODE_WARNING_MODAL => self.android_warning_modal_ui(ui, modal),
|
||||
Self::CRASH_REPORT_MODAL => self.crash_report_modal_ui(ui, modal, cb),
|
||||
@@ -206,11 +206,11 @@ impl Content {
|
||||
}
|
||||
|
||||
/// Draw exit confirmation modal content.
|
||||
fn exit_modal_content(&mut self, ui: &mut egui::Ui, modal: &Modal) {
|
||||
fn exit_modal_content(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
if self.show_exit_progress {
|
||||
if !Node::is_running() {
|
||||
self.exit_allowed = true;
|
||||
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
cb.exit();
|
||||
modal.close();
|
||||
}
|
||||
ui.add_space(16.0);
|
||||
@@ -244,7 +244,7 @@ impl Content {
|
||||
View::button_ui(ui, t!("modal_exit.exit"), Colors::white_or_black(false), |ui| {
|
||||
if !Node::is_running() {
|
||||
self.exit_allowed = true;
|
||||
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
cb.exit();
|
||||
modal.close();
|
||||
} else {
|
||||
Node::stop(true);
|
||||
|
||||
@@ -36,12 +36,10 @@ pub struct WalletsContent {
|
||||
|
||||
/// Wallet selection [`Modal`] content.
|
||||
wallet_selection_content: Option<WalletsModal>,
|
||||
|
||||
/// Wallet opening [`Modal`] content.
|
||||
open_wallet_content: Option<OpenWalletModal>,
|
||||
|
||||
/// Wallet connection selection content.
|
||||
conn_modal_content: Option<WalletConnectionModal>,
|
||||
conn_selection_content: Option<WalletConnectionModal>,
|
||||
|
||||
/// Selected [`Wallet`] content.
|
||||
wallet_content: WalletContent,
|
||||
@@ -70,7 +68,7 @@ impl Default for WalletsContent {
|
||||
wallets: WalletList::default(),
|
||||
wallet_selection_content: None,
|
||||
open_wallet_content: None,
|
||||
conn_modal_content: None,
|
||||
conn_selection_content: None,
|
||||
wallet_content: WalletContent::new(None),
|
||||
creation_content: WalletCreation::default(),
|
||||
show_wallets_at_dual_panel: AppConfig::show_wallets_at_dual_panel(),
|
||||
@@ -106,7 +104,7 @@ impl ModalContainer for WalletsContent {
|
||||
self.creation_content.name_pass_modal_ui(ui, modal, cb)
|
||||
},
|
||||
CONNECTION_SELECTION_MODAL => {
|
||||
if let Some(content) = self.conn_modal_content.as_mut() {
|
||||
if let Some(content) = self.conn_selection_content.as_mut() {
|
||||
content.ui(ui, modal, cb, |id| {
|
||||
// Update wallet connection on select.
|
||||
let list = self.wallets.list();
|
||||
@@ -303,6 +301,7 @@ impl WalletsContent {
|
||||
}
|
||||
}
|
||||
|
||||
/// Show wallet selection with provided optional data.
|
||||
fn show_wallet_selection_modal(&mut self, data: Option<String>) {
|
||||
self.wallet_selection_content = Some(WalletsModal::new(None, data, true));
|
||||
// Show wallet selection modal.
|
||||
@@ -557,7 +556,7 @@ impl WalletsContent {
|
||||
/// Show [`Modal`] to select connection for the wallet.
|
||||
fn show_connection_selector_modal(&mut self, wallet: &Wallet) {
|
||||
let ext_conn = wallet.get_current_ext_conn();
|
||||
self.conn_modal_content = Some(WalletConnectionModal::new(ext_conn));
|
||||
self.conn_selection_content = Some(WalletConnectionModal::new(ext_conn));
|
||||
// Show modal.
|
||||
Modal::new(CONNECTION_SELECTION_MODAL)
|
||||
.position(ModalPosition::CenterTop)
|
||||
|
||||
+30
-6
@@ -260,15 +260,15 @@ fn setup_i18n() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get data provided from deeplink or opened file.
|
||||
pub fn consume_passed_data() -> Option<String> {
|
||||
/// Get data from deeplink or opened file.
|
||||
pub fn consume_incoming_data() -> Option<String> {
|
||||
let has_data = {
|
||||
let r_data = PASSED_DATA.read();
|
||||
let r_data = INCOMING_DATA.read();
|
||||
r_data.is_some()
|
||||
};
|
||||
if has_data {
|
||||
// Clear data.
|
||||
let mut w_data = PASSED_DATA.write();
|
||||
let mut w_data = INCOMING_DATA.write();
|
||||
let data = w_data.clone();
|
||||
*w_data = None;
|
||||
return data;
|
||||
@@ -278,11 +278,35 @@ pub fn consume_passed_data() -> Option<String> {
|
||||
|
||||
/// Provide data from deeplink or opened file.
|
||||
pub fn on_data(data: String) {
|
||||
let mut w_data = PASSED_DATA.write();
|
||||
let mut w_data = INCOMING_DATA.write();
|
||||
*w_data = Some(data);
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Data provided from deeplink or opened file.
|
||||
pub static ref PASSED_DATA: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
|
||||
pub static ref INCOMING_DATA: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
|
||||
}
|
||||
|
||||
/// Callback from Java code with with passed data.
|
||||
#[allow(dead_code)]
|
||||
#[allow(non_snake_case)]
|
||||
#[cfg(target_os = "android")]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_mw_gri_android_MainActivity_onData(
|
||||
_env: jni::JNIEnv,
|
||||
_class: jni::objects::JObject,
|
||||
char: jni::sys::jstring
|
||||
) {
|
||||
unsafe {
|
||||
let j_obj = jni::objects::JString::from_raw(char);
|
||||
if let Ok(j_str) = _env.get_string_unchecked(j_obj.as_ref()) {
|
||||
match j_str.to_str() {
|
||||
Ok(str) => {
|
||||
let mut w_path = INCOMING_DATA.write();
|
||||
*w_path = Some(str.to_string());
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -48,9 +48,10 @@ pub struct Settings {
|
||||
impl Settings {
|
||||
/// Main application directory name.
|
||||
pub const MAIN_DIR_NAME: &'static str = ".grim";
|
||||
|
||||
/// Crash report file name.
|
||||
pub const CRASH_REPORT_FILE_NAME: &'static str = "crash.log";
|
||||
/// Application socket name.
|
||||
pub const SOCKET_NAME: &'static str = "grim.sock";
|
||||
|
||||
/// Initialize settings with app and node configs.
|
||||
fn init() -> Self {
|
||||
@@ -142,10 +143,10 @@ impl Settings {
|
||||
}
|
||||
|
||||
/// Get desktop application socket path.
|
||||
pub fn socket_path() -> String {
|
||||
pub fn socket_path() -> PathBuf {
|
||||
let mut socket_path = Self::base_path(None);
|
||||
socket_path.push("grim.socket");
|
||||
socket_path.to_str().unwrap().to_string()
|
||||
socket_path.push(Self::SOCKET_NAME);
|
||||
socket_path
|
||||
}
|
||||
|
||||
/// Get configuration file path from provided name and sub-directory if needed.
|
||||
|
||||
Reference in New Issue
Block a user