v1.2.0
Co-Authored-By: Quentin Torroba <quentin.torroba@mistral.ai> Co-Authored-By: Michel Thomazo <michel.thomazo@mistral.ai> Co-Authored-By: Kracekumar <kracethekingmaker@gmail.com>
This commit is contained in:
parent
661588de0c
commit
d8dbeeb31e
91 changed files with 4521 additions and 873 deletions
|
|
@ -5,7 +5,7 @@ import sys
|
|||
from rich import print as rprint
|
||||
from textual.app import App
|
||||
|
||||
from vibe.core.config_path import GLOBAL_ENV_FILE
|
||||
from vibe.core.paths.global_paths import GLOBAL_ENV_FILE
|
||||
from vibe.setup.onboarding.screens import (
|
||||
ApiKeyScreen,
|
||||
ThemeSelectionScreen,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ from textual.widgets import Input, Link, Static
|
|||
|
||||
from vibe.cli.clipboard import copy_selection_to_clipboard
|
||||
from vibe.core.config import VibeConfig
|
||||
from vibe.core.config_path import GLOBAL_ENV_FILE
|
||||
from vibe.core.paths.global_paths import GLOBAL_ENV_FILE
|
||||
from vibe.setup.onboarding.base import OnboardingScreen
|
||||
|
||||
PROVIDER_HELP = {
|
||||
|
|
|
|||
187
vibe/setup/trusted_folders/trust_folder_dialog.py
Normal file
187
vibe/setup/trusted_folders/trust_folder_dialog.py
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import tomllib
|
||||
from typing import Any, ClassVar
|
||||
|
||||
from textual import events
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.binding import Binding, BindingType
|
||||
from textual.containers import CenterMiddle, Horizontal
|
||||
from textual.message import Message
|
||||
from textual.widgets import Static
|
||||
|
||||
from vibe.core.paths.global_paths import GLOBAL_CONFIG_FILE, TRUSTED_FOLDERS_FILE
|
||||
|
||||
|
||||
class TrustDialogQuitException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class TrustFolderDialog(CenterMiddle):
|
||||
can_focus = True
|
||||
can_focus_children = True
|
||||
|
||||
BINDINGS: ClassVar[list[BindingType]] = [
|
||||
Binding("left", "move_left", "Left", show=False),
|
||||
Binding("right", "move_right", "Right", show=False),
|
||||
Binding("enter", "select", "Select", show=False),
|
||||
Binding("1", "select_1", "Yes", show=False),
|
||||
Binding("y", "select_1", "Yes", show=False),
|
||||
Binding("2", "select_2", "No", show=False),
|
||||
Binding("n", "select_2", "No", show=False),
|
||||
]
|
||||
|
||||
class Trusted(Message):
|
||||
pass
|
||||
|
||||
class Untrusted(Message):
|
||||
pass
|
||||
|
||||
def __init__(self, folder_path: Path, **kwargs: Any) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.folder_path = folder_path
|
||||
self.selected_option = 0
|
||||
self.option_widgets: list[Static] = []
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
with CenterMiddle(id="trust-dialog"):
|
||||
yield Static("⚠ Trust this folder?", id="trust-dialog-title")
|
||||
yield Static(
|
||||
str(self.folder_path),
|
||||
id="trust-dialog-path",
|
||||
classes="trust-dialog-path",
|
||||
)
|
||||
yield Static(
|
||||
"A .vibe/ directory was found here. Should Vibe load custom configuration and tools from it?",
|
||||
id="trust-dialog-message",
|
||||
classes="trust-dialog-message",
|
||||
)
|
||||
|
||||
with Horizontal(id="trust-options-container"):
|
||||
options = ["Yes", "No"]
|
||||
for idx, text in enumerate(options):
|
||||
widget = Static(f" {idx + 1}. {text}", classes="trust-option")
|
||||
self.option_widgets.append(widget)
|
||||
yield widget
|
||||
|
||||
yield Static("← → navigate Enter select", classes="trust-dialog-help")
|
||||
|
||||
yield Static(
|
||||
f"Setting will be saved in: {TRUSTED_FOLDERS_FILE.path}",
|
||||
id="trust-dialog-save-info",
|
||||
classes="trust-dialog-save-info",
|
||||
)
|
||||
|
||||
async def on_mount(self) -> None:
|
||||
self.selected_option = 1 # Default to "No"
|
||||
self._update_options()
|
||||
self.focus()
|
||||
|
||||
def _update_options(self) -> None:
|
||||
options = ["Yes", "No"]
|
||||
|
||||
if len(self.option_widgets) != len(options):
|
||||
return
|
||||
|
||||
for idx, (text, widget) in enumerate(
|
||||
zip(options, self.option_widgets, strict=True)
|
||||
):
|
||||
is_selected = idx == self.selected_option
|
||||
|
||||
cursor = "› " if is_selected else " "
|
||||
option_text = f"{cursor}{text}"
|
||||
|
||||
widget.update(option_text)
|
||||
|
||||
widget.remove_class("trust-cursor-selected")
|
||||
widget.remove_class("trust-option-selected")
|
||||
|
||||
if is_selected:
|
||||
widget.add_class("trust-cursor-selected")
|
||||
else:
|
||||
widget.add_class("trust-option-selected")
|
||||
|
||||
def action_move_left(self) -> None:
|
||||
self.selected_option = (self.selected_option - 1) % 2
|
||||
self._update_options()
|
||||
|
||||
def action_move_right(self) -> None:
|
||||
self.selected_option = (self.selected_option + 1) % 2
|
||||
self._update_options()
|
||||
|
||||
def action_select(self) -> None:
|
||||
self._handle_selection(self.selected_option)
|
||||
|
||||
def action_select_1(self) -> None:
|
||||
self.selected_option = 0
|
||||
self._handle_selection(0)
|
||||
|
||||
def action_select_2(self) -> None:
|
||||
self.selected_option = 1
|
||||
self._handle_selection(1)
|
||||
|
||||
def _handle_selection(self, option: int) -> None:
|
||||
match option:
|
||||
case 0:
|
||||
self.post_message(self.Trusted())
|
||||
case 1:
|
||||
self.post_message(self.Untrusted())
|
||||
|
||||
def on_blur(self, event: events.Blur) -> None:
|
||||
self.call_after_refresh(self.focus)
|
||||
|
||||
|
||||
class TrustFolderApp(App):
|
||||
CSS_PATH = "trust_folder_dialog.tcss"
|
||||
|
||||
BINDINGS: ClassVar[list[BindingType]] = [
|
||||
Binding("ctrl+q", "quit_without_saving", "Quit", show=False, priority=True),
|
||||
Binding("ctrl+c", "quit_without_saving", "Quit", show=False, priority=True),
|
||||
]
|
||||
|
||||
def __init__(self, folder_path: Path, **kwargs: Any) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.folder_path = folder_path
|
||||
self._result: bool | None = None
|
||||
self._quit_without_saving = False
|
||||
self._load_theme()
|
||||
|
||||
def _load_theme(self) -> None:
|
||||
config_file = GLOBAL_CONFIG_FILE.path
|
||||
if not config_file.is_file():
|
||||
return
|
||||
|
||||
try:
|
||||
with config_file.open("rb") as f:
|
||||
config_data = tomllib.load(f)
|
||||
if textual_theme := config_data.get("textual_theme"):
|
||||
self.theme = textual_theme
|
||||
except (OSError, tomllib.TOMLDecodeError, KeyError):
|
||||
pass
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield TrustFolderDialog(self.folder_path)
|
||||
|
||||
def action_quit_without_saving(self) -> None:
|
||||
self._quit_without_saving = True
|
||||
self.exit()
|
||||
|
||||
def on_trust_folder_dialog_trusted(self, _: TrustFolderDialog.Trusted) -> None:
|
||||
self._result = True
|
||||
self.exit()
|
||||
|
||||
def on_trust_folder_dialog_untrusted(self, _: TrustFolderDialog.Untrusted) -> None:
|
||||
self._result = False
|
||||
self.exit()
|
||||
|
||||
def run_trust_dialog(self) -> bool | None:
|
||||
self.run()
|
||||
if self._quit_without_saving:
|
||||
raise TrustDialogQuitException()
|
||||
return self._result
|
||||
|
||||
|
||||
def ask_trust_folder(folder_path: Path) -> bool | None:
|
||||
app = TrustFolderApp(folder_path)
|
||||
return app.run_trust_dialog()
|
||||
83
vibe/setup/trusted_folders/trust_folder_dialog.tcss
Normal file
83
vibe/setup/trusted_folders/trust_folder_dialog.tcss
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
Screen {
|
||||
align: center middle;
|
||||
background: $background 80%;
|
||||
}
|
||||
|
||||
#trust-dialog {
|
||||
width: 70;
|
||||
max-width: 90%;
|
||||
min-width: 50;
|
||||
height: auto;
|
||||
border: round $foreground-muted;
|
||||
background: $background;
|
||||
padding: 1;
|
||||
}
|
||||
|
||||
#trust-dialog-title {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
text-style: bold;
|
||||
color: $warning;
|
||||
text-align: center;
|
||||
margin-bottom: 1;
|
||||
}
|
||||
|
||||
#trust-dialog-path {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
color: $primary;
|
||||
text-align: center;
|
||||
text-wrap: wrap;
|
||||
margin-bottom: 1;
|
||||
}
|
||||
|
||||
#trust-dialog-message {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
color: $foreground;
|
||||
text-align: center;
|
||||
text-wrap: wrap;
|
||||
margin-bottom: 1;
|
||||
}
|
||||
|
||||
#trust-options-container {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
align: center middle;
|
||||
margin-bottom: 1;
|
||||
}
|
||||
|
||||
.trust-option {
|
||||
height: auto;
|
||||
width: auto;
|
||||
color: $foreground;
|
||||
margin: 0 3;
|
||||
content-align: center middle;
|
||||
}
|
||||
|
||||
.trust-cursor-selected {
|
||||
color: $foreground;
|
||||
text-style: bold;
|
||||
}
|
||||
|
||||
.trust-option-selected {
|
||||
color: $foreground;
|
||||
}
|
||||
|
||||
.trust-dialog-help {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
color: $text-muted;
|
||||
text-align: center;
|
||||
margin-bottom: 1;
|
||||
}
|
||||
|
||||
.trust-dialog-save-info {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
color: $text-muted;
|
||||
text-align: center;
|
||||
text-style: italic;
|
||||
text-wrap: wrap;
|
||||
margin-bottom: 1;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue