diff options
| author | Aram Drevekenin <aram@poor.dev> | 2025-06-23 19:19:37 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-23 19:19:37 +0200 |
| commit | c5ac7968809ddb1033b625562eae22019cccc2f4 (patch) | |
| tree | 932cf07d898dfbcc6ec6a9d4cf5353c06a47accc /zellij-utils/src/plugin_api | |
| parent | feat(ui): add optional tooltip with key hints to the compact bar (#4225) (diff) | |
| download | sl0ppij-c5ac7968809ddb1033b625562eae22019cccc2f4.tar.gz sl0ppij-c5ac7968809ddb1033b625562eae22019cccc2f4.tar.xz sl0ppij-c5ac7968809ddb1033b625562eae22019cccc2f4.zip | |
Feature: web-client/server to share your sessions in the browser (#4242)
* work
* moar work
* notes
* work
* separate to terminal and control channels
* stdin working
* serve html web client initial
* serve static assets loaded with include_dir
* merge
* enable_web_server config parameter
* compile time flag to disable web server capability
* rustfmt
* add license to all xterm.js assets
* mouse working except copy/paste
* helpful comment
* web client improvements
- move script to js file
- add favicon
- add nerd font
- change title
TODO: investigate if font license embedded in otf is sufficient
* get mouse to work properly
* kitty keyboard support initial
* fix wrong type in preload link
* wip axum websocket handlers
- upgrade axum to v0.8.1, enable ws feature
- begin setup of websocket handlers
- tidy up imports
* replace control listener
* handle terminal websocket with axum
* cleanup Cargo.toml
* kitty fixes and bracketed paste
* fix(mouse): pane not found crash
* initial session switching infra
* add `web_client_font` option
* session switching, creation and resurrection working through the session manager
* move session module to zellij-utils and share logic with web-client
* some cleanups
* require restart for enable-web-server
* use session name from router
* write config to disk and watch for config changes
* rename session name to ipc path
* add basic panic handler, make render_to_client exit on channel close
* use while let instead of loop
* handle websocket close
* add mouse motions
* make clipboard work
* add weblink handling and webgl rendering
* add todo
* fix: use session name instead of patch on session switch
* use "default" layout for new sessions
* ui indication for session being shared
* share this session ui
* plugin assets
* Fix process crash on mac with notify watcher.
Use poll watcher instead of recommended as a workaround.
* make url session switching and creation work
* start welcome screen on root url
* scaffold control messages, set font from config
* set dimensions on session start
* bring back session name from url
* send bytes on terminal websocket instead of json
- create web client os input and id before websocket connection
* draft ui
* work
* refactor ui
* remove otf font, remove margins to avoid scrollbar
* version query endpoint for server status
* web session info query endpoint
* refactor: move stuff around
* add web client info to session metadata
* make tests pass
* populate real data in session list
* remove unnecessary endpoint
* add web_client node to config, add font option
* remove web_client_font
* allow disabling the web session through the config - WIP
* formalize sharing/not-sharing configuration
* fix tests
* allow shutting down web server
* display error when web clients are forbidden to attach
* only show sessions that allow web clients if this is a web client
* style(fmt): rustfmt
* fix: query web server from Zellij rather than from each plugin
* remove log spam
* handle some error paths better in the web client
* allow controlling the web server through the cli
* allow configuring the web server's ip/port
* fix tests and format code
* use direct WebServerStatus event instead of piggy-backing on SessionInfo
* plugin revamp initial
* make plugin responsive
* adjust plugin title
* refactor: share plugin
* refactor: share plugin
* add cors middleware
* some fixes for running without a compiled web server capability
* display error when starting the share plugin without web server support
* clarify config
* add pipelines to compile zellij without web support
* display error when unable to start web server
* only query web server when share plugin is running
* refactor(web-client): connection table
* give zellij_server_listener access to the control channel
* fixes and clarifications
* refactor: consolidate generate_unique_session_name
* give proper error when trying to attach to a forbidden session
* change browser URL when switching sessions
* add keyboard shortcut
* enforce https when bound to non-loopback ip
* initial authentication token implementation
* background color from theme
* initial web client theme config
* basic token generation ui
* refactor set config message creation
* also set body background
* allow editing scrollback for plugins too
* set scrollback to 0
* properly parse colors in config
* generate token from plugin
* nice login modals
* initial token management screen
* implement token authentication
* refactor(share): token management screen
* style(fmt): rustfmt
* fix(plugin): some minor bugs
* refactor(share): main screen
* refactor(share): token screen
* refactor(share): main
* refactor(share): ui components
* fix(responsiveness): properly send usage_width to the render function
* fix cli commands and add some verbosity
* add support for settings ansi and selection colors
* add cursor and cursor accent
* basic web client tests
* fix tests
* refactor: web client
* use session tokens for authentication
* improve modals
* move shutdown to ipc
* refactor: ipc logic
* serialize theme config for web client
* update tests
* refactor: move some stuff around to prepare for config hot reload
* config live reloading for the web clients
* change remember-me UI wording
* improve xterm.js link handling
* make sure terminal is focused on mousemove
* remove deprecated sharing indication from compact-bar
* gate deps and functionality behind the web_server_compatibility feature
* feat(build): add --no-web flag in all the places
* fix some other build flows
* add new assets
* update CI for no-web (untested)
* make more dependencies optional
* update axum-extra
* add web client configuration options
* gracefully close connections on server exit
* tests for graceful connection closing
* handle client-side reconnect when server is down
* fix: make sure ipc bus folder exists before starting
* add commands to manage login tokens from the cli
* style(fmt): rustfmt
* some cleanups
* fix(ux): allow alt-right-click on the web client without opening the context menu
* fix: prevent attaching to welcome screen
* fix: reload config issues
* fix long socket path on macos
* normalize config conversion and fix color gap in browser
* revoke session_token cookie if it is not valid
* fix: visual bug with multiple clients in extremely small screen sizes
* fix: only include rusqlite for the web server capability builds
* update e2e snapshots
* refactor(web): client side js
* some cleanups
* moar cleanups
* fix(tests): wait for server instead of using a fixed timeout
* debug CI
* fix(tests): use spawn_blocking for running the test web server
* fix(tests): wait for http rather than tcp port
* fix(tests): properly pass config path - hopefully this is the issue...
* success! bring back the rest of the tests
* attempt to fix the macos CI issue
* docs(changelog): add PR
---------
Co-authored-by: Thomas Linford <linford.t@gmail.com>
Diffstat (limited to 'zellij-utils/src/plugin_api')
| -rw-r--r-- | zellij-utils/src/plugin_api/event.proto | 43 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/event.rs | 154 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_command.proto | 74 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_command.rs | 164 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_permission.proto | 3 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_permission.rs | 2 |
6 files changed, 414 insertions, 26 deletions
diff --git a/zellij-utils/src/plugin_api/event.proto b/zellij-utils/src/plugin_api/event.proto index 760aee0b..52c1801c 100644 --- a/zellij-utils/src/plugin_api/event.proto +++ b/zellij-utils/src/plugin_api/event.proto @@ -54,8 +54,10 @@ enum EventType { FailedToChangeHostFolder = 28; PastedText = 29; ConfigWasWrittenToDisk = 30; - BeforeClose = 31; - InterceptedKeyPress = 32; + WebServerStatus = 31; + BeforeClose = 32; + FailedToStartWebServer = 34; + InterceptedKeyPress = 35; } message EventNameList { @@ -90,14 +92,31 @@ message Event { HostFolderChangedPayload host_folder_changed_payload = 24; FailedToChangeHostFolderPayload failed_to_change_host_folder_payload = 25; PastedTextPayload pasted_text_payload = 26; - key.Key intercepted_key_payload = 27; + WebServerStatusPayload web_server_status_payload = 27; + FailedToStartWebServerPayload failed_to_start_web_server_payload = 28; + key.Key intercepted_key_payload = 29; } } +message FailedToStartWebServerPayload { + string error = 1; +} + message PastedTextPayload { string pasted_text = 1; } +enum WebServerStatusIndication { + Online = 0; + Offline = 1; + DifferentVersion = 2; +} + +message WebServerStatusPayload { + WebServerStatusIndication web_server_status_indication = 1; + optional string payload = 2; +} + message FailedToChangeHostFolderPayload { optional string error_message = 1; } @@ -260,7 +279,9 @@ message SessionManifest { bool is_current_session = 5; repeated LayoutInfo available_layouts = 6; repeated PluginInfo plugins = 7; - repeated ClientTabHistory tab_history = 8; + bool web_clients_allowed = 8; + uint32 web_client_count = 9; + repeated ClientTabHistory tab_history = 10; } message ClientTabHistory { @@ -343,7 +364,19 @@ message ModeUpdatePayload { optional input_mode.InputMode base_mode = 6; optional string editor = 7; optional string shell = 8; - optional bool currently_marking_pane_group = 9; + optional bool web_clients_allowed = 9; + optional WebSharing web_sharing = 10; + optional bool currently_marking_pane_group = 11; + optional bool is_web_client = 12; + optional string web_server_ip = 13; + optional uint32 web_server_port = 14; + optional bool web_server_capability = 15; +} + +enum WebSharing { + On = 0; + Off = 1; + Disabled = 2; } message InputModeKeybinds { diff --git a/zellij-utils/src/plugin_api/event.rs b/zellij-utils/src/plugin_api/event.rs index a853e12d..e363b86c 100644 --- a/zellij-utils/src/plugin_api/event.rs +++ b/zellij-utils/src/plugin_api/event.rs @@ -10,7 +10,9 @@ pub use super::generated_api::api::{ PaneId as ProtobufPaneId, PaneInfo as ProtobufPaneInfo, PaneManifest as ProtobufPaneManifest, PaneType as ProtobufPaneType, PluginInfo as ProtobufPluginInfo, ResurrectableSession as ProtobufResurrectableSession, - SessionManifest as ProtobufSessionManifest, TabInfo as ProtobufTabInfo, *, + SessionManifest as ProtobufSessionManifest, TabInfo as ProtobufTabInfo, + WebServerStatusPayload as ProtobufWebServerStatusPayload, WebSharing as ProtobufWebSharing, + *, }, input_mode::InputMode as ProtobufInputMode, key::Key as ProtobufKey, @@ -20,7 +22,7 @@ pub use super::generated_api::api::{ use crate::data::{ ClientInfo, CopyDestination, Event, EventType, FileMetadata, InputMode, KeyWithModifier, LayoutInfo, ModeInfo, Mouse, PaneId, PaneInfo, PaneManifest, PermissionStatus, - PluginCapabilities, PluginInfo, SessionInfo, Style, TabInfo, + PluginCapabilities, PluginInfo, SessionInfo, Style, TabInfo, WebServerStatus, WebSharing, }; use crate::errors::prelude::*; @@ -28,7 +30,9 @@ use crate::input::actions::Action; use std::collections::{BTreeMap, HashMap, HashSet}; use std::convert::TryFrom; +use std::net::IpAddr; use std::path::PathBuf; +use std::str::FromStr; use std::time::Duration; impl TryFrom<ProtobufEvent> for Event { @@ -359,10 +363,24 @@ impl TryFrom<ProtobufEvent> for Event { None => Ok(Event::ConfigWasWrittenToDisk), _ => Err("Malformed payload for the ConfigWasWrittenToDisk Event"), }, + Some(ProtobufEventType::WebServerStatus) => match protobuf_event.payload { + Some(ProtobufEventPayload::WebServerStatusPayload(web_server_status)) => { + Ok(Event::WebServerStatus(web_server_status.try_into()?)) + }, + _ => Err("Malformed payload for the WebServerStatus Event"), + }, Some(ProtobufEventType::BeforeClose) => match protobuf_event.payload { None => Ok(Event::BeforeClose), _ => Err("Malformed payload for the BeforeClose Event"), }, + Some(ProtobufEventType::FailedToStartWebServer) => match protobuf_event.payload { + Some(ProtobufEventPayload::FailedToStartWebServerPayload( + failed_to_start_web_server_payload, + )) => Ok(Event::FailedToStartWebServer( + failed_to_start_web_server_payload.error, + )), + _ => Err("Malformed payload for the FailedToStartWebServer Event"), + }, Some(ProtobufEventType::InterceptedKeyPress) => match protobuf_event.payload { Some(ProtobufEventPayload::KeyPayload(protobuf_key)) => { Ok(Event::InterceptedKeyPress(protobuf_key.try_into()?)) @@ -743,10 +761,22 @@ impl TryFrom<Event> for ProtobufEvent { name: ProtobufEventType::ConfigWasWrittenToDisk as i32, payload: None, }), + Event::WebServerStatus(web_server_status) => Ok(ProtobufEvent { + name: ProtobufEventType::WebServerStatus as i32, + payload: Some(event::Payload::WebServerStatusPayload( + ProtobufWebServerStatusPayload::try_from(web_server_status)?, + )), + }), Event::BeforeClose => Ok(ProtobufEvent { name: ProtobufEventType::BeforeClose as i32, payload: None, }), + Event::FailedToStartWebServer(error) => Ok(ProtobufEvent { + name: ProtobufEventType::FailedToStartWebServer as i32, + payload: Some(event::Payload::FailedToStartWebServerPayload( + FailedToStartWebServerPayload { error }, + )), + }), Event::InterceptedKeyPress(key) => Ok(ProtobufEvent { name: ProtobufEventType::InterceptedKeyPress as i32, payload: Some(event::Payload::KeyPayload(key.try_into()?)), @@ -789,6 +819,8 @@ impl TryFrom<SessionInfo> for ProtobufSessionManifest { .into_iter() .map(|p| ProtobufPluginInfo::from(p)) .collect(), + web_clients_allowed: session_info.web_clients_allowed, + web_client_count: session_info.web_client_count as u32, tab_history: session_info .tab_history .into_iter() @@ -878,6 +910,8 @@ impl TryFrom<ProtobufSessionManifest> for SessionInfo { .filter_map(|l| LayoutInfo::try_from(l).ok()) .collect(), plugins, + web_clients_allowed: protobuf_session_manifest.web_clients_allowed, + web_client_count: protobuf_session_manifest.web_client_count as usize, tab_history, }) } @@ -1249,11 +1283,29 @@ impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo { .editor .map(|e| PathBuf::from(e)); let shell = protobuf_mode_update_payload.shell.map(|s| PathBuf::from(s)); + let web_clients_allowed = protobuf_mode_update_payload.web_clients_allowed; + let web_sharing = protobuf_mode_update_payload + .web_sharing + .and_then(|w| ProtobufWebSharing::from_i32(w)) + .map(|w| w.into()); let capabilities = PluginCapabilities { arrow_fonts: protobuf_mode_update_payload.arrow_fonts_support, }; let currently_marking_pane_group = protobuf_mode_update_payload.currently_marking_pane_group; + let is_web_client = protobuf_mode_update_payload.is_web_client; + + let web_server_ip = protobuf_mode_update_payload + .web_server_ip + .as_ref() + .and_then(|web_server_ip| IpAddr::from_str(web_server_ip).ok()); + + let web_server_port = protobuf_mode_update_payload + .web_server_port + .map(|w| w as u16); + + let web_server_capability = protobuf_mode_update_payload.web_server_capability; + let mode_info = ModeInfo { mode: current_mode, keybinds, @@ -1263,7 +1315,13 @@ impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo { base_mode, editor, shell, + web_clients_allowed, + web_sharing, currently_marking_pane_group, + is_web_client, + web_server_ip, + web_server_port, + web_server_capability, }; Ok(mode_info) } @@ -1281,7 +1339,13 @@ impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload { let session_name = mode_info.session_name; let editor = mode_info.editor.map(|e| e.display().to_string()); let shell = mode_info.shell.map(|s| s.display().to_string()); + let web_clients_allowed = mode_info.web_clients_allowed; + let web_sharing = mode_info.web_sharing.map(|w| w as i32); let currently_marking_pane_group = mode_info.currently_marking_pane_group; + let is_web_client = mode_info.is_web_client; + let web_server_ip = mode_info.web_server_ip.map(|i| format!("{}", i)); + let web_server_port = mode_info.web_server_port.map(|p| p as u32); + let web_server_capability = mode_info.web_server_capability; let mut protobuf_input_mode_keybinds: Vec<ProtobufInputModeKeybinds> = vec![]; for (input_mode, input_mode_keybinds) in mode_info.keybinds { let mode: ProtobufInputMode = input_mode.try_into()?; @@ -1315,7 +1379,13 @@ impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload { base_mode: base_mode.map(|b_m| b_m as i32), editor, shell, + web_clients_allowed, + web_sharing, currently_marking_pane_group, + is_web_client, + web_server_ip, + web_server_port, + web_server_capability, }) } } @@ -1385,7 +1455,9 @@ impl TryFrom<ProtobufEventType> for EventType { ProtobufEventType::FailedToChangeHostFolder => EventType::FailedToChangeHostFolder, ProtobufEventType::PastedText => EventType::PastedText, ProtobufEventType::ConfigWasWrittenToDisk => EventType::ConfigWasWrittenToDisk, + ProtobufEventType::WebServerStatus => EventType::WebServerStatus, ProtobufEventType::BeforeClose => EventType::BeforeClose, + ProtobufEventType::FailedToStartWebServer => EventType::FailedToStartWebServer, ProtobufEventType::InterceptedKeyPress => EventType::InterceptedKeyPress, }) } @@ -1426,7 +1498,9 @@ impl TryFrom<EventType> for ProtobufEventType { EventType::FailedToChangeHostFolder => ProtobufEventType::FailedToChangeHostFolder, EventType::PastedText => ProtobufEventType::PastedText, EventType::ConfigWasWrittenToDisk => ProtobufEventType::ConfigWasWrittenToDisk, + EventType::WebServerStatus => ProtobufEventType::WebServerStatus, EventType::BeforeClose => ProtobufEventType::BeforeClose, + EventType::FailedToStartWebServer => ProtobufEventType::FailedToStartWebServer, EventType::InterceptedKeyPress => ProtobufEventType::InterceptedKeyPress, }) } @@ -1568,7 +1642,13 @@ fn serialize_mode_update_event_with_non_default_values() { base_mode: Some(InputMode::Locked), editor: Some(PathBuf::from("my_awesome_editor")), shell: Some(PathBuf::from("my_awesome_shell")), + web_clients_allowed: Some(true), + web_sharing: Some(WebSharing::default()), currently_marking_pane_group: Some(false), + is_web_client: Some(false), + web_server_ip: IpAddr::from_str("127.0.0.1").ok(), + web_server_port: Some(8082), + web_server_capability: Some(true), }); let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap(); let serialized_protobuf_event = protobuf_event.encode_to_vec(); @@ -2016,6 +2096,8 @@ fn serialize_session_update_event_with_non_default_values() { LayoutInfo::File("layout3".to_owned()), ], plugins, + web_clients_allowed: false, + web_client_count: 1, tab_history, }; let session_info_2 = SessionInfo { @@ -2032,6 +2114,8 @@ fn serialize_session_update_event_with_non_default_values() { LayoutInfo::File("layout3".to_owned()), ], plugins: Default::default(), + web_clients_allowed: false, + web_client_count: 0, tab_history: Default::default(), }; let session_infos = vec![session_info_1, session_info_2]; @@ -2081,3 +2165,69 @@ impl TryFrom<PaneId> for ProtobufPaneId { } } } + +impl Into<ProtobufWebSharing> for WebSharing { + fn into(self) -> ProtobufWebSharing { + match self { + WebSharing::On => ProtobufWebSharing::On, + WebSharing::Off => ProtobufWebSharing::Off, + WebSharing::Disabled => ProtobufWebSharing::Disabled, + } + } +} + +impl Into<WebSharing> for ProtobufWebSharing { + fn into(self) -> WebSharing { + match self { + ProtobufWebSharing::On => WebSharing::On, + ProtobufWebSharing::Off => WebSharing::Off, + ProtobufWebSharing::Disabled => WebSharing::Disabled, + } + } +} + +impl TryFrom<WebServerStatus> for ProtobufWebServerStatusPayload { + type Error = &'static str; + fn try_from(web_server_status: WebServerStatus) -> Result<Self, &'static str> { + match web_server_status { + WebServerStatus::Online(url) => Ok(ProtobufWebServerStatusPayload { + web_server_status_indication: WebServerStatusIndication::Online as i32, + payload: Some(url), + }), + WebServerStatus::DifferentVersion(version) => Ok(ProtobufWebServerStatusPayload { + web_server_status_indication: WebServerStatusIndication::DifferentVersion as i32, + payload: Some(format!("{}", version)), + }), + WebServerStatus::Offline => Ok(ProtobufWebServerStatusPayload { + web_server_status_indication: WebServerStatusIndication::Offline as i32, + payload: None, + }), + } + } +} + +impl TryFrom<ProtobufWebServerStatusPayload> for WebServerStatus { + type Error = &'static str; + fn try_from( + protobuf_web_server_status: ProtobufWebServerStatusPayload, + ) -> Result<Self, &'static str> { + match WebServerStatusIndication::from_i32( + protobuf_web_server_status.web_server_status_indication, + ) { + Some(WebServerStatusIndication::Online) => { + let payload = protobuf_web_server_status + .payload + .ok_or("payload_not_found")?; + Ok(WebServerStatus::Online(payload)) + }, + Some(WebServerStatusIndication::DifferentVersion) => { + let payload = protobuf_web_server_status + .payload + .ok_or("payload_not_found")?; + Ok(WebServerStatus::DifferentVersion(payload)) + }, + Some(WebServerStatusIndication::Offline) => Ok(WebServerStatus::Offline), + None => Err("Unknown status"), + } + } +} diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto index b8b6bad1..4c1db71f 100644 --- a/zellij-utils/src/plugin_api/plugin_command.proto +++ b/zellij-utils/src/plugin_api/plugin_command.proto @@ -140,13 +140,24 @@ enum CommandName { OpenFileNearPlugin = 124; OpenFileFloatingNearPlugin = 125; OpenFileInPlaceOfPlugin = 126; - GroupAndUngroupPanes = 127; - HighlightAndUnhighlightPanes = 128; - CloseMultiplePanes = 129; - FloatMultiplePanes = 130; - EmbedMultiplePanes = 131; - InterceptKeyPresses = 132; - ClearKeyPressesIntercepts = 133; + StartWebServer = 127; + GroupAndUngroupPanes = 128; + HighlightAndUnhighlightPanes = 129; + CloseMultiplePanes = 130; + FloatMultiplePanes = 131; + EmbedMultiplePanes = 132; + ShareCurrentSession = 133; + StopSharingCurrentSession = 134; + StopWebServer = 135; + QueryWebServerStatus = 136; + SetSelfMouseSelectionSupport = 137; + GenerateWebLoginToken = 138; + RevokeWebLoginToken = 139; + ListWebLoginTokens = 140; + RevokeAllWebLoginTokens = 141; + RenameWebLoginToken = 142; + InterceptKeyPresses = 143; + ClearKeyPressesIntercepts = 144; } message PluginCommand { @@ -248,9 +259,30 @@ message PluginCommand { CloseMultiplePanesPayload close_multiple_panes_payload = 104; FloatMultiplePanesPayload float_multiple_panes_payload = 105; EmbedMultiplePanesPayload embed_multiple_panes_payload = 106; + SetSelfMouseSelectionSupportPayload set_self_mouse_selection_support_payload = 107; + GenerateWebLoginTokenPayload generate_web_login_token_payload = 108; + RevokeWebLoginTokenPayload revoke_web_login_token_payload = 109; + RenameWebLoginTokenPayload rename_web_login_token_payload = 110; } } +message RenameWebLoginTokenPayload { + string old_name = 1; + string new_name = 2; +} + +message RevokeWebLoginTokenPayload { + string token_label = 1; +} + +message GenerateWebLoginTokenPayload { + optional string token_label = 1; +} + +message SetSelfMouseSelectionSupportPayload { + bool support_mouse_selection = 1; +} + message EmbedMultiplePanesPayload { repeated PaneId pane_ids = 1; } @@ -628,3 +660,31 @@ enum FixedOrPercent { Fixed = 0; Percent = 1; } + +message CreateTokenResponse { + optional string token = 1; + optional string token_label = 2; + optional string error = 3; +} + +message RevokeTokenResponse { + bool successfully_revoked = 1; + optional string error = 2; +} + +message ListTokensResponse { + // tokens/creation_times should be synchronized + repeated string tokens = 1; + repeated string creation_times = 2; + optional string error = 3; +} + +message RevokeAllWebTokensResponse { + bool successfully_revoked = 1; + optional string error = 2; +} + +message RenameWebTokenResponse { + bool successfully_renamed = 1; + optional string error = 2; +} diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs index 30a6a03d..7fb583b7 100644 --- a/zellij-utils/src/plugin_api/plugin_command.rs +++ b/zellij-utils/src/plugin_api/plugin_command.rs @@ -6,15 +6,17 @@ pub use super::generated_api::api::{ plugin_command::Payload, BreakPanesToNewTabPayload, BreakPanesToTabWithIndexPayload, ChangeFloatingPanesCoordinatesPayload, ChangeHostFolderPayload, ClearScreenForPaneIdPayload, CliPipeOutputPayload, CloseMultiplePanesPayload, - CloseTabWithIndexPayload, CommandName, ContextItem, EditScrollbackForPaneWithIdPayload, - EmbedMultiplePanesPayload, EnvVariable, ExecCmdPayload, + CloseTabWithIndexPayload, CommandName, ContextItem, + CreateTokenResponse as ProtobufCreateTokenResponse, CreateTokenResponse, + EditScrollbackForPaneWithIdPayload, EmbedMultiplePanesPayload, EnvVariable, ExecCmdPayload, FixedOrPercent as ProtobufFixedOrPercent, FixedOrPercentValue as ProtobufFixedOrPercentValue, FloatMultiplePanesPayload, - FloatingPaneCoordinates as ProtobufFloatingPaneCoordinates, GroupAndUngroupPanesPayload, - HidePaneWithIdPayload, HighlightAndUnhighlightPanesPayload, HttpVerb as ProtobufHttpVerb, - IdAndNewName, KeyToRebind, KeyToUnbind, KillSessionsPayload, LoadNewPluginPayload, - MessageToPluginPayload, MovePaneWithPaneIdInDirectionPayload, MovePaneWithPaneIdPayload, - MovePayload, NewPluginArgs as ProtobufNewPluginArgs, NewTabsWithLayoutInfoPayload, + FloatingPaneCoordinates as ProtobufFloatingPaneCoordinates, GenerateWebLoginTokenPayload, + GroupAndUngroupPanesPayload, HidePaneWithIdPayload, HighlightAndUnhighlightPanesPayload, + HttpVerb as ProtobufHttpVerb, IdAndNewName, KeyToRebind, KeyToUnbind, KillSessionsPayload, + ListTokensResponse, LoadNewPluginPayload, MessageToPluginPayload, + MovePaneWithPaneIdInDirectionPayload, MovePaneWithPaneIdPayload, MovePayload, + NewPluginArgs as ProtobufNewPluginArgs, NewTabsWithLayoutInfoPayload, OpenCommandPaneFloatingNearPluginPayload, OpenCommandPaneInPlaceOfPluginPayload, OpenCommandPaneNearPluginPayload, OpenCommandPanePayload, OpenFileFloatingNearPluginPayload, OpenFileInPlaceOfPluginPayload, @@ -23,10 +25,12 @@ pub use super::generated_api::api::{ PageScrollDownInPaneIdPayload, PageScrollUpInPaneIdPayload, PaneId as ProtobufPaneId, PaneIdAndFloatingPaneCoordinates, PaneType as ProtobufPaneType, PluginCommand as ProtobufPluginCommand, PluginMessagePayload, RebindKeysPayload, - ReconfigurePayload, ReloadPluginPayload, RequestPluginPermissionPayload, - RerunCommandPanePayload, ResizePaneIdWithDirectionPayload, ResizePayload, - RunCommandPayload, ScrollDownInPaneIdPayload, ScrollToBottomInPaneIdPayload, - ScrollToTopInPaneIdPayload, ScrollUpInPaneIdPayload, SetFloatingPanePinnedPayload, + ReconfigurePayload, ReloadPluginPayload, RenameWebLoginTokenPayload, + RenameWebTokenResponse, RequestPluginPermissionPayload, RerunCommandPanePayload, + ResizePaneIdWithDirectionPayload, ResizePayload, RevokeAllWebTokensResponse, + RevokeTokenResponse, RevokeWebLoginTokenPayload, RunCommandPayload, + ScrollDownInPaneIdPayload, ScrollToBottomInPaneIdPayload, ScrollToTopInPaneIdPayload, + ScrollUpInPaneIdPayload, SetFloatingPanePinnedPayload, SetSelfMouseSelectionSupportPayload, SetTimeoutPayload, ShowPaneWithIdPayload, StackPanesPayload, SubscribePayload, SwitchSessionPayload, SwitchTabToPayload, TogglePaneEmbedOrEjectForPaneIdPayload, TogglePaneIdFullscreenPayload, UnsubscribePayload, WebRequestPayload, @@ -1545,6 +1549,27 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { }, _ => Err("Mismatched payload for OpenFileInPlaceOfPlugin"), }, + Some(CommandName::StartWebServer) => { + if protobuf_plugin_command.payload.is_some() { + Err("StartWebServer should not have a payload") + } else { + Ok(PluginCommand::StartWebServer) + } + }, + Some(CommandName::StopWebServer) => { + if protobuf_plugin_command.payload.is_some() { + Err("StopWebServer should not have a payload") + } else { + Ok(PluginCommand::StopWebServer) + } + }, + Some(CommandName::QueryWebServerStatus) => { + if protobuf_plugin_command.payload.is_some() { + Err("QueryWebServerStatus should not have a payload") + } else { + Ok(PluginCommand::QueryWebServerStatus) + } + }, Some(CommandName::GroupAndUngroupPanes) => match protobuf_plugin_command.payload { Some(Payload::GroupAndUngroupPanesPayload(group_and_ungroup_panes_payload)) => { Ok(PluginCommand::GroupAndUngroupPanes( @@ -1617,6 +1642,67 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { }, _ => Err("Mismatched payload for EmbedMultiplePanes"), }, + Some(CommandName::ShareCurrentSession) => { + if protobuf_plugin_command.payload.is_some() { + Err("ShareCurrentSession should not have a payload") + } else { + Ok(PluginCommand::ShareCurrentSession) + } + }, + Some(CommandName::StopSharingCurrentSession) => { + if protobuf_plugin_command.payload.is_some() { + Err("StopSharingCurrentSession should not have a payload") + } else { + Ok(PluginCommand::StopSharingCurrentSession) + } + }, + Some(CommandName::SetSelfMouseSelectionSupport) => { + match protobuf_plugin_command.payload { + Some(Payload::SetSelfMouseSelectionSupportPayload( + set_self_mouse_selection_support_payload, + )) => Ok(PluginCommand::SetSelfMouseSelectionSupport( + set_self_mouse_selection_support_payload.support_mouse_selection, + )), + _ => Err("SetSelfMouseSelectionSupport requires a payload"), + } + }, + Some(CommandName::GenerateWebLoginToken) => match protobuf_plugin_command.payload { + Some(Payload::GenerateWebLoginTokenPayload(generate_web_login_token_payload)) => { + Ok(PluginCommand::GenerateWebLoginToken( + generate_web_login_token_payload.token_label, + )) + }, + _ => Err("GenerateWebLoginToken requires a payload"), + }, + Some(CommandName::RevokeWebLoginToken) => match protobuf_plugin_command.payload { + Some(Payload::RevokeWebLoginTokenPayload(revoke_web_login_token_payload)) => Ok( + PluginCommand::RevokeWebLoginToken(revoke_web_login_token_payload.token_label), + ), + _ => Err("RevokeWebLoginToken requires a payload"), + }, + Some(CommandName::ListWebLoginTokens) => { + if protobuf_plugin_command.payload.is_some() { + Err("ListWebLoginTokens should not have a payload") + } else { + Ok(PluginCommand::ListWebLoginTokens) + } + }, + Some(CommandName::RevokeAllWebLoginTokens) => { + if protobuf_plugin_command.payload.is_some() { + Err("RevokeAllWebLoginTokens should not have a payload") + } else { + Ok(PluginCommand::RevokeAllWebLoginTokens) + } + }, + Some(CommandName::RenameWebLoginToken) => match protobuf_plugin_command.payload { + Some(Payload::RenameWebLoginTokenPayload(rename_web_login_token_payload)) => { + Ok(PluginCommand::RenameWebLoginToken( + rename_web_login_token_payload.old_name, + rename_web_login_token_payload.new_name, + )) + }, + _ => Err("RenameWebLoginToken requires a payload"), + }, Some(CommandName::InterceptKeyPresses) => match protobuf_plugin_command.payload { Some(_) => Err("InterceptKeyPresses should have no payload, found a payload"), None => Ok(PluginCommand::InterceptKeyPresses), @@ -2656,6 +2742,18 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { )), }) }, + PluginCommand::StartWebServer => Ok(ProtobufPluginCommand { + name: CommandName::StartWebServer as i32, + payload: None, + }), + PluginCommand::StopWebServer => Ok(ProtobufPluginCommand { + name: CommandName::StopWebServer as i32, + payload: None, + }), + PluginCommand::QueryWebServerStatus => Ok(ProtobufPluginCommand { + name: CommandName::QueryWebServerStatus as i32, + payload: None, + }), PluginCommand::HighlightAndUnhighlightPanes( panes_to_highlight, panes_to_unhighlight, @@ -2698,6 +2796,50 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { }, )), }), + PluginCommand::ShareCurrentSession => Ok(ProtobufPluginCommand { + name: CommandName::ShareCurrentSession as i32, + payload: None, + }), + PluginCommand::StopSharingCurrentSession => Ok(ProtobufPluginCommand { + name: CommandName::StopSharingCurrentSession as i32, + payload: None, + }), + PluginCommand::SetSelfMouseSelectionSupport(support_mouse_selection) => { + Ok(ProtobufPluginCommand { + name: CommandName::SetSelfMouseSelectionSupport as i32, + payload: Some(Payload::SetSelfMouseSelectionSupportPayload( + SetSelfMouseSelectionSupportPayload { + support_mouse_selection, + }, + )), + }) + }, + PluginCommand::GenerateWebLoginToken(token_label) => Ok(ProtobufPluginCommand { + name: CommandName::GenerateWebLoginToken as i32, + payload: Some(Payload::GenerateWebLoginTokenPayload( + GenerateWebLoginTokenPayload { token_label }, + )), + }), + PluginCommand::RevokeWebLoginToken(token_label) => Ok(ProtobufPluginCommand { + name: CommandName::RevokeWebLoginToken as i32, + payload: Some(Payload::RevokeWebLoginTokenPayload( + RevokeWebLoginTokenPayload { token_label }, + )), + }), + PluginCommand::ListWebLoginTokens => Ok(ProtobufPluginCommand { + name: CommandName::ListWebLoginTokens as i32, + payload: None, + }), + PluginCommand::RevokeAllWebLoginTokens => Ok(ProtobufPluginCommand { + name: CommandName::RevokeAllWebLoginTokens as i32, + payload: None, + }), + PluginCommand::RenameWebLoginToken(old_name, new_name) => Ok(ProtobufPluginCommand { + name: CommandName::RenameWebLoginToken as i32, + payload: Some(Payload::RenameWebLoginTokenPayload( + RenameWebLoginTokenPayload { old_name, new_name }, + )), + }), PluginCommand::InterceptKeyPresses => Ok(ProtobufPluginCommand { name: CommandName::InterceptKeyPresses as i32, payload: None, diff --git a/zellij-utils/src/plugin_api/plugin_permission.proto b/zellij-utils/src/plugin_api/plugin_permission.proto index 72c5b0f9..0f53bb55 100644 --- a/zellij-utils/src/plugin_api/plugin_permission.proto +++ b/zellij-utils/src/plugin_api/plugin_permission.proto @@ -14,5 +14,6 @@ enum PermissionType { MessageAndLaunchOtherPlugins = 8; Reconfigure = 9; FullHdAccess = 10; - InterceptInput = 11; + StartWebServer = 11; + InterceptInput = 12; } diff --git a/zellij-utils/src/plugin_api/plugin_permission.rs b/zellij-utils/src/plugin_api/plugin_permission.rs index ad64b499..926f993f 100644 --- a/zellij-utils/src/plugin_api/plugin_permission.rs +++ b/zellij-utils/src/plugin_api/plugin_permission.rs @@ -26,6 +26,7 @@ impl TryFrom<ProtobufPermissionType> for PermissionType { }, ProtobufPermissionType::Reconfigure => Ok(PermissionType::Reconfigure), ProtobufPermissionType::FullHdAccess => Ok(PermissionType::FullHdAccess), + ProtobufPermissionType::StartWebServer => Ok(PermissionType::StartWebServer), ProtobufPermissionType::InterceptInput => Ok(PermissionType::InterceptInput), } } @@ -54,6 +55,7 @@ impl TryFrom<PermissionType> for ProtobufPermissionType { }, PermissionType::Reconfigure => Ok(ProtobufPermissionType::Reconfigure), PermissionType::FullHdAccess => Ok(ProtobufPermissionType::FullHdAccess), + PermissionType::StartWebServer => Ok(ProtobufPermissionType::StartWebServer), PermissionType::InterceptInput => Ok(ProtobufPermissionType::InterceptInput), } } |
