@umituz/react-native-settings 5.3.50 → 5.3.52
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/dist/account.d.ts +20 -18
- package/dist/presentation/hooks/useSettingsScreenConfig.d.ts +1 -2
- package/package.json +1 -2
- package/src/account.ts +26 -22
- package/src/domains/feedback/infrastructure/useFeatureRequests.ts +38 -6
- package/src/presentation/hooks/useSettingsScreenConfig.ts +32 -25
- package/dist/domains/feedback/domain/repositories/IFeedbackRepository.d.ts +0 -20
- package/dist/presentation/utils/faqTranslator.d.ts +0 -3
package/dist/account.d.ts
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @umituz/react-native-settings/account
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* NOTE: Auth has been removed from this application.
|
|
5
|
+
* This file now provides empty exports for backward compatibility.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* import {
|
|
9
|
-
* useSettingsScreenConfig,
|
|
10
|
-
* AccountScreen,
|
|
11
|
-
* ProfileSection,
|
|
12
|
-
* } from '@umituz/react-native-settings/account';
|
|
13
|
-
*
|
|
14
|
-
* // Pass AccountScreen and ProfileSection as props to SettingsStackNavigator:
|
|
15
|
-
* <SettingsStackNavigator
|
|
16
|
-
* AccountScreenComponent={AccountScreen}
|
|
17
|
-
* ProfileSectionComponent={ProfileSection}
|
|
18
|
-
* ...
|
|
19
|
-
* />
|
|
7
|
+
* Apps that use @umituz/react-native-auth should import directly from that package:
|
|
8
|
+
* import { AccountScreen, ProfileSection } from '@umituz/react-native-auth';
|
|
20
9
|
*/
|
|
21
|
-
export
|
|
22
|
-
export
|
|
23
|
-
export
|
|
10
|
+
export declare const AccountScreen: React.ComponentType<any> | null;
|
|
11
|
+
export declare const ProfileSection: React.ComponentType<any> | null;
|
|
12
|
+
export declare const useAuth: () => {
|
|
13
|
+
user: any;
|
|
14
|
+
loading: boolean;
|
|
15
|
+
isAuthReady: boolean;
|
|
16
|
+
isAnonymous: boolean;
|
|
17
|
+
};
|
|
18
|
+
export declare const useUserProfile: () => any;
|
|
19
|
+
export declare const useAuthHandlers: () => {
|
|
20
|
+
handleRatePress: () => Promise<void>;
|
|
21
|
+
handleSignOut: () => Promise<void>;
|
|
22
|
+
handleDeleteAccount: () => Promise<void>;
|
|
23
|
+
handleSignIn: () => Promise<void>;
|
|
24
|
+
};
|
|
25
|
+
export type AccountScreenConfig = any;
|
|
24
26
|
export { useSettingsScreenConfig } from './presentation/hooks/useSettingsScreenConfig';
|
|
25
27
|
export type { UseSettingsScreenConfigParams, SettingsScreenConfigResult, SettingsFeatures, } from './presentation/hooks/useSettingsScreenConfig';
|
|
26
28
|
export type { AccountConfig } from './presentation/navigation/types';
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* useSettingsScreenConfig Hook
|
|
3
3
|
*
|
|
4
4
|
* One-stop hook for settings screen configuration.
|
|
5
|
-
*
|
|
6
|
-
* Apps pass subscription config from subscription package.
|
|
5
|
+
* Auth has been removed - this is a no-auth version.
|
|
7
6
|
*/
|
|
8
7
|
import type { SettingsConfig, SettingsTranslations } from "../screens/types";
|
|
9
8
|
import type { FeedbackFormData } from "../utils/config-creators";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.52",
|
|
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": "./dist/index.d.ts",
|
|
@@ -166,7 +166,6 @@
|
|
|
166
166
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
167
167
|
"eslint-plugin-react-native": "^5.0.0",
|
|
168
168
|
"expo-apple-authentication": "^8.0.8",
|
|
169
|
-
"expo-auth-session": "^5.0.0",
|
|
170
169
|
"expo-clipboard": "^8.0.8",
|
|
171
170
|
"expo-crypto": "^15.0.8",
|
|
172
171
|
"expo-device": "~7.0.0",
|
package/src/account.ts
CHANGED
|
@@ -1,34 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @umituz/react-native-settings/account
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* NOTE: Auth has been removed from this application.
|
|
5
|
+
* This file now provides empty exports for backward compatibility.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* import {
|
|
9
|
-
* useSettingsScreenConfig,
|
|
10
|
-
* AccountScreen,
|
|
11
|
-
* ProfileSection,
|
|
12
|
-
* } from '@umituz/react-native-settings/account';
|
|
13
|
-
*
|
|
14
|
-
* // Pass AccountScreen and ProfileSection as props to SettingsStackNavigator:
|
|
15
|
-
* <SettingsStackNavigator
|
|
16
|
-
* AccountScreenComponent={AccountScreen}
|
|
17
|
-
* ProfileSectionComponent={ProfileSection}
|
|
18
|
-
* ...
|
|
19
|
-
* />
|
|
7
|
+
* Apps that use @umituz/react-native-auth should import directly from that package:
|
|
8
|
+
* import { AccountScreen, ProfileSection } from '@umituz/react-native-auth';
|
|
20
9
|
*/
|
|
21
10
|
|
|
22
|
-
//
|
|
23
|
-
export
|
|
11
|
+
// Empty exports for backward compatibility
|
|
12
|
+
export const AccountScreen: React.ComponentType<any> | null = null;
|
|
13
|
+
export const ProfileSection: React.ComponentType<any> | null = null;
|
|
14
|
+
|
|
15
|
+
// Stub hooks that return default values
|
|
16
|
+
export const useAuth = () => ({
|
|
17
|
+
user: null,
|
|
18
|
+
loading: false,
|
|
19
|
+
isAuthReady: true,
|
|
20
|
+
isAnonymous: true,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const useUserProfile = () => null;
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
export const useAuthHandlers = () => ({
|
|
26
|
+
handleRatePress: async () => {},
|
|
27
|
+
handleSignOut: async () => {},
|
|
28
|
+
handleDeleteAccount: async () => {},
|
|
29
|
+
handleSignIn: async () => {},
|
|
30
|
+
});
|
|
27
31
|
|
|
28
|
-
//
|
|
29
|
-
export type
|
|
32
|
+
// Empty types
|
|
33
|
+
export type AccountScreenConfig = any;
|
|
30
34
|
|
|
31
|
-
// Base hook (
|
|
35
|
+
// Base hook (no auth version)
|
|
32
36
|
export { useSettingsScreenConfig } from './presentation/hooks/useSettingsScreenConfig';
|
|
33
37
|
|
|
34
38
|
// Re-export types
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import { useState, useEffect, useCallback, useRef } from "react";
|
|
8
8
|
import { Platform } from "react-native";
|
|
9
|
-
import
|
|
9
|
+
import * as Crypto from "expo-crypto";
|
|
10
|
+
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
10
11
|
import {
|
|
11
12
|
collection,
|
|
12
13
|
doc,
|
|
@@ -29,6 +30,31 @@ import type {
|
|
|
29
30
|
} from "../domain/entities/FeatureRequestEntity";
|
|
30
31
|
|
|
31
32
|
const COLLECTION = "feature_requests";
|
|
33
|
+
const ANONYMOUS_USER_ID_KEY = "@anonymous_user_id";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get or create a persistent anonymous user ID
|
|
37
|
+
*/
|
|
38
|
+
async function getAnonymousUserId(): Promise<string> {
|
|
39
|
+
try {
|
|
40
|
+
const existingId = await AsyncStorage.getItem(ANONYMOUS_USER_ID_KEY);
|
|
41
|
+
if (existingId) return existingId;
|
|
42
|
+
|
|
43
|
+
// Create a new anonymous ID using device UUID
|
|
44
|
+
const randomBytes = await Crypto.getRandomBytesAsync(16);
|
|
45
|
+
const newId = Array.from(randomBytes)
|
|
46
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
47
|
+
.join("");
|
|
48
|
+
|
|
49
|
+
await AsyncStorage.setItem(ANONYMOUS_USER_ID_KEY, newId);
|
|
50
|
+
return newId;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
// Fallback to timestamp-based ID if crypto fails
|
|
53
|
+
const fallbackId = `anon_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
54
|
+
await AsyncStorage.setItem(ANONYMOUS_USER_ID_KEY, fallbackId);
|
|
55
|
+
return fallbackId;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
32
58
|
|
|
33
59
|
export interface UseFeatureRequestsResult {
|
|
34
60
|
requests: FeatureRequestItem[];
|
|
@@ -41,13 +67,19 @@ export interface UseFeatureRequestsResult {
|
|
|
41
67
|
}
|
|
42
68
|
|
|
43
69
|
export function useFeatureRequests(): UseFeatureRequestsResult {
|
|
44
|
-
const
|
|
45
|
-
const userId = user?.uid ?? null;
|
|
70
|
+
const [userId, setUserId] = useState<string | null>(null);
|
|
46
71
|
|
|
47
72
|
const [requests, setRequests] = useState<FeatureRequestItem[]>([]);
|
|
48
73
|
const [userVotes, setUserVotes] = useState<Record<string, VoteType>>({});
|
|
49
74
|
const [isLoading, setIsLoading] = useState(true);
|
|
50
75
|
|
|
76
|
+
// Initialize anonymous user ID
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
getAnonymousUserId().then((id) => {
|
|
79
|
+
setUserId(id);
|
|
80
|
+
});
|
|
81
|
+
}, []);
|
|
82
|
+
|
|
51
83
|
// Ref to avoid stale closure in vote()
|
|
52
84
|
const userVotesRef = useRef(userVotes);
|
|
53
85
|
userVotesRef.current = userVotes;
|
|
@@ -188,7 +220,7 @@ export function useFeatureRequests(): UseFeatureRequestsResult {
|
|
|
188
220
|
const submitRequest = useCallback(async (data: { title: string; description: string; type: string; rating?: number }) => {
|
|
189
221
|
const db = getFirestore();
|
|
190
222
|
if (!db) throw new Error("Firestore not available");
|
|
191
|
-
if (!userId) throw new Error("User not
|
|
223
|
+
if (!userId) throw new Error("User ID not available");
|
|
192
224
|
|
|
193
225
|
// Create the feature request
|
|
194
226
|
const docRef = await addDoc(collection(db, COLLECTION), {
|
|
@@ -199,7 +231,7 @@ export function useFeatureRequests(): UseFeatureRequestsResult {
|
|
|
199
231
|
votes: 1,
|
|
200
232
|
commentCount: 0,
|
|
201
233
|
createdBy: userId,
|
|
202
|
-
isAnonymous:
|
|
234
|
+
isAnonymous: true,
|
|
203
235
|
platform: Platform.OS,
|
|
204
236
|
rating: data.rating ?? null,
|
|
205
237
|
createdAt: serverTimestamp(),
|
|
@@ -213,7 +245,7 @@ export function useFeatureRequests(): UseFeatureRequestsResult {
|
|
|
213
245
|
});
|
|
214
246
|
|
|
215
247
|
await fetchAll();
|
|
216
|
-
}, [userId,
|
|
248
|
+
}, [userId, fetchAll]);
|
|
217
249
|
|
|
218
250
|
return { requests, userVotes, isLoading, vote, submitRequest, reload: fetchAll, userId };
|
|
219
251
|
}
|
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
* useSettingsScreenConfig Hook
|
|
3
3
|
*
|
|
4
4
|
* One-stop hook for settings screen configuration.
|
|
5
|
-
*
|
|
6
|
-
* Apps pass subscription config from subscription package.
|
|
5
|
+
* Auth has been removed - this is a no-auth version.
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
8
|
import { useMemo } from "react";
|
|
10
|
-
import { useAuth, useUserProfile, useAuthHandlers } from "@umituz/react-native-auth";
|
|
11
9
|
import { createUserProfileDisplay } from "../utils/userProfileUtils";
|
|
12
10
|
import { createAccountConfig, type AccountTranslations } from "../utils/accountConfigUtils";
|
|
13
11
|
import { useSettingsConfigFactory } from "../utils/settingsConfigFactory";
|
|
@@ -67,12 +65,27 @@ export const useSettingsScreenConfig = (
|
|
|
67
65
|
subscription: showSubscription = true,
|
|
68
66
|
} = features;
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
const
|
|
68
|
+
// No-auth version - always ready
|
|
69
|
+
const loading = false;
|
|
70
|
+
const isAuthReady = true;
|
|
72
71
|
|
|
73
|
-
//
|
|
74
|
-
const
|
|
75
|
-
|
|
72
|
+
// Default handlers (no-ops for no-auth version)
|
|
73
|
+
const handleRatePress = useMemo(() => async () => {
|
|
74
|
+
// Default rate behavior - could be implemented with expo-store-review
|
|
75
|
+
console.warn("[useSettingsScreenConfig] Rate press handler not implemented in no-auth version");
|
|
76
|
+
}, []);
|
|
77
|
+
|
|
78
|
+
const handleSignOut = useMemo(() => async () => {
|
|
79
|
+
// No-op in no-auth version
|
|
80
|
+
}, []);
|
|
81
|
+
|
|
82
|
+
const handleDeleteAccount = useMemo(() => async () => {
|
|
83
|
+
// No-op in no-auth version
|
|
84
|
+
}, []);
|
|
85
|
+
|
|
86
|
+
const handleSignIn = useMemo(() => async () => {
|
|
87
|
+
// No-op in no-auth version
|
|
88
|
+
}, []);
|
|
76
89
|
|
|
77
90
|
// Use settings config factory
|
|
78
91
|
const baseSettingsConfig = useSettingsConfigFactory({
|
|
@@ -133,30 +146,24 @@ export const useSettingsScreenConfig = (
|
|
|
133
146
|
return config;
|
|
134
147
|
}, [baseSettingsConfig, translations]);
|
|
135
148
|
|
|
149
|
+
// Empty user profile (no-auth version)
|
|
136
150
|
const userProfile = useMemo(() => createUserProfileDisplay({
|
|
137
|
-
profileData:
|
|
151
|
+
profileData: null,
|
|
138
152
|
onSignIn: handleSignIn,
|
|
139
|
-
}), [
|
|
153
|
+
}), [handleSignIn]);
|
|
140
154
|
|
|
155
|
+
// Minimal account config (no-auth version)
|
|
141
156
|
const accountConfig = useMemo(() => createAccountConfig({
|
|
142
|
-
displayName:
|
|
143
|
-
userId:
|
|
144
|
-
photoURL:
|
|
145
|
-
isAnonymous:
|
|
146
|
-
avatarUrl:
|
|
157
|
+
displayName: undefined,
|
|
158
|
+
userId: undefined,
|
|
159
|
+
photoURL: undefined,
|
|
160
|
+
isAnonymous: true,
|
|
161
|
+
avatarUrl: undefined,
|
|
147
162
|
onSignIn: handleSignIn,
|
|
148
163
|
onLogout: handleSignOut,
|
|
149
164
|
onDeleteAccount: handleDeleteAccount,
|
|
150
|
-
translations:
|
|
151
|
-
|
|
152
|
-
translations?.account?.logoutConfirmTitle &&
|
|
153
|
-
translations?.account?.logoutConfirmMessage &&
|
|
154
|
-
translations?.account?.deleteConfirmTitle &&
|
|
155
|
-
translations?.account?.deleteConfirmMessage &&
|
|
156
|
-
translations?.account?.cancel)
|
|
157
|
-
? translations.account as AccountTranslations
|
|
158
|
-
: undefined,
|
|
159
|
-
}), [user, userProfileData, handleSignIn, handleSignOut, handleDeleteAccount, translations]);
|
|
165
|
+
translations: undefined,
|
|
166
|
+
}), [handleSignIn, handleSignOut, handleDeleteAccount]);
|
|
160
167
|
|
|
161
168
|
return {
|
|
162
169
|
settingsConfig,
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Feedback Repository Interface
|
|
3
|
-
*/
|
|
4
|
-
import type { FeedbackEntity } from '../entities/FeedbackEntity';
|
|
5
|
-
export interface FeedbackError {
|
|
6
|
-
message: string;
|
|
7
|
-
code?: 'SUBMIT_FAILED' | 'FETCH_FAILED' | 'DELETE_FAILED' | 'VALIDATION_ERROR';
|
|
8
|
-
}
|
|
9
|
-
export type FeedbackResult<T> = {
|
|
10
|
-
success: true;
|
|
11
|
-
data: T;
|
|
12
|
-
} | {
|
|
13
|
-
success: false;
|
|
14
|
-
error: FeedbackError;
|
|
15
|
-
};
|
|
16
|
-
export interface IFeedbackRepository {
|
|
17
|
-
submitFeedback(feedback: FeedbackEntity | Omit<FeedbackEntity, 'id'>): Promise<FeedbackResult<FeedbackEntity>>;
|
|
18
|
-
getUserFeedback(userId: string): Promise<FeedbackResult<FeedbackEntity[]>>;
|
|
19
|
-
deleteFeedback(feedbackId: string): Promise<FeedbackResult<boolean>>;
|
|
20
|
-
}
|