读取 git 仓库数据(如有)并显示
This commit is contained in:
29
src/main/code-launchpad/project-git.ts
Normal file
29
src/main/code-launchpad/project-git.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { ProjectGitDto } from '@my-type/ide-projects'
|
||||
import simpleGit from 'simple-git'
|
||||
|
||||
/**
|
||||
* 获取指定项目的 git 数据(如有)
|
||||
* @param path 项目路径,应该是 {@link IdeProjectDto.path}
|
||||
*/
|
||||
export async function getProjectGitInfo(path: string): Promise<ProjectGitDto | null> {
|
||||
try {
|
||||
const git = simpleGit(path)
|
||||
if (!(await git.checkIsRepo())) {
|
||||
console.log(`路径 ${path} 的项目不存在 git 仓库。`)
|
||||
return null
|
||||
}
|
||||
const status = await git.status()
|
||||
return {
|
||||
current: status.current,
|
||||
tracking: status.tracking,
|
||||
created: status.created.length,
|
||||
deleted: status.deleted.length,
|
||||
modified: status.modified.length,
|
||||
renamed: status.renamed.length,
|
||||
staged: status.staged.length
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { getJetBrainsProjects, getVscodeProjects, openProject } from './code-lau
|
||||
import { createCodeLaunchpadTray, createCodeLaunchpadWindow } from './code-launchpad/code-launchpad'
|
||||
import type { IDECode } from '@my-type/settings'
|
||||
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
|
||||
import { getProjectGitInfo } from './code-launchpad/project-git'
|
||||
|
||||
let mainWindow: BrowserWindow | null = null
|
||||
// @ts-ignore 保存引用,禁用报错
|
||||
@@ -161,6 +162,9 @@ app.whenReady().then(async () => {
|
||||
ipcMain.handle('codeLaunchpad:openProject', (_, ide: IDECode, path: string) => {
|
||||
return openProject(ide, path)
|
||||
})
|
||||
ipcMain.handle('codeLaunchpad:getProjectGitInfo', (_, path: string) => {
|
||||
return getProjectGitInfo(path)
|
||||
})
|
||||
|
||||
await checkIDEs()
|
||||
await checkIDEsVersion()
|
||||
|
||||
10
src/my-type/ide-projects.d.ts
vendored
10
src/my-type/ide-projects.d.ts
vendored
@@ -10,3 +10,13 @@ export interface IdeProjectDto {
|
||||
}
|
||||
|
||||
export type IdeProjectsDto = IdeProjectDto[]
|
||||
|
||||
export interface ProjectGitDto {
|
||||
current: string | null
|
||||
tracking: string | null
|
||||
created: number
|
||||
deleted: number
|
||||
modified: number
|
||||
renamed: number
|
||||
staged: number
|
||||
}
|
||||
|
||||
13
src/preload/index.d.ts
vendored
13
src/preload/index.d.ts
vendored
@@ -1,13 +1,13 @@
|
||||
import { ElectronAPI } from '@electron-toolkit/preload'
|
||||
import { settingsDto, checkIDEsResultDto } from '@my-type/settings'
|
||||
import { ElectronAPI } from "@electron-toolkit/preload";
|
||||
import { settingsDto, checkIDEsResultDto } from "@my-type/settings";
|
||||
import { checkIDEsVersionDto } from "../my-type/settings";
|
||||
import { IdeProjectsDto } from "../my-type/ide-projects";
|
||||
import { GitProjectDto, IdeProjectsDto } from "../my-type/ide-projects";
|
||||
|
||||
// 此处只有签名
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
electron: ElectronAPI
|
||||
electron: ElectronAPI;
|
||||
api: {
|
||||
_saveSettings: (settings: settingsDto) => Promise<boolean>
|
||||
_updateSettings: () => Promise<settingsDto>
|
||||
@@ -17,7 +17,7 @@ declare global {
|
||||
_maximize: () => Promise<void>
|
||||
_closeWindow: () => Promise<void>
|
||||
_exit: () => Promise<void>
|
||||
}
|
||||
};
|
||||
codeLaunchpad: {
|
||||
_getIDEs: () => Promise<checkIDEsResultDto>
|
||||
_checkIDEs: () => Promise<checkIDEsResultDto>
|
||||
@@ -26,6 +26,7 @@ declare global {
|
||||
_getVSCodeProjects: () => Promise<IdeProjectsDto>
|
||||
_getJetBrainsProjects: () => Promise<IdeProjectsDto>
|
||||
_openProject: (ide: string, path: string) => Promise<boolean>
|
||||
}
|
||||
_getProjectGitInfo: (path: string) => Promise<GitProjectDto | null>
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ const codeLaunchpadApi = {
|
||||
_getVSCodeProjects: () => ipcRenderer.invoke('codeLaunchpad:getVSCodeProjects'),
|
||||
_getJetBrainsProjects: () => ipcRenderer.invoke('codeLaunchpad:getJetBrainsProjects'),
|
||||
_openProject: (ide: string, path: string) =>
|
||||
ipcRenderer.invoke('codeLaunchpad:openProject', ide, path)
|
||||
ipcRenderer.invoke('codeLaunchpad:openProject', ide, path),
|
||||
_getProjectGitInfo: (path: string) => ipcRenderer.invoke('codeLaunchpad:getProjectGitInfo', path)
|
||||
}
|
||||
|
||||
// Use `contextBridge` APIs to expose Electron APIs to
|
||||
|
||||
1
src/renderer/components.d.ts
vendored
1
src/renderer/components.d.ts
vendored
@@ -33,6 +33,7 @@ declare module 'vue' {
|
||||
NH2: typeof import('naive-ui')['NH2']
|
||||
NH3: typeof import('naive-ui')['NH3']
|
||||
NH4: typeof import('naive-ui')['NH4']
|
||||
NH5: typeof import('naive-ui')['NH5']
|
||||
NIcon: typeof import('naive-ui')['NIcon']
|
||||
NInput: typeof import('naive-ui')['NInput']
|
||||
NInputNumber: typeof import('naive-ui')['NInputNumber']
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { IdeProjectDto } from '@my-type/ide-projects'
|
||||
import { toProductDisplayName } from '@my-type/jetbrains-state-tools'
|
||||
import { useMessage } from 'naive-ui'
|
||||
import { formatTimestamp } from '@my-type/dataFormatter'
|
||||
import ProjectGit from '@renderer/components-code-launchpad/ProjectGit.vue'
|
||||
|
||||
const message = useMessage()
|
||||
|
||||
@@ -85,6 +86,7 @@ async function openWithIDE(ide: string): Promise<void> {
|
||||
<n-p v-if="project.timestamp !== 0" class="no-margin-bottom" type="default">
|
||||
上次打开于 {{ formatTimestamp(project.timestamp) }}
|
||||
</n-p>
|
||||
<ProjectGit :path="project.path" />
|
||||
<n-flex>
|
||||
<n-button-group>
|
||||
<n-button
|
||||
|
||||
54
src/renderer/src/components-code-launchpad/ProjectGit.vue
Normal file
54
src/renderer/src/components-code-launchpad/ProjectGit.vue
Normal file
@@ -0,0 +1,54 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { CreateOutline as CreatedIcon } from '@vicons/ionicons5'
|
||||
import {
|
||||
ChangeHistoryOutlined as ModifiedIcon,
|
||||
DeleteOutlined as DeletedIcon,
|
||||
DriveFileRenameOutlineSharp as RenamedIcon
|
||||
} from '@vicons/material'
|
||||
import { ProjectGitDto } from '@my-type/ide-projects'
|
||||
import ProjectGitIconWidget from '@renderer/components-code-launchpad/ProjectGitIconWidget.vue'
|
||||
|
||||
const info = ref<ProjectGitDto | null>(null)
|
||||
const loading = ref(true)
|
||||
|
||||
const props = defineProps<{ path: string }>()
|
||||
|
||||
onMounted(async () => {
|
||||
info.value = await window.codeLaunchpad._getProjectGitInfo(props.path)
|
||||
loading.value = false
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-card content-class="small-padding">
|
||||
<n-p v-if="loading">正在查找 git 仓库</n-p>
|
||||
<n-flex v-else-if="info !== null" vertical size="large">
|
||||
<n-flex>
|
||||
<n-tag round size="large" type="success">
|
||||
{{ info.current }}
|
||||
</n-tag>
|
||||
<n-tag round size="large" type="info">
|
||||
{{ info.tracking ? info.tracking : '无远程' }}
|
||||
</n-tag>
|
||||
</n-flex>
|
||||
<n-flex justify="end">
|
||||
<ProjectGitIconWidget name="新建" :count="info.created" color="#63e2b7">
|
||||
<CreatedIcon />
|
||||
</ProjectGitIconWidget>
|
||||
<ProjectGitIconWidget name="更名" :count="info.renamed" color="#bbb935">
|
||||
<RenamedIcon />
|
||||
</ProjectGitIconWidget>
|
||||
<ProjectGitIconWidget name="修改" :count="info.modified" color="#8acbec">
|
||||
<ModifiedIcon />
|
||||
</ProjectGitIconWidget>
|
||||
<ProjectGitIconWidget name="删除" :count="info.deleted" color="#e38686">
|
||||
<DeletedIcon />
|
||||
</ProjectGitIconWidget>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
<n-p v-else>未在项目中发现 git 仓库</n-p>
|
||||
</n-card>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,39 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
count: number
|
||||
color: string
|
||||
}>()
|
||||
|
||||
const finalColor = computed(() => {
|
||||
return props.count === 0 ? '#989898' : props.color
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="icon-widget">
|
||||
<n-icon size="large">
|
||||
<slot />
|
||||
</n-icon>
|
||||
<n-text style="font-size: 11px">{{ name }}</n-text>
|
||||
<n-text strong style="font-size: 16px">{{ count }}</n-text>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
div.icon-widget {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
border: 1px solid v-bind(finalColor);
|
||||
border-radius: 4px;
|
||||
padding: 3px 6px;
|
||||
|
||||
* {
|
||||
color: v-bind(finalColor);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user