mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-01 20:23:36 +00:00
Merge branch: resolve conflict in worktree-actions-dropdown.tsx
This commit is contained in:
@@ -1,15 +1,51 @@
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { LogOut, User } from 'lucide-react';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { toast } from 'sonner';
|
||||
import { LogOut, User, Code2, RefreshCw } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { logout } from '@/lib/http-api-client';
|
||||
import { useAuthStore } from '@/store/auth-store';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import {
|
||||
useAvailableEditors,
|
||||
useEffectiveDefaultEditor,
|
||||
} from '@/components/views/board-view/worktree-panel/hooks/use-available-editors';
|
||||
import { getEditorIcon } from '@/components/icons/editor-icons';
|
||||
|
||||
export function AccountSection() {
|
||||
const navigate = useNavigate();
|
||||
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
||||
|
||||
// Editor settings
|
||||
const { editors, isLoading: isLoadingEditors, isRefreshing, refresh } = useAvailableEditors();
|
||||
const defaultEditorCommand = useAppStore((s) => s.defaultEditorCommand);
|
||||
const setDefaultEditorCommand = useAppStore((s) => s.setDefaultEditorCommand);
|
||||
|
||||
// Use shared hook for effective default editor
|
||||
const effectiveEditor = useEffectiveDefaultEditor(editors);
|
||||
|
||||
// Normalize Select value: if saved editor isn't found, show 'auto'
|
||||
const hasSavedEditor =
|
||||
!!defaultEditorCommand && editors.some((e) => e.command === defaultEditorCommand);
|
||||
const selectValue = hasSavedEditor ? defaultEditorCommand : 'auto';
|
||||
|
||||
// Get icon component for the effective editor
|
||||
const EffectiveEditorIcon = effectiveEditor ? getEditorIcon(effectiveEditor.command) : null;
|
||||
|
||||
const handleRefreshEditors = async () => {
|
||||
await refresh();
|
||||
toast.success('Editor list refreshed');
|
||||
};
|
||||
|
||||
const handleLogout = async () => {
|
||||
setIsLoggingOut(true);
|
||||
try {
|
||||
@@ -43,6 +79,81 @@ export function AccountSection() {
|
||||
<p className="text-sm text-muted-foreground/80 ml-12">Manage your session and account.</p>
|
||||
</div>
|
||||
<div className="p-6 space-y-4">
|
||||
{/* Default IDE */}
|
||||
<div className="flex items-center justify-between gap-4 p-4 rounded-xl bg-muted/30 border border-border/30">
|
||||
<div className="flex items-center gap-3.5 min-w-0">
|
||||
<div className="w-11 h-11 rounded-xl bg-gradient-to-br from-muted/50 to-muted/30 border border-border/30 flex items-center justify-center shrink-0">
|
||||
<Code2 className="w-5 h-5 text-muted-foreground" />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<p className="font-medium text-foreground">Default IDE</p>
|
||||
<p className="text-xs text-muted-foreground/70 mt-0.5">
|
||||
Default IDE to use when opening branches or worktrees
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Select
|
||||
value={selectValue}
|
||||
onValueChange={(value) => setDefaultEditorCommand(value === 'auto' ? null : value)}
|
||||
disabled={isLoadingEditors || isRefreshing || editors.length === 0}
|
||||
>
|
||||
<SelectTrigger className="w-[180px] shrink-0">
|
||||
<SelectValue placeholder="Select editor">
|
||||
{effectiveEditor ? (
|
||||
<span className="flex items-center gap-2">
|
||||
{EffectiveEditorIcon && <EffectiveEditorIcon className="w-4 h-4" />}
|
||||
{effectiveEditor.name}
|
||||
{selectValue === 'auto' && (
|
||||
<span className="text-muted-foreground text-xs">(Auto)</span>
|
||||
)}
|
||||
</span>
|
||||
) : (
|
||||
'Select editor'
|
||||
)}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="auto">
|
||||
<span className="flex items-center gap-2">
|
||||
<Code2 className="w-4 h-4" />
|
||||
Auto-detect
|
||||
</span>
|
||||
</SelectItem>
|
||||
{editors.map((editor) => {
|
||||
const Icon = getEditorIcon(editor.command);
|
||||
return (
|
||||
<SelectItem key={editor.command} value={editor.command}>
|
||||
<span className="flex items-center gap-2">
|
||||
<Icon className="w-4 h-4" />
|
||||
{editor.name}
|
||||
</span>
|
||||
</SelectItem>
|
||||
);
|
||||
})}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={handleRefreshEditors}
|
||||
disabled={isRefreshing || isLoadingEditors}
|
||||
className="shrink-0 h-9 w-9"
|
||||
>
|
||||
<RefreshCw className={cn('w-4 h-4', isRefreshing && 'animate-spin')} />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Refresh available editors</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Logout */}
|
||||
<div className="flex items-center justify-between gap-4 p-4 rounded-xl bg-muted/30 border border-border/30">
|
||||
<div className="flex items-center gap-3.5 min-w-0">
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
QwenIcon,
|
||||
MistralIcon,
|
||||
MetaIcon,
|
||||
getProviderIconForModel,
|
||||
} from '@/components/ui/provider-icon';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
@@ -513,27 +514,8 @@ export function PhaseModelSelector({
|
||||
const isSelected = selectedModel === model.id;
|
||||
const isFavorite = favoriteModels.includes(model.id);
|
||||
|
||||
// Get the appropriate icon based on provider
|
||||
const ProviderIcon = (() => {
|
||||
switch (model.provider) {
|
||||
case 'opencode':
|
||||
return OpenCodeIcon;
|
||||
case 'amazon-bedrock-anthropic':
|
||||
return AnthropicIcon;
|
||||
case 'amazon-bedrock-deepseek':
|
||||
return DeepSeekIcon;
|
||||
case 'amazon-bedrock-amazon':
|
||||
return NovaIcon;
|
||||
case 'amazon-bedrock-meta':
|
||||
return MetaIcon;
|
||||
case 'amazon-bedrock-mistral':
|
||||
return MistralIcon;
|
||||
case 'amazon-bedrock-qwen':
|
||||
return QwenIcon;
|
||||
default:
|
||||
return OpenCodeIcon;
|
||||
}
|
||||
})();
|
||||
// Get the appropriate icon based on the specific model ID
|
||||
const ProviderIcon = getProviderIconForModel(model.id);
|
||||
|
||||
return (
|
||||
<CommandItem
|
||||
|
||||
@@ -431,6 +431,16 @@ export function PromptCustomizationSection({
|
||||
updatePrompt('enhancement', 'acceptanceSystemPrompt', value)
|
||||
}
|
||||
/>
|
||||
|
||||
<PromptField
|
||||
label="User Experience Mode"
|
||||
description="Review and enhance from a user experience and design perspective"
|
||||
defaultValue={DEFAULT_ENHANCEMENT_PROMPTS.uxReviewerSystemPrompt}
|
||||
customValue={promptCustomization?.enhancement?.uxReviewerSystemPrompt}
|
||||
onCustomValueChange={(value) =>
|
||||
updatePrompt('enhancement', 'uxReviewerSystemPrompt', value)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
AnthropicIcon,
|
||||
MistralIcon,
|
||||
MetaIcon,
|
||||
getProviderIconForModel,
|
||||
} from '@/components/ui/provider-icon';
|
||||
import type { ComponentType } from 'react';
|
||||
|
||||
@@ -31,27 +32,10 @@ interface OpencodeModelConfigurationProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate icon component for a given OpenCode provider
|
||||
* Returns the appropriate icon component for a given OpenCode model ID
|
||||
*/
|
||||
function getProviderIcon(provider: OpencodeProvider): ComponentType<{ className?: string }> {
|
||||
switch (provider) {
|
||||
case 'opencode':
|
||||
return OpenCodeIcon;
|
||||
case 'amazon-bedrock-anthropic':
|
||||
return AnthropicIcon;
|
||||
case 'amazon-bedrock-deepseek':
|
||||
return DeepSeekIcon;
|
||||
case 'amazon-bedrock-amazon':
|
||||
return NovaIcon;
|
||||
case 'amazon-bedrock-meta':
|
||||
return MetaIcon;
|
||||
case 'amazon-bedrock-mistral':
|
||||
return MistralIcon;
|
||||
case 'amazon-bedrock-qwen':
|
||||
return QwenIcon;
|
||||
default:
|
||||
return OpenCodeIcon;
|
||||
}
|
||||
function getModelIcon(modelId: OpencodeModelId): ComponentType<{ className?: string }> {
|
||||
return getProviderIconForModel(modelId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,11 +130,11 @@ export function OpencodeModelConfiguration({
|
||||
{enabledOpencodeModels.map((modelId) => {
|
||||
const model = OPENCODE_MODEL_CONFIG_MAP[modelId];
|
||||
if (!model) return null;
|
||||
const ProviderIconComponent = getProviderIcon(model.provider);
|
||||
const ModelIconComponent = getModelIcon(modelId);
|
||||
return (
|
||||
<SelectItem key={modelId} value={modelId}>
|
||||
<div className="flex items-center gap-2">
|
||||
<ProviderIconComponent className="w-4 h-4" />
|
||||
<ModelIconComponent className="w-4 h-4" />
|
||||
<span>{model.label}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
@@ -167,7 +151,9 @@ export function OpencodeModelConfiguration({
|
||||
const models = modelsByProvider[provider];
|
||||
if (!models || models.length === 0) return null;
|
||||
|
||||
const ProviderIconComponent = getProviderIcon(provider);
|
||||
// Use the first model's icon as the provider icon
|
||||
const ProviderIconComponent =
|
||||
models.length > 0 ? getModelIcon(models[0].id) : OpenCodeIcon;
|
||||
|
||||
return (
|
||||
<div key={provider} className="space-y-2">
|
||||
|
||||
Reference in New Issue
Block a user