desktop: Add file dialogs to Ruffle if no FILE argv V2 (close #1774)

Introduce file dialogs if no FILE argv is passed.
Use altered version of due to https://github.com/jdm/tinyfiledialogs-rs/issues/19
This commit is contained in:
Sam Morrow 2020-12-02 16:29:36 +01:00 committed by Mike Welsh
parent b8c202a7f7
commit d5e597052e
3 changed files with 46 additions and 13 deletions

10
Cargo.lock generated
View File

@ -2979,6 +2979,7 @@ dependencies = [
"lyon", "lyon",
"ruffle_core", "ruffle_core",
"ruffle_render_wgpu", "ruffle_render_wgpu",
"tinyfiledialogs",
"url 2.2.0", "url 2.2.0",
"webbrowser", "webbrowser",
"winapi 0.3.9", "winapi 0.3.9",
@ -3514,6 +3515,15 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "tinyfiledialogs"
version = "3.3.10"
source = "git+https://github.com/jdm/tinyfiledialogs-rs?rev=1a235d1#1a235d1b14f05354af23ecd0781dba2fe72fdd83"
dependencies = [
"cc",
"libc",
]
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.1.0" version = "1.1.0"

View File

@ -24,6 +24,7 @@ url = "2.2.0"
clipboard = "0.5.0" clipboard = "0.5.0"
dirs = "3.0" dirs = "3.0"
isahc = "0.9.13" isahc = "0.9.13"
tinyfiledialogs = {git ="https://github.com/jdm/tinyfiledialogs-rs", rev="1a235d1"}
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = "0.3.9" winapi = "0.3.9"

View File

@ -22,6 +22,7 @@ use ruffle_render_wgpu::WgpuRenderBackend;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::Arc; use std::sync::Arc;
use std::time::Instant; use std::time::Instant;
use tinyfiledialogs::open_file_dialog;
use url::Url; use url::Url;
use crate::storage::DiskStorageBackend; use crate::storage::DiskStorageBackend;
@ -44,7 +45,7 @@ use winit::window::{Icon, WindowBuilder};
struct Opt { struct Opt {
/// Path to a flash movie (swf) to play /// Path to a flash movie (swf) to play
#[clap(name = "FILE", parse(from_os_str))] #[clap(name = "FILE", parse(from_os_str))]
input_path: PathBuf, input_path: Option<PathBuf>,
/// A "flashvars" parameter to provide to the movie. /// A "flashvars" parameter to provide to the movie.
/// This can be repeated multiple times, for example -Pkey=value -Pfoo=bar /// This can be repeated multiple times, for example -Pkey=value -Pfoo=bar
@ -128,17 +129,33 @@ fn load_movie_from_path(
} }
fn run_player(opt: Opt) -> Result<(), Box<dyn std::error::Error>> { fn run_player(opt: Opt) -> Result<(), Box<dyn std::error::Error>> {
let movie_url = if opt.input_path.exists() { let movie_url = match &opt.input_path {
let absolute_path = opt Some(path) => {
.input_path if path.exists() {
.canonicalize() let absolute_path = path.canonicalize().unwrap_or_else(|_| path.to_owned());
.unwrap_or_else(|_| opt.input_path.to_owned()); Url::from_file_path(absolute_path)
Url::from_file_path(absolute_path) .map_err(|_| "Path must be absolute and cannot be a URL")?
.map_err(|_| "Path must be absolute and cannot be a URL")? } else {
} else { Url::parse(path.to_str().unwrap_or_default())
Url::parse(opt.input_path.to_str().unwrap_or_default()) .map_err(|_| "Input path is not a file and could not be parsed as a URL.")?
.map_err(|_| "Input path is not a file and could not be parsed as a URL.")? }
}
None => {
let result = open_file_dialog("Load a Flash File", "", Some((&["*.swf"], ".swf")));
let selected = match result {
Some(file_path) => PathBuf::from(file_path),
None => return Ok(()),
};
let absolute_path = selected
.canonicalize()
.unwrap_or_else(|_| selected.to_owned());
Url::from_file_path(absolute_path)
.map_err(|_| "Path must be absolute and cannot be a URL")?
}
}; };
let mut movie = load_movie_from_path(movie_url.to_owned(), opt.proxy.to_owned())?; let mut movie = load_movie_from_path(movie_url.to_owned(), opt.proxy.to_owned())?;
let movie_size = LogicalSize::new(movie.width(), movie.height()); let movie_size = LogicalSize::new(movie.width(), movie.height());
@ -186,14 +203,19 @@ fn run_player(opt: Opt) -> Result<(), Box<dyn std::error::Error>> {
)?); )?);
let (executor, chan) = GlutinAsyncExecutor::new(event_loop.create_proxy()); let (executor, chan) = GlutinAsyncExecutor::new(event_loop.create_proxy());
let navigator = Box::new(navigator::ExternalNavigatorBackend::new( let navigator = Box::new(navigator::ExternalNavigatorBackend::new(
movie_url, movie_url.clone(),
chan, chan,
event_loop.create_proxy(), event_loop.create_proxy(),
opt.proxy, opt.proxy,
)); //TODO: actually implement this backend type )); //TODO: actually implement this backend type
let input = Box::new(input::WinitInputBackend::new(window.clone())); let input = Box::new(input::WinitInputBackend::new(window.clone()));
let storage = Box::new(DiskStorageBackend::new( let storage = Box::new(DiskStorageBackend::new(
opt.input_path.file_name().unwrap_or_default().as_ref(), movie_url
.to_file_path()
.unwrap_or_default()
.file_name()
.unwrap_or_default()
.as_ref(),
)); ));
let locale = Box::new(locale::DesktopLocaleBackend::new()); let locale = Box::new(locale::DesktopLocaleBackend::new());
let player = Player::new( let player = Player::new(