mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
feat: add red theme and board background modal
- Introduced a new red theme with custom color variables for a bold aesthetic. - Updated the theme management to include the new red theme option. - Added a BoardBackgroundModal component for managing board background settings, including image uploads and opacity controls. - Enhanced KanbanCard and KanbanColumn components to support new background settings such as opacity and border visibility. - Updated API client to handle saving and deleting board backgrounds. - Refactored theme application logic to accommodate the new preview theme functionality.
This commit is contained in:
@@ -27,7 +27,8 @@ export type ThemeMode =
|
||||
| "gruvbox"
|
||||
| "catppuccin"
|
||||
| "onedark"
|
||||
| "synthwave";
|
||||
| "synthwave"
|
||||
| "red";
|
||||
|
||||
export type KanbanCardDetailLevel = "minimal" | "standard" | "detailed";
|
||||
|
||||
@@ -39,23 +40,39 @@ export interface ApiKeys {
|
||||
|
||||
// Keyboard Shortcut with optional modifiers
|
||||
export interface ShortcutKey {
|
||||
key: string; // The main key (e.g., "K", "N", "1")
|
||||
shift?: boolean; // Shift key modifier
|
||||
cmdCtrl?: boolean; // Cmd on Mac, Ctrl on Windows/Linux
|
||||
alt?: boolean; // Alt/Option key modifier
|
||||
key: string; // The main key (e.g., "K", "N", "1")
|
||||
shift?: boolean; // Shift key modifier
|
||||
cmdCtrl?: boolean; // Cmd on Mac, Ctrl on Windows/Linux
|
||||
alt?: boolean; // Alt/Option key modifier
|
||||
}
|
||||
|
||||
// Helper to parse shortcut string to ShortcutKey object
|
||||
export function parseShortcut(shortcut: string): ShortcutKey {
|
||||
const parts = shortcut.split("+").map(p => p.trim());
|
||||
const parts = shortcut.split("+").map((p) => p.trim());
|
||||
const result: ShortcutKey = { key: parts[parts.length - 1] };
|
||||
|
||||
// Normalize common OS-specific modifiers (Cmd/Ctrl/Win/Super symbols) into cmdCtrl
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
const modifier = parts[i].toLowerCase();
|
||||
if (modifier === "shift") result.shift = true;
|
||||
else if (modifier === "cmd" || modifier === "ctrl" || modifier === "win" || modifier === "super" || modifier === "⌘" || modifier === "^" || modifier === "⊞" || modifier === "◆") result.cmdCtrl = true;
|
||||
else if (modifier === "alt" || modifier === "opt" || modifier === "option" || modifier === "⌥") result.alt = true;
|
||||
else if (
|
||||
modifier === "cmd" ||
|
||||
modifier === "ctrl" ||
|
||||
modifier === "win" ||
|
||||
modifier === "super" ||
|
||||
modifier === "⌘" ||
|
||||
modifier === "^" ||
|
||||
modifier === "⊞" ||
|
||||
modifier === "◆"
|
||||
)
|
||||
result.cmdCtrl = true;
|
||||
else if (
|
||||
modifier === "alt" ||
|
||||
modifier === "opt" ||
|
||||
modifier === "option" ||
|
||||
modifier === "⌥"
|
||||
)
|
||||
result.alt = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -67,36 +84,49 @@ export function formatShortcut(shortcut: string, forDisplay = false): string {
|
||||
const parts: string[] = [];
|
||||
|
||||
// Prefer User-Agent Client Hints when available; fall back to legacy
|
||||
const platform: 'darwin' | 'win32' | 'linux' = (() => {
|
||||
if (typeof navigator === 'undefined') return 'linux';
|
||||
const platform: "darwin" | "win32" | "linux" = (() => {
|
||||
if (typeof navigator === "undefined") return "linux";
|
||||
|
||||
const uaPlatform = (navigator as Navigator & { userAgentData?: { platform?: string } })
|
||||
.userAgentData?.platform?.toLowerCase?.();
|
||||
const uaPlatform = (
|
||||
navigator as Navigator & { userAgentData?: { platform?: string } }
|
||||
).userAgentData?.platform?.toLowerCase?.();
|
||||
const legacyPlatform = navigator.platform?.toLowerCase?.();
|
||||
const platformString = uaPlatform || legacyPlatform || '';
|
||||
const platformString = uaPlatform || legacyPlatform || "";
|
||||
|
||||
if (platformString.includes('mac')) return 'darwin';
|
||||
if (platformString.includes('win')) return 'win32';
|
||||
return 'linux';
|
||||
if (platformString.includes("mac")) return "darwin";
|
||||
if (platformString.includes("win")) return "win32";
|
||||
return "linux";
|
||||
})();
|
||||
|
||||
// Primary modifier - OS-specific
|
||||
if (parsed.cmdCtrl) {
|
||||
if (forDisplay) {
|
||||
parts.push(platform === 'darwin' ? '⌘' : platform === 'win32' ? '⊞' : '◆');
|
||||
parts.push(
|
||||
platform === "darwin" ? "⌘" : platform === "win32" ? "⊞" : "◆"
|
||||
);
|
||||
} else {
|
||||
parts.push(platform === 'darwin' ? 'Cmd' : platform === 'win32' ? 'Win' : 'Super');
|
||||
parts.push(
|
||||
platform === "darwin" ? "Cmd" : platform === "win32" ? "Win" : "Super"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Alt/Option
|
||||
if (parsed.alt) {
|
||||
parts.push(forDisplay ? (platform === 'darwin' ? '⌥' : 'Alt') : (platform === 'darwin' ? 'Opt' : 'Alt'));
|
||||
parts.push(
|
||||
forDisplay
|
||||
? platform === "darwin"
|
||||
? "⌥"
|
||||
: "Alt"
|
||||
: platform === "darwin"
|
||||
? "Opt"
|
||||
: "Alt"
|
||||
);
|
||||
}
|
||||
|
||||
// Shift
|
||||
if (parsed.shift) {
|
||||
parts.push(forDisplay ? '⇧' : 'Shift');
|
||||
parts.push(forDisplay ? "⇧" : "Shift");
|
||||
}
|
||||
|
||||
parts.push(parsed.key.toUpperCase());
|
||||
@@ -139,22 +169,22 @@ export const DEFAULT_KEYBOARD_SHORTCUTS: KeyboardShortcuts = {
|
||||
context: "C",
|
||||
settings: "S",
|
||||
profiles: "M",
|
||||
|
||||
|
||||
// UI
|
||||
toggleSidebar: "`",
|
||||
|
||||
|
||||
// Actions
|
||||
// Note: Some shortcuts share the same key (e.g., "N" for addFeature, newSession, addProfile)
|
||||
// This is intentional as they are context-specific and only active in their respective views
|
||||
addFeature: "N", // Only active in board view
|
||||
addContextFile: "N", // Only active in context view
|
||||
startNext: "G", // Only active in board view
|
||||
newSession: "N", // Only active in agent view
|
||||
openProject: "O", // Global shortcut
|
||||
projectPicker: "P", // Global shortcut
|
||||
cyclePrevProject: "Q", // Global shortcut
|
||||
cycleNextProject: "E", // Global shortcut
|
||||
addProfile: "N", // Only active in profiles view
|
||||
addFeature: "N", // Only active in board view
|
||||
addContextFile: "N", // Only active in context view
|
||||
startNext: "G", // Only active in board view
|
||||
newSession: "N", // Only active in agent view
|
||||
openProject: "O", // Global shortcut
|
||||
projectPicker: "P", // Global shortcut
|
||||
cyclePrevProject: "Q", // Global shortcut
|
||||
cycleNextProject: "E", // Global shortcut
|
||||
addProfile: "N", // Only active in profiles view
|
||||
};
|
||||
|
||||
export interface ImageAttachment {
|
||||
@@ -246,7 +276,7 @@ export interface Feature {
|
||||
// Worktree info - set when a feature is being worked on in an isolated git worktree
|
||||
worktreePath?: string; // Path to the worktree directory
|
||||
branchName?: string; // Name of the feature branch
|
||||
justFinished?: boolean; // Set to true when agent just finished and moved to waiting_approval
|
||||
justFinishedAt?: string; // ISO timestamp when agent just finished and moved to waiting_approval (shows badge for 2 minutes)
|
||||
}
|
||||
|
||||
// File tree node for project analysis
|
||||
@@ -303,10 +333,13 @@ export interface AppState {
|
||||
chatHistoryOpen: boolean;
|
||||
|
||||
// Auto Mode (per-project state, keyed by project ID)
|
||||
autoModeByProject: Record<string, {
|
||||
isRunning: boolean;
|
||||
runningTasks: string[]; // Feature IDs being worked on
|
||||
}>;
|
||||
autoModeByProject: Record<
|
||||
string,
|
||||
{
|
||||
isRunning: boolean;
|
||||
runningTasks: string[]; // Feature IDs being worked on
|
||||
}
|
||||
>;
|
||||
autoModeActivityLog: AutoModeActivity[];
|
||||
maxConcurrency: number; // Maximum number of concurrent agent tasks
|
||||
|
||||
@@ -336,11 +369,22 @@ export interface AppState {
|
||||
isAnalyzing: boolean;
|
||||
|
||||
// Board Background Settings (per-project, keyed by project path)
|
||||
boardBackgroundByProject: Record<string, {
|
||||
imagePath: string | null; // Path to background image in .automaker directory
|
||||
cardOpacity: number; // Opacity of cards (0-100)
|
||||
columnOpacity: number; // Opacity of columns (0-100)
|
||||
}>;
|
||||
boardBackgroundByProject: Record<
|
||||
string,
|
||||
{
|
||||
imagePath: string | null; // Path to background image in .automaker directory
|
||||
cardOpacity: number; // Opacity of cards (0-100)
|
||||
columnOpacity: number; // Opacity of columns (0-100)
|
||||
columnBorderEnabled: boolean; // Whether to show column borders
|
||||
cardGlassmorphism: boolean; // Whether to use glassmorphism (backdrop-blur) on cards
|
||||
cardBorderEnabled: boolean; // Whether to show card borders
|
||||
cardBorderOpacity: number; // Opacity of card borders (0-100)
|
||||
hideScrollbar: boolean; // Whether to hide the board scrollbar
|
||||
}
|
||||
>;
|
||||
|
||||
// Theme Preview (for hover preview in theme selectors)
|
||||
previewTheme: ThemeMode | null;
|
||||
}
|
||||
|
||||
export interface AutoModeActivity {
|
||||
@@ -386,7 +430,8 @@ export interface AppActions {
|
||||
// Theme actions
|
||||
setTheme: (theme: ThemeMode) => void;
|
||||
setProjectTheme: (projectId: string, theme: ThemeMode | null) => void; // Set per-project theme (null to clear)
|
||||
getEffectiveTheme: () => ThemeMode; // Get the effective theme (project or global)
|
||||
getEffectiveTheme: () => ThemeMode; // Get the effective theme (project, global, or preview if set)
|
||||
setPreviewTheme: (theme: ThemeMode | null) => void; // Set preview theme for hover preview (null to clear)
|
||||
|
||||
// Feature actions
|
||||
setFeatures: (features: Feature[]) => void;
|
||||
@@ -422,7 +467,10 @@ export interface AppActions {
|
||||
addRunningTask: (projectId: string, taskId: string) => void;
|
||||
removeRunningTask: (projectId: string, taskId: string) => void;
|
||||
clearRunningTasks: (projectId: string) => void;
|
||||
getAutoModeState: (projectId: string) => { isRunning: boolean; runningTasks: string[] };
|
||||
getAutoModeState: (projectId: string) => {
|
||||
isRunning: boolean;
|
||||
runningTasks: string[];
|
||||
};
|
||||
addAutoModeActivity: (
|
||||
activity: Omit<AutoModeActivity, "id" | "timestamp">
|
||||
) => void;
|
||||
@@ -462,14 +510,31 @@ export interface AppActions {
|
||||
clearAnalysis: () => void;
|
||||
|
||||
// Agent Session actions
|
||||
setLastSelectedSession: (projectPath: string, sessionId: string | null) => void;
|
||||
setLastSelectedSession: (
|
||||
projectPath: string,
|
||||
sessionId: string | null
|
||||
) => void;
|
||||
getLastSelectedSession: (projectPath: string) => string | null;
|
||||
|
||||
// Board Background actions
|
||||
setBoardBackground: (projectPath: string, imagePath: string | null) => void;
|
||||
setCardOpacity: (projectPath: string, opacity: number) => void;
|
||||
setColumnOpacity: (projectPath: string, opacity: number) => void;
|
||||
getBoardBackground: (projectPath: string) => { imagePath: string | null; cardOpacity: number; columnOpacity: number };
|
||||
setColumnBorderEnabled: (projectPath: string, enabled: boolean) => void;
|
||||
getBoardBackground: (projectPath: string) => {
|
||||
imagePath: string | null;
|
||||
cardOpacity: number;
|
||||
columnOpacity: number;
|
||||
columnBorderEnabled: boolean;
|
||||
cardGlassmorphism: boolean;
|
||||
cardBorderEnabled: boolean;
|
||||
cardBorderOpacity: number;
|
||||
hideScrollbar: boolean;
|
||||
};
|
||||
setCardGlassmorphism: (projectPath: string, enabled: boolean) => void;
|
||||
setCardBorderEnabled: (projectPath: string, enabled: boolean) => void;
|
||||
setCardBorderOpacity: (projectPath: string, opacity: number) => void;
|
||||
setHideScrollbar: (projectPath: string, hide: boolean) => void;
|
||||
clearBoardBackground: (projectPath: string) => void;
|
||||
|
||||
// Reset
|
||||
@@ -481,7 +546,8 @@ const DEFAULT_AI_PROFILES: AIProfile[] = [
|
||||
{
|
||||
id: "profile-heavy-task",
|
||||
name: "Heavy Task",
|
||||
description: "Claude Opus with Ultrathink for complex architecture, migrations, or deep debugging.",
|
||||
description:
|
||||
"Claude Opus with Ultrathink for complex architecture, migrations, or deep debugging.",
|
||||
model: "opus",
|
||||
thinkingLevel: "ultrathink",
|
||||
provider: "claude",
|
||||
@@ -491,7 +557,8 @@ const DEFAULT_AI_PROFILES: AIProfile[] = [
|
||||
{
|
||||
id: "profile-balanced",
|
||||
name: "Balanced",
|
||||
description: "Claude Sonnet with medium thinking for typical development tasks.",
|
||||
description:
|
||||
"Claude Sonnet with medium thinking for typical development tasks.",
|
||||
model: "sonnet",
|
||||
thinkingLevel: "medium",
|
||||
provider: "claude",
|
||||
@@ -574,6 +641,7 @@ const initialState: AppState = {
|
||||
projectAnalysis: null,
|
||||
isAnalyzing: false,
|
||||
boardBackgroundByProject: {},
|
||||
previewTheme: null,
|
||||
};
|
||||
|
||||
export const useAppStore = create<AppState & AppActions>()(
|
||||
@@ -699,7 +767,9 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
// Add to project history (MRU order)
|
||||
const currentHistory = get().projectHistory;
|
||||
// Remove this project if it's already in history
|
||||
const filteredHistory = currentHistory.filter((id) => id !== project.id);
|
||||
const filteredHistory = currentHistory.filter(
|
||||
(id) => id !== project.id
|
||||
);
|
||||
// Add to the front (most recent)
|
||||
const newHistory = [project.id, ...filteredHistory];
|
||||
// Reset history index to 0 (current project)
|
||||
@@ -739,7 +809,7 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
currentProject: targetProject,
|
||||
projectHistory: validHistory,
|
||||
projectHistoryIndex: newIndex,
|
||||
currentView: "board"
|
||||
currentView: "board",
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -764,9 +834,8 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
if (currentIndex === -1) currentIndex = 0;
|
||||
|
||||
// Move to the previous index (going forward = lower index), wrapping around
|
||||
const newIndex = currentIndex <= 0
|
||||
? validHistory.length - 1
|
||||
: currentIndex - 1;
|
||||
const newIndex =
|
||||
currentIndex <= 0 ? validHistory.length - 1 : currentIndex - 1;
|
||||
const targetProjectId = validHistory[newIndex];
|
||||
const targetProject = projects.find((p) => p.id === targetProjectId);
|
||||
|
||||
@@ -776,7 +845,7 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
currentProject: targetProject,
|
||||
projectHistory: validHistory,
|
||||
projectHistoryIndex: newIndex,
|
||||
currentView: "board"
|
||||
currentView: "board",
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -828,6 +897,11 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
},
|
||||
|
||||
getEffectiveTheme: () => {
|
||||
// If preview theme is set, use it (for hover preview)
|
||||
const previewTheme = get().previewTheme;
|
||||
if (previewTheme) {
|
||||
return previewTheme;
|
||||
}
|
||||
const currentProject = get().currentProject;
|
||||
// If current project has a theme set, use it
|
||||
if (currentProject?.theme) {
|
||||
@@ -837,6 +911,8 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
return get().theme;
|
||||
},
|
||||
|
||||
setPreviewTheme: (theme) => set({ previewTheme: theme }),
|
||||
|
||||
// Feature actions
|
||||
setFeatures: (features) => set({ features }),
|
||||
|
||||
@@ -988,7 +1064,10 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
// Auto Mode actions (per-project)
|
||||
setAutoModeRunning: (projectId, running) => {
|
||||
const current = get().autoModeByProject;
|
||||
const projectState = current[projectId] || { isRunning: false, runningTasks: [] };
|
||||
const projectState = current[projectId] || {
|
||||
isRunning: false,
|
||||
runningTasks: [],
|
||||
};
|
||||
set({
|
||||
autoModeByProject: {
|
||||
...current,
|
||||
@@ -999,7 +1078,10 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
|
||||
addRunningTask: (projectId, taskId) => {
|
||||
const current = get().autoModeByProject;
|
||||
const projectState = current[projectId] || { isRunning: false, runningTasks: [] };
|
||||
const projectState = current[projectId] || {
|
||||
isRunning: false,
|
||||
runningTasks: [],
|
||||
};
|
||||
if (!projectState.runningTasks.includes(taskId)) {
|
||||
set({
|
||||
autoModeByProject: {
|
||||
@@ -1015,13 +1097,18 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
|
||||
removeRunningTask: (projectId, taskId) => {
|
||||
const current = get().autoModeByProject;
|
||||
const projectState = current[projectId] || { isRunning: false, runningTasks: [] };
|
||||
const projectState = current[projectId] || {
|
||||
isRunning: false,
|
||||
runningTasks: [],
|
||||
};
|
||||
set({
|
||||
autoModeByProject: {
|
||||
...current,
|
||||
[projectId]: {
|
||||
...projectState,
|
||||
runningTasks: projectState.runningTasks.filter((id) => id !== taskId),
|
||||
runningTasks: projectState.runningTasks.filter(
|
||||
(id) => id !== taskId
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1029,7 +1116,10 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
|
||||
clearRunningTasks: (projectId) => {
|
||||
const current = get().autoModeByProject;
|
||||
const projectState = current[projectId] || { isRunning: false, runningTasks: [] };
|
||||
const projectState = current[projectId] || {
|
||||
isRunning: false,
|
||||
runningTasks: [],
|
||||
};
|
||||
set({
|
||||
autoModeByProject: {
|
||||
...current,
|
||||
@@ -1170,7 +1260,16 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
// Board Background actions
|
||||
setBoardBackground: (projectPath, imagePath) => {
|
||||
const current = get().boardBackgroundByProject;
|
||||
const existing = current[projectPath] || { imagePath: null, cardOpacity: 100, columnOpacity: 100 };
|
||||
const existing = current[projectPath] || {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
columnBorderEnabled: true,
|
||||
cardGlassmorphism: true,
|
||||
cardBorderEnabled: true,
|
||||
cardBorderOpacity: 100,
|
||||
hideScrollbar: false,
|
||||
};
|
||||
set({
|
||||
boardBackgroundByProject: {
|
||||
...current,
|
||||
@@ -1184,7 +1283,16 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
|
||||
setCardOpacity: (projectPath, opacity) => {
|
||||
const current = get().boardBackgroundByProject;
|
||||
const existing = current[projectPath] || { imagePath: null, cardOpacity: 100, columnOpacity: 100 };
|
||||
const existing = current[projectPath] || {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
columnBorderEnabled: true,
|
||||
cardGlassmorphism: true,
|
||||
cardBorderEnabled: true,
|
||||
cardBorderOpacity: 100,
|
||||
hideScrollbar: false,
|
||||
};
|
||||
set({
|
||||
boardBackgroundByProject: {
|
||||
...current,
|
||||
@@ -1198,7 +1306,16 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
|
||||
setColumnOpacity: (projectPath, opacity) => {
|
||||
const current = get().boardBackgroundByProject;
|
||||
const existing = current[projectPath] || { imagePath: null, cardOpacity: 100, columnOpacity: 100 };
|
||||
const existing = current[projectPath] || {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
columnBorderEnabled: true,
|
||||
cardGlassmorphism: true,
|
||||
cardBorderEnabled: true,
|
||||
cardBorderOpacity: 100,
|
||||
hideScrollbar: false,
|
||||
};
|
||||
set({
|
||||
boardBackgroundByProject: {
|
||||
...current,
|
||||
@@ -1212,18 +1329,153 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
|
||||
getBoardBackground: (projectPath) => {
|
||||
const settings = get().boardBackgroundByProject[projectPath];
|
||||
return settings || { imagePath: null, cardOpacity: 100, columnOpacity: 100 };
|
||||
return (
|
||||
settings || {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
columnBorderEnabled: true,
|
||||
cardGlassmorphism: true,
|
||||
cardBorderEnabled: true,
|
||||
cardBorderOpacity: 100,
|
||||
hideScrollbar: false,
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
clearBoardBackground: (projectPath) => {
|
||||
setColumnBorderEnabled: (projectPath, enabled) => {
|
||||
const current = get().boardBackgroundByProject;
|
||||
const existing = current[projectPath] || {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
columnBorderEnabled: true,
|
||||
cardGlassmorphism: true,
|
||||
cardBorderEnabled: true,
|
||||
cardBorderOpacity: 100,
|
||||
hideScrollbar: false,
|
||||
};
|
||||
set({
|
||||
boardBackgroundByProject: {
|
||||
...current,
|
||||
[projectPath]: {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
...existing,
|
||||
columnBorderEnabled: enabled,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
setCardGlassmorphism: (projectPath, enabled) => {
|
||||
const current = get().boardBackgroundByProject;
|
||||
const existing = current[projectPath] || {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
columnBorderEnabled: true,
|
||||
cardGlassmorphism: true,
|
||||
cardBorderEnabled: true,
|
||||
cardBorderOpacity: 100,
|
||||
hideScrollbar: false,
|
||||
};
|
||||
set({
|
||||
boardBackgroundByProject: {
|
||||
...current,
|
||||
[projectPath]: {
|
||||
...existing,
|
||||
cardGlassmorphism: enabled,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
setCardBorderEnabled: (projectPath, enabled) => {
|
||||
const current = get().boardBackgroundByProject;
|
||||
const existing = current[projectPath] || {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
columnBorderEnabled: true,
|
||||
cardGlassmorphism: true,
|
||||
cardBorderEnabled: true,
|
||||
cardBorderOpacity: 100,
|
||||
hideScrollbar: false,
|
||||
};
|
||||
set({
|
||||
boardBackgroundByProject: {
|
||||
...current,
|
||||
[projectPath]: {
|
||||
...existing,
|
||||
cardBorderEnabled: enabled,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
setCardBorderOpacity: (projectPath, opacity) => {
|
||||
const current = get().boardBackgroundByProject;
|
||||
const existing = current[projectPath] || {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
columnBorderEnabled: true,
|
||||
cardGlassmorphism: true,
|
||||
cardBorderEnabled: true,
|
||||
cardBorderOpacity: 100,
|
||||
hideScrollbar: false,
|
||||
};
|
||||
set({
|
||||
boardBackgroundByProject: {
|
||||
...current,
|
||||
[projectPath]: {
|
||||
...existing,
|
||||
cardBorderOpacity: opacity,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
setHideScrollbar: (projectPath, hide) => {
|
||||
const current = get().boardBackgroundByProject;
|
||||
const existing = current[projectPath] || {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
columnBorderEnabled: true,
|
||||
cardGlassmorphism: true,
|
||||
cardBorderEnabled: true,
|
||||
cardBorderOpacity: 100,
|
||||
hideScrollbar: false,
|
||||
};
|
||||
set({
|
||||
boardBackgroundByProject: {
|
||||
...current,
|
||||
[projectPath]: {
|
||||
...existing,
|
||||
hideScrollbar: hide,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
clearBoardBackground: (projectPath) => {
|
||||
const current = get().boardBackgroundByProject;
|
||||
const existing = current[projectPath] || {
|
||||
imagePath: null,
|
||||
cardOpacity: 100,
|
||||
columnOpacity: 100,
|
||||
columnBorderEnabled: true,
|
||||
cardGlassmorphism: true,
|
||||
cardBorderEnabled: true,
|
||||
cardBorderOpacity: 100,
|
||||
hideScrollbar: false,
|
||||
};
|
||||
set({
|
||||
boardBackgroundByProject: {
|
||||
...current,
|
||||
[projectPath]: {
|
||||
...existing,
|
||||
imagePath: null, // Only clear the image, preserve other settings
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user