@umituz/react-native-settings 4.23.44 → 4.23.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/domains/appearance/hooks/useAppearance.ts +18 -17
- package/src/domains/appearance/hooks/useAppearanceActions.ts +3 -2
- package/src/domains/appearance/application/ports/IAppearanceRepository.ts +0 -8
- package/src/domains/appearance/infrastructure/repositories/AppearanceRepository.ts +0 -34
- package/src/domains/appearance/infrastructure/services/README.md +0 -141
- package/src/domains/appearance/infrastructure/services/appearanceService.ts +0 -51
- package/src/domains/appearance/infrastructure/services/systemThemeDetection.ts +0 -73
- package/src/domains/appearance/infrastructure/services/validation.ts +0 -91
- package/src/domains/appearance/presentation/hooks/mutations/useAppearanceMutations.ts +0 -36
- package/src/domains/appearance/presentation/hooks/queries/useAppearanceQuery.ts +0 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "4.23.
|
|
3
|
+
"version": "4.23.46",
|
|
4
4
|
"description": "Complete settings hub for React Native apps - consolidated package with settings, localization, about, legal, appearance, feedback, FAQs, rating, and gamification",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useAppearanceMutations } from "../presentation/hooks/mutations/useAppearanceMutations";
|
|
3
|
-
import { ThemeMode, CustomThemeColors } from "@umituz/react-native-design-system";
|
|
1
|
+
import { useTheme, useDesignSystemTheme, type ThemeMode, type CustomThemeColors } from "@umituz/react-native-design-system";
|
|
4
2
|
|
|
5
3
|
export const useAppearance = () => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
updateThemeMutation,
|
|
9
|
-
updateColorsMutation,
|
|
10
|
-
resetAppearanceMutation
|
|
11
|
-
} = useAppearanceMutations();
|
|
4
|
+
const { themeMode, isInitialized, setThemeMode: setThemeModeAction } = useTheme();
|
|
5
|
+
const { customColors, setCustomColors: setCustomColorsAction } = useDesignSystemTheme();
|
|
12
6
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
7
|
+
return {
|
|
8
|
+
themeMode,
|
|
9
|
+
customColors,
|
|
10
|
+
isLoading: !isInitialized,
|
|
11
|
+
setThemeMode: (mode: ThemeMode) => {
|
|
12
|
+
void setThemeModeAction(mode);
|
|
13
|
+
},
|
|
14
|
+
setCustomColors: (colors: CustomThemeColors) => {
|
|
15
|
+
setCustomColorsAction(colors);
|
|
16
|
+
},
|
|
17
|
+
reset: () => {
|
|
18
|
+
void setThemeModeAction("light");
|
|
19
|
+
setCustomColorsAction(undefined);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
21
22
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect } from "react";
|
|
2
2
|
import { useAppearance } from "./useAppearance";
|
|
3
|
-
import { CustomThemeColors } from "@umituz/react-native-design-system";
|
|
3
|
+
import type { CustomThemeColors, ThemeMode } from "@umituz/react-native-design-system";
|
|
4
4
|
|
|
5
5
|
export const useAppearanceActions = () => {
|
|
6
6
|
const { themeMode, customColors, setThemeMode, setCustomColors, reset } = useAppearance();
|
|
@@ -12,7 +12,7 @@ export const useAppearanceActions = () => {
|
|
|
12
12
|
}
|
|
13
13
|
}, [customColors]);
|
|
14
14
|
|
|
15
|
-
const handleThemeSelect = useCallback((mode:
|
|
15
|
+
const handleThemeSelect = useCallback((mode: ThemeMode) => {
|
|
16
16
|
setThemeMode(mode);
|
|
17
17
|
}, [setThemeMode]);
|
|
18
18
|
|
|
@@ -28,6 +28,7 @@ export const useAppearanceActions = () => {
|
|
|
28
28
|
}, [reset]);
|
|
29
29
|
|
|
30
30
|
return {
|
|
31
|
+
themeMode,
|
|
31
32
|
localCustomColors,
|
|
32
33
|
handleThemeSelect,
|
|
33
34
|
handleColorChange,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { ThemeMode, CustomThemeColors } from "@umituz/react-native-design-system";
|
|
2
|
-
import { AppearanceSettings } from "../../types";
|
|
3
|
-
|
|
4
|
-
export interface IAppearanceRepository {
|
|
5
|
-
getSettings(): Promise<AppearanceSettings>;
|
|
6
|
-
saveSettings(settings: AppearanceSettings): Promise<void>;
|
|
7
|
-
clearSettings(): Promise<void>;
|
|
8
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { storageRepository, unwrap } from "@umituz/react-native-design-system";
|
|
2
|
-
import { IAppearanceRepository } from "../../application/ports/IAppearanceRepository";
|
|
3
|
-
import { AppearanceSettings } from "../../types";
|
|
4
|
-
|
|
5
|
-
const STORAGE_KEY = "@appearance_settings";
|
|
6
|
-
const DEFAULT_SETTINGS: AppearanceSettings = {
|
|
7
|
-
themeMode: "dark",
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export class AppearanceRepository implements IAppearanceRepository {
|
|
11
|
-
async getSettings(): Promise<AppearanceSettings> {
|
|
12
|
-
const result = await storageRepository.getItem<AppearanceSettings>(
|
|
13
|
-
STORAGE_KEY,
|
|
14
|
-
DEFAULT_SETTINGS
|
|
15
|
-
);
|
|
16
|
-
return unwrap(result, DEFAULT_SETTINGS);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async saveSettings(settings: AppearanceSettings): Promise<void> {
|
|
20
|
-
const result = await storageRepository.setItem(STORAGE_KEY, settings);
|
|
21
|
-
if (!result.success) {
|
|
22
|
-
throw new Error("Failed to save appearance settings");
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async clearSettings(): Promise<void> {
|
|
27
|
-
const result = await storageRepository.removeItem(STORAGE_KEY);
|
|
28
|
-
if (!result.success) {
|
|
29
|
-
throw new Error("Failed to clear appearance settings");
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export const getAppearanceRepository = () => new AppearanceRepository();
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
# Appearance Services
|
|
2
|
-
|
|
3
|
-
Service layer for appearance domain including system theme detection, validation, and appearance management.
|
|
4
|
-
|
|
5
|
-
## Purpose
|
|
6
|
-
|
|
7
|
-
Provides business logic services for managing appearance settings including theme mode, custom colors, and system theme detection. Services encapsulate complex operations and provide a clean API for the domain.
|
|
8
|
-
|
|
9
|
-
## File Paths
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
src/domains/appearance/infrastructure/services/
|
|
13
|
-
├── AppearanceService.ts # Main appearance management
|
|
14
|
-
├── SystemThemeDetectionService.ts # System theme detection
|
|
15
|
-
└── ValidationService.ts # Color/theme validation
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Strategy
|
|
19
|
-
|
|
20
|
-
1. **Service Encapsulation**: Encapsulate complex appearance logic in service classes
|
|
21
|
-
2. **System Integration**: Detect and respond to system theme changes
|
|
22
|
-
3. **Validation First**: Validate all appearance changes before applying
|
|
23
|
-
4. **Event-Driven**: Use event listeners for system theme changes
|
|
24
|
-
5. **Type Safety**: Provide strongly typed service interfaces
|
|
25
|
-
|
|
26
|
-
## Restrictions
|
|
27
|
-
|
|
28
|
-
### DO NOT
|
|
29
|
-
|
|
30
|
-
- ❌ DO NOT include UI components or React hooks in services
|
|
31
|
-
- ❌ DO NOT directly access storage; use repositories
|
|
32
|
-
- ❌ DO NOT mix validation logic with business logic
|
|
33
|
-
- ❌ DO NOT create circular dependencies between services
|
|
34
|
-
- ❌ DO NOT swallow validation errors
|
|
35
|
-
|
|
36
|
-
### NEVER
|
|
37
|
-
|
|
38
|
-
- ❌ NEVER apply invalid color values
|
|
39
|
-
- ❌ NEVER assume system theme is available
|
|
40
|
-
- ❌ EVER bypass validation for any reason
|
|
41
|
-
- ❌ EVER store raw hex values without validation
|
|
42
|
-
|
|
43
|
-
### AVOID
|
|
44
|
-
|
|
45
|
-
- ❌ AVOID creating god services that do too much
|
|
46
|
-
- ❌ AVOID tight coupling between services
|
|
47
|
-
- ❌ AVOID synchronous operations for appearance changes
|
|
48
|
-
- ❌ AVOID ignoring system theme change events
|
|
49
|
-
|
|
50
|
-
## Rules
|
|
51
|
-
|
|
52
|
-
### ALWAYS
|
|
53
|
-
|
|
54
|
-
- ✅ ALWAYS validate theme modes before applying
|
|
55
|
-
- ✅ ALWAYS validate hex color format before applying
|
|
56
|
-
- ✅ ALWAYS handle system theme unsubscription
|
|
57
|
-
- ✅ ALWAYS return typed results from service methods
|
|
58
|
-
- ✅ ALWAYS handle service errors gracefully
|
|
59
|
-
|
|
60
|
-
### MUST
|
|
61
|
-
|
|
62
|
-
- ✅ MUST validate all inputs before processing
|
|
63
|
-
- ✅ MUST provide clear error messages for validation failures
|
|
64
|
-
- ✅ MUST clean up event listeners on cleanup
|
|
65
|
-
- ✅ MUST respect user preferences over system defaults
|
|
66
|
-
|
|
67
|
-
### SHOULD
|
|
68
|
-
|
|
69
|
-
- ✅ SHOULD provide reactive interfaces for theme changes
|
|
70
|
-
- ✅ SHOULD cache theme detection results
|
|
71
|
-
- ✅ SHOULD offer batch operations for multiple changes
|
|
72
|
-
- ✅ SHOULD log important service operations
|
|
73
|
-
|
|
74
|
-
## AI Agent Guidelines
|
|
75
|
-
|
|
76
|
-
1. **When creating services**: Keep them focused and single-purpose
|
|
77
|
-
2. **When adding validation**: Provide clear, actionable error messages
|
|
78
|
-
3. **When detecting system theme**: Use native APIs with fallbacks
|
|
79
|
-
4. **When managing colors**: Validate hex format (#RRGGBB) before applying
|
|
80
|
-
5. **When handling errors**: Transform technical errors into user-friendly messages
|
|
81
|
-
|
|
82
|
-
## Services Reference
|
|
83
|
-
|
|
84
|
-
### AppearanceService
|
|
85
|
-
|
|
86
|
-
Main service for managing appearance settings including theme mode, custom colors, and system theme detection.
|
|
87
|
-
|
|
88
|
-
**Location**: `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/appearance/infrastructure/services/AppearanceService.ts`
|
|
89
|
-
|
|
90
|
-
**Methods**:
|
|
91
|
-
- `getThemeMode(): Promise<'light' | 'dark' | 'auto'>` - Get current theme mode
|
|
92
|
-
- `setThemeMode(mode: 'light' | 'dark' | 'auto'): Promise<void>` - Set theme mode
|
|
93
|
-
- `getCustomColors(): Promise<ColorPalette | undefined>` - Get custom colors
|
|
94
|
-
- `setCustomColors(colors: ColorPalette): Promise<void>` - Set custom colors
|
|
95
|
-
- `resetColors(): Promise<void>` - Reset to default colors
|
|
96
|
-
|
|
97
|
-
### SystemThemeDetectionService
|
|
98
|
-
|
|
99
|
-
Service for detecting and monitoring system theme changes.
|
|
100
|
-
|
|
101
|
-
**Location**: `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/appearance/infrastructure/services/SystemThemeDetectionService.ts`
|
|
102
|
-
|
|
103
|
-
**Methods**:
|
|
104
|
-
- `getSystemTheme(): 'light' | 'dark' | null` - Get current system theme
|
|
105
|
-
- `listen(callback: (theme: 'light' | 'dark') => void): () => void` - Listen for changes
|
|
106
|
-
|
|
107
|
-
### ValidationService
|
|
108
|
-
|
|
109
|
-
Service for validating appearance settings.
|
|
110
|
-
|
|
111
|
-
**Location**: `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/appearance/infrastructure/services/ValidationService.ts`
|
|
112
|
-
|
|
113
|
-
**Methods**:
|
|
114
|
-
- `validateThemeMode(mode: string): boolean` - Validate theme mode
|
|
115
|
-
- `validateColor(color: string): boolean` - Validate hex color
|
|
116
|
-
- `validateColorPalette(palette: ColorPalette): boolean` - Validate complete palette
|
|
117
|
-
|
|
118
|
-
## Color Palette Structure
|
|
119
|
-
|
|
120
|
-
**Primary**: Main brand color (#FF5722)
|
|
121
|
-
**Secondary**: Secondary brand color (#2196F3)
|
|
122
|
-
**Accent**: Highlight color (#FFC107)
|
|
123
|
-
**Background**: Background color (#FFFFFF)
|
|
124
|
-
**Surface**: Surface/card color (#F5F5F5)
|
|
125
|
-
**Error**: Error state color (#F44336)
|
|
126
|
-
**Success**: Success state color (#4CAF50)
|
|
127
|
-
**Warning**: Warning state color (#FF9800)
|
|
128
|
-
|
|
129
|
-
## Best Practices
|
|
130
|
-
|
|
131
|
-
1. **Validation**: Always validate colors before saving
|
|
132
|
-
2. **System Theme**: Respect system theme when mode is 'auto'
|
|
133
|
-
3. **Cleanup**: Unsubscribe from theme listeners on unmount
|
|
134
|
-
4. **Error Handling**: Handle invalid colors gracefully
|
|
135
|
-
5. **Hex Format**: Use proper hex color format (#RRGGBB)
|
|
136
|
-
6. **Persistence**: Save theme changes immediately
|
|
137
|
-
7. **Performance**: Cache theme detection results
|
|
138
|
-
|
|
139
|
-
## License
|
|
140
|
-
|
|
141
|
-
MIT
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useTheme,
|
|
3
|
-
useDesignSystemTheme,
|
|
4
|
-
ThemeMode,
|
|
5
|
-
CustomThemeColors
|
|
6
|
-
} from "@umituz/react-native-design-system";
|
|
7
|
-
import { IAppearanceRepository } from "../../application/ports/IAppearanceRepository";
|
|
8
|
-
import { getAppearanceRepository } from "../repositories/AppearanceRepository";
|
|
9
|
-
import { AppearanceSettings } from "../../types";
|
|
10
|
-
|
|
11
|
-
export class AppearanceService {
|
|
12
|
-
constructor(private readonly repository: IAppearanceRepository = getAppearanceRepository()) { }
|
|
13
|
-
|
|
14
|
-
async getSettings(): Promise<AppearanceSettings> {
|
|
15
|
-
return this.repository.getSettings();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async setThemeMode(mode: ThemeMode): Promise<void> {
|
|
19
|
-
const settings = await this.repository.getSettings();
|
|
20
|
-
const newSettings = { ...settings, themeMode: mode };
|
|
21
|
-
await this.repository.saveSettings(newSettings);
|
|
22
|
-
this.syncWithDesignSystem(newSettings);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async setCustomColors(colors: CustomThemeColors): Promise<void> {
|
|
26
|
-
const settings = await this.repository.getSettings();
|
|
27
|
-
const newSettings = {
|
|
28
|
-
...settings,
|
|
29
|
-
customColors: { ...settings.customColors, ...colors }
|
|
30
|
-
};
|
|
31
|
-
await this.repository.saveSettings(newSettings);
|
|
32
|
-
this.syncWithDesignSystem(newSettings);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async resetSettings(): Promise<void> {
|
|
36
|
-
await this.repository.clearSettings();
|
|
37
|
-
const defaultSettings = await this.repository.getSettings();
|
|
38
|
-
this.syncWithDesignSystem(defaultSettings);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private syncWithDesignSystem(settings: AppearanceSettings): void {
|
|
42
|
-
useTheme.getState().setThemeMode(settings.themeMode);
|
|
43
|
-
useDesignSystemTheme.getState().setThemeMode(settings.themeMode);
|
|
44
|
-
if (settings.customColors) {
|
|
45
|
-
useDesignSystemTheme.getState().setCustomColors(settings.customColors);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export const getAppearanceService = () => new AppearanceService();
|
|
51
|
-
export const appearanceService = getAppearanceService();
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* System Theme Detection Utilities
|
|
3
|
-
*
|
|
4
|
-
* Utilities for detecting device theme preferences
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { Appearance, Platform } from 'react-native';
|
|
8
|
-
import type { ThemeMode } from '@umituz/react-native-design-system';
|
|
9
|
-
|
|
10
|
-
declare const window: any;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Get system theme mode from device settings
|
|
14
|
-
* @returns System theme mode ('light' | 'dark' | null)
|
|
15
|
-
*/
|
|
16
|
-
export const getSystemTheme = (): ThemeMode | null => {
|
|
17
|
-
try {
|
|
18
|
-
// On web, use matchMedia
|
|
19
|
-
if (Platform.OS === 'web') {
|
|
20
|
-
if (typeof window !== 'undefined' && (window as any).matchMedia) {
|
|
21
|
-
const darkModeQuery = (window as any).matchMedia('(prefers-color-scheme: dark)');
|
|
22
|
-
if (darkModeQuery.matches) {
|
|
23
|
-
return 'dark';
|
|
24
|
-
}
|
|
25
|
-
return 'light';
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// On native platforms, use Appearance API
|
|
30
|
-
const colorScheme = Appearance.getColorScheme();
|
|
31
|
-
return colorScheme === 'dark' ? 'dark' : 'light';
|
|
32
|
-
} catch {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Check if system theme is dark
|
|
39
|
-
* @returns true if system prefers dark mode
|
|
40
|
-
*/
|
|
41
|
-
export const isSystemThemeDark = (): boolean => {
|
|
42
|
-
return getSystemTheme() === 'dark';
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Check if system theme is light
|
|
47
|
-
* @returns true if system prefers light mode
|
|
48
|
-
*/
|
|
49
|
-
export const isSystemThemeLight = (): boolean => {
|
|
50
|
-
return getSystemTheme() === 'light';
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Add system theme change listener
|
|
55
|
-
* @param callback - Function to call when theme changes
|
|
56
|
-
* @returns Cleanup function to remove listener
|
|
57
|
-
*/
|
|
58
|
-
export const addSystemThemeListener = (
|
|
59
|
-
callback: (themeMode: ThemeMode) => void,
|
|
60
|
-
): (() => void) => {
|
|
61
|
-
try {
|
|
62
|
-
const subscription = Appearance.addChangeListener(({ colorScheme }) => {
|
|
63
|
-
const themeMode: ThemeMode = colorScheme === 'dark' ? 'dark' : 'light';
|
|
64
|
-
callback(themeMode);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
return () => {
|
|
68
|
-
subscription?.remove();
|
|
69
|
-
};
|
|
70
|
-
} catch {
|
|
71
|
-
return () => { }; // Return empty cleanup function
|
|
72
|
-
}
|
|
73
|
-
};
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Appearance Validation Utilities
|
|
3
|
-
*
|
|
4
|
-
* Validation functions for appearance settings and colors
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { ThemeMode, CustomThemeColors } from '@umituz/react-native-design-system';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Validate theme mode
|
|
11
|
-
* @param mode - Theme mode to validate
|
|
12
|
-
* @returns true if valid theme mode
|
|
13
|
-
*/
|
|
14
|
-
export const isValidThemeMode = (mode: string): mode is ThemeMode => {
|
|
15
|
-
return mode === 'light' || mode === 'dark';
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Validate hex color format
|
|
20
|
-
* @param color - Color string to validate
|
|
21
|
-
* @returns true if valid hex color
|
|
22
|
-
*/
|
|
23
|
-
export const isValidHexColor = (color: string): boolean => {
|
|
24
|
-
if (!color || typeof color !== 'string') {
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const hexRegex = /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/;
|
|
29
|
-
return hexRegex.test(color);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Validate custom colors object
|
|
34
|
-
* @param colors - Custom colors to validate
|
|
35
|
-
* @returns Validation result with errors
|
|
36
|
-
*/
|
|
37
|
-
export const validateCustomColors = (
|
|
38
|
-
colors: CustomThemeColors
|
|
39
|
-
): { isValid: boolean; errors: string[] } => {
|
|
40
|
-
const errors: string[] = [];
|
|
41
|
-
|
|
42
|
-
// Check each color if provided
|
|
43
|
-
const colorFields: (keyof CustomThemeColors)[] = [
|
|
44
|
-
'primary', 'primaryLight', 'primaryDark',
|
|
45
|
-
'secondary', 'secondaryLight', 'secondaryDark',
|
|
46
|
-
'accent', 'accentLight', 'accentDark',
|
|
47
|
-
'buttonPrimary', 'buttonSecondary'
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
for (const field of colorFields) {
|
|
51
|
-
const color = colors[field];
|
|
52
|
-
if (color && !isValidHexColor(color)) {
|
|
53
|
-
errors.push(`Invalid ${field} color: ${color}`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
isValid: errors.length === 0,
|
|
59
|
-
errors
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Validate appearance settings
|
|
65
|
-
* @param settings - Settings to validate
|
|
66
|
-
* @returns Validation result with errors
|
|
67
|
-
*/
|
|
68
|
-
export const validateAppearanceSettings = (settings: {
|
|
69
|
-
themeMode?: string;
|
|
70
|
-
customColors?: CustomThemeColors;
|
|
71
|
-
}): { isValid: boolean; errors: string[] } => {
|
|
72
|
-
const errors: string[] = [];
|
|
73
|
-
|
|
74
|
-
// Validate theme mode
|
|
75
|
-
if (settings.themeMode && !isValidThemeMode(settings.themeMode)) {
|
|
76
|
-
errors.push(`Invalid theme mode: ${settings.themeMode}`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Validate custom colors
|
|
80
|
-
if (settings.customColors) {
|
|
81
|
-
const colorValidation = validateCustomColors(settings.customColors);
|
|
82
|
-
if (!colorValidation.isValid) {
|
|
83
|
-
errors.push(...colorValidation.errors);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
isValid: errors.length === 0,
|
|
89
|
-
errors
|
|
90
|
-
};
|
|
91
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { useMutation, useQueryClient } from "@umituz/react-native-design-system";
|
|
2
|
-
import { getAppearanceService } from "../../../infrastructure/services/appearanceService";
|
|
3
|
-
import { appearanceKeys } from "../queries/useAppearanceQuery";
|
|
4
|
-
import { ThemeMode, CustomThemeColors } from "@umituz/react-native-design-system";
|
|
5
|
-
|
|
6
|
-
export const useAppearanceMutations = () => {
|
|
7
|
-
const queryClient = useQueryClient();
|
|
8
|
-
const service = getAppearanceService();
|
|
9
|
-
|
|
10
|
-
const updateThemeMutation = useMutation({
|
|
11
|
-
mutationFn: (mode: ThemeMode) => service.setThemeMode(mode),
|
|
12
|
-
onSuccess: () => {
|
|
13
|
-
queryClient.invalidateQueries({ queryKey: appearanceKeys.settings() });
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const updateColorsMutation = useMutation({
|
|
18
|
-
mutationFn: (colors: CustomThemeColors) => service.setCustomColors(colors),
|
|
19
|
-
onSuccess: () => {
|
|
20
|
-
queryClient.invalidateQueries({ queryKey: appearanceKeys.settings() });
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const resetAppearanceMutation = useMutation({
|
|
25
|
-
mutationFn: () => service.resetSettings(),
|
|
26
|
-
onSuccess: () => {
|
|
27
|
-
queryClient.invalidateQueries({ queryKey: appearanceKeys.settings() });
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
updateThemeMutation,
|
|
33
|
-
updateColorsMutation,
|
|
34
|
-
resetAppearanceMutation,
|
|
35
|
-
};
|
|
36
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { useQuery } from "@umituz/react-native-design-system";
|
|
2
|
-
import { getAppearanceService } from "../../../infrastructure/services/appearanceService";
|
|
3
|
-
|
|
4
|
-
export const appearanceKeys = {
|
|
5
|
-
all: ["appearance"] as const,
|
|
6
|
-
settings: () => [...appearanceKeys.all, "settings"] as const,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export const useAppearanceQuery = () => {
|
|
10
|
-
const service = getAppearanceService();
|
|
11
|
-
return useQuery({
|
|
12
|
-
queryKey: appearanceKeys.settings(),
|
|
13
|
-
queryFn: () => service.getSettings(),
|
|
14
|
-
});
|
|
15
|
-
};
|