Repository: haydenull/logseq-plugin-git Branch: main Commit: e0ae1958ab58 Files: 20 Total size: 31.6 KB Directory structure: gitextract_ftc14837/ ├── .github/ │ └── workflows/ │ └── release.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.html ├── package.json ├── postcss.config.js ├── release.config.js ├── src/ │ ├── App.css │ ├── App.tsx │ ├── helper/ │ │ ├── constants.ts │ │ ├── git.ts │ │ └── util.ts │ ├── index.css │ ├── main.tsx │ └── vite-env.d.ts ├── tailwind.config.js ├── tsconfig.json └── vite.config.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/release.yml ================================================ name: Release on: push: branches: - main jobs: release: name: Release runs-on: ubuntu-20.04 steps: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: 18 - name: Install pnpm uses: pnpm/action-setup@v2 with: version: 8 run_install: false - name: Install dependencies run: pnpm install - name: Build run: pnpm build - name: Release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npx semantic-release ================================================ FILE: .gitignore ================================================ node_modules .DS_Store dist dist-ssr *.local ================================================ FILE: CHANGELOG.md ================================================ # [1.7.0](https://github.com/haydenull/logseq-plugin-git/compare/v1.6.0...v1.7.0) (2024-05-21) ### Features * Added Custom Commit Message ([#60](https://github.com/haydenull/logseq-plugin-git/issues/60)) ([3773f8b](https://github.com/haydenull/logseq-plugin-git/commit/3773f8bbcf5a1004fa93d8af6c043c62a4104d9e)) # [1.6.0](https://github.com/haydenull/logseq-plugin-git/compare/v1.5.5...v1.6.0) (2024-05-21) ### Bug Fixes * :bug: release action error ([52d170b](https://github.com/haydenull/logseq-plugin-git/commit/52d170b88f4f1edb28810fe26a501978b0cfde6b)) ### Features * New keyboard shortcut to commit without pushing ([#59](https://github.com/haydenull/logseq-plugin-git/issues/59)) ([fc799b8](https://github.com/haydenull/logseq-plugin-git/commit/fc799b8a8a364487db5c44631d3982323343926d)) ## [1.5.5](https://github.com/haydenull/logseq-plugin-git/compare/v1.5.4...v1.5.5) (2023-12-28) ### Bug Fixes * patch git exec command ([#50](https://github.com/haydenull/logseq-plugin-git/issues/50)) ([b4a4229](https://github.com/haydenull/logseq-plugin-git/commit/b4a422930288ff32cf2ff2fd23a71f0ca862b606)) ## [1.5.4](https://github.com/haydenull/logseq-plugin-git/compare/v1.5.3...v1.5.4) (2023-07-27) ### Bug Fixes * exported inProcess() was not set correctly breaking checkIsSynced ([#37](https://github.com/haydenull/logseq-plugin-git/issues/37)) ([cf78518](https://github.com/haydenull/logseq-plugin-git/commit/cf785180e4f68e589a153b71056a2fe1163fade6)) ## [1.5.3](https://github.com/haydenull/logseq-plugin-git/compare/v1.5.2...v1.5.3) (2023-07-26) ### Bug Fixes * [#30](https://github.com/haydenull/logseq-plugin-git/issues/30), shortcut mod+alt+s will pull rebase ([5f42bd5](https://github.com/haydenull/logseq-plugin-git/commit/5f42bd5674cdcdff6ae60e789ddf9bc66223ed38)) * stack git operations not to get errors when auto actions are already performing ([e78bb2c](https://github.com/haydenull/logseq-plugin-git/commit/e78bb2c185787e731cb7b1af07487b6901389396)), closes [#34](https://github.com/haydenull/logseq-plugin-git/issues/34) ## [1.5.2](https://github.com/haydenull/logseq-plugin-git/compare/v1.5.1...v1.5.2) (2023-04-20) ### Bug Fixes * :bug: the mask was not turned off after initilization ([a84acb5](https://github.com/haydenull/logseq-plugin-git/commit/a84acb5a7133da1f0693c15112ab5c903f0a1774)) ## [1.5.1](https://github.com/haydenull/logseq-plugin-git/compare/v1.5.0...v1.5.1) (2023-04-16) ### Bug Fixes * In the Logseq 0.9.2 version, there is an issue with the panel display that needs to be fixed. ([a81bceb](https://github.com/haydenull/logseq-plugin-git/commit/a81bceb10996a6e3d3901fe1f1fef63d6d1c4052)) # [1.5.0](https://github.com/haydenull/logseq-plugin-git/compare/v1.4.2...v1.5.0) (2023-02-14) ### Features * logseq sdk version ([#26](https://github.com/haydenull/logseq-plugin-git/issues/26)) ([d616d82](https://github.com/haydenull/logseq-plugin-git/commit/d616d820df800809cdc37e718fa0a43ff380498b)) ## [1.4.2](https://github.com/haydenull/logseq-plugin-git/compare/v1.4.1...v1.4.2) (2022-11-06) ### Bug Fixes * button color ([d3a5bd1](https://github.com/haydenull/logseq-plugin-git/commit/d3a5bd169ee74634983c04f160677a9f34f8971e)) ## [1.4.1](https://github.com/haydenull/logseq-plugin-git/compare/v1.4.0...v1.4.1) (2022-11-01) ### Bug Fixes * button style ([d32ef80](https://github.com/haydenull/logseq-plugin-git/commit/d32ef80c2105b3d7fb14da9b813c2eb29b7d3045)) # [1.4.0](https://github.com/haydenull/logseq-plugin-git/compare/v1.3.0...v1.4.0) (2022-08-23) ### Features * ✨ Support for turning off auto-check sync ([a2ac2bd](https://github.com/haydenull/logseq-plugin-git/commit/a2ac2bd44cd9685c15827bdb82bdec6c18139823)) # [1.3.0](https://github.com/haydenull/logseq-plugin-git/compare/v1.2.0...v1.3.0) (2022-08-19) ### Features * add default value: pull rebase ([90862ba](https://github.com/haydenull/logseq-plugin-git/commit/90862ba1d2d0d258c6d7b7a58f552fb0187f2df9)) # [1.2.0](https://github.com/haydenull/logseq-plugin-git/compare/v1.1.0...v1.2.0) (2022-06-11) ### Features * supports disable checkWhenDBChanged ([85428aa](https://github.com/haydenull/logseq-plugin-git/commit/85428aa217361a797f64c5eadd8a008e39cb49b2)) # [1.1.0](https://github.com/haydenull/logseq-plugin-git/compare/v1.0.2...v1.1.0) (2022-05-22) ### Features * ✨ add pull and checkout buttons ([f950626](https://github.com/haydenull/logseq-plugin-git/commit/f950626e2a3776c805a96267bbd37ba7a7eae9da)) ## [1.0.2](https://github.com/haydenull/logseq-plugin-git/compare/v1.0.1...v1.0.2) (2022-05-20) ### Bug Fixes * The id does not match expectations ([dffcaa3](https://github.com/haydenull/logseq-plugin-git/commit/dffcaa3b71086bad022350494c841bed7576d9c3)) ## [1.0.1](https://github.com/haydenull/logseq-plugin-git/compare/v1.0.0...v1.0.1) (2022-05-05) ### Bug Fixes * 🐛 Adapt logseq 0.6.7 ([02ffdf7](https://github.com/haydenull/logseq-plugin-git/commit/02ffdf70d493f0adc70d95d4847a7bb6ed6751b7)) * default value error[skip ci] ([a5cfc2b](https://github.com/haydenull/logseq-plugin-git/commit/a5cfc2b9184119f820946fcb0d33f5e5dc098e5d)) # 1.0.0 (2022-04-08) ### Features * ✨ add icon ([0f52416](https://github.com/haydenull/logseq-plugin-git/commit/0f52416ef8594525fb2fb527bc05c98fa327e308)) # [1.1.0](https://github.com/haydenull/logseq-plugin-git/compare/v1.0.0...v1.1.0) (2022-03-08) ### Features * add antd ([036577d](https://github.com/haydenull/logseq-plugin-git/commit/036577dc529db4e4a5964c287a55d112bae654bc)) # 1.0.0 (2022-01-18) ### Features * ✨ initial commit ([cca0e7f](https://github.com/haydenull/logseq-plugin-git/commit/cca0e7fcba33830eaf534fd9ca6b867b57147de4)) ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2022 Hayden Chen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # logseq-plugin-git > git plugin for logseq [![latest release version](https://img.shields.io/github/v/release/haydenull/logseq-plugin-git)](https://github.com/haydenull/logseq-plugin-git/releases) [![License](https://img.shields.io/github/license/haydenull/logseq-plugin-git?color=blue)](https://github.com/haydenull/logseq-plugin-git/blob/main/LICENSE) Logseq Git Plugin is a plugin for Logseq that provides easy access to common git commands, and helps you keep your notes synchronized with a remote git repository. With this plugin, you can: - Know explicitly if there are unsaved notes in the current repository and if they are synchronized with the remote repository. When there are unsaved files locally, the plugin will show a red indicator in the toolbar icon. - Quickly commit changes to notes. The plugin provides shortcut keys (mod+s) to perform commit&push operations. - Provide buttons to quickly execute common commands. Click the plugin icon, and the drop-down menu will show you some buttons to help you quickly execute commands (you can specify the desired buttons in the settings). - Prompt you if you have synchronized with the remote repository. The plugin automatically detects if the current repository is up-to-date and prompts when logseq starts and other times. ## Installation Install from the Logseq Plugin Store ## Shortcuts The plugin provides a shortcut key (mod+s) to quickly commit and push changes to the remote repository. ## Toolbar Icon - icon: everything is up-to-date. - icon with red dot: there are unsaved files locally. - icon with blinking red dot: the plugin is committing or pushing changes to the remote repository. ## Commands The drop-down menu shows the following commands: - Check Status: check the status of the current repository. - Show Log: show the log of the current repository. - Pull: pull changes from the remote repository. - Pull Rebase: pull changes from the remote repository and rebase. - Commit: commit changes to the current repository. - Push: push changes to the remote repository. - Commit & Push: commit changes and push to the remote repository. ## Demo ![demo](./demo.png) ================================================ FILE: index.html ================================================ Vite App
================================================ FILE: package.json ================================================ { "name": "logseq-plugin-git", "version": "1.7.0", "main": "dist/index.html", "logseq": { "id": "logseq-git", "icon": "logo.png" }, "scripts": { "dev": "vite", "build": "tsc && vite build", "preview": "vite preview" }, "dependencies": { "@logseq/libs": "^0.0.16", "antd": "^4.18.9", "react": "^17.0.2", "react-dom": "^17.0.2" }, "devDependencies": { "@semantic-release/changelog": "^6.0.1", "@semantic-release/exec": "^6.0.3", "@semantic-release/git": "^10.0.1", "@semantic-release/npm": "^10.0.4", "@types/node": "^20.4.5", "@types/react": "^18.2.17", "@types/react-dom": "^18.2.7", "@vitejs/plugin-react": "^4.0.3", "autoprefixer": "^10.4.2", "postcss": "^8.4.27", "semantic-release": "^21.1.2", "tailwindcss": "^3.3.3", "typescript": "^5.1.6", "vite": "^4.4.7", "vite-plugin-importer": "^0.2.5" }, "packageManager": "pnpm@8.6.10" } ================================================ FILE: postcss.config.js ================================================ module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, } ================================================ FILE: release.config.js ================================================ const pluginName = require('./package.json').name module.exports = { branches: 'main', plugins: [ '@semantic-release/commit-analyzer', '@semantic-release/release-notes-generator', '@semantic-release/changelog', [ '@semantic-release/npm', { npmPublish: false } ], [ '@semantic-release/git', { assets: ['CHANGELOG.md', 'package.json'], message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}' } ], [ '@semantic-release/exec', { prepareCmd: 'zip -qq -r ' + pluginName + '-${nextRelease.version}.zip package.json logo.png dist/' } ], [ '@semantic-release/github', { assets: [`${pluginName}-*.zip`] } ] ] } ================================================ FILE: src/App.css ================================================ ================================================ FILE: src/App.tsx ================================================ import './App.css' const App: React.FC<{ env: string }> = ({ env }) => { return (
logseq.hideMainUI()}>

logseq-plugin-git

Current Env: {env}

) } export default App ================================================ FILE: src/helper/constants.ts ================================================ import { SettingSchemaDesc } from "@logseq/libs/dist/LSPlugin.user"; export const COMMON_STYLE = ` .ui-items-container[data-type=toolbar] > .list-wrap { overflow: visible; } #injected-ui-item-git-logseq-git { position: relative; } .plugin-git-container { display: none; } .plugin-git-container .plugin-git-mask { position: fixed; width: 100vw; height: 100vh; left: 0; top: 0; z-index: 99; } .plugin-git-container .plugin-git-popup { position: fixed; z-index: 99; background-color: var(--ls-secondary-background-color); padding: 10px; border-radius: .375rem; --tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),0 4px 6px -2px rgba(0, 0, 0, 0.05); box-shadow: var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow); } .plugin-git-container .plugin-git-popup::before { content: ''; position: absolute; top: -8px; left: 50%; transform: translateX(-50%); width: 0; height: 0; border-style: solid; border-width: 0 10px 8px 10px; border-color: transparent transparent var(--ls-secondary-background-color) transparent; } `; export const SHOW_POPUP_STYLE = ` .plugin-git-container { display: block; } `; export const HIDE_POPUP_STYLE = ` .plugin-git-container { display: none; } `; export const INACTIVE_STYLE = ` ${COMMON_STYLE} #injected-ui-item-git-logseq-git::after { display: none; } `; export const ACTIVE_STYLE = ` ${COMMON_STYLE} #injected-ui-item-git-logseq-git::after { display: block; content: ''; position: absolute; width: 8px; height: 8px; border-radius: 100%; background-color: rgb(237, 66, 69); right: 8px; top: 6px; } `; export const LOADING_STYLE = ` ${COMMON_STYLE} #injected-ui-item-git-logseq-git::after { display: block; content: ''; position: absolute; width: 8px; height: 8px; border-radius: 100%; background-color: rgb(237, 66, 69); right: 8px; top: 6px; animation: blink 1s linear infinite; } @keyframes blink { 0% { opacity: 0; } 50% { opacity: 1; } 100% { opacity: 0; } } `; export const BUTTONS = [ { key: "status", title: "Check Status", event: "check" }, { key: "log", title: "Show Log", event: "log" }, { key: "pull", title: "Pull", event: "pull" }, { key: "pullRebase", title: "Pull Rebase", event: "pullRebase" }, { key: "checkout", title: "Checkout", event: "checkout" }, { key: "commit", title: "Commit", event: "commit" }, { key: "push", title: "Push", event: "push" }, { key: "commitAndPush", title: "Commit & Push", event: "commitAndPush" }, ]; export const SETTINGS_SCHEMA: SettingSchemaDesc[] = [ { key: "buttons", title: "Buttons", type: "enum", default: ["Check Status", "Show Log", "Pull Rebase", "Commit & Push"], description: "Select buttons to show", enumPicker: "checkbox", enumChoices: BUTTONS.map(({ title }) => title), }, { key: "checkWhenDBChanged", title: "Check Status when DB Changed", type: "boolean", default: true, description: "Check status when DB changed, restart logseq to take effect", }, { key: "autoCheckSynced", title: "Auto Check If Synced", type: "boolean", default: false, description: "Automatically check if the local version is the same as the remote", }, { key: "autoPush", title: "Auto Push", type: "boolean", default: false, description: "Auto push when logseq hide", }, { key: "typeCommitMessage", title: "Type Commit Message", type: "enum", default: "Default Message With Date", description: "Type of commit message to use", enumPicker: "select", enumChoices: ['Custom Message' , 'Default Message', 'Custom Message With Date', 'Default Message With Date'], }, { key: "customCommitMessage", title: "Custom Commit Message", type: "string", default: "", description: "Custom commit message for plugin (valid only if commit message is set to Custom Message)", } ]; ================================================ FILE: src/helper/git.ts ================================================ // https://logseq.github.io/plugins/interfaces/IAppProxy.html#execGitCommand import type { IGitResult } from "@logseq/libs/dist/LSPlugin.user" let _inProgress: Promise | undefined = undefined export const execGitCommand = async (args: string[]) : Promise => { if (_inProgress) await _inProgress let res try { const currentGitFolder = (await logseq.App.getCurrentGraph())?.path const runArgs = currentGitFolder ? ['-C', currentGitFolder, ...args] : args _inProgress = logseq.Git.execCommand(runArgs) res = await _inProgress } finally { _inProgress = undefined } return res } export const inProgress = () => _inProgress export const status = async (showRes = true): Promise => { // git status --porcelain | awk '{print $2}' // git status --porcelain | wc -l const res = await execGitCommand(['status', '--porcelain']) console.log('[faiz:] === git status', res) if (showRes) { if (res.exitCode === 0) { logseq.UI.showMsg('Git status success') } else { logseq.UI.showMsg(`Git status failed\n${res.stderr}`, 'error') } } /** * res * modify * { * exitCode: 0, * stderr: '', * stdout: 'M foo.md\n?? bar.md\n', * } * ahead & uptodate & behind * { * exitCode: 0, * stderr: '', * stdout: '', * } */ // changed files staged files return res } // log with git log --pretty=format:"%h %ad | %s%d [%an]" --date=short export const log = async (showRes = true): Promise => { // git log --pretty=format:"%h %s" -n 1 // git log --pretty=format:"%h %ad | %s%d [%an]" --date=short // return await logseq.App.execGitCommand(['log', '--pretty=format:"%h %s"']) const res = await execGitCommand(['log', '--pretty=format:"%h %ad | %s [%an]"', '--date=format:"%Y-%m-%d %H:%M:%S"', '--name-status']) console.log('[faiz:] === git log', res) if (showRes) { if (res.exitCode === 0) { logseq.UI.showMsg('Git log success') } else { logseq.UI.showMsg(`Git log failed\n${res.stderr}`, 'error') } } return res } // git pull export const pull = async (showRes = true): Promise => { const res = await execGitCommand(['pull']) console.log('[faiz:] === git pull', res) if (showRes) { if (res.exitCode === 0) { logseq.UI.showMsg('Git pull success') } else { logseq.UI.showMsg(`Git pull failed\n${res.stderr}`, 'error') } } return res } // git pull --rebase export const pullRebase = async (showRes = true): Promise => { const res = await execGitCommand(['pull', '--rebase']) console.log('[faiz:] === git pull --rebase', res) if (showRes) { if (res.exitCode === 0) { logseq.UI.showMsg('Git pull --rebase success') } else { logseq.UI.showMsg(`Git pull --rebase failed\n${res.stderr}`, 'error') } } return res } // git checkout . export const checkout = async (showRes = true): Promise => { const res = await execGitCommand(['checkout', '.']) console.log('[faiz:] === git checkout .', res) if (showRes) { if (res.exitCode === 0) { logseq.UI.showMsg('Git checkout success') } else { logseq.UI.showMsg(`Git checkout failed\n${res.stderr}`, 'error') } } return res } // git commit export const commit = async (showRes = true, message: string): Promise => { await execGitCommand(['add', '.']) // git commit -m "message" const res = await execGitCommand(['commit', '-m', message]) console.log('[faiz:] === git commit', res) if (showRes) { if (res.exitCode === 0) { logseq.UI.showMsg('Git commit success') } else { logseq.UI.showMsg(`Git commit failed\n${res.stdout || res.stderr}`, 'error') } } return res } // push export const push = async (showRes = true): Promise => { // git push const res = await execGitCommand(['push']) console.log('[faiz:] === git push', res) if (showRes) { if (res.exitCode === 0) { logseq.UI.showMsg('Git push success') } else { logseq.UI.showMsg(`Git push failed\n${res.stderr}`, 'error') } } return res } /** * Returns the commit message based on the selected commit message type in the logseq settings. * @returns The commit message. */ export const commitMessage = () : string => { let defaultMessage = "[logseq-plugin-git:commit]"; switch (logseq.settings?.typeCommitMessage as string) { case "Default Message": return defaultMessage; case "Default Message With Date": return defaultMessage + " " + new Date().toISOString(); case "Custom Message": let customMessage = logseq.settings?.customCommitMessage as string; if (customMessage.trim() === "") { return defaultMessage; } else { return customMessage; } case "Custom Message With Date": let customMessageWithDate = logseq.settings?.customCommitMessage as string; if (customMessageWithDate.trim() === "") { return defaultMessage + " " + new Date().toISOString(); } else { return customMessageWithDate + " " + new Date().toISOString(); } default: return defaultMessage; } } ================================================ FILE: src/helper/util.ts ================================================ import { ACTIVE_STYLE, HIDE_POPUP_STYLE, INACTIVE_STYLE, SHOW_POPUP_STYLE, } from "./constants"; import { status, inProgress, execGitCommand } from "./git"; export const checkStatus = async () => { console.log("Checking status..."); const statusRes = await status(false); if (statusRes?.stdout === "") { console.log("No changes", statusRes); setPluginStyle(INACTIVE_STYLE); } else { console.log("Need save", statusRes); setPluginStyle(ACTIVE_STYLE); } return statusRes; }; let pluginStyle = ""; export const setPluginStyle = (style: string) => { pluginStyle = style; logseq.provideStyle({ key: "git", style }); }; export const getPluginStyle = () => pluginStyle; export const showPopup = () => { const _style = getPluginStyle(); logseq.UI.queryElementRect("#logseq-git--git").then((triggerIconRect) => { console.log("[faiz:] === triggerIconRect", triggerIconRect); if (!triggerIconRect) return; const popupWidth = 120 + 10 * 2; const left = triggerIconRect.left + triggerIconRect.width / 2 - popupWidth / 2; const top = triggerIconRect.top + triggerIconRect.height; const _style = getPluginStyle(); setPluginStyle( `${_style}\n.plugin-git-popup{left:${left}px;top:${top}px;}` ); }); setPluginStyle(`${_style}\n${SHOW_POPUP_STYLE}`); }; export const hidePopup = () => { const _style = getPluginStyle(); setPluginStyle(`${_style}\n${HIDE_POPUP_STYLE}`); }; export const debounce = (fn, wait: number = 100, environment?: any) => { let timer = null; return function () { // @ts-ignore const context = environment || this; const args = arguments; if (timer) { clearTimeout(timer); timer = null; } // @ts-ignore timer = setTimeout(function () { fn.apply(context, args); }, wait); }; }; export const checkStatusWithDebounce = debounce(() => { checkStatus(); }, 2000); export const isRepoUpTodate = async () => { await execGitCommand(["fetch"]); const local = await execGitCommand(["rev-parse", "HEAD"]); const remote = await execGitCommand(["rev-parse", "@{u}"]); logseq.UI.showMsg(`${local.stdout} === ${remote.stdout}`, "success", { timeout: 30 }); return local.stdout === remote.stdout; }; export const checkIsSynced = async () => { if (inProgress()) { console.log("[faiz:] === checkIsSynced Git in progress, skip check"); return } const isSynced = await isRepoUpTodate(); if (!isSynced) logseq.UI.showMsg( `The current repository is not synchronized with the remote repository, please check.`, "warning", { timeout: 0 } ); }; ================================================ FILE: src/index.css ================================================ @tailwind base; @tailwind components; @tailwind utilities; html, body { background-color: transparent; } #root { @apply w-screen h-screen; } ================================================ FILE: src/main.tsx ================================================ import "@logseq/libs"; import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; import { BUTTONS, LOADING_STYLE, SETTINGS_SCHEMA } from "./helper/constants"; import { checkout, commit, commitMessage, log, pull, pullRebase, push, status, } from "./helper/git"; import { checkStatus, debounce, hidePopup, setPluginStyle, showPopup, checkIsSynced, checkStatusWithDebounce, getPluginStyle, } from "./helper/util"; import "./index.css"; // TODO: patch logseq Git command for the temporary fix solution // https://github.com/haydenull/logseq-plugin-git/issues/48 try { // @ts-ignore top.logseq.sdk.git.exec_command(['status']) } catch (e) { // @ts-ignore logseq.Git['execCommand'] = async function (args: string[]) { const ret = await logseq.App.execGitCommand(args) return {exitCode: ret == undefined ? 1 : 0, stdout: ret} } } const isDevelopment = import.meta.env.DEV if (isDevelopment) { renderApp("browser"); } else { console.log("=== logseq-plugin-git loaded ==="); logseq.ready(() => { const operations = { check: debounce(async function () { const status = await checkStatus(); if (status?.stdout === "") { logseq.UI.showMsg("No changes detected."); } else { logseq.UI.showMsg("Changes detected:\n" + status.stdout, "success", { timeout: 0, }); } hidePopup(); }), pull: debounce(async function () { console.log("[faiz:] === pull click"); setPluginStyle(LOADING_STYLE); hidePopup(); await pull(false); checkStatus(); }), pullRebase: debounce(async function () { console.log("[faiz:] === pullRebase click"); setPluginStyle(LOADING_STYLE); hidePopup(); await pullRebase(); checkStatus(); }), checkout: debounce(async function () { console.log("[faiz:] === checkout click"); hidePopup(); checkout(); }), commit: debounce(async function () { hidePopup(); await commit(true, commitMessage()); checkStatus(); }), push: debounce(async function () { setPluginStyle(LOADING_STYLE); hidePopup(); await push(); checkStatus(); }), commitAndPush: debounce(async function () { setPluginStyle(LOADING_STYLE); hidePopup(); const status = await checkStatus(); const changed = status?.stdout !== ""; if (changed) { const res = await commit( true, commitMessage() ); if (res.exitCode === 0) await push(true); } checkStatus(); }), log: debounce(async function () { console.log("[faiz:] === log click"); const res = await log(false); logseq.UI.showMsg(res?.stdout, "success", { timeout: 0 }); hidePopup(); }), showPopup: debounce(async function () { console.log("[faiz:] === showPopup click"); showPopup(); }), hidePopup: debounce(function () { console.log("[faiz:] === hidePopup click"); hidePopup(); }), }; logseq.provideModel(operations); logseq.App.registerUIItem("toolbar", { key: "git", template: '
', }); logseq.useSettingsSchema(SETTINGS_SCHEMA); setTimeout(() => { const buttons = (logseq.settings?.buttons as string[]) ?.map((title) => BUTTONS.find((b) => b.title === title)) .filter(Boolean); if (top && buttons?.length) { const parser = new DOMParser(); const doc = parser.parseFromString( `
${buttons .map( (button) => `` ) .join("\n")}
`, "text/html" ); // remove .plugin-git-container if exists const container = top?.document?.querySelector(".plugin-git-container"); console.log("[faiz:] === container", container); if (container) top?.document?.body.removeChild(container); top?.document?.body.appendChild( doc.body.childNodes?.[0]?.cloneNode(true) ); top?.document ?.querySelector(".plugin-git-mask") ?.addEventListener("click", hidePopup); buttons.forEach((button) => { top?.document ?.querySelector(`.plugin-git-${button?.key}`) ?.addEventListener("click", operations?.[button!?.event]); }); } }, 1000); logseq.App.onRouteChanged(async () => { checkStatusWithDebounce(); }); if (logseq.settings?.checkWhenDBChanged) { logseq.DB.onChanged(({ blocks, txData, txMeta }) => { checkStatusWithDebounce(); }); } if (logseq.settings?.autoCheckSynced) checkIsSynced(); checkStatusWithDebounce(); if (top) { top.document?.addEventListener("visibilitychange", async () => { const visibilityState = top?.document?.visibilityState; if (visibilityState === "visible") { if (logseq.settings?.autoCheckSynced) checkIsSynced(); } else if (visibilityState === "hidden") { // logseq.UI.showMsg(`Page is hidden: ${new Date()}`, 'success', { timeout: 0 }) // noChange void // changed commit push if (logseq.settings?.autoPush) { operations.commitAndPush(); } } }); } logseq.App.registerCommandPalette( { key: "logseq-plugin-git:commit", label: "Commit", keybinding: { binding: "alt+shift+s", mode: "global", }, }, () => operations.commit() ); logseq.App.registerCommandPalette( { key: "logseq-plugin-git:commit&push", label: "Commit & Push", keybinding: { binding: "mod+s", mode: "global", }, }, () => operations.commitAndPush() ); logseq.App.registerCommandPalette( { key: "logseq-plugin-git:rebase", label: "Pull Rebase", keybinding: { binding: "mod+alt+s", mode: "global", }, }, () => operations.pullRebase() ); }); } function renderApp(env: string) { ReactDOM.render( , document.getElementById("root") ); } ================================================ FILE: src/vite-env.d.ts ================================================ /// ================================================ FILE: tailwind.config.js ================================================ module.exports = { content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,css}'], theme: { extend: {}, }, plugins: [], } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], "allowJs": false, "skipLibCheck": false, "esModuleInterop": false, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "module": "ESNext", "moduleResolution": "Node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "noImplicitAny": false, "jsx": "react-jsx" }, "include": ["./src"] } ================================================ FILE: vite.config.ts ================================================ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import usePluginImport from 'vite-plugin-importer' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ react(), usePluginImport({ libraryName: "antd", libraryDirectory: "es", style: "css", }), ], base: './', })