mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-28 13:26:16 +03:00
more general palette code, dedupe some main.rs code, start of branch switcher
This commit is contained in:
parent
01a5c572dc
commit
524591821a
@ -177,15 +177,7 @@ fn list_sessions(
|
|||||||
handle: tauri::AppHandle,
|
handle: tauri::AppHandle,
|
||||||
project_id: &str,
|
project_id: &str,
|
||||||
) -> Result<Vec<sessions::Session>, Error> {
|
) -> Result<Vec<sessions::Session>, Error> {
|
||||||
let app_state = handle.state::<App>();
|
let repo = repo_for_project(handle, project_id)?;
|
||||||
|
|
||||||
let repo = repositories::Repository::open(
|
|
||||||
&app_state.projects_storage,
|
|
||||||
&app_state.users_storage,
|
|
||||||
project_id,
|
|
||||||
)
|
|
||||||
.with_context(|| format!("Failed to open repository for project {}", project_id))?;
|
|
||||||
|
|
||||||
let sessions = repo
|
let sessions = repo
|
||||||
.sessions()
|
.sessions()
|
||||||
.with_context(|| format!("Failed to list sessions for project {}", project_id))?;
|
.with_context(|| format!("Failed to list sessions for project {}", project_id))?;
|
||||||
@ -338,16 +330,8 @@ fn list_session_files(
|
|||||||
session_id: &str,
|
session_id: &str,
|
||||||
paths: Option<Vec<&str>>,
|
paths: Option<Vec<&str>>,
|
||||||
) -> Result<HashMap<String, String>, Error> {
|
) -> Result<HashMap<String, String>, Error> {
|
||||||
let app_state = handle.state::<App>();
|
let repo = repo_for_project(handle, project_id)?;
|
||||||
|
|
||||||
let repo = repositories::Repository::open(
|
|
||||||
&app_state.projects_storage,
|
|
||||||
&app_state.users_storage,
|
|
||||||
project_id,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let files = repo.files(session_id, paths)?;
|
let files = repo.files(session_id, paths)?;
|
||||||
|
|
||||||
Ok(files)
|
Ok(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,16 +341,8 @@ fn list_deltas(
|
|||||||
project_id: &str,
|
project_id: &str,
|
||||||
session_id: &str,
|
session_id: &str,
|
||||||
) -> Result<HashMap<String, Vec<Delta>>, Error> {
|
) -> Result<HashMap<String, Vec<Delta>>, Error> {
|
||||||
let app_state = handle.state::<App>();
|
let repo = repo_for_project(handle, project_id)?;
|
||||||
|
|
||||||
let repo = repositories::Repository::open(
|
|
||||||
&app_state.projects_storage,
|
|
||||||
&app_state.users_storage,
|
|
||||||
project_id,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let deltas = repo.deltas(session_id)?;
|
let deltas = repo.deltas(session_id)?;
|
||||||
|
|
||||||
Ok(deltas)
|
Ok(deltas)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,29 +351,14 @@ fn git_status(
|
|||||||
handle: tauri::AppHandle,
|
handle: tauri::AppHandle,
|
||||||
project_id: &str,
|
project_id: &str,
|
||||||
) -> Result<HashMap<String, String>, Error> {
|
) -> Result<HashMap<String, String>, Error> {
|
||||||
let app_state = handle.state::<App>();
|
let repo = repo_for_project(handle, project_id)?;
|
||||||
|
|
||||||
let repo = repositories::Repository::open(
|
|
||||||
&app_state.projects_storage,
|
|
||||||
&app_state.users_storage,
|
|
||||||
project_id,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let files = repo.status().with_context(|| "Failed to get git status")?;
|
let files = repo.status().with_context(|| "Failed to get git status")?;
|
||||||
|
|
||||||
Ok(files)
|
Ok(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn git_file_paths(handle: tauri::AppHandle, project_id: &str) -> Result<Vec<String>, Error> {
|
fn git_file_paths(handle: tauri::AppHandle, project_id: &str) -> Result<Vec<String>, Error> {
|
||||||
let app_state = handle.state::<App>();
|
let repo = repo_for_project(handle, project_id)?;
|
||||||
|
|
||||||
let repo = repositories::Repository::open(
|
|
||||||
&app_state.projects_storage,
|
|
||||||
&app_state.users_storage,
|
|
||||||
project_id,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let files = repo
|
let files = repo
|
||||||
.file_paths()
|
.file_paths()
|
||||||
.with_context(|| "Failed to get file paths")?;
|
.with_context(|| "Failed to get file paths")?;
|
||||||
@ -411,6 +372,18 @@ fn git_match_paths(
|
|||||||
project_id: &str,
|
project_id: &str,
|
||||||
match_pattern: &str,
|
match_pattern: &str,
|
||||||
) -> Result<Vec<String>, Error> {
|
) -> Result<Vec<String>, Error> {
|
||||||
|
let repo = repo_for_project(handle, project_id)?;
|
||||||
|
let files = repo
|
||||||
|
.match_file_paths(match_pattern)
|
||||||
|
.with_context(|| "Failed to get file paths")?;
|
||||||
|
|
||||||
|
Ok(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn repo_for_project(
|
||||||
|
handle: tauri::AppHandle,
|
||||||
|
project_id: &str,
|
||||||
|
) -> Result<repositories::Repository, Error> {
|
||||||
let app_state = handle.state::<App>();
|
let app_state = handle.state::<App>();
|
||||||
|
|
||||||
let repo = repositories::Repository::open(
|
let repo = repositories::Repository::open(
|
||||||
@ -419,10 +392,15 @@ fn git_match_paths(
|
|||||||
project_id,
|
project_id,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let files = repo
|
Ok(repo)
|
||||||
.match_file_paths(match_pattern)
|
}
|
||||||
.with_context(|| "Failed to get file paths")?;
|
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
fn git_branches(handle: tauri::AppHandle, project_id: &str) -> Result<Vec<String>, Error> {
|
||||||
|
let repo = repo_for_project(handle, project_id)?;
|
||||||
|
let files = repo
|
||||||
|
.branches()
|
||||||
|
.with_context(|| "Failed to get file paths")?;
|
||||||
Ok(files)
|
Ok(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,14 +412,7 @@ fn git_commit(
|
|||||||
files: Vec<&str>,
|
files: Vec<&str>,
|
||||||
push: bool,
|
push: bool,
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error> {
|
||||||
let app_state = handle.state::<App>();
|
let repo = repo_for_project(handle, project_id)?;
|
||||||
|
|
||||||
let repo = repositories::Repository::open(
|
|
||||||
&app_state.projects_storage,
|
|
||||||
&app_state.users_storage,
|
|
||||||
project_id,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let success = repo
|
let success = repo
|
||||||
.commit(message, files, push)
|
.commit(message, files, push)
|
||||||
.with_context(|| "Failed to commit")?;
|
.with_context(|| "Failed to commit")?;
|
||||||
@ -563,6 +534,7 @@ fn main() {
|
|||||||
git_status,
|
git_status,
|
||||||
git_file_paths,
|
git_file_paths,
|
||||||
git_match_paths,
|
git_match_paths,
|
||||||
|
git_branches,
|
||||||
git_commit
|
git_commit
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -156,6 +156,15 @@ impl Repository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn branches(&self) -> Result<Vec<String>> {
|
||||||
|
let mut branches = vec![];
|
||||||
|
for branch in self.git_repository.branches(None)? {
|
||||||
|
let (branch, _) = branch?;
|
||||||
|
branches.push(branch.name()?.unwrap().to_string());
|
||||||
|
}
|
||||||
|
Ok(branches)
|
||||||
|
}
|
||||||
|
|
||||||
// get file status from git
|
// get file status from git
|
||||||
pub fn status(&self) -> Result<HashMap<String, String>> {
|
pub fn status(&self) -> Result<HashMap<String, String>> {
|
||||||
let mut options = git2::StatusOptions::new();
|
let mut options = git2::StatusOptions::new();
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
import { shortPath } from '$lib/paths';
|
import { shortPath } from '$lib/paths';
|
||||||
import { currentProject } from '$lib/current_project';
|
import { currentProject } from '$lib/current_project';
|
||||||
import type { Project } from '$lib/projects';
|
import type { Project } from '$lib/projects';
|
||||||
|
import { placeholder } from '@codemirror/view';
|
||||||
|
|
||||||
let showPalette = <string | false>false;
|
let showPalette = <string | false>false;
|
||||||
let keysDown = <string[]>[];
|
let keysDown = <string[]>[];
|
||||||
@ -19,6 +20,7 @@
|
|||||||
let changedFiles = {};
|
let changedFiles = {};
|
||||||
let commitMessage = '';
|
let commitMessage = '';
|
||||||
let commitMessageInput: HTMLElement;
|
let commitMessageInput: HTMLElement;
|
||||||
|
let paletteMode = 'command';
|
||||||
|
|
||||||
const listFiles = (params: { projectId: string }) =>
|
const listFiles = (params: { projectId: string }) =>
|
||||||
invoke<Record<string, string>>('git_status', params);
|
invoke<Record<string, string>>('git_status', params);
|
||||||
@ -26,6 +28,9 @@
|
|||||||
const matchFiles = (params: { projectId: string; matchPattern: string }) =>
|
const matchFiles = (params: { projectId: string; matchPattern: string }) =>
|
||||||
invoke<Array<string>>('git_match_paths', params);
|
invoke<Array<string>>('git_match_paths', params);
|
||||||
|
|
||||||
|
const listBranches = (params: { projectId: string }) =>
|
||||||
|
invoke<Array<string>>('git_branches', params);
|
||||||
|
|
||||||
const listProjects = () => invoke<Project[]>('list_projects');
|
const listProjects = () => invoke<Project[]>('list_projects');
|
||||||
|
|
||||||
const commit = (params: {
|
const commit = (params: {
|
||||||
@ -44,6 +49,7 @@
|
|||||||
break;
|
break;
|
||||||
case 'Escape':
|
case 'Escape':
|
||||||
showPalette = false;
|
showPalette = false;
|
||||||
|
paletteMode = 'command';
|
||||||
break;
|
break;
|
||||||
case 'ArrowDown':
|
case 'ArrowDown':
|
||||||
if (showPalette == 'command') {
|
if (showPalette == 'command') {
|
||||||
@ -78,6 +84,9 @@
|
|||||||
if (keysDown.includes('e')) {
|
if (keysDown.includes('e')) {
|
||||||
executeCommand('contact');
|
executeCommand('contact');
|
||||||
}
|
}
|
||||||
|
if (keysDown.includes('r')) {
|
||||||
|
executeCommand('branch');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +179,8 @@
|
|||||||
case 'bookmark':
|
case 'bookmark':
|
||||||
break;
|
break;
|
||||||
case 'branch':
|
case 'branch':
|
||||||
showBranch = true;
|
showPalette = 'command';
|
||||||
|
branchSwitcher();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,11 +234,11 @@
|
|||||||
if (!showCommand) {
|
if (!showCommand) {
|
||||||
search = '';
|
search = '';
|
||||||
}
|
}
|
||||||
if (searchValue.length == 0) {
|
if (searchValue.length == 0 && paletteMode == 'command') {
|
||||||
updateMenu([]);
|
updateMenu([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($currentProject) {
|
if ($currentProject && searchValue.length > 0) {
|
||||||
const searchPattern = '.*' + Array.from(searchValue).join('(.*)');
|
const searchPattern = '.*' + Array.from(searchValue).join('(.*)');
|
||||||
matchFiles({ projectId: $currentProject.id, matchPattern: searchPattern }).then((files) => {
|
matchFiles({ projectId: $currentProject.id, matchPattern: searchPattern }).then((files) => {
|
||||||
let searchResults = [];
|
let searchResults = [];
|
||||||
@ -240,6 +250,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function branchSwitcher() {
|
||||||
|
console.log('branchSwitcher', $currentProject);
|
||||||
|
paletteMode = 'branch';
|
||||||
|
if ($currentProject) {
|
||||||
|
listBranches({ projectId: $currentProject.id }).then((refs) => {
|
||||||
|
let branches = <Object[]>[];
|
||||||
|
refs.forEach((b) => {
|
||||||
|
branches.push({ text: b, icon: BranchIcon });
|
||||||
|
});
|
||||||
|
menuItems = branches;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateMenu(searchResults: Array<{ text: string }>) {
|
function updateMenu(searchResults: Array<{ text: string }>) {
|
||||||
if (searchResults.length == 0) {
|
if (searchResults.length == 0) {
|
||||||
menuItems = commandList();
|
menuItems = commandList();
|
||||||
@ -299,29 +323,34 @@
|
|||||||
background-color: rgba(24, 24, 27, 0.60);
|
background-color: rgba(24, 24, 27, 0.60);
|
||||||
border: 0.5px solid rgba(63, 63, 70, 0.50);"
|
border: 0.5px solid rgba(63, 63, 70, 0.50);"
|
||||||
>
|
>
|
||||||
<div class="relative">
|
{#if paletteMode == 'command'}
|
||||||
<svg
|
<div class="relative">
|
||||||
class="pointer-events-none absolute top-3.5 left-4 h-5 w-5 text-zinc-500"
|
<svg
|
||||||
fill="none"
|
class="pointer-events-none absolute top-3.5 left-4 h-5 w-5 text-zinc-500"
|
||||||
viewBox="0 0 24 24"
|
fill="none"
|
||||||
stroke-width="1.5"
|
viewBox="0 0 24 24"
|
||||||
stroke="currentColor"
|
stroke-width="1.5"
|
||||||
aria-hidden="true"
|
stroke="currentColor"
|
||||||
>
|
aria-hidden="true"
|
||||||
<path
|
>
|
||||||
stroke-linecap="round"
|
<path
|
||||||
stroke-linejoin="round"
|
stroke-linecap="round"
|
||||||
d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"
|
stroke-linejoin="round"
|
||||||
|
d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<input
|
||||||
|
id="command"
|
||||||
|
type="text"
|
||||||
|
bind:value={search}
|
||||||
|
class="h-12 w-full border-0 bg-transparent pl-11 pr-4 text-white focus:ring-0 sm:text-sm"
|
||||||
|
placeholder="Search..."
|
||||||
/>
|
/>
|
||||||
</svg>
|
</div>
|
||||||
<input
|
{/if}
|
||||||
id="command"
|
{#if paletteMode == 'branch'}
|
||||||
type="text"
|
<div class="text-lg p-4">Branch Switcher</div>
|
||||||
bind:value={search}
|
{/if}
|
||||||
class="h-12 w-full border-0 bg-transparent pl-11 pr-4 text-white focus:ring-0 sm:text-sm"
|
|
||||||
placeholder="Search..."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Default state, show/hide based on command palette state. -->
|
<!-- Default state, show/hide based on command palette state. -->
|
||||||
<ul class="scroll-py-2 divide-y divide-zinc-500 divide-opacity-20 overflow-y-auto">
|
<ul class="scroll-py-2 divide-y divide-zinc-500 divide-opacity-20 overflow-y-auto">
|
||||||
|
Loading…
Reference in New Issue
Block a user