Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .planning/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
"plan_check": true,
"verifier": true
}
}
}
2 changes: 1 addition & 1 deletion .planning/debug/viewer3d-standalone.html
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,8 @@ <h2>Debug Log</h2>

<script type="module">
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

// Make available globally for onclick handlers
window.THREE = THREE;
Expand Down
4 changes: 2 additions & 2 deletions biome.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"organizeImports": { "enabled": true },
"$schema": "https://biomejs.dev/schemas/2.4.4/schema.json",
"assist": { "actions": { "source": { "organizeImports": "on" } } },
"linter": { "enabled": true, "rules": { "recommended": true } },
"formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2 }
}
12 changes: 10 additions & 2 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ export default defineConfig({
description: "A visual Git client built with Tauri, React, and TypeScript",
base: "/FlowForge/",

head: [["link", { rel: "icon", type: "image/svg+xml", href: "/FlowForge/logo.svg" }]],
head: [
[
"link",
{ rel: "icon", type: "image/svg+xml", href: "/FlowForge/logo.svg" },
],
],

themeConfig: {
nav: [
Expand Down Expand Up @@ -72,7 +77,10 @@ export default defineConfig({
},

socialLinks: [
{ icon: "github", link: "https://github.com/Atypical-Consulting/FlowForge" },
{
icon: "github",
link: "https://github.com/Atypical-Consulting/FlowForge",
},
],
},

Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<title>FlowForge</title>
<!-- FOUC Prevention: Set theme class before React loads -->
<script>
(function () {
(() => {
const stored = localStorage.getItem("flowforge-theme");
let theme = stored;

Expand Down
5 changes: 4 additions & 1 deletion renovate.json
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
{"$schema":"https://docs.renovatebot.com/renovate-schema.json","extends":["config:recommended"]}
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"]
}
178 changes: 134 additions & 44 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,131 @@
import { listen } from "@tauri-apps/api/event";
import { useQueryClient } from "@tanstack/react-query";
import { listen } from "@tauri-apps/api/event";
import { useSelector } from "@xstate/react";
import { Suspense, useCallback, useEffect } from "react";
import "./core/workflows";
import "./core/commands";
import "./core/commands/toolbar-actions";
import "./core/blades/_discovery";
import { gitHookBus } from "@/core/services/gitHookBus";
import { CommandPalette } from "@/framework/command-palette/components";
import { ExtensionAPI } from "@/framework/extension-system/ExtensionAPI";
import { BladeRenderer } from "@/framework/layout/BladeRenderer";
import { useBladeRegistry } from "@/framework/layout/bladeRegistry";
import {
getNavigationActor,
NavigationProvider,
useNavigationActorRef,
} from "@/framework/layout/navigation/context";
import { selectBladeStack } from "@/framework/layout/navigation/selectors";
import { commands as tauriCommands } from "./bindings";
import { Header } from "./core/components/Header";
import { RepositoryView } from "./core/components/RepositoryView";
import { ContextMenuPortal } from "./core/components/ui/ContextMenu";
import { StatusBar } from "./core/components/ui/StatusBar";
import { ToastContainer } from "./core/components/ui/ToastContainer";
import { useKeyboardShortcuts } from "./core/hooks/useKeyboardShortcuts";
import { BladeRenderer } from "@/framework/layout/BladeRenderer";
import { getNavigationActor, NavigationProvider, useNavigationActorRef } from "@/framework/layout/navigation/context";
import { selectBladeStack } from "@/framework/layout/navigation/selectors";
import { usePreferencesStore as useBranchMetadataStore } from "./core/stores/domain/preferences";
import { usePreferencesStore as useNavigationStore } from "./core/stores/domain/preferences";
import { useGitOpsStore } from "./core/stores/domain/git-ops";
import { useGitOpsStore as useRepositoryStore } from "./core/stores/domain/git-ops";
import { usePreferencesStore as useReviewChecklistStore } from "./core/stores/domain/preferences";
import { usePreferencesStore as useSettingsStore } from "./core/stores/domain/preferences";
import { usePreferencesStore as useThemeStore } from "./core/stores/domain/preferences";
import { useGitOpsStore as useUndoStore } from "./core/stores/domain/git-ops";
import { useBladeRegistry } from "@/framework/layout/bladeRegistry";
import { modKeyLabel } from "./core/lib/platform";
import { useExtensionHost, configureExtensionHost } from "./extensions";
import { ExtensionAPI } from "@/framework/extension-system/ExtensionAPI";
import { gitHookBus } from "@/core/services/gitHookBus";
import { commands as tauriCommands } from "./bindings";
import { onActivate as viewerCodeActivate, onDeactivate as viewerCodeDeactivate } from "./extensions/viewer-code";
import { onActivate as viewerMarkdownActivate, onDeactivate as viewerMarkdownDeactivate } from "./extensions/viewer-markdown";
import { onActivate as viewer3dActivate, onDeactivate as viewer3dDeactivate } from "./extensions/viewer-3d";
import { onActivate as ccActivate, onDeactivate as ccDeactivate } from "./extensions/conventional-commits";
import { onActivate as gitflowActivate, onDeactivate as gitflowDeactivate } from "./extensions/gitflow";
import { onActivate as worktreesActivate, onDeactivate as worktreesDeactivate } from "./extensions/worktrees";
import { onActivate as githubActivate, onDeactivate as githubDeactivate } from "./extensions/github";
import { onActivate as initRepoActivate, onDeactivate as initRepoDeactivate } from "./extensions/init-repo";
import { onActivate as viewerImageActivate, onDeactivate as viewerImageDeactivate } from "./extensions/viewer-image";
import { onActivate as viewerNupkgActivate, onDeactivate as viewerNupkgDeactivate } from "./extensions/viewer-nupkg";
import { onActivate as viewerPlaintextActivate, onDeactivate as viewerPlaintextDeactivate } from "./extensions/viewer-plaintext";
import { onActivate as welcomeActivate, onDeactivate as welcomeDeactivate } from "./extensions/welcome-screen";
import { onActivate as topologyActivate, onDeactivate as topologyDeactivate } from "./extensions/topology";
import { onActivate as conflictActivate, onDeactivate as conflictDeactivate } from "./extensions/conflict-resolution";
import { onActivate as insightsActivate, onDeactivate as insightsDeactivate } from "./extensions/git-insights";
import { onActivate as repositoryExtActivate, onDeactivate as repositoryExtDeactivate } from "./extensions/repository";
import { onActivate as branchesExtActivate, onDeactivate as branchesExtDeactivate } from "./extensions/branches";
import { onActivate as syncExtActivate, onDeactivate as syncExtDeactivate } from "./extensions/sync";
import { onActivate as diffExtActivate, onDeactivate as diffExtDeactivate } from "./extensions/diff";
import { onActivate as commitsExtActivate, onDeactivate as commitsExtDeactivate } from "./extensions/commits";
import { onActivate as stashExtActivate, onDeactivate as stashExtDeactivate } from "./extensions/stash";
import { onActivate as tagsExtActivate, onDeactivate as tagsExtDeactivate } from "./extensions/tags";
import {
useGitOpsStore,
useGitOpsStore as useRepositoryStore,
useGitOpsStore as useUndoStore,
} from "./core/stores/domain/git-ops";
import {
usePreferencesStore as useBranchMetadataStore,
usePreferencesStore as useNavigationStore,
usePreferencesStore as useReviewChecklistStore,
usePreferencesStore as useSettingsStore,
usePreferencesStore as useThemeStore,
} from "./core/stores/domain/preferences";
import { configureExtensionHost, useExtensionHost } from "./extensions";
import {
onActivate as branchesExtActivate,
onDeactivate as branchesExtDeactivate,
} from "./extensions/branches";
import {
onActivate as commitsExtActivate,
onDeactivate as commitsExtDeactivate,
} from "./extensions/commits";
import {
onActivate as conflictActivate,
onDeactivate as conflictDeactivate,
} from "./extensions/conflict-resolution";
import {
onActivate as ccActivate,
onDeactivate as ccDeactivate,
} from "./extensions/conventional-commits";
import {
onActivate as diffExtActivate,
onDeactivate as diffExtDeactivate,
} from "./extensions/diff";
import {
onActivate as insightsActivate,
onDeactivate as insightsDeactivate,
} from "./extensions/git-insights";
import {
onActivate as gitflowActivate,
onDeactivate as gitflowDeactivate,
} from "./extensions/gitflow";
import {
onActivate as githubActivate,
onDeactivate as githubDeactivate,
} from "./extensions/github";
import {
onActivate as initRepoActivate,
onDeactivate as initRepoDeactivate,
} from "./extensions/init-repo";
import {
onActivate as repositoryExtActivate,
onDeactivate as repositoryExtDeactivate,
} from "./extensions/repository";
import {
onActivate as stashExtActivate,
onDeactivate as stashExtDeactivate,
} from "./extensions/stash";
import {
onActivate as syncExtActivate,
onDeactivate as syncExtDeactivate,
} from "./extensions/sync";
import {
onActivate as tagsExtActivate,
onDeactivate as tagsExtDeactivate,
} from "./extensions/tags";
import {
onActivate as topologyActivate,
onDeactivate as topologyDeactivate,
} from "./extensions/topology";
import {
onActivate as viewer3dActivate,
onDeactivate as viewer3dDeactivate,
} from "./extensions/viewer-3d";
import {
onActivate as viewerCodeActivate,
onDeactivate as viewerCodeDeactivate,
} from "./extensions/viewer-code";
import {
onActivate as viewerImageActivate,
onDeactivate as viewerImageDeactivate,
} from "./extensions/viewer-image";
import {
onActivate as viewerMarkdownActivate,
onDeactivate as viewerMarkdownDeactivate,
} from "./extensions/viewer-markdown";
import {
onActivate as viewerNupkgActivate,
onDeactivate as viewerNupkgDeactivate,
} from "./extensions/viewer-nupkg";
import {
onActivate as viewerPlaintextActivate,
onDeactivate as viewerPlaintextDeactivate,
} from "./extensions/viewer-plaintext";
import {
onActivate as welcomeActivate,
onDeactivate as welcomeDeactivate,
} from "./extensions/welcome-screen";
import {
onActivate as worktreesActivate,
onDeactivate as worktreesDeactivate,
} from "./extensions/worktrees";

// Configure ExtensionHost with Tauri-specific discovery
configureExtensionHost({
Expand All @@ -68,12 +142,17 @@ function WelcomeFallback() {
const { openRepository } = useGitOpsStore();
const actorRef = useNavigationActorRef();
const bladeStack = useSelector(actorRef, selectBladeStack);
const pushedBlade = bladeStack.length > 1 ? bladeStack[bladeStack.length - 1] : null;
const pushedBlade =
bladeStack.length > 1 ? bladeStack[bladeStack.length - 1] : null;

const openDialog = useCallback(async () => {
const { open } = await import("@tauri-apps/plugin-dialog");
const { commands } = await import("./bindings");
const selected = await open({ directory: true, multiple: false, title: "Open Git Repository" });
const selected = await open({
directory: true,
multiple: false,
title: "Open Git Repository",
});
if (selected && typeof selected === "string") {
const isRepo = await commands.isGitRepository(selected);
if (isRepo.status === "ok" && isRepo.data) {
Expand All @@ -85,7 +164,8 @@ function WelcomeFallback() {
useEffect(() => {
const handler = () => openDialog();
document.addEventListener("open-repository-dialog", handler);
return () => document.removeEventListener("open-repository-dialog", handler);
return () =>
document.removeEventListener("open-repository-dialog", handler);
}, [openDialog]);

// Render blades pushed via command palette / toolbar (e.g. Extension Manager, Settings)
Expand Down Expand Up @@ -161,7 +241,10 @@ function App() {
(defaultTab === "topology" || defaultTab === "history") &&
useBladeRegistry.getState().items.has("topology-graph")
) {
getNavigationActor().send({ type: "SWITCH_WORKFLOW", workflow: "topology" });
getNavigationActor().send({
type: "SWITCH_WORKFLOW",
workflow: "topology",
});
}
});
initNavigation();
Expand Down Expand Up @@ -344,7 +427,14 @@ function App() {
activate: tagsExtActivate,
deactivate: tagsExtDeactivate,
});
}, [initTheme, initSettings, initNavigation, initMetadata, initChecklist, registerBuiltIn]);
}, [
initTheme,
initSettings,
initNavigation,
initMetadata,
initChecklist,
registerBuiltIn,
]);

// Discover and activate extensions when a repository is opened
useEffect(() => {
Expand Down
Loading
Loading