@umituz/react-native-settings 4.23.131 → 4.23.133

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-settings",
3
- "version": "4.23.131",
3
+ "version": "4.23.133",
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,11 +1,11 @@
1
1
  /**
2
2
  * StatsCard Component - Modern Design
3
- * Clean card-based stat display with emoji icons
3
+ * Clean card-based stat display with large emoji icons
4
4
  */
5
5
 
6
6
  import React from "react";
7
7
  import { View, StyleSheet, type ViewStyle, type TextStyle } from "react-native";
8
- import { useAppDesignTokens, AtomicText, useResponsive } from "@umituz/react-native-design-system";
8
+ import { useAppDesignTokens, AtomicText, useResponsive, withAlpha } from "@umituz/react-native-design-system";
9
9
 
10
10
  export interface StatsCardProps {
11
11
  value: number;
@@ -35,7 +35,7 @@ export const StatsCard: React.FC<StatsCardProps> = ({
35
35
  subtextColor,
36
36
  }) => {
37
37
  const tokens = useAppDesignTokens();
38
- const { getFontSize } = useResponsive();
38
+ const { getFontSize, getIconSize } = useResponsive();
39
39
 
40
40
  const finalAccentColor = accentColor || tokens.colors.primary;
41
41
  const finalBackgroundColor = backgroundColor || tokens.colors.surface;
@@ -44,7 +44,7 @@ export const StatsCard: React.FC<StatsCardProps> = ({
44
44
  const valueFontSize = getFontSize(48);
45
45
  const suffixFontSize = getFontSize(16);
46
46
  const labelFontSize = getFontSize(12);
47
- const emojiSize = getFontSize(32);
47
+ const iconSize = getIconSize(56);
48
48
 
49
49
  return (
50
50
  <View style={[
@@ -61,17 +61,27 @@ export const StatsCard: React.FC<StatsCardProps> = ({
61
61
  },
62
62
  containerStyle
63
63
  ]}>
64
- {/* Emoji Icon at Top */}
64
+ {/* Emoji Icon in Circle */}
65
65
  {icon && (
66
- <AtomicText style={[
67
- styles.emoji,
66
+ <View style={[
67
+ styles.iconContainer,
68
68
  {
69
- fontSize: emojiSize,
70
- marginBottom: tokens.spacing.sm,
69
+ width: iconSize,
70
+ height: iconSize,
71
+ backgroundColor: withAlpha(finalAccentColor, 0.15),
72
+ borderRadius: iconSize / 2,
73
+ marginBottom: tokens.spacing.md,
71
74
  }
72
75
  ]}>
73
- {icon}
74
- </AtomicText>
76
+ <AtomicText style={[
77
+ styles.emoji,
78
+ {
79
+ fontSize: iconSize * 0.55,
80
+ }
81
+ ]}>
82
+ {icon}
83
+ </AtomicText>
84
+ </View>
75
85
  )}
76
86
 
77
87
  {/* Large Value in Center */}
@@ -122,6 +132,10 @@ const styles = StyleSheet.create({
122
132
  minWidth: "45%",
123
133
  alignItems: "center",
124
134
  },
135
+ iconContainer: {
136
+ justifyContent: "center",
137
+ alignItems: "center",
138
+ },
125
139
  emoji: {
126
140
  textAlign: "center",
127
141
  },
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * StreakDisplay Component - Modern Design
3
- * Clean card-based design with emoji icons
3
+ * Clean card-based design with gradient fire icon
4
4
  */
5
5
 
6
6
  import React from "react";
@@ -36,7 +36,7 @@ export const StreakDisplay: React.FC<StreakDisplayProps> = ({
36
36
  subtextColor,
37
37
  }) => {
38
38
  const tokens = useAppDesignTokens();
39
- const { getFontSize } = useResponsive();
39
+ const { getFontSize, getIconSize } = useResponsive();
40
40
 
41
41
  const finalPrimaryColor = primaryColor || tokens.colors.primary;
42
42
  const finalBackgroundColor = backgroundColor || tokens.colors.surface;
@@ -46,6 +46,7 @@ export const StreakDisplay: React.FC<StreakDisplayProps> = ({
46
46
  const streakLabelSize = getFontSize(13);
47
47
  const bestNumberSize = getFontSize(20);
48
48
  const bestLabelSize = getFontSize(11);
49
+ const iconSize = getIconSize(48);
49
50
 
50
51
  return (
51
52
  <View style={[
@@ -64,7 +65,24 @@ export const StreakDisplay: React.FC<StreakDisplayProps> = ({
64
65
  ]}>
65
66
  {/* Main Streak Section */}
66
67
  <View style={styles.mainSection}>
67
- <AtomicText style={styles.emoji}>🔥</AtomicText>
68
+ {/* Fire Icon */}
69
+ <View style={[
70
+ styles.fireIcon,
71
+ {
72
+ width: iconSize,
73
+ height: iconSize,
74
+ backgroundColor: withAlpha(finalPrimaryColor, 0.15),
75
+ borderRadius: iconSize / 2,
76
+ }
77
+ ]}>
78
+ <AtomicText style={[
79
+ styles.fireEmoji,
80
+ { fontSize: iconSize * 0.6 }
81
+ ]}>
82
+ 🔥
83
+ </AtomicText>
84
+ </View>
85
+
68
86
  <View style={styles.streakNumbers}>
69
87
  <View style={styles.currentStreak}>
70
88
  <AtomicText style={[
@@ -139,8 +157,12 @@ const styles = StyleSheet.create({
139
157
  gap: 16,
140
158
  flex: 1,
141
159
  },
142
- emoji: {
143
- fontSize: 40,
160
+ fireIcon: {
161
+ justifyContent: "center",
162
+ alignItems: "center",
163
+ },
164
+ fireEmoji: {
165
+ textAlign: "center",
144
166
  },
145
167
  streakNumbers: {
146
168
  flex: 1,
@@ -19,6 +19,11 @@ async function translateMissing(targetDir, srcDir) {
19
19
 
20
20
  // Integrated Workflow: Ensure setup and sync
21
21
  const skipSync = process.argv.includes('--no-sync');
22
+ const forceRetranslate = process.argv.includes('--force');
23
+
24
+ if (forceRetranslate) {
25
+ console.log('⚠️ Force re-translation mode enabled. All keys will be re-translated.\n');
26
+ }
22
27
 
23
28
  if (!fs.existsSync(path.join(localesDir, 'index.ts'))) {
24
29
  console.log('🔄 Initializing localization setup...');
@@ -48,28 +53,28 @@ async function translateMissing(targetDir, srcDir) {
48
53
  if (!targetLang || targetLang === 'en') continue;
49
54
 
50
55
  console.log(`🌍 Translating ${langCode} (${langName})...`);
51
-
56
+
52
57
  const targetPath = path.join(localesDir, file);
53
58
  const target = parseTypeScriptFile(targetPath);
54
-
59
+
55
60
  const stats = { count: 0, checked: 0, translatedKeys: [] };
56
- await translateObject(enUS, target, targetLang, '', stats);
57
-
61
+ await translateObject(enUS, target, targetLang, '', stats, { forceRetranslate });
62
+
58
63
  // Clear progress line
59
64
  process.stdout.write('\r' + ' '.repeat(80) + '\r');
60
65
 
61
66
  if (stats.count > 0) {
62
67
  const content = generateTypeScriptContent(target, langCode);
63
68
  fs.writeFileSync(targetPath, content);
64
-
69
+
65
70
  console.log(` ✅ Successfully translated ${stats.count} keys:`);
66
-
71
+
67
72
  // Detailed logging of translated keys
68
73
  const displayCount = Math.min(stats.translatedKeys.length, 15);
69
74
  stats.translatedKeys.slice(0, displayCount).forEach(item => {
70
75
  console.log(` • ${item.key}: "${item.from}" → "${item.to}"`);
71
76
  });
72
-
77
+
73
78
  if (stats.translatedKeys.length > displayCount) {
74
79
  console.log(` ... and ${stats.translatedKeys.length - displayCount} more.`);
75
80
  }
@@ -32,7 +32,7 @@ async function translateText(text, targetLang) {
32
32
  }
33
33
  }
34
34
 
35
- function needsTranslation(value, enValue) {
35
+ function needsTranslation(value, enValue, forceRetranslate = false) {
36
36
  if (typeof enValue !== 'string' || !enValue.trim()) return false;
37
37
  if (shouldSkipWord(enValue)) return false;
38
38
 
@@ -49,13 +49,25 @@ function needsTranslation(value, enValue) {
49
49
  return !isSingleWord;
50
50
  }
51
51
 
52
+ // Force re-translation if flag is set
53
+ if (forceRetranslate) return true;
54
+
55
+ // Detect outdated template patterns (e.g., {{appName}}, {{variable}})
56
+ if (value && typeof value === 'string') {
57
+ const hasTemplatePattern = value.includes('{{') && value.includes('}}');
58
+ if (hasTemplatePattern && !enValue.includes('{{')) {
59
+ return true;
60
+ }
61
+ }
62
+
52
63
  return false;
53
64
  }
54
65
 
55
- export async function translateObject(enObj, targetObj, targetLang, path = '', stats = { count: 0, checked: 0, translatedKeys: [] }) {
66
+ export async function translateObject(enObj, targetObj, targetLang, path = '', stats = { count: 0, checked: 0, translatedKeys: [] }, options = {}) {
56
67
  const keys = Object.keys(enObj);
57
-
68
+
58
69
  if (!stats.translatedKeys) stats.translatedKeys = [];
70
+ const { forceRetranslate = false } = options;
59
71
 
60
72
  for (const key of keys) {
61
73
  const enValue = enObj[key];
@@ -64,13 +76,13 @@ export async function translateObject(enObj, targetObj, targetLang, path = '', s
64
76
 
65
77
  if (typeof enValue === 'object' && enValue !== null) {
66
78
  if (!targetObj[key] || typeof targetObj[key] !== 'object') targetObj[key] = {};
67
- await translateObject(enValue, targetObj[key], targetLang, currentPath, stats);
79
+ await translateObject(enValue, targetObj[key], targetLang, currentPath, stats, options);
68
80
  } else if (typeof enValue === 'string') {
69
81
  stats.checked++;
70
- if (needsTranslation(targetValue, enValue)) {
82
+ if (needsTranslation(targetValue, enValue, forceRetranslate)) {
71
83
  // Show progress for translations
72
84
  process.stdout.write(` \r Progress: ${stats.checked} keys checked, ${stats.count} translated...`);
73
-
85
+
74
86
  const translated = await translateText(enValue, targetLang);
75
87
  if (translated !== enValue) {
76
88
  targetObj[key] = translated;