app-expo-cli 1.0.5 → 1.0.7
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/README.md +11 -5
- package/package.json +1 -1
- package/src/copy-template.js +19 -1
- package/src/install-deps.js +6 -0
- package/template/assets/fonts/Inter_18pt-Black.ttf +0 -0
- package/template/assets/fonts/Inter_18pt-BlackItalic.ttf +0 -0
- package/template/assets/icon/index.ts +146 -0
- package/template/assets/images/about_us.png +0 -0
- package/template/assets/images/index.ts +6 -0
- package/template/assets/images/logo.png +0 -0
- package/template/assets/images/privacy_policy.png +0 -0
- package/template/assets/images/terms_and_conditions.png +0 -0
- package/template/src/app/_layout.tsx +3 -3
- package/template/src/app/auth/change_pass.tsx +18 -15
- package/template/src/app/auth/change_pass_modal.tsx +32 -51
- package/template/src/app/auth/forgot.tsx +74 -88
- package/template/src/app/auth/index.tsx +161 -192
- package/template/src/app/auth/opt_verify.tsx +93 -103
- package/template/src/app/auth/register.tsx +198 -260
- package/template/src/app/auth/reset_pass.tsx +102 -105
- package/template/src/app/index.tsx +70 -7
- package/template/src/app/modals/confirmation_logout_modal.tsx +0 -5
- package/template/src/app/modals/success_modal.tsx +28 -48
- package/template/src/app/settings/about_us.tsx +1 -1
- package/template/src/app/settings/privacy_policy.tsx +1 -1
- package/template/src/app/settings/terms_and_conditions.tsx +1 -1
- package/template/src/lib/DateTimePicker/DateTimePicker.tsx +63 -0
- package/template/src/lib/Empty/EmptyCard.tsx +67 -0
- package/template/src/lib/Error/GlobalErrorBoundary.tsx +111 -0
- package/template/src/lib/animate/AniImage.tsx +32 -0
- package/template/src/lib/backHeader/BackButton.tsx +62 -0
- package/template/src/lib/backHeader/BackWithCoponent.tsx +112 -0
- package/template/src/lib/backHeader/BackWithHeader.tsx +46 -0
- package/template/src/lib/backHeader/BackWithTitle.tsx +53 -0
- package/template/src/lib/buttons/IButton.tsx +69 -0
- package/template/src/lib/buttons/IwtButton.tsx +199 -0
- package/template/src/lib/buttons/Or.tsx +27 -0
- package/template/src/lib/buttons/SimpleButton.tsx +45 -0
- package/template/src/lib/buttons/TButton.tsx +70 -0
- package/template/src/lib/cards/Card.tsx +175 -0
- package/template/src/lib/cards/OptionSelect.tsx +44 -0
- package/template/src/lib/cards/SearchCard.tsx +35 -0
- package/template/src/lib/editor/TextEditor.tsx +81 -0
- package/template/src/lib/expend/ExpendComponent.tsx +36 -0
- package/template/src/lib/imageViewer/ImageViwer.tsx +332 -0
- package/template/src/lib/imageZoomer/ImageZoomer.tsx +104 -0
- package/template/src/lib/inputs/CheckBox.tsx +86 -0
- package/template/src/lib/inputs/InputText.tsx +232 -0
- package/template/src/lib/loader/GLoading.tsx +26 -0
- package/template/src/lib/loading/MLoading.tsx +14 -0
- package/template/src/lib/loading/SLoading.tsx +14 -0
- package/template/src/lib/modals/ActionModal.tsx +97 -0
- package/template/src/lib/modals/BottomModal.tsx +224 -0
- package/template/src/lib/modals/ConfrimationModal.tsx +116 -0
- package/template/src/lib/modals/DateModal.tsx +152 -0
- package/template/src/lib/modals/NormalModal.tsx +73 -0
- package/template/src/lib/modals/SideModal.tsx +57 -0
- package/template/src/lib/modals/Toaster.tsx +256 -0
- package/template/src/lib/payment/PaymentCardForD.tsx +47 -0
- package/template/src/lib/progressBar/ProgressBar.tsx +64 -0
- package/template/src/lib/tailwind.js +9 -0
- package/template/src/lib/ui/Avatar.tsx +55 -0
- package/template/src/redux/api-config/baseApi.ts +0 -22
- package/template/src/redux/interface/interface.ts +11 -193
- package/template/src/redux/store.ts +2 -2
- package/template/src/app/home/_layout.tsx +0 -29
- package/template/src/app/home/drawer/_layout.tsx +0 -27
- package/template/src/app/home/tabs/_layout.tsx +0 -75
- package/template/src/app/home/tabs/index.tsx +0 -11
- package/template/src/app/modals/payment_modal.tsx +0 -105
- package/template/src/hooks/useCheckLocation.ts +0 -36
- package/template/src/hooks/useDocPicker.ts +0 -83
- package/template/src/hooks/useSuggestionLocation.ts +0 -36
- package/template/src/hooks/useUploadProgress.ts +0 -127
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import Svg, { Circle } from "react-native-svg";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { View } from "react-native";
|
|
5
|
+
// CircularProgressBar.js
|
|
6
|
+
import tw from "@/src/lib/tailwind"; // Assuming you use tailwind-react-native-classnames
|
|
7
|
+
|
|
8
|
+
interface CircularProgressBarProps {
|
|
9
|
+
size?: number;
|
|
10
|
+
strokeWidth?: number;
|
|
11
|
+
progress?: number;
|
|
12
|
+
bgColor?: string;
|
|
13
|
+
progressColor?: string;
|
|
14
|
+
children?: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const CircularProgressBar = ({
|
|
18
|
+
size = 130,
|
|
19
|
+
strokeWidth = 10,
|
|
20
|
+
progress = 75, // The progress percentage (0-100)
|
|
21
|
+
bgColor = "#AFAFAF",
|
|
22
|
+
progressColor = "#FF6D00",
|
|
23
|
+
children,
|
|
24
|
+
}: CircularProgressBarProps) => {
|
|
25
|
+
// 1. Calculations
|
|
26
|
+
const radius = (size - strokeWidth) / 2;
|
|
27
|
+
const circumference = 2 * Math.PI * radius;
|
|
28
|
+
const strokeDashoffset = circumference - (circumference * progress) / 100;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<View style={tw`justify-center items-center`}>
|
|
32
|
+
<Svg width={size} height={size}>
|
|
33
|
+
{/* Background Circle */}
|
|
34
|
+
<Circle
|
|
35
|
+
stroke={bgColor}
|
|
36
|
+
fill="none"
|
|
37
|
+
cx={size / 2}
|
|
38
|
+
cy={size / 2}
|
|
39
|
+
r={radius}
|
|
40
|
+
strokeWidth={strokeWidth}
|
|
41
|
+
/>
|
|
42
|
+
|
|
43
|
+
{/* Progress Circle */}
|
|
44
|
+
<Circle
|
|
45
|
+
stroke={progressColor}
|
|
46
|
+
fill="none"
|
|
47
|
+
cx={size / 2}
|
|
48
|
+
cy={size / 2}
|
|
49
|
+
r={radius}
|
|
50
|
+
strokeWidth={strokeWidth}
|
|
51
|
+
strokeDasharray={circumference}
|
|
52
|
+
strokeDashoffset={strokeDashoffset}
|
|
53
|
+
strokeLinecap="round"
|
|
54
|
+
transform={`rotate(-90 ${size / 2} ${size / 2})`} // Start from the top
|
|
55
|
+
/>
|
|
56
|
+
</Svg>
|
|
57
|
+
|
|
58
|
+
{/* Optional: Render content in the center */}
|
|
59
|
+
<View style={tw`absolute`}>{children}</View>
|
|
60
|
+
</View>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default CircularProgressBar;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Image, View } from "react-native";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import tw from "../tailwind";
|
|
5
|
+
|
|
6
|
+
interface IAvatar {
|
|
7
|
+
source: { uri: string };
|
|
8
|
+
name?: string;
|
|
9
|
+
size?: number;
|
|
10
|
+
containerStyle?: any;
|
|
11
|
+
imageStyle?: any;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const Avatar = ({
|
|
15
|
+
source,
|
|
16
|
+
size = 30,
|
|
17
|
+
containerStyle,
|
|
18
|
+
imageStyle,
|
|
19
|
+
name,
|
|
20
|
+
}: IAvatar) => {
|
|
21
|
+
return (
|
|
22
|
+
<View style={containerStyle}>
|
|
23
|
+
{name && (
|
|
24
|
+
<Image
|
|
25
|
+
style={[
|
|
26
|
+
tw`rounded-full`,
|
|
27
|
+
{
|
|
28
|
+
height: size,
|
|
29
|
+
width: size,
|
|
30
|
+
},
|
|
31
|
+
imageStyle,
|
|
32
|
+
]}
|
|
33
|
+
source={{
|
|
34
|
+
uri: `https://ui-avatars.com/api/?background=random&name=${name}&bold=true`,
|
|
35
|
+
}}
|
|
36
|
+
/>
|
|
37
|
+
)}
|
|
38
|
+
{source && (
|
|
39
|
+
<Image
|
|
40
|
+
style={[
|
|
41
|
+
tw`rounded-full`,
|
|
42
|
+
{
|
|
43
|
+
height: size,
|
|
44
|
+
width: size,
|
|
45
|
+
},
|
|
46
|
+
imageStyle,
|
|
47
|
+
]}
|
|
48
|
+
source={source}
|
|
49
|
+
/>
|
|
50
|
+
)}
|
|
51
|
+
</View>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default Avatar;
|
|
@@ -39,21 +39,6 @@ const baseQueryWithRath: BaseQueryFn<BaseQueryArgs, unknown, unknown> = async (
|
|
|
39
39
|
},
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
// console.log(result?.headers);
|
|
43
|
-
// Check if response data is a string and malformed
|
|
44
|
-
|
|
45
|
-
// console.log(result.request, "result from base url");
|
|
46
|
-
|
|
47
|
-
// if (result?.status === 403) {
|
|
48
|
-
// AsyncStorage.removeItem("token");
|
|
49
|
-
// AsyncStorage.removeItem("user");
|
|
50
|
-
// }
|
|
51
|
-
|
|
52
|
-
// if (result?.status === 401) {
|
|
53
|
-
// AsyncStorage.removeItem("token");
|
|
54
|
-
// AsyncStorage.removeItem("user");
|
|
55
|
-
// }
|
|
56
|
-
|
|
57
42
|
return { data: result?.data };
|
|
58
43
|
} catch (error: any) {
|
|
59
44
|
return {
|
|
@@ -71,9 +56,6 @@ export const api = createApi({
|
|
|
71
56
|
tagTypes: tagTypesList,
|
|
72
57
|
});
|
|
73
58
|
|
|
74
|
-
// export const imageUrl = 'http://192.168.12.160:7000/';
|
|
75
|
-
// export const imageUrl = "http://103.186.20.114:8050";
|
|
76
|
-
|
|
77
59
|
export const getImageUrl = (url: string) => {
|
|
78
60
|
if (!url) return "";
|
|
79
61
|
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
@@ -83,7 +65,3 @@ export const getImageUrl = (url: string) => {
|
|
|
83
65
|
const path = url.replace(/^\/+/, "");
|
|
84
66
|
return `${base}/${path}`;
|
|
85
67
|
};
|
|
86
|
-
|
|
87
|
-
export const getMedia = (url: string) => {
|
|
88
|
-
return `${BaseURl}${url}`;
|
|
89
|
-
};
|
|
@@ -1,196 +1,14 @@
|
|
|
1
|
-
import { IFetchData, Paginate } from "./common";
|
|
1
|
+
// import { IFetchData, Paginate } from "./common";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
_id: string;
|
|
5
|
-
name: string;
|
|
6
|
-
display_name: string;
|
|
7
|
-
avatar: string;
|
|
8
|
-
role: string;
|
|
9
|
-
ghost: boolean;
|
|
10
|
-
bio: string;
|
|
11
|
-
verified: boolean;
|
|
12
|
-
email: string;
|
|
13
|
-
status: "active" | "inactive" | "deleted";
|
|
14
|
-
vibes: number;
|
|
15
|
-
audio: number;
|
|
16
|
-
podcast: number;
|
|
17
|
-
following: number;
|
|
18
|
-
followers: number;
|
|
19
|
-
views: number;
|
|
20
|
-
clicks: number;
|
|
21
|
-
is_friend?: boolean;
|
|
22
|
-
subscription?: Subscriptions;
|
|
23
|
-
plan?: IPlans;
|
|
24
|
-
last_post_mode: {
|
|
25
|
-
_id: string;
|
|
26
|
-
icon: string;
|
|
27
|
-
name: string;
|
|
28
|
-
};
|
|
29
|
-
}
|
|
3
|
+
//======== Example of uses ===============
|
|
30
4
|
|
|
31
|
-
export interface
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
subscription_status: string;
|
|
40
|
-
createdAt: string;
|
|
41
|
-
updatedAt: string;
|
|
42
|
-
}
|
|
5
|
+
// export interface IPrivateCircleUser {
|
|
6
|
+
// _id: string;
|
|
7
|
+
// name: string;
|
|
8
|
+
// display_name: string;
|
|
9
|
+
// avatar: string;
|
|
10
|
+
// email: string;
|
|
11
|
+
// already_added: boolean;
|
|
12
|
+
// }
|
|
43
13
|
|
|
44
|
-
export
|
|
45
|
-
_id: string;
|
|
46
|
-
file_type: string;
|
|
47
|
-
url: string;
|
|
48
|
-
is_favorite: boolean;
|
|
49
|
-
duration?: number;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export type IUserFetch = IFetchData<IUser>;
|
|
53
|
-
|
|
54
|
-
export interface IPost {
|
|
55
|
-
_id: string;
|
|
56
|
-
user: {
|
|
57
|
-
_id: string;
|
|
58
|
-
name: string;
|
|
59
|
-
avatar: string;
|
|
60
|
-
display_name: string;
|
|
61
|
-
ghost: string;
|
|
62
|
-
verified: string;
|
|
63
|
-
};
|
|
64
|
-
is_followed: boolean;
|
|
65
|
-
post_type: "audio" | "vibes" | "podcast";
|
|
66
|
-
privacy: "public" | "private_circle" | "solo";
|
|
67
|
-
private_circle: [];
|
|
68
|
-
captions: string;
|
|
69
|
-
location: {
|
|
70
|
-
address: string;
|
|
71
|
-
type: "Point";
|
|
72
|
-
coordinates: [number, number];
|
|
73
|
-
};
|
|
74
|
-
createdAt: string;
|
|
75
|
-
updatedAt: string;
|
|
76
|
-
id: string;
|
|
77
|
-
mood: {
|
|
78
|
-
_id: string;
|
|
79
|
-
name: string;
|
|
80
|
-
color: string;
|
|
81
|
-
icon: string;
|
|
82
|
-
};
|
|
83
|
-
music_station: boolean;
|
|
84
|
-
is_verified: boolean;
|
|
85
|
-
image: IMedia[];
|
|
86
|
-
audio: IMedia[];
|
|
87
|
-
podcast: IMedia[];
|
|
88
|
-
likes: number;
|
|
89
|
-
is_liked: false;
|
|
90
|
-
is_favorite: false;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export interface IMoods {
|
|
94
|
-
_id: string;
|
|
95
|
-
createdAt: string;
|
|
96
|
-
icon: string;
|
|
97
|
-
user: string;
|
|
98
|
-
name: string;
|
|
99
|
-
updatedAt: string;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export interface IFriends {
|
|
103
|
-
_id: string;
|
|
104
|
-
name: string;
|
|
105
|
-
display_name: string;
|
|
106
|
-
role: string;
|
|
107
|
-
ghost: boolean;
|
|
108
|
-
bio: string;
|
|
109
|
-
avatar: string;
|
|
110
|
-
verified: boolean;
|
|
111
|
-
email: string;
|
|
112
|
-
status: string;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export enum EPlanLevel {
|
|
116
|
-
ONE = "one",
|
|
117
|
-
TWO = "two",
|
|
118
|
-
THREE = "three",
|
|
119
|
-
FOUR = "four",
|
|
120
|
-
FIVE = "five",
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export interface IPlans {
|
|
124
|
-
_id: string;
|
|
125
|
-
name: string;
|
|
126
|
-
slug: string;
|
|
127
|
-
price: string;
|
|
128
|
-
currency: string;
|
|
129
|
-
interval: string;
|
|
130
|
-
features: string[];
|
|
131
|
-
level: EPlanLevel;
|
|
132
|
-
color: string;
|
|
133
|
-
stripe_product_id: string;
|
|
134
|
-
stripe_price_id: string;
|
|
135
|
-
isActive: string;
|
|
136
|
-
createdAt: string;
|
|
137
|
-
updatedAt: string;
|
|
138
|
-
current_plan: boolean;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
interface IStatistics {
|
|
142
|
-
price: string;
|
|
143
|
-
plan_level: string;
|
|
144
|
-
plan_name: string;
|
|
145
|
-
plan_interval: string;
|
|
146
|
-
plan_color: string;
|
|
147
|
-
is_active: boolean;
|
|
148
|
-
start_date: number;
|
|
149
|
-
end_date: number;
|
|
150
|
-
total_click: number;
|
|
151
|
-
total_views: number;
|
|
152
|
-
total_followers: number;
|
|
153
|
-
durations: number;
|
|
154
|
-
remaining_days: number;
|
|
155
|
-
days_progress: number;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export interface IComment {
|
|
159
|
-
_id: string;
|
|
160
|
-
user: {
|
|
161
|
-
_id: string;
|
|
162
|
-
name: string;
|
|
163
|
-
avatar: string;
|
|
164
|
-
};
|
|
165
|
-
edited: boolean;
|
|
166
|
-
post: string;
|
|
167
|
-
parent_comment: string;
|
|
168
|
-
comment: string;
|
|
169
|
-
createdAt: Date;
|
|
170
|
-
updatedAt: Date;
|
|
171
|
-
replies: IComment[];
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export type ICommentFetch = Paginate<IComment>;
|
|
175
|
-
|
|
176
|
-
export type ISinglePost = IFetchData<IPost>;
|
|
177
|
-
export type IFriendsFetch = IFetchData<IFriends[]>;
|
|
178
|
-
|
|
179
|
-
export type IStatisticsFetch = IFetchData<IStatistics>;
|
|
180
|
-
|
|
181
|
-
export type IPostFetch = Paginate<IPost>;
|
|
182
|
-
|
|
183
|
-
export type IPlansFetch = IFetchData<IPlans[]>;
|
|
184
|
-
|
|
185
|
-
export type IMoodsFetch = IFetchData<IMoods[]>;
|
|
186
|
-
|
|
187
|
-
export interface IPrivateCircleUser {
|
|
188
|
-
_id: string;
|
|
189
|
-
name: string;
|
|
190
|
-
display_name: string;
|
|
191
|
-
avatar: string;
|
|
192
|
-
email: string;
|
|
193
|
-
already_added: boolean;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export type IPrivateCircleUserFetch = IFetchData<IPrivateCircleUser[]>;
|
|
14
|
+
// export type IPrivateCircleUserFetch = IFetchData<IPrivateCircleUser[]>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { configureStore } from "@reduxjs/toolkit";
|
|
2
|
-
import { api } from "./api/baseApi";
|
|
3
|
-
import userSlice from "./service/
|
|
2
|
+
import { api } from "./api-config/baseApi";
|
|
3
|
+
import userSlice from "./service/demo";
|
|
4
4
|
|
|
5
5
|
const store = configureStore({
|
|
6
6
|
reducer: {
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Stack } from "expo-router";
|
|
2
|
-
|
|
3
|
-
export const unstable_settings = {
|
|
4
|
-
initialRouteName: "index",
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export default function RootLayout() {
|
|
8
|
-
// const { top, bottom } = useSafeAreaInsets();
|
|
9
|
-
return (
|
|
10
|
-
<Stack
|
|
11
|
-
screenOptions={{
|
|
12
|
-
headerShown: false,
|
|
13
|
-
// statusBarAnimation: "fade",
|
|
14
|
-
statusBarStyle: "light",
|
|
15
|
-
}}
|
|
16
|
-
>
|
|
17
|
-
<Stack.Screen name="tabs" options={{}} />
|
|
18
|
-
<Stack.Screen name="other_user" options={{}} />
|
|
19
|
-
<Stack.Screen name="post_vibe" options={{}} />
|
|
20
|
-
<Stack.Screen name="post_music" options={{}} />
|
|
21
|
-
<Stack.Screen name="post_podcast" options={{}} />
|
|
22
|
-
<Stack.Screen name="create_mood" options={{}} />
|
|
23
|
-
<Stack.Screen name="view_post" options={{}} />
|
|
24
|
-
<Stack.Screen name="report" options={{}} />
|
|
25
|
-
<Stack.Screen name="report_details" options={{}} />
|
|
26
|
-
<Stack.Screen name="appeal" options={{}} />
|
|
27
|
-
</Stack>
|
|
28
|
-
);
|
|
29
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Drawer } from "expo-router/drawer";
|
|
2
|
-
|
|
3
|
-
function CustomDrawerContent(props) {
|
|
4
|
-
return (
|
|
5
|
-
<DrawerContentScrollView {...props}>
|
|
6
|
-
<DrawerItemList {...props} />
|
|
7
|
-
<DrawerItem
|
|
8
|
-
label="Help"
|
|
9
|
-
onPress={() => Linking.openURL("https://mywebsite.com/help")}
|
|
10
|
-
/>
|
|
11
|
-
</DrawerContentScrollView>
|
|
12
|
-
);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default function Layout() {
|
|
16
|
-
return (
|
|
17
|
-
<Drawer>
|
|
18
|
-
<Drawer.Screen
|
|
19
|
-
name="index" // This is the name of the page and must match the url from root
|
|
20
|
-
options={{
|
|
21
|
-
drawerLabel: "Home",
|
|
22
|
-
title: "overview",
|
|
23
|
-
}}
|
|
24
|
-
/>
|
|
25
|
-
</Drawer>
|
|
26
|
-
);
|
|
27
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { Text, View } from "react-native";
|
|
2
|
-
|
|
3
|
-
import { Tabs } from "expo-router";
|
|
4
|
-
|
|
5
|
-
// Define your route params
|
|
6
|
-
|
|
7
|
-
// Props type for MyTabBar
|
|
8
|
-
function MyTabBar({ state, descriptors, navigation }) {
|
|
9
|
-
return (
|
|
10
|
-
<View style={{ flexDirection: "row" }}>
|
|
11
|
-
{state.routes.map((route, index) => {
|
|
12
|
-
const { options } = descriptors[route.key];
|
|
13
|
-
const label =
|
|
14
|
-
options.tabBarLabel !== undefined
|
|
15
|
-
? options.tabBarLabel
|
|
16
|
-
: options.title !== undefined
|
|
17
|
-
? options.title
|
|
18
|
-
: route.name;
|
|
19
|
-
|
|
20
|
-
const isFocused = state.index === index;
|
|
21
|
-
|
|
22
|
-
const onPress = () => {
|
|
23
|
-
const event = navigation.emit({
|
|
24
|
-
type: "tabPress",
|
|
25
|
-
target: route.key,
|
|
26
|
-
canPreventDefault: true,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
if (!isFocused && !event.defaultPrevented) {
|
|
30
|
-
navigation.navigate(route.name, route.params);
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const onLongPress = () => {
|
|
35
|
-
navigation.emit({
|
|
36
|
-
type: "tabLongPress",
|
|
37
|
-
target: route.key,
|
|
38
|
-
});
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<PlatformPressable
|
|
43
|
-
key={route.key}
|
|
44
|
-
href={buildHref(route.name, route.params)}
|
|
45
|
-
accessibilityState={isFocused ? { selected: true } : {}}
|
|
46
|
-
accessibilityLabel={options.tabBarAccessibilityLabel}
|
|
47
|
-
testID={options.tabBarButtonTestID}
|
|
48
|
-
onPress={onPress}
|
|
49
|
-
onLongPress={onLongPress}
|
|
50
|
-
style={{ flex: 1 }}
|
|
51
|
-
>
|
|
52
|
-
<Text style={{ color: isFocused ? colors.primary : colors.text }}>
|
|
53
|
-
{label}
|
|
54
|
-
</Text>
|
|
55
|
-
</PlatformPressable>
|
|
56
|
-
);
|
|
57
|
-
})}
|
|
58
|
-
</View>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export default function Layout() {
|
|
63
|
-
return (
|
|
64
|
-
<Tabs
|
|
65
|
-
screenOptions={{
|
|
66
|
-
headerShown: false,
|
|
67
|
-
tabBarHideOnKeyboard: true,
|
|
68
|
-
lazy: true,
|
|
69
|
-
}}
|
|
70
|
-
tabBar={(props: any) => <MyTabBar {...props} />}
|
|
71
|
-
>
|
|
72
|
-
<Tabs.Screen name="index" />
|
|
73
|
-
</Tabs>
|
|
74
|
-
);
|
|
75
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { _HIGHT, _WIDTH } from "@/src/utils/utils";
|
|
2
|
-
import { router, useGlobalSearchParams } from "expo-router";
|
|
3
|
-
import { Alert, View } from "react-native";
|
|
4
|
-
|
|
5
|
-
import ModalHeader from "@/src/components/ModalHeader";
|
|
6
|
-
import tw from "@/src/lib/tailwind";
|
|
7
|
-
import React from "react";
|
|
8
|
-
import { WebView } from "react-native-webview";
|
|
9
|
-
|
|
10
|
-
const userAgent =
|
|
11
|
-
"Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36";
|
|
12
|
-
|
|
13
|
-
// --- This JavaScript will try to force the loaded website's background to black ---
|
|
14
|
-
// This is useful if the website itself doesn't have a dark mode.
|
|
15
|
-
|
|
16
|
-
// --- Main Purchase Screen Component ---
|
|
17
|
-
const PurchaseScreen = () => {
|
|
18
|
-
const [data, setData] = React.useState<any>(null);
|
|
19
|
-
|
|
20
|
-
const handlePurchase = (values: any) => {
|
|
21
|
-
// console.log("Payment Details:", values);
|
|
22
|
-
Alert.alert("Payment Successful", "Your plan has been purchased.");
|
|
23
|
-
router.dismiss();
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const param = useGlobalSearchParams();
|
|
27
|
-
|
|
28
|
-
React.useLayoutEffect(() => {
|
|
29
|
-
try {
|
|
30
|
-
const parsedData = JSON?.parse(
|
|
31
|
-
Array.isArray(param.data) ? param.data[0] : param.data || "{}"
|
|
32
|
-
);
|
|
33
|
-
setData(parsedData);
|
|
34
|
-
} catch (e) {
|
|
35
|
-
console.error("Failed to parse data:", e);
|
|
36
|
-
setData({}); // Set to empty object on error
|
|
37
|
-
}
|
|
38
|
-
}, [param.data]);
|
|
39
|
-
|
|
40
|
-
// console.log(data);
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<View style={tw`flex-1 bg-black/60 justify-end items-center w-full`}>
|
|
44
|
-
<View
|
|
45
|
-
style={[
|
|
46
|
-
// Changed bg-base to bg-black to make the modal background dark
|
|
47
|
-
tw`bg-black rounded-t-2xl`,
|
|
48
|
-
{
|
|
49
|
-
height: _HIGHT * 0.9,
|
|
50
|
-
width: _WIDTH,
|
|
51
|
-
},
|
|
52
|
-
]}
|
|
53
|
-
>
|
|
54
|
-
{/* Header */}
|
|
55
|
-
<ModalHeader title="Payment" onPress={() => router.dismiss()} />
|
|
56
|
-
{data?.session_url || data?.url ? (
|
|
57
|
-
<WebView
|
|
58
|
-
// Changed bg-base to bg-black and added flex-1
|
|
59
|
-
// This makes the WebView's own background black and ensures it fills the space
|
|
60
|
-
style={tw`bg-black flex-1`}
|
|
61
|
-
source={
|
|
62
|
-
param.type === "subscription"
|
|
63
|
-
? {
|
|
64
|
-
uri: data?.session_url,
|
|
65
|
-
}
|
|
66
|
-
: {
|
|
67
|
-
uri: data?.url,
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
startInLoadingState={true}
|
|
71
|
-
userAgent={userAgent}
|
|
72
|
-
javaScriptEnabled={true}
|
|
73
|
-
domStorageEnabled={true}
|
|
74
|
-
forceDarkOn={true} // You already had this, which is correct!
|
|
75
|
-
// --- Injected JavaScript ---
|
|
76
|
-
// This runs the code from `forceDarkJS` to force the website content
|
|
77
|
-
// to have a black background, just in case forceDarkOn isn't enough.
|
|
78
|
-
// injectedJavaScript={forceDarkJS}
|
|
79
|
-
// Run this on the first load
|
|
80
|
-
onMessage={() => {}} // Required for injectedJavaScript to run on first load
|
|
81
|
-
directionalLockEnabled
|
|
82
|
-
sharedCookiesEnabled={true}
|
|
83
|
-
thirdPartyCookiesEnabled={true}
|
|
84
|
-
originWhitelist={["*"]}
|
|
85
|
-
onNavigationStateChange={(navState) => {
|
|
86
|
-
if (navState.url.includes("success")) {
|
|
87
|
-
handlePurchase(data);
|
|
88
|
-
}
|
|
89
|
-
if (navState.url.includes("cancel")) {
|
|
90
|
-
router.dismiss();
|
|
91
|
-
}
|
|
92
|
-
}}
|
|
93
|
-
/>
|
|
94
|
-
) : (
|
|
95
|
-
// Added a fallback view in case session_url is missing
|
|
96
|
-
<View style={tw`flex-1 items-center justify-center bg-black`}>
|
|
97
|
-
{/* You could put a loading spinner or error message here */}
|
|
98
|
-
</View>
|
|
99
|
-
)}
|
|
100
|
-
</View>
|
|
101
|
-
</View>
|
|
102
|
-
);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
export default PurchaseScreen;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import * as Location from "expo-location";
|
|
2
|
-
|
|
3
|
-
import { router } from "expo-router";
|
|
4
|
-
import { useState } from "react";
|
|
5
|
-
|
|
6
|
-
interface Ilocation {
|
|
7
|
-
longitude: number;
|
|
8
|
-
latitude: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const useCheckLocation = () => {
|
|
12
|
-
const [location, setLocation] = useState<Ilocation | null>(null);
|
|
13
|
-
const [loading, setLoading] = useState(false);
|
|
14
|
-
|
|
15
|
-
const getLocation = async () => {
|
|
16
|
-
setLoading(true);
|
|
17
|
-
let { status } = await Location.requestForegroundPermissionsAsync();
|
|
18
|
-
if (status !== "granted") {
|
|
19
|
-
// router?.dismiss();
|
|
20
|
-
router?.push("/modals/toaster?content=Location access denied");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
let location = await Location.getCurrentPositionAsync({});
|
|
24
|
-
// console.log(location);
|
|
25
|
-
|
|
26
|
-
const { latitude, longitude } = location.coords;
|
|
27
|
-
|
|
28
|
-
setLocation({
|
|
29
|
-
latitude,
|
|
30
|
-
longitude,
|
|
31
|
-
});
|
|
32
|
-
setLoading(false);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
return { location, loading, getLocation, setLoading };
|
|
36
|
-
};
|