Ely Office: six offline-first desktop apps in Rust and GPUI
ElyDoc, ElyTable, ElyShow (LibreOfficeKit), ElyPDF (MuPDF), ElyTree (Git), ElyMark (Milkdown and CodeMirror in CEF). ElyMail and ElyAgent follow.
This commit is contained in:
817 files changed
+143101
No files matched your search
@@ -0,0 +1,97 @@
|
||||
//! The Repository menu, and File's New and Open as repositories.
|
||||
|
||||
use ely_ui::commands;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use gpui::{App, Context, KeyBinding, Menu, MenuItem, PathPromptOptions, Window, actions};
|
||||
|
||||
use crate::tree::{Tree, text};
|
||||
|
||||
actions!(
|
||||
tree,
|
||||
[
|
||||
CloneRepository,
|
||||
CloseRepository,
|
||||
Fetch,
|
||||
Pull,
|
||||
Push,
|
||||
ForcePush,
|
||||
OpenTerminal,
|
||||
Reveal,
|
||||
CleanUntracked,
|
||||
ChooseEditor
|
||||
]
|
||||
);
|
||||
|
||||
pub const CONTEXT: &str = "tree";
|
||||
|
||||
pub fn bind(cx: &mut App) {
|
||||
cx.bind_keys([KeyBinding::new(
|
||||
"secondary-w",
|
||||
CloseRepository,
|
||||
Some(CONTEXT),
|
||||
)]);
|
||||
}
|
||||
|
||||
pub fn menus(cx: &App) -> Vec<Menu> {
|
||||
vec![Menu::new(text(cx, "tree.menu.repository", &[])).items([
|
||||
MenuItem::action(text(cx, "tree.clone", &[]), CloneRepository),
|
||||
MenuItem::action(text(cx, "tree.close", &[]), CloseRepository),
|
||||
MenuItem::separator(),
|
||||
MenuItem::action(text(cx, "tree.net.fetch", &[]), Fetch),
|
||||
MenuItem::action(text(cx, "tree.net.pull", &[]), Pull),
|
||||
MenuItem::action(text(cx, "tree.net.push", &[]), Push),
|
||||
MenuItem::action(text(cx, "tree.force.open", &[]), ForcePush),
|
||||
MenuItem::separator(),
|
||||
MenuItem::action(text(cx, "tree.tool.terminal", &[]), OpenTerminal),
|
||||
MenuItem::action(text(cx, "tree.tool.reveal", &[]), Reveal),
|
||||
MenuItem::action(text(cx, "tree.clean.open", &[]), CleanUntracked),
|
||||
MenuItem::action(text(cx, "tree.tool.editor", &[]), ChooseEditor),
|
||||
])]
|
||||
}
|
||||
|
||||
impl Tree {
|
||||
/// Asks for folders; `then` gets each one picked.
|
||||
fn pick(
|
||||
&mut self,
|
||||
multiple: bool,
|
||||
then: fn(&mut Tree, PathBuf, &mut Context<Tree>),
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let picked = cx.prompt_for_paths(PathPromptOptions {
|
||||
files: false,
|
||||
directories: true,
|
||||
multiple,
|
||||
prompt: None,
|
||||
});
|
||||
cx.spawn(async move |this, cx| {
|
||||
let picked = picked
|
||||
.await
|
||||
.map_err(|error| error.to_string())
|
||||
.and_then(|picked| picked.map_err(|error| error.to_string()));
|
||||
this.update(cx, |tree, cx| match picked {
|
||||
Ok(Some(paths)) => paths.into_iter().for_each(|path| then(tree, path, cx)),
|
||||
Ok(None) => log::info!("tree: the folder panel was cancelled"),
|
||||
Err(error) => tree.failed("tree.error.panel", &error, cx),
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn on_open(&mut self, _: &commands::Open, _: &mut Window, cx: &mut Context<Self>) {
|
||||
self.pick(true, Tree::open_path, cx);
|
||||
}
|
||||
|
||||
pub fn on_new(&mut self, _: &commands::New, _: &mut Window, cx: &mut Context<Self>) {
|
||||
self.pick(false, Tree::init_at, cx);
|
||||
}
|
||||
|
||||
pub fn on_clone(&mut self, _: &CloneRepository, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.ask_url(window, cx);
|
||||
}
|
||||
|
||||
pub fn on_close(&mut self, _: &CloseRepository, _: &mut Window, cx: &mut Context<Self>) {
|
||||
self.close_active(cx);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user