login and sign up with account

master
Netcup Gituser 2023-12-09 23:57:16 +01:00
parent 0c25cc8e36
commit aebc1e4b79
29 changed files with 832 additions and 439 deletions

View File

@ -10,16 +10,22 @@ import LinearGradient from 'react-native-linear-gradient';
import {MyIcon} from './MyIcon';
import {useSelector} from 'react-redux';
import {RootState} from '@redux/store';
import {Text} from '@gluestack-ui/themed';
import {Spinner, Text} from '@gluestack-ui/themed';
import {MyTouchableOpacity} from './MyTouchableOpacity';
import {TouchableOpacityProps} from 'react-native';
interface MyImageButtonProps {
interface MyImageButtonProps extends TouchableOpacityProps {
image: ImageSourcePropType;
imageStyle?: StyleProp<ImageStyle>;
text: string;
}
export function MyImageButton({image, imageStyle, text}: MyImageButtonProps) {
export function MyImageButton({
image,
imageStyle,
text,
...rest
}: MyImageButtonProps) {
const currentTheme = useSelector(
(state: RootState) => state.nonSaveVariables.theme.colors,
);
@ -32,7 +38,8 @@ export function MyImageButton({image, imageStyle, text}: MyImageButtonProps) {
padding: 10,
flexDirection: 'row',
borderRadius: 10,
}}>
}}
{...rest}>
<Image source={image} style={imageStyle} />
<Text
bold
@ -53,6 +60,7 @@ interface MyButtonProps {
text: string;
onPress?: () => void;
disabled?: boolean;
isLoading?: boolean;
}
export function MyButton({
@ -61,15 +69,21 @@ export function MyButton({
text,
onPress,
disabled,
isLoading,
...rest
}: MyButtonProps) {
const currentTheme = useSelector(
(state: RootState) => state.nonSaveVariables.theme,
);
const ButtonText = () => (
<Text color={currentTheme.colors.white} bold size="lg">
{text}
</Text>
<View style={{flexDirection: 'row', gap: 10, alignItems: 'center'}}>
{isLoading && <Spinner color="$primary100" />}
<Text color="$white" bold size="lg">
{text}
</Text>
</View>
);
return (
@ -80,8 +94,9 @@ export function MyButton({
borderRadius: 10,
},
]}
disabled={disabled}
onPress={onPress}>
disabled={disabled || isLoading}
onPress={onPress}
{...rest}>
{type === 'primary' ? (
<LinearGradient
colors={[

131
src/components/MyToast.tsx Normal file
View File

@ -0,0 +1,131 @@
import {Alert, CloseIcon, useToast} from '@gluestack-ui/themed';
import {HStack} from '@gluestack-ui/themed';
import {Text} from '@gluestack-ui/themed';
import {VStack} from '@gluestack-ui/themed';
import {AlertIcon} from '@gluestack-ui/themed';
import {MyButton} from './MyButton';
const Toast = () => {
const toast = useToast();
const ToastDetails = [
{
title: 'Account verified',
variant: 'solid',
description: 'Thanks for signing up with us.',
isClosable: true,
},
{
title: 'Something went wrong',
variant: 'subtle',
description: 'Please create a support ticket from the support page',
},
{
title: 'Network connection restored',
variant: 'left-accent',
description:
'This is to inform you that your network connectivity is restored',
isClosable: true,
},
{
title: 'Invalid email address',
variant: 'top-accent',
description: 'Please enter a valid email address',
},
{
title: 'Invalid email address',
variant: 'outline',
description: 'Please enter a valid email address',
},
];
};
interface toastType {
id?: string;
action?: 'info' | 'error' | 'success' | 'warning' | 'muted' | undefined;
variant: 'solid' | 'outline' | 'accent' | undefined;
title: any;
description: any;
isClosable?: boolean;
rest: any;
}
interface alertType extends toastType {
id: string;
}
function showToast(toast: any, item: toastType) {
const ToastAlert = ({
id,
action,
variant,
title,
description,
isClosable,
rest,
}: alertType) => (
<Alert
maxWidth="95%"
alignSelf="center"
flexDirection="row"
action={action}
variant={variant}
{...rest}>
<VStack space="xs" flexShrink={1} w="100%">
<HStack
flexShrink={1}
alignItems="center"
justifyContent="space-between">
<HStack space="sm" flexShrink={1} alignItems="center">
<AlertIcon />
<Text
fontWeight="medium"
flexShrink={1}
color={
variant === 'solid'
? '$white'
: variant !== 'outline'
? '$black'
: null
}>
{title}
</Text>
</HStack>
{isClosable ? (
<MyButton
type="secondary"
text="X"
onPress={() => toast.close(id)}
/>
) : /*<IconButton
variant="unstyled"
icon={<CloseIcon size="3" />}
_icon={{
color: variant === 'solid' ? 'lightText' : 'darkText',
}}
onPress={() => toast.close(id)}
/> */
null}
</HStack>
<Text
px="$6"
color={
variant === 'solid'
? '$white'
: variant !== 'outline'
? '$black'
: null
}>
{description}
</Text>
</VStack>
</Alert>
);
toast.show({
render: ({id}: {id: string}) => {
return <ToastAlert id={id} {...item} />;
},
});
}
export default showToast;

View File

@ -5,39 +5,20 @@ import {
GestureResponderEvent,
StyleProp,
TouchableOpacity,
TouchableOpacityProps,
ViewStyle,
} from 'react-native';
import {useSelector} from 'react-redux';
interface CustomTouchableProps {
children?: ReactNode;
onPress?: () => void;
onLongPress?: ((event: GestureResponderEvent) => void) | undefined;
style?: StyleProp<ViewStyle>;
disabled?: boolean;
accessibilityRole?: AccessibilityRole | undefined;
}
interface CustomTouchableProps extends TouchableOpacityProps {}
export function MyTouchableOpacity({
children,
onPress,
onLongPress,
style,
disabled,
accessibilityRole,
}: CustomTouchableProps) {
export function MyTouchableOpacity({children, ...rest}: CustomTouchableProps) {
const currentTheme = useSelector(
(state: RootState) => state.nonSaveVariables.theme.opacity,
);
return (
<TouchableOpacity
disabled={disabled}
onPress={onPress}
onLongPress={onLongPress}
style={style}
activeOpacity={currentTheme[80]}
accessibilityRole={accessibilityRole}>
<TouchableOpacity activeOpacity={currentTheme[80]} {...rest}>
{children}
</TouchableOpacity>
);

View File

@ -1,25 +1,24 @@
import React from 'react';
import {View, Text, Image, StyleSheet} from 'react-native';
import {PA_Point} from './cluster/getData';
import {MarkerView} from '@rnmapbox/maps';
import {useSelector} from 'react-redux';
import {RootState, store} from '@redux/store';
import CircleNumber from './cluster/Cluster';
import {EventMarker} from './EventMarker';
import {PA_Point} from './types';
function DisplayMarkerList(props: {markers: PA_Point[]}) {
const eventMapMarkers = props.markers;
/*const eventMapMarkers = useSelector(
function DisplayMarkerList() {
const eventMapMarkers = useSelector(
(state: RootState) => state.nonSaveVariables.eventMapMarkers,
);*/
);
const colors = store.getState().nonSaveVariables.theme.colors;
return (
<React.Fragment>
{eventMapMarkers.map((marker: PA_Point) => {
return marker.type === 'event' ? (
return marker.type === 'event' || marker.type === 'eventStore' ? (
<MarkerView
key={marker.id}
anchor={{x: 0.5, y: 1}}

View File

@ -1,9 +1,9 @@
import React from 'react';
import {Animated} from 'react-native';
import {Animated, TouchableOpacity} from 'react-native';
import colors from '@configs/colors';
import {View, Image, Text, StyleSheet} from 'react-native';
import {PA_Point} from './cluster/getData';
import {PA_Point, PA_Point_Event, PA_Point_EventStore} from './types';
import {store} from '@redux/store';
import {
@ -15,11 +15,17 @@ import {
} from '@gluestack-ui/themed';
import tate from '@assets/tate.jpg';
import {RootScreenNavigationProp} from '@navigation/navigation';
import {useNavigation} from '@react-navigation/native';
export function EventMarker(props: {marker: PA_Point}) {
type EventType = PA_Point_Event | PA_Point_EventStore;
export function EventMarker(props: {marker: EventType}) {
const marker = props.marker;
const colors = store.getState().nonSaveVariables.theme.colors;
const navigation = useNavigation<RootScreenNavigationProp>();
const fadeAnim = React.useRef(new Animated.Value(0)).current;
const fadeAnim2 = React.useRef(new Animated.Value(0.9)).current;
@ -39,9 +45,38 @@ export function EventMarker(props: {marker: PA_Point}) {
}).start();
}, [fadeAnim2]);
return (
<Animated.View
style={{
...(marker.theme === 1 ? styles.marker1 : styles.marker),
backgroundColor: colors.backgroundDark400,
opacity: fadeAnim,
transform: [{scale: fadeAnim2}],
margin: 50,
}}>
<TouchableOpacity
onPress={() => {
console.log('marker pressed');
navigation.navigate('Home', {
screen: 'Map',
params: {screen: 'Event', params: {eventID: marker.id}},
});
}}>
{marker.theme === 1 ? (
<MarkerTheme1 marker={marker} />
) : (
<MarkerTheme0 marker={marker} />
)}
</TouchableOpacity>
{/*<Text style={styles.markerText}>{marker.type}</Text>*/}
</Animated.View>
);
}
function getEventAvatars(marker: EventType, length: number) {
const avatars = [
{
src: 'https://image.stern.de/32707724/t/o5/v2/w1440/r1.7778/-/andrew-tate.jpg',
src: tate,
alt: 'Sandeep Srivastva',
color: '$emerald600',
},
@ -66,65 +101,100 @@ export function EventMarker(props: {marker: PA_Point}) {
color: '$red400',
},
];
const extraAvatars = avatars.slice(3);
const remainingCount = extraAvatars.length;
const extraAvatars = avatars.slice(length);
const remainingCount = extraAvatars.length > 99 ? 99 : extraAvatars.length;
return {avatars, remainingCount};
}
function MarkerTheme1({marker}: {marker: EventType}) {
const colors = store.getState().nonSaveVariables.theme.colors;
return (
<Animated.View
style={{
...styles.marker,
backgroundColor: colors.backgroundDark400,
opacity: fadeAnim,
transform: [{scale: fadeAnim2}],
}}>
<AvatarGroup>
{avatars.slice(0, 3).map((avatar, index) => {
return (
<React.Fragment>
<Image source={tate} style={styles.markerImage1} />
</React.Fragment>
);
}
function MarkerTheme0({marker}: {marker: EventType}) {
const colors = store.getState().nonSaveVariables.theme.colors;
const {avatars, remainingCount} = getEventAvatars(marker, 3);
return (
<React.Fragment>
<Image source={tate} style={styles.markerImage} />
<AvatarGroup style={styles.avatarGroup}>
{[
remainingCount > 0 ? (
<Avatar
key="remaining"
size="sm"
borderColor="$backgroundDark400"
borderWidth="$2"
bg="$backgroundDark200"
style={{flexShrink: 0, minWidth: 16}}>
<Text
style={{
color: colors.textLight0,
textAlign: 'center',
fontWeight: 'bold',
}}
numberOfLines={1}>
+{remainingCount}
</Text>
</Avatar>
) : (
<></>
),
...avatars.slice(0, 3).map((avatar, index) => (
<Avatar
key={index}
size="sm"
borderColor="$black"
borderColor="$backgroundDark400"
borderWidth="$2"
bg={avatar.color}
sx={{
_dark: {
borderColor: '$black',
},
}}>
bg={avatar.color}>
<AvatarFallbackText>{avatar.alt}</AvatarFallbackText>
<AvatarImage source={avatar.src} alt={avatar.alt} />
</Avatar>
);
})}
<Avatar
size="sm"
borderColor="$white"
borderWidth="$2"
bg="$gray600"
sx={{
_dark: {
borderColor: '$black',
},
}}>
<AvatarFallbackText>{'+ ' + remainingCount + ''}</AvatarFallbackText>
</Avatar>
)),
]}
</AvatarGroup>
<Image
source={tate}
style={{width: 100, height: 100, alignSelf: 'center'}}
/>
<Text style={styles.markerText}>{marker.type}</Text>
</Animated.View>
</React.Fragment>
);
}
const styles = StyleSheet.create({
marker: {
padding: 5,
borderRadius: 5,
padding: 3,
borderRadius: 10,
},
marker1: {
padding: 3,
borderRadius: (90 + 3 * 2) / 2,
},
markerImage: {
borderRadius: 10 - 3,
width: 160,
height: 100,
alignSelf: 'center',
},
markerImage1: {
borderRadius: 90 / 2,
width: 90,
height: 90,
alignSelf: 'center',
},
markerText: {
color: 'white',
fontWeight: 'bold',
},
avatarGroup: {
position: 'absolute',
top: -8 - 5,
//right: -8 - 5,
right: -5,
},
});

View File

@ -1,32 +1,14 @@
import {Position} from '@rnmapbox/maps/src/types/Position';
import { getDistance } from 'geolib';
import {getDistance} from 'geolib';
import { PA_Point, PA_Point_Cluster, PA_Point_Event } from '../types';
interface PA_Point_Cluster {
latitude: number;
longitude: number;
cluster: number;
type: 'cluster';
id: string;
}
interface PA_Point_Event {
latitude: number;
longitude: number;
type: 'event';
id: number;
}
type PA_Point = PA_Point_Cluster | PA_Point_Event;
export type {PA_Point_Cluster, PA_Point_Event, PA_Point};
const createChecksum = (ids: (number | string)[]) => {
let checksum = 0;
for (const id of ids.sort()) {
const value = typeof id === 'string' ? parseInt(id, 36) : id;
checksum ^= value & 0xFFFF;
checksum ^= value & 0xffff;
}
return checksum;
};
@ -68,33 +50,25 @@ const clusterMarkers = (markers: PA_Point[], threshold: number) => {
longitudes.reduce((a, b) => a + b, 0) / longitudes.length;
const sumValues = cluster.reduce((sum, marker) => {
if (marker.type === 'event') {
if(isEvent === 0)
isEvent = 1;
else if(isEvent === 1)
isEvent = -1;
return sum + 1};
if (isEvent === 0) isEvent = 1;
else if (isEvent === 1) isEvent = -1;
isEvent = -1;
return sum + 1;
}
isEvent = -1;
marker = marker as PA_Point_Cluster;
return sum + (marker.cluster || 0);
}, 0);
if(isEvent === 1)
{
return {
latitude: centerLatitude,
longitude: centerLongitude,
type: 'event',
id: cluster[0].id,
} as PA_Point;
if (isEvent === 1) {
return cluster[0] as PA_Point_Event;
}
const ids = cluster.map(marker => marker.id);
const idChecksum = createChecksum(ids);
return {
latitude: centerLatitude,
@ -102,8 +76,7 @@ const clusterMarkers = (markers: PA_Point[], threshold: number) => {
type: 'cluster',
cluster: sumValues,
id: idChecksum.toString(),
} as PA_Point;
} as PA_Point_Cluster;
});
return centerPoints;
@ -118,18 +91,16 @@ const clusterMarkers = (markers: PA_Point[], threshold: number) => {
};*/
const calculateRadius = (bounds: [Position, Position]) => {
const distanceInMeters = getDistance(
{ latitude: bounds[0][0], longitude: bounds[0][1] },
{ latitude: bounds[1][0], longitude: bounds[1][1] }
);
return distanceInMeters/600000/(1.5/*android bug fix for roteration*/);
const distanceInMeters = getDistance(
{latitude: bounds[0][0], longitude: bounds[0][1]},
{latitude: bounds[1][0], longitude: bounds[1][1]},
);
return distanceInMeters / 600000 / 1.5 /*android bug fix for roteration*/;
};
function getLocationData(
bounds: [Position, Position], zoomLevel: number
bounds: [Position, Position],
zoomLevel: number,
): Promise<{locations: PA_Point[]} | undefined> {
if (bounds === undefined) return Promise.resolve(undefined);
@ -148,43 +119,51 @@ function getLocationData(
{"latitude": 50.1109, "longitude": 8.6821, "cluster": 23, "type": "cluster", "id": "467132"},
{"latitude": 51.0493, "longitude": 13.7384, "cluster": 8, "type": "cluster", "id": "842906"},
{"latitude": 49.0069, "longitude": 8.4037, "cluster": 46, "type": "cluster", "id": "346708"},*/
{"latitude": 51.9674, "longitude": 7.6194, "type": "event", "id": 203867},
{"latitude": 50.7753, "longitude": 6.0839, "type": "event", "id": 501298},
{"latitude": 53.0793, "longitude": 8.8017, "type": "event", "id": 763159},
{"latitude": 48.7758, "longitude": 9.1829, "type": "event", "id": 917425},
{"latitude": 52.3759, "longitude": 9.732, "type": "event", "id": 635028},
{"latitude": 51.512, "longitude": 7.4653, "type": "event", "id": 841592},
{"latitude": 49.4875, "longitude": 8.466, "type": "event", "id": 180356},
{"latitude": 51.3611, "longitude": 7.0119, "type": "event", "id": 592874},
{"latitude": 54.3227, "longitude": 10.1356, "type": "event", "id": 384791},
{"latitude": 51.8049, "longitude": 10.3351, "type": "event", "id": 273495},
{"latitude": 50.3213, "longitude": 11.8676, "type": "event", "id": 699318},
{"latitude": 49.8765, "longitude": 6.6695, "type": "event", "id": 159627},
{"latitude": 52.2651, "longitude": 7.3085, "type": "event", "id": 903716},
{"latitude": 53.9638, "longitude": 12.413, "type": "event", "id": 487612},
{"latitude": 50.9321, "longitude": 9.1847, "type": "event", "id": 827464},
{"latitude": 52.4378, "longitude": 13.2847, "type": "event", "id": 931845},
{"latitude": 49.4644, "longitude": 11.0168, "type": "event", "id": 674132},
{"latitude": 51.1983, "longitude": 8.8998, "type": "event", "id": 298473}
{
latitude: 51.9674,
longitude: 7.6197,
type: 'event',
id: "203868",
theme: 1,
},
{
latitude: 51.9674,
longitude: 7.6196,
type: 'event',
id: "203866",
theme: 1,
},
{latitude: 51.9674, longitude: 7.6194, type: 'event', id: "203867"},
{latitude: 50.7753, longitude: 6.0839, type: 'event', id: "501298"},
{latitude: 53.0793, longitude: 8.8017, type: 'event', id: "763159"},
{latitude: 48.7758, longitude: 9.1829, type: 'event', id: "917425"},
{latitude: 52.3759, longitude: 9.732, type: 'event', id: "635028"},
{latitude: 51.512, longitude: 7.4653, type: 'event', id: "841592"},
{latitude: 49.4875, longitude: 8.466, type: 'event', id: "180356"},
{latitude: 51.3611, longitude: 7.0119, type: 'event', id: "592874"},
{latitude: 54.3227, longitude: 10.1356, type: 'event', id: "384791"},
{latitude: 51.8049, longitude: 10.3351, type: 'event', id: "273495"},
{latitude: 50.3213, longitude: 11.8676, type: 'event', id: "699318"},
{latitude: 49.8765, longitude: 6.6695, type: 'event', id: "159627"},
{latitude: 52.2651, longitude: 7.3085, type: 'event', id: "903716"},
{latitude: 53.9638, longitude: 12.413, type: 'event', id: "487612"},
{latitude: 50.9321, longitude: 9.1847, type: 'event', id: "827464"},
{latitude: 52.4378, longitude: 13.2847, type: 'event', id: "931845"},
{latitude: 49.4644, longitude: 11.0168, type: 'event', id: "674132"},
{latitude: 51.1983, longitude: 8.8998, type: 'event', id: "298473"},
],
};
console.log("got data");
const zoomLevelChanged = calculateRadius(bounds);
console.log(zoomLevelChanged);
//console.log(zoomLevelChanged);
const data = {
locations: clusterMarkers(rawData.locations, zoomLevelChanged),//calculateThreshold(bounds)
locations: clusterMarkers(rawData.locations, zoomLevelChanged), //calculateThreshold(bounds)
};
console.log("clustered data");
resolve(data);
}, 120); // Simulating a delay of 1 second for the asynchronous operation
}, 2); // Simulating a delay of 1 second for the asynchronous operation
});
}

View File

@ -0,0 +1,32 @@
type EventID = string;
interface BasicEvent {
id: EventID;
latitude: number;
longitude: number;
}
interface PA_Point_Cluster extends BasicEvent {
type: 'cluster';
cluster: number;
}
interface PA_Point_Event extends BasicEvent {
type: 'event';
theme?: number;
}
interface PA_Point_EventStore extends BasicEvent {
type: 'eventStore';
theme?: number;
}
type PA_Point = PA_Point_Cluster | PA_Point_Event | PA_Point_EventStore;
export type {
PA_Point_Cluster,
PA_Point_Event,
PA_Point_EventStore,
PA_Point,
EventID,
};

View File

@ -2,12 +2,12 @@
import {chatEntity, roomId} from '@configs/chat/types';
import {User} from '@user/types';
import {UserId} from './types';
import {AccountName} from './types';
import {getVersionByNum, VersionType} from '@helper/version';
import configDarkTheme, {ThemeTokensType} from '@configs/colors';
import { PA_Point } from '@components/map/cluster/getData';
import {PA_Point} from '@components/map/cluster/getData';
export const APP_VERSION = getVersionByNum(1);
export const AppVarMaxBackups: number = 10;
@ -30,7 +30,7 @@ export interface NON_SAVE_VARS {
appStatus: appStatus;
theme: ThemeTokensType;
connectionStatus: connectionStatus;
cachedUsers: {[key: UserId]: User};
cachedUsers: {[key: AccountName]: User};
chats: {[key: roomId]: chatEntity};
chatActivity: roomId[];
selectedChat: roomId | 'none';

View File

@ -5,7 +5,7 @@ import {ThemeTokensType} from '@configs/colors';
import {chatEntity, roomId} from '@configs/chat/types';
import {User} from '@user/types';
import {UserId} from './types';
import {AccountName} from './types';
import {PA_Point} from '@components/map/cluster/getData';
export const appNonSaveVariablesSlice = createSlice({
@ -19,9 +19,9 @@ export const appNonSaveVariablesSlice = createSlice({
state.theme = action.payload;
},
setCachedUser: (state, action: PayloadAction<User>) => {
state.cachedUsers[action.payload.UserId] = action.payload;
state.cachedUsers[action.payload.AccountName] = action.payload;
},
removeCachedUser: (state, action: PayloadAction<UserId>) => {
removeCachedUser: (state, action: PayloadAction<AccountName>) => {
delete state.cachedUsers[action.payload];
},
setSelectedChat: (state, action: PayloadAction<roomId>) => {
@ -56,7 +56,7 @@ export const appNonSaveVariablesSlice = createSlice({
},
setMapMarkers: (state, action: PayloadAction<PA_Point[]>) => {
state.eventMapMarkers = action.payload;
}
},
},
});

View File

@ -1,4 +1,4 @@
import {EMail, UserId, XToken} from '@configs/types';
import {XToken, AccountName, Username} from '@configs/types';
import {VersionType} from '@helper/version';
import {MyUserAccount} from '@user/types';
import {APP_VERSION} from './appNonSaveVar';
@ -41,9 +41,11 @@ export function applyUpdateChanges(appVar: any): Promise<void> {
//these variables may be changed by the user and will be saved in storage
export interface RegisterProcess {
isRegistering: false | 'stepTwo' | 'stepFinal';
XToken: XToken | undefined;
EMail: EMail;
//isRegistering: false | 'stepTwo' | 'stepFinal';
//XToken: XToken | undefined;
Username: Username;
Password: string;
AccountName: AccountName;
}
export interface PREFERENCES_VARS {
@ -51,8 +53,8 @@ export interface PREFERENCES_VARS {
version: VersionType;
theme: ThemeMode;
RegisterProcess: RegisterProcess;
selectedAccount: UserId | 'none';
accounts: {[key: UserId]: MyUserAccount};
selectedAccount: AccountName | 'none';
accounts: {[key: AccountName]: MyUserAccount};
}
export const preferences_vars_default: PREFERENCES_VARS = {
@ -60,9 +62,11 @@ export const preferences_vars_default: PREFERENCES_VARS = {
version: APP_VERSION, //version of datatypes in storage
theme: ThemeMode.Dark,
RegisterProcess: {
isRegistering: false,
XToken: undefined,
EMail: '',
Username: '',
Password: '',
//isRegistering: false,
//XToken: undefined,
AccountName: '',
},
selectedAccount: 'none',
accounts: {},

View File

@ -7,7 +7,7 @@ import {
} from './appVar';
import LangFormat from '@lang/default';
import {lang as defaultLang} from '@lang/en';
import {UserId} from './types';
import {AccountName} from './types';
import {MyUserAccount} from '@user/types';
import {ThemeMode} from './colors';
@ -37,11 +37,11 @@ export const appVariablesSlice = createSlice({
setRegisterProcess: (state, action: PayloadAction<RegisterProcess>) => {
state.preferences.RegisterProcess = action.payload;
},
setCurrentAccount: (state, action: PayloadAction<UserId>) => {
setCurrentAccount: (state, action: PayloadAction<AccountName>) => {
state.preferences.selectedAccount = action.payload;
},
setAccount: (state, action: PayloadAction<MyUserAccount>) => {
state.preferences.accounts[action.payload.UserId] = action.payload;
state.preferences.accounts[action.payload.AccountName] = action.payload;
},
setDBEK: (state, action: PayloadAction<number>) => {
state.preferences.dbek = action.payload;

View File

@ -1,6 +1,6 @@
import {ThemeMode} from './appVar';
//import {ThemeMode} from './appVar';
export type EMail = string;
//export type EMail = string;
export type langCode = 'en' | string;
@ -11,11 +11,11 @@ export type Username = string | undefined;
export type Password = string;
export type UserAgent = string;
export type XToken = string;
export type verifyId = string;
//export type verifyId = string;
export type XAuthorization = string;
export type UserId = string;
export type WebSocketSessionId = string;
//export type UserId = string;
//export type WebSocketSessionId = string;
export const accountNameOptions = {
minLength: 4,
@ -42,6 +42,7 @@ export const passwordOptions = {
},
};
/*
export const emailOptions = {
maxLength: 48,
isAllowed: (email: string) => {
@ -49,4 +50,4 @@ export const emailOptions = {
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
);
},
};
}; */

View File

@ -1,6 +1,5 @@
import {useFocusEffect} from '@react-navigation/native';
import {animated, useSpring} from '@react-spring/native';
import {useEffect} from 'react';
import {Dimensions, View} from 'react-native';
const AnimationView = animated(View);

9
src/helper/base64.ts Normal file
View File

@ -0,0 +1,9 @@
import {Buffer} from 'buffer';
export function ToBase64(str: string) {
return Buffer.from(str).toString('base64');
}
export function FromBase64(str: string) {
return Buffer.from(str, 'base64').toString();
}

View File

@ -1,39 +1,35 @@
import {types} from '@babel/core';
import {store} from '@redux/store';
import {Any} from '@react-spring/types';
import {type} from 'os';
import {Platform} from 'react-native';
import getUserAgent from './userAgent';
import {
AccountName,
EMail,
Password,
XAuthorization,
UserId,
Username,
verifyId,
WebSocketSessionId,
XToken,
} from '../configs/types';
import MyUserManager from '@user/MyUserManager';
export const apiPath = {
backend: {
prefix: 'https://alpha-api.clickandjoin.umbach.dev/v1',
prefix: 'https://api-partyapp.ex.umbach.dev/api/v1',
},
};
export enum apiBackendRequest {
REGISTER_STEP_1 = '/admin/users/email',
LOGIN = '/user/login',
APP_START = '/appstart',
GET_USER_PROFILE = '/users/:accountName',
LOGOUT = '/user/logout',
SIGN_UP = '/user/signup',
/*REGISTER_STEP_1 = '/admin/users/email',
REGISTER_RESEND_MAIL = '/admin/users/email/resend',
REGISTER_STEP_2 = '/verify/email/:xToken/:verifyId',
REGISTER_STEP_FINAL = '/admin/users',
REGISTER_STEP_FINAL_ACCOUNT_NAME_CHECK = '/admin/users/validation/accountname',
LOGIN = '/user',
GET_USER_PROFILE = '/users/:userId',
APP_START = '/appstart',
APP_START = '/appstart', */
}
type requestGET = {[key: string]: string};
@ -46,6 +42,7 @@ export interface defaultRequest {
requestHeader?: requestHeader;
}
/*
interface REGISTER_STEP_1 extends defaultRequest {
path: apiBackendRequest.REGISTER_STEP_1;
@ -105,17 +102,30 @@ interface REGISTER_STEP_FINAL extends defaultRequest {
WebSocketSessionId: WebSocketSessionId;
};
}
*/
interface LOGIN extends defaultRequest {
path: apiBackendRequest.LOGIN;
request: {
Email: EMail;
AccountName: AccountName;
//Email: EMail;
Password: Password;
};
response?: {
XAuthorization: XAuthorization;
UserId: UserId;
WebSocketSessionId: WebSocketSessionId;
Username: Username;
};
}
interface SIGN_UP extends defaultRequest {
path: apiBackendRequest.SIGN_UP;
request: {
AccountName: AccountName;
Username: Username;
Password: Password;
};
response?: {
XAuthorization: XAuthorization;
Username: Username;
};
}
@ -123,10 +133,10 @@ interface GET_USER_PROFILE extends defaultRequest {
path: apiBackendRequest.GET_USER_PROFILE;
requestGET: {
':userId': UserId;
':accountName': AccountName;
};
response: {
AccountName: AccountName;
//AccountName: AccountName;
Username: Username;
Description: string;
FollowersCount: number;
@ -141,7 +151,7 @@ interface APP_START extends defaultRequest {
path: apiBackendRequest.APP_START;
response: {
TokenValid: boolean;
/* TokenValid: boolean;
AccountName: AccountName;
Username: Username;
Description: string;
@ -151,23 +161,30 @@ interface APP_START extends defaultRequest {
XpPoints: number;
AccountStatus: number;
AvatarUrl: string;
Events: any;
Events: any; */
};
}
interface LOGOUT extends defaultRequest {
path: apiBackendRequest.LOGOUT;
}
type FetchTypes =
| REGISTER_STEP_1
| LOGIN
| SIGN_UP
/*| REGISTER_STEP_1
| REGISTER_RESEND_MAIL
| REGISTER_STEP_2
| REGISTER_STEP_FINAL
| REGISTER_STEP_FINAL_ACCOUNT_NAME_CHECK
| LOGIN
| LOGIN*/
| GET_USER_PROFILE
| APP_START;
| APP_START
| LOGOUT;
/*
function isA(obj: any): obj is REGISTER_STEP_1 {
return obj.request !== undefined;
}
} */
export function makeRequest<T1 extends FetchTypes>(type: T1): Promise<T1> {
let makeRequestObj: any = type;
@ -204,6 +221,8 @@ export function makeRequest<T1 extends FetchTypes>(type: T1): Promise<T1> {
const SessionId = MyUserManager.getSessionId();
if (SessionId !== undefined) headers['X-Authorization'] = SessionId;
console.log('session id: ' + SessionId);
const requestOptions: RequestInit = {
method: makeRequestObj.request !== undefined ? 'POST' : 'GET',

View File

@ -63,7 +63,7 @@ export async function openMyDatabase(
schema: databaseConfType,
nameObj: databaseNameSuffix,
): Promise<DBType> {
const folderPath = MyUserManager.getSelectedUserId();
const folderPath = MyUserManager.getSelectedUserAccount();
const path =
folderPath +
'/' +

View File

@ -5,26 +5,25 @@ import {setEntry} from '../set';
import {databaseConf, possibleDBKeys} from '../types';
enum keys {
UserId = 'a',
AccountName = 'b',
Username = 'c',
Description = 'd',
FollowersCount = 'e',
FollowingCount = 'f',
lastUpdateTimestamp = 'g',
ProfilePicture = 'h',
ProfilePictureBinaryLQ = 'i',
ProfilePictureBinaryHQ = 'j',
// UserId = 'a',
AccountName = 'a',
Username = 'b',
Description = 'c',
FollowersCount = 'd',
FollowingCount = 'e',
lastUpdateTimestamp = 'f',
ProfilePicture = 'g',
ProfilePictureBinaryLQ = 'h',
ProfilePictureBinaryHQ = 'i',
XpLevel = 'k',
XpPoints = 'l',
XpLevel = 'j',
XpPoints = 'k',
}
const name = 'users';
const primaryKey: keyof typeof propsDefault = keys.UserId;
const primaryKey: keyof typeof propsDefault = keys.AccountName;
const propsType: {[key in keyof typeof propsDefault]: string} = {
[keys.UserId]: 'string',
[keys.AccountName]: 'string',
[keys.Username]: 'string',
[keys.Description]: 'string',
@ -40,7 +39,6 @@ const propsType: {[key in keyof typeof propsDefault]: string} = {
};
const propsDefault = {
[keys.UserId]: '',
[keys.AccountName]: '',
[keys.Username]: '',
[keys.Description]: '',

View File

@ -58,7 +58,7 @@ export const lang: LangFormat = {
},
login: {
title: 'Welcome back!',
inputPhoneNumberOrAccountName: 'PHONE NUMBER OR ACCOUNT NAME',
inputPhoneNumberOrAccountName: 'ACCOUNT NAME',
inputPassword: 'PASSWORD',
},
signUpStepUsername: {

View File

@ -38,6 +38,8 @@ export default function Navigation() {
const currentUser =
reduxStore.getState().appVariables.preferences.selectedAccount;
console.log('NAVIGATION', currentUser);
return (
<Stack.Navigator
screenOptions={{

View File

@ -25,16 +25,16 @@ import {Login} from '@pages/welcome/login/login';
import {
SignUpStepAccountName,
SignUpStepPassword,
SignUpStepPhoneNumber,
//SignUpStepPhoneNumber,
SignUpStepUsername,
SignUpStepVerifyPhoneNumber,
//SignUpStepVerifyPhoneNumber,
} from '@pages/welcome/signUp/signUp';
export type RegistrationStackNavigatorParamList = {
SignUpPreview: undefined;
SignUpStepUsername: undefined;
SignUpStepPhoneNumber: undefined;
SignUpStepVerifyPhoneNumber: undefined;
// SignUpStepPhoneNumber: undefined;
// SignUpStepVerifyPhoneNumber: undefined;
SignUpStepPassword: undefined;
SignUpStepAccountName: undefined;
LoginPreview: undefined;
@ -64,6 +64,19 @@ export function RegistrationScreen() {
headerTitle: '',
};
/*
<RegistrationStack.Screen
name="SignUpStepPhoneNumber"
component={SignUpStepPhoneNumber}
options={{...headerStyle}}
/>
<RegistrationStack.Screen
name="SignUpStepVerifyPhoneNumber"
component={SignUpStepVerifyPhoneNumber}
options={{...headerStyle}}
/>
*/
return (
<RegistrationStack.Navigator screenOptions={{headerShown: false}}>
<RegistrationStack.Screen
@ -81,16 +94,6 @@ export function RegistrationScreen() {
component={SignUpStepUsername}
options={{...headerStyle}}
/>
<RegistrationStack.Screen
name="SignUpStepPhoneNumber"
component={SignUpStepPhoneNumber}
options={{...headerStyle}}
/>
<RegistrationStack.Screen
name="SignUpStepVerifyPhoneNumber"
component={SignUpStepVerifyPhoneNumber}
options={{...headerStyle}}
/>
<RegistrationStack.Screen
name="SignUpStepPassword"
component={SignUpStepPassword}

View File

@ -10,10 +10,14 @@ import {useSelector} from 'react-redux';
import {Map} from '@pages/map/map';
import {EventID} from '@components/map/types';
export const MapTabName = 'Map';
export type MapStackNavigatorParamList = {
Overview: undefined;
Event: {eventID: EventID};
EventStore: {eventID: EventID};
};
const MapStack = createNativeStackNavigator<MapStackNavigatorParamList>();
@ -41,6 +45,16 @@ function MapTab() {
options={{headerShown: false}}
component={MapScreen}
/>
<MapStack.Screen
name="Event"
options={{headerShown: true}}
component={MapScreen}
/>
<MapStack.Screen
name="EventStore"
options={{headerShown: true}}
component={MapScreen}
/>
</MapStack.Navigator>
);
}

View File

@ -5,19 +5,13 @@ import {SafeAreaView} from 'react-native-safe-area-context';
import {useSelector} from 'react-redux';
import {RootState, store} from '@redux/store';
import {useEffect} from 'react';
import imgSrc from '@img/maimg.png';
import {placeholder} from '@lang/default';
import {initAppData} from '@helper/appData';
import {appStatus} from '@configs/appNonSaveVar';
import {appNonSaveVarActions} from '@configs/appNonSaveVarReducer';
import BigDataManager from '@helper/storage/BigDataManager';
import {initKey} from '@helper/storage/bdm/encryption';
import UserManager from '@user/UserManager';
import MyUserManager from '@user/MyUserManager';
import DBSchemas from '@helper/storage/bdm/schemas';
import {chatTags, convertDatabaseChat} from '@configs/chat/types';
import {convertDatabaseChat} from '@configs/chat/types';
import {addChatEntity} from '@components/chat/initChatDatabase';
import {initDatabase} from '@helper/storage/bdm/init';
@ -68,7 +62,6 @@ export async function onAppStart() {
console.log('finish');
const usrDBKeys = BigDataManager.databases.users.keys;
await BigDataManager.databases.users.setEntry({
[usrDBKeys.UserId]: 'test',
[usrDBKeys.AccountName]: '#845613',
[usrDBKeys.Username]: 'TestGroupVirtual',
[usrDBKeys.Description]: 'This is a test account that is not real. ^^',

View File

@ -21,7 +21,7 @@ let isRerenderData = 0;
export const Map = () => {
const mapRef = React.useRef<Mapbox.MapView | null>(null);
const [mapMarkers, setMapMarkers] = useState<PA_Point[]>([]); // Add useState for visibleBounds
//const [mapMarkers, setMapMarkers] = useState<PA_Point[]>([]); // Add useState for visibleBounds
const [lastDataRerender, setLastDataRerender] = useState(0); // Add useState for visibleBounds
const getVisibleBounds = async () => {
@ -32,7 +32,7 @@ export const Map = () => {
isRerenderData = now;
console.log('----1');
//console.log('----1');
if (mapRef.current) {
const visibleBounds = await (
@ -53,17 +53,17 @@ export const Map = () => {
//const zoomLevel = await (mapRef.current as Mapbox.MapView).getZoom();
console.log('----2', Date.now() - now + 'ms');
//console.log('----2', Date.now() - now + 'ms');
//console.log(visibleBounds);
let markerData = (await getLocationData(visibleBounds, 0))?.locations;
console.log('----3', Date.now() - now + 'ms');
//console.log('----3', Date.now() - now + 'ms');
//store.dispatch(appNonSaveVarActions.setMapMarkers(markerData || []));
setMapMarkers(markerData || []);
store.dispatch(appNonSaveVarActions.setMapMarkers(markerData || []));
//setMapMarkers(markerData || []);
console.log('----4', Date.now() - now + 'ms');
//console.log('----4', Date.now() - now + 'ms');
}
isRerenderData = 0;
@ -75,7 +75,7 @@ export const Map = () => {
if (now - lastCameraChange > 500) {
lastCameraChange = now;
setTimeout(getVisibleBounds, 500);
console.log('------------5', Date.now() - now + 'ms');
//console.log('------------5', Date.now() - now + 'ms');
}
}
@ -117,7 +117,7 @@ export const Map = () => {
logoPosition={{top: 10, left: 10}}
styleURL="mapbox://styles/titaniumbach/clpij5uoo00o301pg2dj23j0m"
projection="globe">
<DisplayMarkerList markers={mapMarkers} />
<DisplayMarkerList />
</Mapbox.MapView>
</View>
</View>

View File

@ -14,6 +14,9 @@ import {useSelector} from 'react-redux';
import {RootState} from '@redux/store';
import {Text} from '@gluestack-ui/themed';
import {MyTouchableOpacity} from '@components/MyTouchableOpacity';
import UserManager from '@user/UserManager';
import MyUserManager from '@user/MyUserManager';
import {apiBackendRequest, makeRequest} from '@helper/request';
function UserAvatar() {
return (
@ -29,6 +32,11 @@ export function ProfileOverview() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.profile.overview.statistics,
);
const user = UserManager.getUserSelector(
useSelector(
(state: RootState) => state.appVariables.preferences.selectedAccount,
),
);
return (
<MyScreenContainer
@ -41,14 +49,16 @@ export function ProfileOverview() {
<UserAvatar />
</View>
<MyTitle text="Max Mustermann" />
<MyTitle
text={user.Username.data === undefined ? '' : user.Username.data}
/>
<View style={{flexDirection: 'row', gap: 12}}>
<Statistic title={lang.followers} value="400.3k" />
<Statistic title={lang.followers} value="0" />
<MyVerticalDivider />
<Statistic title={lang.following} value="40.3k" />
<Statistic title={lang.following} value="0" />
<MyVerticalDivider />
<Statistic title={lang.visited} value="2k" />
<Statistic title={lang.visited} value="0" />
</View>
</MyScreenContainer>
);
@ -97,6 +107,20 @@ export function ProfileSettings() {
const navigation = useNavigation<ProfileScreenNavigationProp>();
const rootNavigation = useNavigation<RootScreenNavigationProp>();
const user = UserManager.getUserSelector(
useSelector(
(state: RootState) => state.appVariables.preferences.selectedAccount,
),
);
/*
<SettingsItem
icon="phone-iphone"
title={lang.accountData.phoneNumber}
value="+49 1510 21334143"
/>
*/
return (
<MyScreenContainer
scrollView
@ -111,21 +135,15 @@ export function ProfileSettings() {
<SettingsItem
icon="person"
title={lang.accountData.accountName}
value="max_mustermann"
value={user.AccountName === undefined ? '' : user.AccountName}
/>
<SettingsItem
icon="person"
title={lang.accountData.username}
value="Max Mustermann"
value={user.Username.data === undefined ? '' : user.Username.data}
onPress={() => navigation.navigate('UpdateUsername')}
/>
<SettingsItem
icon="phone-iphone"
title={lang.accountData.phoneNumber}
value="+49 1510 21334143"
/>
</SettingsItemContainer>
<SettingsItemContainer title={lang.changePassword.title}>
@ -153,9 +171,18 @@ export function ProfileSettings() {
<SettingsItem
icon="logout"
title={lang.moreInfo.logout}
onPress={() =>
rootNavigation.navigate('Registration', {screen: 'LoginPreview'})
}
onPress={() => {
makeRequest({
path: apiBackendRequest.LOGOUT,
request: {},
response: {},
}).catch(reason => {
console.log('logout failed, err: ', reason);
});
MyUserManager.logoutMyUser();
rootNavigation.navigate('Registration', {screen: 'LoginPreview'});
}}
/>
</SettingsItemContainer>
</MyScreenContainer>

View File

@ -1,58 +1,114 @@
import { MyButton } from "@components/MyButton";
import { MyIconInput } from "@components/MyInput";
import { MyScreenContainer } from "@components/MyScreenContainer";
import { MyTitle } from "@components/MyTitle";
import { RootScreenNavigationProp } from "@navigation/navigation";
import { ContentContainer, navigateToHome } from "@navigation/registration/registration";
import { useNavigation } from "@react-navigation/native";
import { RootState } from "@redux/store";
import { useState } from "react";
import { View } from "react-native";
import { useSelector } from "react-redux";
import {MyButton} from '@components/MyButton';
import {MyIconInput} from '@components/MyInput';
import {MyScreenContainer} from '@components/MyScreenContainer';
import {MyTitle} from '@components/MyTitle';
import {apiBackendRequest, makeRequest} from '@helper/request';
import {RootScreenNavigationProp} from '@navigation/navigation';
import {
ContentContainer,
navigateToHome,
} from '@navigation/registration/registration';
import {useNavigation} from '@react-navigation/native';
import {RootState} from '@redux/store';
import MyUserManager from '@user/MyUserManager';
import {useState} from 'react';
import {View} from 'react-native';
import {useSelector} from 'react-redux';
import {ToBase64} from '@helper/base64';
import showToast from '@components/MyToast';
import {useToast} from '@gluestack-ui/themed';
export function Login() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
);
const navigation = useNavigation<RootScreenNavigationProp>();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const loginEnabled = username.length > 0 && password.length > 0;
return (
<MyScreenContainer
style={{
flexDirection: 'column',
}}>
<ContentContainer>
<MyTitle text={lang.login.title} />
<View style={{gap: 12}}>
<MyIconInput
text={lang.login.inputPhoneNumberOrAccountName}
iconName="person"
value={username}
onChangeText={text => setUsername(text)}
/>
<MyIconInput
text={lang.login.inputPassword}
iconName="lock"
secureTextEntry
value={password}
onChangeText={text => setPassword(text)}
/>
<MyButton
type="primary"
text={lang.buttonLogin}
style={{marginBottom: 20}}
onPress={() => navigateToHome(navigation)}
disabled={!loginEnabled}
/>
</View>
</ContentContainer>
</MyScreenContainer>
);
}
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
);
const navigation = useNavigation<RootScreenNavigationProp>();
const toast = useToast();
const [isLoading, setIsLoading] = useState(false);
const [accountName, setAccountName] = useState('anna');
const [password, setPassword] = useState('testtesttest');
const loginEnabled = accountName.length > 0 && password.length > 0;
return (
<MyScreenContainer
style={{
flexDirection: 'column',
}}>
<ContentContainer>
<MyTitle text={lang.login.title} />
<View style={{gap: 12}}>
<MyIconInput
text={lang.login.inputPhoneNumberOrAccountName}
iconName="person"
value={accountName}
onChangeText={text => setAccountName(text)}
/>
<MyIconInput
text={lang.login.inputPassword}
iconName="lock"
secureTextEntry
value={password}
onChangeText={text => setPassword(text)}
/>
<MyButton
type="primary"
isLoading={isLoading}
text={lang.buttonLogin}
style={{marginBottom: 20}}
onPress={() => {
console.log('login');
setIsLoading(true);
makeRequest({
path: apiBackendRequest.LOGIN,
request: {
AccountName: accountName,
Password: ToBase64(password),
},
response: {
XAuthorization: '',
Username: '',
},
})
.then(resp => {
console.log('resp', resp);
MyUserManager.createNewMyUser(
accountName,
resp.response.Username,
resp.response.XAuthorization,
)
.then(async () => {
setIsLoading(false);
navigateToHome(navigation);
})
.catch(err => {
console.log('catch', err);
});
})
.catch(reason => {
console.log('reason', reason);
setIsLoading(false);
showToast(toast, {
title: 'Failed',
variant: 'solid',
action: 'error',
description: undefined,
isClosable: true,
rest: {colorScheme: 'primary'},
});
});
}}
disabled={!loginEnabled}
/>
</View>
</ContentContainer>
</MyScreenContainer>
);
}

View File

@ -1,17 +1,21 @@
import {MyButton} from '@components/MyButton';
import {MyClickableText} from '@components/MyClickableText';
import {ConfirmationCodeInput, MyIconInput} from '@components/MyInput';
import {MyIconInput} from '@components/MyInput';
import {MyScreenContainer} from '@components/MyScreenContainer';
import {MyTitle} from '@components/MyTitle';
import {appVarActions} from '@configs/appVarReducer';
import {ToBase64} from '@helper/base64';
import {apiBackendRequest, makeRequest} from '@helper/request';
import {RootScreenNavigationProp} from '@navigation/navigation';
import {
ContentContainer,
navigateToHome,
} from '@navigation/registration/registration';
import {useNavigation} from '@react-navigation/native';
import {RootState} from '@redux/store';
import {RootState, store} from '@redux/store';
import MyUserManager from '@user/MyUserManager';
import {useState} from 'react';
import {Text} from 'react-native';
import {KeyboardAvoidingView, ScrollView, View} from 'react-native';
import {View} from 'react-native';
import {useSelector} from 'react-redux';
function Title({text, description}: {text: string; description?: string}) {
@ -29,6 +33,12 @@ export function SignUpStepUsername() {
);
const navigation = useNavigation<RootScreenNavigationProp>();
const registerProcess = useSelector(
(state: RootState) => state.appVariables.preferences.RegisterProcess,
);
const [username, setUsername] = useState('');
return (
<MyScreenContainer
style={{
@ -44,6 +54,8 @@ export function SignUpStepUsername() {
<MyIconInput
text={lang.signUpStepUsername.inputUsername}
iconName="person"
value={username}
onChangeText={text => setUsername(text)}
/>
<MyButton
@ -51,8 +63,14 @@ export function SignUpStepUsername() {
text={lang.buttonNext}
style={{marginBottom: 20}}
onPress={() => {
let rp = {...registerProcess};
rp.Username = username;
store.dispatch(appVarActions.setRegisterProcess(rp));
navigation.navigate('Registration', {
screen: 'SignUpStepPhoneNumber',
screen: /*'SignUpStepPhoneNumber' */ 'SignUpStepPassword',
});
}}
/>
@ -61,7 +79,7 @@ export function SignUpStepUsername() {
</MyScreenContainer>
);
}
/*
export function SignUpStepPhoneNumber() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
@ -143,13 +161,19 @@ export function SignUpStepVerifyPhoneNumber() {
</MyScreenContainer>
);
}
*/
export function SignUpStepPassword() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
);
const navigation = useNavigation<RootScreenNavigationProp>();
const registerProcess = useSelector(
(state: RootState) => state.appVariables.preferences.RegisterProcess,
);
const [password, setPassword] = useState('');
return (
<MyScreenContainer
style={{
@ -166,17 +190,25 @@ export function SignUpStepPassword() {
text={lang.signUpStepPassword.inputPassword}
iconName="lock"
secureTextEntry
value={password}
onChangeText={text => setPassword(text)}
/>
<MyButton
type="secondary"
text={lang.buttonNext}
style={{marginBottom: 2}}
onPress={() =>
onPress={() => {
let rp = {...registerProcess};
rp.Password = ToBase64(password);
store.dispatch(appVarActions.setRegisterProcess(rp));
navigation.navigate('Registration', {
screen: 'SignUpStepAccountName',
})
}
});
}}
/>
</View>
</ContentContainer>
@ -190,6 +222,13 @@ export function SignUpStepAccountName() {
);
const navigation = useNavigation<RootScreenNavigationProp>();
const registerProcess = useSelector(
(state: RootState) => state.appVariables.preferences.RegisterProcess,
);
const [isLoading, setIsLoading] = useState(false);
const [accountName, setAccountName] = useState('');
return (
<MyScreenContainer
scrollView
@ -206,13 +245,53 @@ export function SignUpStepAccountName() {
<MyIconInput
text={lang.signUpStepAccountName.inputAccountName}
iconName="person"
value={accountName}
onChangeText={text => setAccountName(text)}
/>
<MyButton
type="primary"
text={lang.signUpStepAccountName.buttonGetStarted}
style={{marginBottom: 2}}
onPress={() => navigateToHome(navigation)}
isLoading={isLoading}
onPress={() => {
let rp = {...registerProcess};
rp.AccountName = accountName;
store.dispatch(appVarActions.setRegisterProcess(rp));
console.log('registerProcess', rp);
makeRequest({
path: apiBackendRequest.SIGN_UP,
request: rp,
method: 'POST',
response: {
XAuthorization: '',
Username: '',
},
})
.then(resp => {
console.log('response', resp);
MyUserManager.createNewMyUser(
accountName,
resp.response.Username,
resp.response.XAuthorization,
)
.then(async () => {
setIsLoading(false);
navigateToHome(navigation);
})
.catch(err => {
console.log('catch', err);
});
})
.catch(error => {
console.log('error', error);
});
}}
/>
</View>
</ContentContainer>

View File

@ -1,12 +1,5 @@
import {appVarActions} from '@configs/appVarReducer';
import {
AccountName,
EMail,
XAuthorization,
UserId,
Username,
WebSocketSessionId,
} from '@configs/types';
import {AccountName, XAuthorization, Username} from '@configs/types';
import {saveVarChanges} from '@helper/appData';
import {apiBackendRequest, makeRequest} from '@helper/request';
import BigDataManager from '@helper/storage/BigDataManager';
@ -15,30 +8,24 @@ import {useSelector} from 'react-redux';
import {MyUserAccount, createUserProp, SourceProp} from './types';
function createNewMyUser(
UserId: UserId,
AccountName: AccountName,
Username: Username,
EMail: EMail,
SessionId: XAuthorization,
WebSocketSessionId: WebSocketSessionId,
): Promise<void> {
return new Promise((resolve, reject) => {
let user: MyUserAccount = {
UserId,
AccountName: createUserProp(SourceProp.offline, AccountName),
AccountName /*: createUserProp(SourceProp.offline, AccountName)*/,
Username: createUserProp(SourceProp.offline, Username),
Description: createUserProp(SourceProp.online),
/* Description: createUserProp(SourceProp.online),
FollowersCount: createUserProp(SourceProp.online),
FollowingCount: createUserProp(SourceProp.online),
XpLevel: createUserProp(SourceProp.online),
XpPoints: createUserProp(SourceProp.online),
EMail,
SessionId,
WebSocketSessionId,
lastUpdateTimestamp: Math.floor(new Date().getTime() / 1000),
ProfilePicture: {
lq: createUserProp(SourceProp.online),
},
}, */
SessionId,
userSettings: {
lang: store.getState().appVariables.lang.details.langCode,
theme: store.getState().appVariables.preferences.theme,
@ -48,10 +35,13 @@ function createNewMyUser(
createMyUser(user);
BigDataManager.initDatabase();
console.log('appstart');
makeRequest({
path: apiBackendRequest.APP_START,
requestGET: {':userId': UserId},
requestGET: {':AccountName': AccountName},
response: {
/*
AccountName: '',
Description: '',
FollowersCount: 0,
@ -62,19 +52,20 @@ function createNewMyUser(
AvatarUrl: '',
AccountStatus: 0,
Events: {},
TokenValid: false,
TokenValid: false, */
},
})
.then(resp => {
let user = {...getMyUser(UserId)};
let user = {...getMyUser(AccountName)};
/*
user.AccountName = createUserProp(
SourceProp.offline,
resp.response.AccountName,
);
);
user.Username = createUserProp(
SourceProp.offline,
resp.response.Username,
);
);
user.Description = createUserProp(
SourceProp.offline,
resp.response.Description,
@ -94,13 +85,13 @@ function createNewMyUser(
user.XpPoints = createUserProp(
SourceProp.offline,
resp.response.XpPoints,
);
);*/
setMyUser(user);
resolve();
})
.catch(resp => {
console.error(resp.status);
console.error(`appstart req failed: ${resp.status}`);
reject();
});
});
@ -108,12 +99,12 @@ function createNewMyUser(
function createMyUser(user: MyUserAccount) {
store.dispatch(appVarActions.setAccount(user));
store.dispatch(appVarActions.setCurrentAccount(user.UserId));
store.dispatch(appVarActions.setCurrentAccount(user.AccountName));
saveVarChanges();
}
function getMyUser(userId: UserId): MyUserAccount {
return store.getState().appVariables.preferences.accounts[userId];
function getMyUser(accountName: AccountName): MyUserAccount {
return store.getState().appVariables.preferences.accounts[accountName];
}
function setMyUser(user: MyUserAccount) {
@ -126,7 +117,7 @@ function logoutMyUser() {
saveVarChanges();
}
function getSelectedUserId(): UserId {
function getSelectedUserAccount(): AccountName {
return store.getState().appVariables.preferences.selectedAccount;
}
@ -142,9 +133,12 @@ function getSelectedMyUserSelector(): MyUserAccount | undefined {
return myUser;
}
function getSessionId(userId?: UserId): XAuthorization | undefined {
function getSessionId(accountName?: AccountName): XAuthorization | undefined {
const preferences = store.getState().appVariables.preferences;
let user = preferences.accounts[userId || preferences.selectedAccount];
console.log('pref', preferences);
let user = preferences.accounts[accountName || preferences.selectedAccount];
if (user === undefined) return undefined;
@ -156,7 +150,7 @@ function getSessionId(userId?: UserId): XAuthorization | undefined {
const MyUserManager = {
createNewMyUser,
getSessionId,
getSelectedUserId,
getSelectedUserAccount,
logoutMyUser,
getSelectedMyUserSelector,
};

View File

@ -1,6 +1,6 @@
import {maxCachedUsers} from '@configs/appNonSaveVar';
import {appNonSaveVarActions} from '@configs/appNonSaveVarReducer';
import {UserId, XAuthorization} from '@configs/types';
import {AccountName, XAuthorization} from '@configs/types';
import {makeRequest, apiBackendRequest} from '@helper/request';
import BigDataManager from '@helper/storage/BigDataManager';
import {RootState, store} from '@redux/store';
@ -14,13 +14,13 @@ import {
User,
} from './types';
let cachedUserList: UserId[] = [];
let cachedUserList: AccountName[] = [];
async function getUser(
UserId: UserId,
AccountName: AccountName,
save?: boolean,
): Promise<User | undefined> {
if (UserId === 'none') {
if (AccountName === 'none') {
return undefined;
}
@ -30,35 +30,34 @@ async function getUser(
let userIsInCache = false;
{
const usr = state.nonSaveVariables.cachedUsers[UserId];
const usr = state.nonSaveVariables.cachedUsers[AccountName];
if (usr !== undefined) {
user = usr;
userIsInCache = true;
}
}
if (UserId === state.appVariables.preferences.selectedAccount) {
const usr = state.appVariables.preferences.accounts[UserId];
if (AccountName === state.appVariables.preferences.selectedAccount) {
const usr = state.appVariables.preferences.accounts[AccountName];
if (usr !== undefined) {
user = {
AccountName: usr.AccountName,
Description: usr.Description,
/*Description: usr.Description,
FollowersCount: usr.FollowersCount,
FollowingCount: usr.FollowingCount,
lastUpdateTimestamp: usr.lastUpdateTimestamp,
ProfilePicture: usr.ProfilePicture,
UserId,
Username: usr.Username,
ProfilePicture: usr.ProfilePicture, */
Username: usr.Username /*
XpLevel: usr.XpLevel,
XpPoints: usr.XpPoints,
XpPoints: usr.XpPoints,*/,
};
}
}
if (user === undefined) {
const usrDBKeys = BigDataManager.databases.users.keys;
const usr = await BigDataManager.databases.users.getEntry(UserId);
const usr = await BigDataManager.databases.users.getEntry(AccountName);
if (usr !== undefined && usr !== null) {
let ProfilePicture = {
@ -87,10 +86,7 @@ async function getUser(
};
user = {
AccountName: createUserProp(
SourceProp.offline,
usr[usrDBKeys.AccountName],
),
AccountName,
Description: createUserProp(
SourceProp.offline,
usr[usrDBKeys.Description],
@ -105,7 +101,6 @@ async function getUser(
),
lastUpdateTimestamp: usr[usrDBKeys.lastUpdateTimestamp],
ProfilePicture,
UserId,
Username: createUserProp(SourceProp.offline, usr[usrDBKeys.Username]),
XpLevel: createUserProp(SourceProp.offline, usr[usrDBKeys.XpLevel]),
XpPoints: createUserProp(SourceProp.offline, usr[usrDBKeys.XpPoints]),
@ -117,9 +112,8 @@ async function getUser(
try {
const resp = await makeRequest({
path: apiBackendRequest.GET_USER_PROFILE,
requestGET: {':userId': UserId},
requestGET: {':accountName': AccountName},
response: {
AccountName: '',
Description: '',
FollowersCount: 0,
FollowingCount: 0,
@ -131,10 +125,7 @@ async function getUser(
});
user = {
AccountName: createUserProp(
SourceProp.cached,
resp.response.AccountName,
),
AccountName: AccountName,
Description: createUserProp(
SourceProp.cached,
resp.response.Description,
@ -155,7 +146,6 @@ async function getUser(
resp.response.AvatarUrl,
),
},
UserId,
Username: createUserProp(SourceProp.offline, resp.response.Username),
XpLevel: createUserProp(SourceProp.cached, resp.response.XpLevel),
XpPoints: createUserProp(SourceProp.cached, resp.response.XpPoints),
@ -170,7 +160,7 @@ async function getUser(
if (userIsInCache === false && user !== undefined) {
console.log('save in cache');
store.dispatch(appNonSaveVarActions.setCachedUser(user));
cachedUserList.push(user.UserId);
cachedUserList.push(user.AccountName);
if (cachedUserList.length > maxCachedUsers) {
let usrId = cachedUserList[0];
@ -189,47 +179,47 @@ enum GetParam {
SAVE,
}
let getUserList: {[key: UserId]: GetParam} = {};
let getUserList: {[key: AccountName]: GetParam} = {};
async function refreshUsers() {
for (let UserId in getUserList) {
const param = getUserList[UserId];
delete getUserList[UserId];
for (let AccountName in getUserList) {
const param = getUserList[AccountName];
delete getUserList[AccountName];
await getUser(UserId);
await getUser(AccountName);
}
}
setInterval(refreshUsers, 500);
function addUserToGetQueue(UserId: UserId, param: GetParam) {
if (getUserList[UserId] === undefined) {
getUserList[UserId] = param;
} else if (getUserList[UserId] < param) {
getUserList[UserId] = param;
function addUserToGetQueue(AccountName: AccountName, param: GetParam) {
if (getUserList[AccountName] === undefined) {
getUserList[AccountName] = param;
} else if (getUserList[AccountName] < param) {
getUserList[AccountName] = param;
}
}
function getUserSelector(UserId: UserId) {
addUserToGetQueue(UserId, GetParam.CACHE);
function getUserSelector(AccountName: AccountName) {
addUserToGetQueue(AccountName, GetParam.CACHE);
const myUser = useSelector(
(state: RootState) => state.nonSaveVariables.cachedUsers[UserId],
(state: RootState) => state.nonSaveVariables.cachedUsers[AccountName],
);
if (myUser === undefined) {
return initUndefinedUser(UserId);
return initUndefinedUser(AccountName);
}
return myUser;
}
function getUserSelectorPicture(UserId: UserId): ProfilePicture {
addUserToGetQueue(UserId, GetParam.CACHE);
function getUserSelectorPicture(AccountName: AccountName): ProfilePicture {
addUserToGetQueue(AccountName, GetParam.CACHE);
const myUser = useSelector(
(state: RootState) =>
state.nonSaveVariables.cachedUsers[UserId]?.ProfilePicture,
state.nonSaveVariables.cachedUsers[AccountName]?.ProfilePicture,
);
if (myUser === undefined) {
@ -241,13 +231,15 @@ function getUserSelectorPicture(UserId: UserId): ProfilePicture {
return myUser;
}
function getUserSelectorAccountName(UserId: UserId): BasicUserProp<string> {
addUserToGetQueue(UserId, GetParam.CACHE);
/*
function getUserSelectorAccountName(
AccountName: AccountName,
): AccountName {
addUserToGetQueue(AccountName, GetParam.CACHE);
const myUser = useSelector(
(state: RootState) =>
state.nonSaveVariables.cachedUsers[UserId]?.AccountName,
state.nonSaveVariables.cachedUsers[AccountName]?.AccountName,
);
if (myUser === undefined) {
@ -255,23 +247,22 @@ function getUserSelectorAccountName(UserId: UserId): BasicUserProp<string> {
}
return myUser;
}
} */
function initUndefinedUser(UserId: UserId): User {
function initUndefinedUser(AccountName: AccountName): User {
return {
AccountName: createUserProp(SourceProp.online),
Description: createUserProp(SourceProp.online),
AccountName: AccountName,
/* Description: createUserProp(SourceProp.online),
FollowersCount: createUserProp(SourceProp.online),
FollowingCount: createUserProp(SourceProp.online),
lastUpdateTimestamp: 0,
ProfilePicture: {
lq: createUserProp(SourceProp.online),
hq: createUserProp(SourceProp.online),
},
UserId,
Username: createUserProp(SourceProp.online),
}, */
Username: createUserProp(SourceProp.online) /*
XpLevel: createUserProp(SourceProp.online),
XpPoints: createUserProp(SourceProp.online),
XpPoints: createUserProp(SourceProp.online), */,
};
}
@ -279,7 +270,7 @@ const UserManager = {
getUser,
getUserSelector,
getUserSelectorPicture,
getUserSelectorAccountName,
//getUserSelectorAccountName,
initUndefinedUser,
};
export default UserManager;

View File

@ -1,13 +1,10 @@
import {ThemeMode} from '@configs/colors';
import {
AccountName,
EMail,
langCode,
XAuthorization,
timestamp,
UserId,
Username,
WebSocketSessionId,
} from '@configs/types';
export enum SourceProp {
@ -30,23 +27,23 @@ export interface ProfilePicture {
}
export interface User {
UserId: UserId;
//UserId: UserId;
AccountName: AccountName;
ProfilePicture: ProfilePicture;
lastUpdateTimestamp: timestamp;
AccountName: BasicUserProp<AccountName>;
Username: BasicUserProp<Username>;
/* ProfilePicture: ProfilePicture;
lastUpdateTimestamp: timestamp; */
Username: BasicUserProp<Username> /*
Description: BasicUserProp<string>;
FollowersCount: BasicUserProp<number>;
FollowingCount: BasicUserProp<number>;
XpLevel: BasicUserProp<number>;
XpPoints: BasicUserProp<number>;
XpPoints: BasicUserProp<number>; */;
}
export interface MyUserAccount extends User {
EMail: EMail;
//EMail: EMail;
SessionId: XAuthorization;
WebSocketSessionId: WebSocketSessionId;
//WebSocketSessionId: WebSocketSessionId;
userSettings: userSettings;
}