desktop: Add network access dialog
Add network access dialog written in egui and replace rfd's socket confirmation with it.
This commit is contained in:
parent
9fb669a343
commit
e179b41ca7
|
@ -0,0 +1,6 @@
|
|||
network-access-dialog-title = Requesting Network Access
|
||||
|
||||
network-access-dialog-message = The current movie is attempting to connect to the following host. Are you sure you want to allow it?
|
||||
network-access-dialog-port = (port { $port })
|
||||
|
||||
network-access-dialog-allow = Allow
|
|
@ -1,14 +1,18 @@
|
|||
use rfd::{AsyncMessageDialog, MessageButtons, MessageDialog, MessageDialogResult, MessageLevel};
|
||||
use rfd::{MessageButtons, MessageDialog, MessageDialogResult, MessageLevel};
|
||||
use ruffle_frontend_utils::backends::navigator::NavigatorInterface;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::ErrorKind;
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tokio::sync::oneshot;
|
||||
use url::Url;
|
||||
use winit::event_loop::EventLoopProxy;
|
||||
|
||||
use crate::custom_event::RuffleEvent;
|
||||
use crate::gui::dialogs::network_access_dialog::{
|
||||
NetworkAccessDialogConfiguration, NetworkAccessDialogResult,
|
||||
};
|
||||
use crate::gui::DialogDescriptor;
|
||||
use crate::util::open_url;
|
||||
|
||||
|
@ -66,8 +70,15 @@ impl NavigatorInterface for DesktopNavigatorInterface {
|
|||
}
|
||||
|
||||
async fn confirm_socket(&self, host: &str, port: u16) -> bool {
|
||||
AsyncMessageDialog::new().set_level(MessageLevel::Warning).set_description(format!("The current movie is attempting to connect to {:?} (port {}).\n\nTo allow it to do so, click Yes to grant network access to that host.\n\nOtherwise, click No to deny access.", host, port)).set_buttons(MessageButtons::YesNo)
|
||||
.show()
|
||||
.await == MessageDialogResult::Yes
|
||||
let (notifier, receiver) = oneshot::channel();
|
||||
let _ = self
|
||||
.event_loop
|
||||
.lock()
|
||||
.expect("Non-poisoned event loop")
|
||||
.send_event(RuffleEvent::OpenDialog(DialogDescriptor::NetworkAccess(
|
||||
NetworkAccessDialogConfiguration::new(notifier, host, port),
|
||||
)));
|
||||
let result = receiver.await;
|
||||
result == Ok(NetworkAccessDialogResult::Allow)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod about_dialog;
|
||||
mod bookmarks_dialog;
|
||||
pub mod message_dialog;
|
||||
pub mod network_access_dialog;
|
||||
mod open_dialog;
|
||||
mod open_url_dialog;
|
||||
mod preferences_dialog;
|
||||
|
@ -11,11 +12,12 @@ use crate::player::LaunchOptions;
|
|||
use crate::preferences::GlobalPreferences;
|
||||
use bookmarks_dialog::{BookmarkAddDialog, BookmarksDialog};
|
||||
use message_dialog::{MessageDialog, MessageDialogConfiguration};
|
||||
use network_access_dialog::{NetworkAccessDialog, NetworkAccessDialogConfiguration};
|
||||
use open_dialog::OpenDialog;
|
||||
use open_url_dialog::OpenUrlDialog;
|
||||
use preferences_dialog::PreferencesDialog;
|
||||
use ruffle_core::Player;
|
||||
use std::sync::Weak;
|
||||
use std::{collections::VecDeque, sync::Weak};
|
||||
use unic_langid::LanguageIdentifier;
|
||||
use url::Url;
|
||||
use volume_controls::VolumeControls;
|
||||
|
@ -33,6 +35,12 @@ pub struct Dialogs {
|
|||
open_url_dialog: Option<OpenUrlDialog>,
|
||||
message_dialog: Option<MessageDialog>,
|
||||
|
||||
// Use a queue for the following dialogs in order to:
|
||||
// 1. support handling multiple instances of them,
|
||||
// 2. prevent new instances popping up over existing ones
|
||||
// (and possibly stealing a click).
|
||||
network_access_dialog_queue: VecDeque<NetworkAccessDialog>,
|
||||
|
||||
open_dialog: OpenDialog,
|
||||
is_open_dialog_visible: bool,
|
||||
|
||||
|
@ -47,6 +55,7 @@ pub struct Dialogs {
|
|||
pub enum DialogDescriptor {
|
||||
OpenUrl(url::Url),
|
||||
ShowMessage(MessageDialogConfiguration),
|
||||
NetworkAccess(NetworkAccessDialogConfiguration),
|
||||
}
|
||||
|
||||
impl Dialogs {
|
||||
|
@ -65,6 +74,8 @@ impl Dialogs {
|
|||
open_url_dialog: None,
|
||||
message_dialog: None,
|
||||
|
||||
network_access_dialog_queue: VecDeque::new(),
|
||||
|
||||
open_dialog: OpenDialog::new(
|
||||
player_options,
|
||||
default_path,
|
||||
|
@ -138,6 +149,9 @@ impl Dialogs {
|
|||
DialogDescriptor::ShowMessage(config) => {
|
||||
self.message_dialog = Some(MessageDialog::new(config));
|
||||
}
|
||||
DialogDescriptor::NetworkAccess(config) => self
|
||||
.network_access_dialog_queue
|
||||
.push_back(NetworkAccessDialog::new(config)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,6 +169,7 @@ impl Dialogs {
|
|||
self.show_about_dialog(locale, egui_ctx);
|
||||
self.show_open_url_dialog(locale, egui_ctx);
|
||||
self.show_message_dialog(locale, egui_ctx);
|
||||
self.show_network_access_dialog(locale, egui_ctx);
|
||||
}
|
||||
|
||||
fn show_open_dialog(&mut self, locale: &LanguageIdentifier, egui_ctx: &egui::Context) {
|
||||
|
@ -239,4 +254,19 @@ impl Dialogs {
|
|||
self.message_dialog = None;
|
||||
}
|
||||
}
|
||||
|
||||
fn show_network_access_dialog(
|
||||
&mut self,
|
||||
locale: &LanguageIdentifier,
|
||||
egui_ctx: &egui::Context,
|
||||
) {
|
||||
let keep_open = if let Some(dialog) = &mut self.network_access_dialog_queue.front_mut() {
|
||||
dialog.show(locale, egui_ctx)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
if !keep_open {
|
||||
self.network_access_dialog_queue.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
use crate::gui::{text, text_with_args};
|
||||
use egui::{Align2, Ui, Window};
|
||||
use fluent_templates::fluent_bundle::FluentValue;
|
||||
use std::collections::HashMap;
|
||||
use tokio::sync::oneshot::Sender;
|
||||
use unic_langid::LanguageIdentifier;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub enum NetworkAccessDialogResult {
|
||||
Allow,
|
||||
Cancel,
|
||||
}
|
||||
|
||||
pub struct NetworkAccessDialogConfiguration {
|
||||
notifier: Option<Sender<NetworkAccessDialogResult>>,
|
||||
host: String,
|
||||
port: u16,
|
||||
}
|
||||
|
||||
impl NetworkAccessDialogConfiguration {
|
||||
pub fn new(
|
||||
notifier: Sender<NetworkAccessDialogResult>,
|
||||
host: impl Into<String>,
|
||||
port: u16,
|
||||
) -> Self {
|
||||
Self {
|
||||
notifier: Some(notifier),
|
||||
host: host.into(),
|
||||
port,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NetworkAccessDialog {
|
||||
config: NetworkAccessDialogConfiguration,
|
||||
}
|
||||
|
||||
impl Drop for NetworkAccessDialog {
|
||||
fn drop(&mut self) {
|
||||
self.respond(NetworkAccessDialogResult::Cancel);
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkAccessDialog {
|
||||
pub fn new(config: NetworkAccessDialogConfiguration) -> Self {
|
||||
Self { config }
|
||||
}
|
||||
|
||||
fn respond(&mut self, result: NetworkAccessDialogResult) {
|
||||
if let Some(notifier) = std::mem::take(&mut self.config.notifier) {
|
||||
let _ = notifier.send(result);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show(&mut self, locale: &LanguageIdentifier, egui_ctx: &egui::Context) -> bool {
|
||||
let mut keep_open = true;
|
||||
let mut should_close = false;
|
||||
|
||||
Window::new(text(locale, "network-access-dialog-title"))
|
||||
.open(&mut keep_open)
|
||||
.anchor(Align2::CENTER_CENTER, egui::Vec2::ZERO)
|
||||
.collapsible(false)
|
||||
.resizable(false)
|
||||
.show(egui_ctx, |ui| {
|
||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||
should_close = self.render_window_contents(locale, ui)
|
||||
});
|
||||
});
|
||||
|
||||
keep_open && !should_close
|
||||
}
|
||||
|
||||
pub fn render_window_contents(&mut self, locale: &LanguageIdentifier, ui: &mut Ui) -> bool {
|
||||
let mut should_close = false;
|
||||
|
||||
ui.label(text(locale, "network-access-dialog-message"));
|
||||
ui.label("");
|
||||
ui.horizontal(|ui| {
|
||||
ui.monospace(&self.config.host);
|
||||
ui.label(text_with_args(
|
||||
locale,
|
||||
"network-access-dialog-port",
|
||||
&HashMap::from([(
|
||||
"port",
|
||||
FluentValue::String(self.config.port.to_string().into()),
|
||||
)]),
|
||||
));
|
||||
});
|
||||
ui.label("");
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui
|
||||
.button(text(locale, "network-access-dialog-allow"))
|
||||
.clicked()
|
||||
{
|
||||
self.respond(NetworkAccessDialogResult::Allow);
|
||||
should_close = true;
|
||||
}
|
||||
if ui.button(text(locale, "dialog-cancel")).clicked() {
|
||||
should_close = true;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
should_close
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue