Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ i18n-embed-fl = "0.10"
icu = { version = "2.0.0", features = ["compiled_data"] }
rust-embed = "8"
url = "2.5"
secret-service = { version = "5.0.0", features = ["rt-tokio-crypto-rust"], optional = true }
thiserror = { version = "2.0", optional = true }
secstr = { version = "0.5", optional = true }

[dependencies.cosmic-files]
git = "https://github.com/pop-os/cosmic-files.git"
Expand All @@ -48,10 +51,11 @@ features = ["about", "multi-window", "tokio", "winit", "surface-message"]
fork = "0.2"

[features]
default = ["dbus-config", "wgpu", "wayland"]
default = ["dbus-config", "wgpu", "wayland", "password_manager"]
dbus-config = ["libcosmic/dbus-config"]
wgpu = ["libcosmic/wgpu", "cosmic-files/wgpu"]
wayland = ["libcosmic/wayland", "cosmic-files/wayland"]
password_manager = [ "secret-service", "thiserror", "secstr" ]

[profile.release-with-debug]
inherits = "release"
Expand Down
7 changes: 7 additions & 0 deletions i18n/en/cosmic_term.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,10 @@ pane-toggle-maximize = Toggle maximized
menu-color-schemes = Color schemes...
menu-settings = Settings...
menu-about = About COSMIC Terminal...

# Password Manager
menu-password-manager = Passwords...
passwords-title = Passwords
add-password = Add Password
password-input = Password
password-input-description = Description
7 changes: 7 additions & 0 deletions i18n/sv-SE/cosmic_term.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,10 @@ menu-settings = Inställningar…
menu-about = Om COSMIC Terminal…
repository = Källkod
support = Support

# Lösenordshanterare
menu-password-manager = Lösenord…
passwords-title = Lösenord
add-password = Lägg till lösenord
password-input = Lösenord
password-input-description = Beskrivning
2 changes: 2 additions & 0 deletions src/key_bind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pub fn key_binds() -> HashMap<KeyBind, Action> {
Key::Character("X".into()),
PaneToggleMaximized
);
#[cfg(feature = "password_manager")]
bind!([Ctrl, Alt], Key::Character("p".into()), PasswordManager);

// Ctrl+Tab and Ctrl+Shift+Tab cycle through tabs
// Ctrl+Tab is not a special key for terminals and is free to use
Expand Down
57 changes: 57 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ use terminal_box::terminal_box;
use crate::dnd::DndDrop;
mod terminal_box;

#[cfg(feature = "password_manager")]
mod password_manager;
mod terminal_theme;

mod dnd;
Expand Down Expand Up @@ -236,6 +238,8 @@ pub enum Action {
Profiles,
SelectAll,
Settings,
#[cfg(feature = "password_manager")]
PasswordManager,
ShowHeaderBar(bool),
TabActivate0,
TabActivate1,
Expand Down Expand Up @@ -278,6 +282,8 @@ impl Action {
Self::PaneSplitHorizontal => Message::PaneSplit(pane_grid::Axis::Horizontal),
Self::PaneSplitVertical => Message::PaneSplit(pane_grid::Axis::Vertical),
Self::PaneToggleMaximized => Message::PaneToggleMaximized,
#[cfg(feature = "password_manager")]
Self::PasswordManager => Message::ToggleContextPage(ContextPage::PasswordManager),
Self::Paste => Message::Paste(entity_opt),
Self::PastePrimary => Message::PastePrimary(entity_opt),
Self::ProfileOpen(profile_id) => Message::ProfileOpen(*profile_id),
Expand Down Expand Up @@ -362,6 +368,10 @@ pub enum Message {
PaneResized(pane_grid::ResizeEvent),
PaneSplit(pane_grid::Axis),
PaneToggleMaximized,
#[cfg(feature = "password_manager")]
PasswordManager(password_manager::PasswordManagerMessage),
#[cfg(feature = "password_manager")]
PasswordPaste(secstr::SecUtf8, pane_grid::Pane),
Paste(Option<segmented_button::Entity>),
PastePrimary(Option<segmented_button::Entity>),
PasteValue(Option<segmented_button::Entity>, String),
Expand Down Expand Up @@ -412,6 +422,8 @@ pub enum ContextPage {
ColorSchemes(ColorSchemeKind),
Profiles,
Settings,
#[cfg(feature = "password_manager")]
PasswordManager,
}

/// The [`App`] stores application-specific state.
Expand Down Expand Up @@ -456,6 +468,8 @@ pub struct App {
profile_expanded: Option<ProfileId>,
show_advanced_font_settings: bool,
modifiers: Modifiers,
#[cfg(feature = "password_manager")]
password_mgr: password_manager::PasswordManager,
}

impl App {
Expand Down Expand Up @@ -1569,6 +1583,8 @@ impl Application for App {
profile_expanded: None,
show_advanced_font_settings: false,
modifiers: Modifiers::empty(),
#[cfg(feature = "password_manager")]
password_mgr: Default::default(),
};

app.set_curr_font_weights_and_stretches();
Expand All @@ -1582,6 +1598,10 @@ impl Application for App {
if self.core.window.show_context {
// Close context drawer if open
self.core.window.show_context = false;
#[cfg(feature = "password_manager")]
if self.context_page == ContextPage::PasswordManager {
self.password_mgr.clear();
}
} else if self.find {
// Close find if open
self.find = false;
Expand All @@ -1596,6 +1616,10 @@ impl Application for App {
if self.core.window.show_context {
Task::none()
} else {
#[cfg(feature = "password_manager")]
if self.context_page == ContextPage::PasswordManager {
self.password_mgr.clear();
}
self.update_focus()
}
}
Expand Down Expand Up @@ -2147,6 +2171,23 @@ impl Application for App {
self.pane_model.panes.drop(pane, target);
}
Message::PaneDragged(_) => {}
#[cfg(feature = "password_manager")]
Message::PasswordManager(msg) => {
return self.password_mgr.update(msg);
}
#[cfg(feature = "password_manager")]
Message::PasswordPaste(password, pane) => {
if let Some(tab_model) = self.pane_model.panes.get(pane) {
let entity = tab_model.active();
if let Some(terminal) = tab_model.data::<Mutex<Terminal>>(entity) {
let terminal = terminal.lock().unwrap();
terminal.paste(password.into_unsecure());
terminal.input_scroll(b"\n".as_slice());
self.core.window.show_context = false;
self.password_mgr.clear();
}
}
}
Message::Paste(entity_opt) => {
return clipboard::read().map(move |value_opt| match value_opt {
Some(value) => action::app(Message::PasteValue(entity_opt, value)),
Expand Down Expand Up @@ -2612,6 +2653,16 @@ impl Application for App {
ColorSchemeKind::Light => light_entity,
});
}

#[cfg(feature = "password_manager")]
if ContextPage::PasswordManager == context_page {
if self.core.window.show_context {
self.password_mgr.pane = Some(self.pane_model.focused());
return self.password_mgr.refresh_password_list();
} else {
self.password_mgr.clear();
}
}
}
Message::UpdateDefaultProfile((default, profile_id)) => {
config_set!(default_profile, default.then_some(profile_id));
Expand Down Expand Up @@ -2685,6 +2736,12 @@ impl Application for App {
Message::ToggleContextPage(ContextPage::Settings),
)
.title(fl!("settings")),
#[cfg(feature = "password_manager")]
ContextPage::PasswordManager => context_drawer::context_drawer(
self.password_mgr.context_page(self.core.system_theme()),
Message::ToggleContextPage(ContextPage::PasswordManager),
)
.title(fl!("passwords-title")),
})
}

Expand Down
Loading