appstart, create event, common inputs
parent
00045692ad
commit
cc569a8187
|
@ -0,0 +1,259 @@
|
||||||
|
import {useEffect, useState} from 'react';
|
||||||
|
import {MyIconInput, MyInputError} from './MyInput';
|
||||||
|
import {useSelector} from 'react-redux';
|
||||||
|
import {RootState} from '@redux/store';
|
||||||
|
import {
|
||||||
|
accountNameOptions,
|
||||||
|
passwordOptions,
|
||||||
|
userNameOptions,
|
||||||
|
} from '@configs/types';
|
||||||
|
import reactStringReplace from 'react-string-replace';
|
||||||
|
import {MyIconButton} from './MyButton';
|
||||||
|
import {MyIcon} from './MyIcon';
|
||||||
|
import {Spinner} from '@gluestack-ui/themed';
|
||||||
|
import {apiBackendRequest, makeRequest} from '@helper/request';
|
||||||
|
|
||||||
|
export function usernameValid(username: string) {
|
||||||
|
if (username.length < userNameOptions.minLength) {
|
||||||
|
return false;
|
||||||
|
} else if (!userNameOptions.isAllowed(username)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MyUsernameInputProps {
|
||||||
|
username: string;
|
||||||
|
setUsername: (username: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MyUsernameInput(props: MyUsernameInputProps) {
|
||||||
|
const lang = useSelector(
|
||||||
|
(state: RootState) => state.appVariables.lang.commonInputs.username,
|
||||||
|
);
|
||||||
|
|
||||||
|
const [inputTouched, setInputTouched] = useState(false);
|
||||||
|
|
||||||
|
const errorText = () => {
|
||||||
|
if (props.username.length < userNameOptions.minLength) {
|
||||||
|
return reactStringReplace(
|
||||||
|
lang.errorLength,
|
||||||
|
'${minLength}',
|
||||||
|
(match, i) => {
|
||||||
|
return userNameOptions.minLength.toString();
|
||||||
|
},
|
||||||
|
).join('');
|
||||||
|
} else if (!userNameOptions.isAllowed(props.username)) {
|
||||||
|
return lang.errorUsernameInvalid;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MyIconInput
|
||||||
|
iconName="person"
|
||||||
|
text={lang.label}
|
||||||
|
value={props.username}
|
||||||
|
onChangeText={text => {
|
||||||
|
props.setUsername(text);
|
||||||
|
setInputTouched(true);
|
||||||
|
}}
|
||||||
|
maxLength={userNameOptions.maxLength}
|
||||||
|
helper={
|
||||||
|
inputTouched &&
|
||||||
|
!usernameValid(props.username) && <MyInputError text={errorText()} />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function passwordValid(password: string) {
|
||||||
|
if (password.length < passwordOptions.minLength) {
|
||||||
|
return false;
|
||||||
|
} else if (!passwordOptions.isAllowed(password)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MyPasswordInputProps {
|
||||||
|
password: string;
|
||||||
|
setPassword: (password: string) => void;
|
||||||
|
disableContainer?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MyPasswordInput(props: MyPasswordInputProps) {
|
||||||
|
const lang = useSelector(
|
||||||
|
(state: RootState) => state.appVariables.lang.commonInputs.password,
|
||||||
|
);
|
||||||
|
|
||||||
|
const [inputTouched, setInputTouched] = useState(false);
|
||||||
|
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
||||||
|
|
||||||
|
const togglePasswordVisibility = () =>
|
||||||
|
setIsPasswordVisible(!isPasswordVisible);
|
||||||
|
|
||||||
|
const errorText = () => {
|
||||||
|
if (props.password.length < passwordOptions.minLength) {
|
||||||
|
return reactStringReplace(lang.errorLength, '${minLength}', () => {
|
||||||
|
return passwordOptions.minLength.toString();
|
||||||
|
}).join('');
|
||||||
|
} else if (!passwordOptions.isAllowed(props.password)) {
|
||||||
|
return lang.errorPasswordInvalid;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MyIconInput
|
||||||
|
text={lang.label}
|
||||||
|
iconName="lock"
|
||||||
|
secureTextEntry={!isPasswordVisible}
|
||||||
|
value={props.password}
|
||||||
|
maxLength={passwordOptions.maxLength}
|
||||||
|
onChangeText={text => {
|
||||||
|
props.setPassword(text);
|
||||||
|
setInputTouched(true);
|
||||||
|
}}
|
||||||
|
rightComponent={
|
||||||
|
<MyIconButton
|
||||||
|
MyIconProps={{
|
||||||
|
name: isPasswordVisible ? 'visibility-off' : 'visibility',
|
||||||
|
size: 24,
|
||||||
|
}}
|
||||||
|
onPress={togglePasswordVisibility}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
helper={
|
||||||
|
inputTouched &&
|
||||||
|
!passwordValid(props.password) && <MyInputError text={errorText()} />
|
||||||
|
}
|
||||||
|
disableContainer={props.disableContainer}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function accountNameValid(accountName: string) {
|
||||||
|
if (accountName.length < accountNameOptions.minLength) {
|
||||||
|
return false;
|
||||||
|
} else if (!accountNameOptions.isAllowed(accountName)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AccountNameAvailable {
|
||||||
|
Loading,
|
||||||
|
Available,
|
||||||
|
NotAvailable,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MyAccountNameInputProps {
|
||||||
|
accountName: string;
|
||||||
|
setAccountName: (accountName: string) => void;
|
||||||
|
checkAccountNameAvailability?: boolean;
|
||||||
|
isAccountNameAvailable?: AccountNameAvailable;
|
||||||
|
setIsAccountNameAvailable?: (
|
||||||
|
isAccountNameAvailable: AccountNameAvailable,
|
||||||
|
) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MyAccountNameInput(props: MyAccountNameInputProps) {
|
||||||
|
const lang = useSelector(
|
||||||
|
(state: RootState) => state.appVariables.lang.commonInputs.accountName,
|
||||||
|
);
|
||||||
|
const currentTheme = useSelector(
|
||||||
|
(state: RootState) => state.nonSaveVariables.theme.colors,
|
||||||
|
);
|
||||||
|
|
||||||
|
const [inputTouched, setInputTouched] = useState(false);
|
||||||
|
|
||||||
|
const rightComponent = () => {
|
||||||
|
const closeIcon = (
|
||||||
|
<MyIcon name="close" size={24} color={currentTheme.red600} />
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!accountNameValid(props.accountName)) {
|
||||||
|
return closeIcon;
|
||||||
|
} else if (props.isAccountNameAvailable === AccountNameAvailable.Loading) {
|
||||||
|
return <Spinner />;
|
||||||
|
} else if (
|
||||||
|
props.isAccountNameAvailable === AccountNameAvailable.Available
|
||||||
|
) {
|
||||||
|
return <MyIcon name="check" size={24} color={currentTheme.green400} />;
|
||||||
|
} else {
|
||||||
|
return closeIcon;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const errorText = () => {
|
||||||
|
if (props.accountName.length < accountNameOptions.minLength) {
|
||||||
|
return reactStringReplace(lang.errorLength, '${minLength}', () => {
|
||||||
|
return accountNameOptions.minLength.toString();
|
||||||
|
}).join('');
|
||||||
|
} else if (!accountNameOptions.isAllowed(props.accountName)) {
|
||||||
|
return lang.errorAccountNameInvalid;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
if (props.checkAccountNameAvailability) {
|
||||||
|
useEffect(() => {
|
||||||
|
if (!accountNameValid(props.accountName)) return;
|
||||||
|
|
||||||
|
const delay = 400;
|
||||||
|
const timeoutId = setTimeout(() => {
|
||||||
|
makeRequest({
|
||||||
|
path: apiBackendRequest.CHECK_ACCOUNT_NAME,
|
||||||
|
requestGET: {':accountName': props.accountName},
|
||||||
|
response: {},
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
if (props.checkAccountNameAvailability) {
|
||||||
|
if (props.setIsAccountNameAvailable) {
|
||||||
|
props.setIsAccountNameAvailable(AccountNameAvailable.Available);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
if (props.setIsAccountNameAvailable) {
|
||||||
|
props.setIsAccountNameAvailable(
|
||||||
|
AccountNameAvailable.NotAvailable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, delay);
|
||||||
|
|
||||||
|
// Cleanup the timeout on component unmount or when inputValue changes
|
||||||
|
return () => clearTimeout(timeoutId);
|
||||||
|
}, [props.accountName]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MyIconInput
|
||||||
|
text={lang.label}
|
||||||
|
iconName="person"
|
||||||
|
value={props.accountName}
|
||||||
|
onChangeText={text => {
|
||||||
|
props.setAccountName(text);
|
||||||
|
setInputTouched(true);
|
||||||
|
|
||||||
|
if (props.setIsAccountNameAvailable) {
|
||||||
|
props.setIsAccountNameAvailable(AccountNameAvailable.Loading);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
maxLength={accountNameOptions.maxLength}
|
||||||
|
rightComponent={props.checkAccountNameAvailability && rightComponent()}
|
||||||
|
helper={
|
||||||
|
inputTouched &&
|
||||||
|
!accountNameValid(props.accountName) && (
|
||||||
|
<MyInputError text={errorText()} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
|
@ -2,14 +2,12 @@
|
||||||
|
|
||||||
import {chatEntity, roomId} from '@configs/chat/types';
|
import {chatEntity, roomId} from '@configs/chat/types';
|
||||||
import {User} from '@user/types';
|
import {User} from '@user/types';
|
||||||
import {AccountName} from './types';
|
import {UserId} from './types';
|
||||||
|
|
||||||
import {getVersionByNum, VersionType} from '@helper/version';
|
import {getVersionByNum, VersionType} from '@helper/version';
|
||||||
import configDarkTheme, {ThemeTokensType} from '@configs/colors';
|
import configDarkTheme, {ThemeTokensType} from '@configs/colors';
|
||||||
import { EventID, PAEvent } from '@event/types';
|
import {EventID, PAEvent} from '@event/types';
|
||||||
import { PA_Point } from '@components/map/types';
|
import {PA_Point} from '@components/map/types';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const APP_VERSION = getVersionByNum(1);
|
export const APP_VERSION = getVersionByNum(1);
|
||||||
export const AppVarMaxBackups: number = 10;
|
export const AppVarMaxBackups: number = 10;
|
||||||
|
@ -33,7 +31,7 @@ export interface NON_SAVE_VARS {
|
||||||
appStatus: appStatus;
|
appStatus: appStatus;
|
||||||
theme: ThemeTokensType;
|
theme: ThemeTokensType;
|
||||||
connectionStatus: connectionStatus;
|
connectionStatus: connectionStatus;
|
||||||
cachedUsers: {[key: AccountName]: User};
|
cachedUsers: {[key: UserId]: User};
|
||||||
cachedEvents: {[key: EventID]: PAEvent};
|
cachedEvents: {[key: EventID]: PAEvent};
|
||||||
chats: {[key: roomId]: chatEntity};
|
chats: {[key: roomId]: chatEntity};
|
||||||
chatActivity: roomId[];
|
chatActivity: roomId[];
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {ThemeTokensType} from '@configs/colors';
|
||||||
|
|
||||||
import {chatEntity, roomId} from '@configs/chat/types';
|
import {chatEntity, roomId} from '@configs/chat/types';
|
||||||
import {SourceProp, User} from '@user/types';
|
import {SourceProp, User} from '@user/types';
|
||||||
import {AccountName, EventId} from './types';
|
import {EventId, UserId} from './types';
|
||||||
import {PA_Point} from '@components/map/types';
|
import {PA_Point} from '@components/map/types';
|
||||||
import {PAEvent, createEventProp} from '@event/types';
|
import {PAEvent, createEventProp} from '@event/types';
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@ export const appNonSaveVariablesSlice = createSlice({
|
||||||
state.theme = action.payload;
|
state.theme = action.payload;
|
||||||
},
|
},
|
||||||
setCachedUser: (state, action: PayloadAction<User>) => {
|
setCachedUser: (state, action: PayloadAction<User>) => {
|
||||||
state.cachedUsers[action.payload.AccountName] = action.payload;
|
state.cachedUsers[action.payload.UserId] = action.payload;
|
||||||
},
|
},
|
||||||
removeCachedUser: (state, action: PayloadAction<AccountName>) => {
|
removeCachedUser: (state, action: PayloadAction<UserId>) => {
|
||||||
delete state.cachedUsers[action.payload];
|
delete state.cachedUsers[action.payload];
|
||||||
},
|
},
|
||||||
setCachedEvent: (state, action: PayloadAction<PAEvent>) => {
|
setCachedEvent: (state, action: PayloadAction<PAEvent>) => {
|
||||||
|
@ -31,8 +31,14 @@ export const appNonSaveVariablesSlice = createSlice({
|
||||||
removeCachedEvent: (state, action: PayloadAction<EventId>) => {
|
removeCachedEvent: (state, action: PayloadAction<EventId>) => {
|
||||||
delete state.cachedEvents[action.payload];
|
delete state.cachedEvents[action.payload];
|
||||||
},
|
},
|
||||||
setJoinedEvent: (state, action: PayloadAction<{id: EventId, isJoined: number}>) => {
|
setJoinedEvent: (
|
||||||
state.cachedEvents[action.payload.id].isJoined = createEventProp(SourceProp.cached, action.payload.isJoined);
|
state,
|
||||||
|
action: PayloadAction<{id: EventId; isJoined: number}>,
|
||||||
|
) => {
|
||||||
|
state.cachedEvents[action.payload.id].isJoined = createEventProp(
|
||||||
|
SourceProp.cached,
|
||||||
|
action.payload.isJoined,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
setSelectedChat: (state, action: PayloadAction<roomId>) => {
|
setSelectedChat: (state, action: PayloadAction<roomId>) => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {XToken, AccountName, Username} from '@configs/types';
|
import {AccountName, Username, UserId} from '@configs/types';
|
||||||
import {VersionType} from '@helper/version';
|
import {VersionType} from '@helper/version';
|
||||||
import {MyUserAccount} from '@user/types';
|
import {MyUserAccount} from '@user/types';
|
||||||
import {APP_VERSION} from './appNonSaveVar';
|
import {APP_VERSION} from './appNonSaveVar';
|
||||||
|
@ -53,8 +53,8 @@ export interface PREFERENCES_VARS {
|
||||||
version: VersionType;
|
version: VersionType;
|
||||||
theme: ThemeMode;
|
theme: ThemeMode;
|
||||||
RegisterProcess: RegisterProcess;
|
RegisterProcess: RegisterProcess;
|
||||||
selectedAccount: AccountName | 'none';
|
selectedAccount: UserId | 'none';
|
||||||
accounts: {[key: AccountName]: MyUserAccount};
|
accounts: {[key: UserId]: MyUserAccount};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const preferences_vars_default: PREFERENCES_VARS = {
|
export const preferences_vars_default: PREFERENCES_VARS = {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
} from './appVar';
|
} from './appVar';
|
||||||
import LangFormat from '@lang/default';
|
import LangFormat from '@lang/default';
|
||||||
import {lang as defaultLang} from '@lang/en';
|
import {lang as defaultLang} from '@lang/en';
|
||||||
import {AccountName} from './types';
|
import {UserId} from './types';
|
||||||
import {MyUserAccount} from '@user/types';
|
import {MyUserAccount} from '@user/types';
|
||||||
import {ThemeMode} from './colors';
|
import {ThemeMode} from './colors';
|
||||||
|
|
||||||
|
@ -21,6 +21,17 @@ const initialState: appVariablesState = {
|
||||||
lang: defaultLang,
|
lang: defaultLang,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
store.dispatch(
|
||||||
|
appVarActions.setAccountName({
|
||||||
|
name: response.response.accountName,
|
||||||
|
uuid: "",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
to save changes:
|
||||||
|
helper/appData.ts
|
||||||
|
*/
|
||||||
export const appVariablesSlice = createSlice({
|
export const appVariablesSlice = createSlice({
|
||||||
name: 'appVariables',
|
name: 'appVariables',
|
||||||
initialState,
|
initialState,
|
||||||
|
@ -37,11 +48,25 @@ export const appVariablesSlice = createSlice({
|
||||||
setRegisterProcess: (state, action: PayloadAction<RegisterProcess>) => {
|
setRegisterProcess: (state, action: PayloadAction<RegisterProcess>) => {
|
||||||
state.preferences.RegisterProcess = action.payload;
|
state.preferences.RegisterProcess = action.payload;
|
||||||
},
|
},
|
||||||
setCurrentAccount: (state, action: PayloadAction<AccountName>) => {
|
setCurrentAccount: (state, action: PayloadAction<UserId>) => {
|
||||||
state.preferences.selectedAccount = action.payload;
|
state.preferences.selectedAccount = action.payload;
|
||||||
},
|
},
|
||||||
setAccount: (state, action: PayloadAction<MyUserAccount>) => {
|
setAccount: (state, action: PayloadAction<MyUserAccount>) => {
|
||||||
state.preferences.accounts[action.payload.AccountName] = action.payload;
|
state.preferences.accounts[action.payload.UserId] = action.payload;
|
||||||
|
},
|
||||||
|
setAccountName: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<{userId: string; name: string}>,
|
||||||
|
) => {
|
||||||
|
state.preferences.accounts[action.payload.userId].AccountName.data =
|
||||||
|
action.payload.name;
|
||||||
|
},
|
||||||
|
setUsername: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<{userId: string; username: string}>,
|
||||||
|
) => {
|
||||||
|
state.preferences.accounts[action.payload.userId].Username.data =
|
||||||
|
action.payload.username;
|
||||||
},
|
},
|
||||||
setDBEK: (state, action: PayloadAction<number>) => {
|
setDBEK: (state, action: PayloadAction<number>) => {
|
||||||
state.preferences.dbek = action.payload;
|
state.preferences.dbek = action.payload;
|
||||||
|
|
|
@ -14,7 +14,7 @@ export type XToken = string;
|
||||||
//export type verifyId = string;
|
//export type verifyId = string;
|
||||||
|
|
||||||
export type XAuthorization = string;
|
export type XAuthorization = string;
|
||||||
//export type UserId = string;
|
export type UserId = string;
|
||||||
//export type WebSocketSessionId = string;
|
//export type WebSocketSessionId = string;
|
||||||
|
|
||||||
export type EventId = string;
|
export type EventId = string;
|
||||||
|
@ -32,7 +32,8 @@ export const userNameOptions = {
|
||||||
minLength: 2,
|
minLength: 2,
|
||||||
maxLength: 24,
|
maxLength: 24,
|
||||||
isAllowed: (text: string): boolean => {
|
isAllowed: (text: string): boolean => {
|
||||||
return true;
|
// allows usernames that start and end with a lowercase letter or digit, with optional dots or underscores in the middle, and it is case-insensitive
|
||||||
|
return text.match(/^[a-z0-9](?:[._]*[a-z0-9])*$/i) !== null;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {AppVarMaxBackups, APP_VERSION} from '@configs/appNonSaveVar';
|
||||||
import {appVarActions} from '@configs/appVarReducer';
|
import {appVarActions} from '@configs/appVarReducer';
|
||||||
import {store} from '@redux/store';
|
import {store} from '@redux/store';
|
||||||
import {getData, setData} from './storage/appData';
|
import {getData, setData} from './storage/appData';
|
||||||
import {getVersionByType, stepUpVersionCalc} from './version';
|
|
||||||
|
|
||||||
const APP_CHANGE_BACKUP = 'appVerChangeBackup';
|
const APP_CHANGE_BACKUP = 'appVerChangeBackup';
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
Password,
|
Password,
|
||||||
XAuthorization,
|
XAuthorization,
|
||||||
Username,
|
Username,
|
||||||
|
UserId,
|
||||||
} from '../configs/types';
|
} from '../configs/types';
|
||||||
import MyUserManager from '@user/MyUserManager';
|
import MyUserManager from '@user/MyUserManager';
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ export const apiPath = {
|
||||||
export enum apiBackendRequest {
|
export enum apiBackendRequest {
|
||||||
LOGIN = '/user/login',
|
LOGIN = '/user/login',
|
||||||
APP_START = '/user',
|
APP_START = '/user',
|
||||||
GET_USER_PROFILE = '/users/:accountName',
|
GET_USER_PROFILE = '/users/:userId',
|
||||||
LOGOUT = '/user/logout',
|
LOGOUT = '/user/logout',
|
||||||
SIGN_UP = '/user/signup',
|
SIGN_UP = '/user/signup',
|
||||||
CHECK_ACCOUNT_NAME = '/user/check/:accountName',
|
CHECK_ACCOUNT_NAME = '/user/check/:accountName',
|
||||||
|
@ -112,6 +113,7 @@ interface LOGIN extends defaultRequest {
|
||||||
};
|
};
|
||||||
response?: {
|
response?: {
|
||||||
XAuthorization: XAuthorization;
|
XAuthorization: XAuthorization;
|
||||||
|
UserId: UserId;
|
||||||
Username: Username;
|
Username: Username;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -125,6 +127,7 @@ interface SIGN_UP extends defaultRequest {
|
||||||
};
|
};
|
||||||
response?: {
|
response?: {
|
||||||
XAuthorization: XAuthorization;
|
XAuthorization: XAuthorization;
|
||||||
|
UserId: UserId;
|
||||||
Username: Username;
|
Username: Username;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -133,7 +136,7 @@ interface GET_USER_PROFILE extends defaultRequest {
|
||||||
path: apiBackendRequest.GET_USER_PROFILE;
|
path: apiBackendRequest.GET_USER_PROFILE;
|
||||||
|
|
||||||
requestGET: {
|
requestGET: {
|
||||||
':accountName': AccountName;
|
':userId': UserId;
|
||||||
};
|
};
|
||||||
response: {
|
response: {
|
||||||
//AccountName: AccountName;
|
//AccountName: AccountName;
|
||||||
|
|
|
@ -13,6 +13,28 @@ export default interface LangFormat {
|
||||||
join: string;
|
join: string;
|
||||||
quit: string;
|
quit: string;
|
||||||
};
|
};
|
||||||
|
eventCreateion: {
|
||||||
|
newEventTitle: string;
|
||||||
|
newPublicEventTitle: string;
|
||||||
|
newPrivateEventTitle: string;
|
||||||
|
name: string;
|
||||||
|
uploadImage: string;
|
||||||
|
description: string;
|
||||||
|
location: string;
|
||||||
|
create: string;
|
||||||
|
website: string;
|
||||||
|
datetime: string;
|
||||||
|
openingHoursFlag: string;
|
||||||
|
};
|
||||||
|
days: {
|
||||||
|
monday: string;
|
||||||
|
tuesday: string;
|
||||||
|
wednesday: string;
|
||||||
|
thursday: string;
|
||||||
|
friday: string;
|
||||||
|
saturday: string;
|
||||||
|
sunday: string;
|
||||||
|
};
|
||||||
navigation: {
|
navigation: {
|
||||||
home: {
|
home: {
|
||||||
profile: {
|
profile: {
|
||||||
|
@ -41,6 +63,23 @@ export default interface LangFormat {
|
||||||
info: string;
|
info: string;
|
||||||
error: string;
|
error: string;
|
||||||
success: string;
|
success: string;
|
||||||
|
commonInputs: {
|
||||||
|
username: {
|
||||||
|
label: string;
|
||||||
|
errorLength: string;
|
||||||
|
errorUsernameInvalid: string;
|
||||||
|
};
|
||||||
|
accountName: {
|
||||||
|
label: string;
|
||||||
|
errorLength: string;
|
||||||
|
errorAccountNameInvalid: string;
|
||||||
|
};
|
||||||
|
password: {
|
||||||
|
label: string;
|
||||||
|
errorLength: string;
|
||||||
|
errorPasswordInvalid: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
registration: {
|
registration: {
|
||||||
buttonLogin: string;
|
buttonLogin: string;
|
||||||
buttonSignUp: string;
|
buttonSignUp: string;
|
||||||
|
@ -71,12 +110,9 @@ export default interface LangFormat {
|
||||||
signUpStepUsername: {
|
signUpStepUsername: {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
inputUsername: string;
|
|
||||||
error: string;
|
|
||||||
};
|
};
|
||||||
signUpStepPhoneNumber: {
|
signUpStepPhoneNumber: {
|
||||||
title: string;
|
title: string;
|
||||||
inputPhoneNumber: string;
|
|
||||||
};
|
};
|
||||||
signUpStepVerifyPhoneNumber: {
|
signUpStepVerifyPhoneNumber: {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -86,9 +122,6 @@ export default interface LangFormat {
|
||||||
signUpStepPassword: {
|
signUpStepPassword: {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
inputPassword: string;
|
|
||||||
errorLength: string;
|
|
||||||
errorPasswordInvalid: string;
|
|
||||||
};
|
};
|
||||||
signUpStepAccountName: {
|
signUpStepAccountName: {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -96,8 +129,6 @@ export default interface LangFormat {
|
||||||
inputAccountName: string;
|
inputAccountName: string;
|
||||||
buttonGetStarted: string;
|
buttonGetStarted: string;
|
||||||
signUpError: {[key: number]: string};
|
signUpError: {[key: number]: string};
|
||||||
errorLength: string;
|
|
||||||
errorAccountNameInvalid: string;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
profile: {
|
profile: {
|
||||||
|
|
|
@ -12,6 +12,28 @@ export const lang: LangFormat = {
|
||||||
join: 'Join',
|
join: 'Join',
|
||||||
quit: 'Quit',
|
quit: 'Quit',
|
||||||
},
|
},
|
||||||
|
eventCreateion: {
|
||||||
|
newEventTitle: 'New Event',
|
||||||
|
newPublicEventTitle: 'New Public Event',
|
||||||
|
newPrivateEventTitle: 'New Private Event',
|
||||||
|
name: 'Name',
|
||||||
|
uploadImage: 'Upload banner',
|
||||||
|
description: 'Description',
|
||||||
|
location: 'Location',
|
||||||
|
create: 'Create',
|
||||||
|
website: 'Website',
|
||||||
|
datetime: 'Date & Time',
|
||||||
|
openingHoursFlag: 'Opening hours / days',
|
||||||
|
},
|
||||||
|
days: {
|
||||||
|
monday: 'Monday',
|
||||||
|
tuesday: 'Tuesday',
|
||||||
|
wednesday: 'Wednesday',
|
||||||
|
thursday: 'Thursday',
|
||||||
|
friday: 'Friday',
|
||||||
|
saturday: 'Saturday',
|
||||||
|
sunday: 'Sunday',
|
||||||
|
},
|
||||||
appName: 'Party App',
|
appName: 'Party App',
|
||||||
navigation: {
|
navigation: {
|
||||||
home: {
|
home: {
|
||||||
|
@ -41,6 +63,26 @@ export const lang: LangFormat = {
|
||||||
info: 'Info',
|
info: 'Info',
|
||||||
error: 'Error',
|
error: 'Error',
|
||||||
success: 'Success',
|
success: 'Success',
|
||||||
|
commonInputs: {
|
||||||
|
username: {
|
||||||
|
label: 'USERNAME',
|
||||||
|
errorLength: 'At least ${minLength} characters are required',
|
||||||
|
errorUsernameInvalid:
|
||||||
|
'Username can only contain a-z, 0-9, underscores and dots',
|
||||||
|
},
|
||||||
|
accountName: {
|
||||||
|
label: 'ACCOUNT NAME',
|
||||||
|
errorLength: 'Account name must be at least ${minLength} characters long',
|
||||||
|
errorAccountNameInvalid:
|
||||||
|
'Account name can only contain a-z, 0-9, underscores and dots',
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
label: 'PASSWORD',
|
||||||
|
errorLength: 'Password must be at least ${minLength} characters long',
|
||||||
|
errorPasswordInvalid:
|
||||||
|
'Must include at least on uppercase letter, one lowercase letter, one number and one special character',
|
||||||
|
},
|
||||||
|
},
|
||||||
registration: {
|
registration: {
|
||||||
buttonLogin: 'Login',
|
buttonLogin: 'Login',
|
||||||
buttonSignUp: 'Sign up',
|
buttonSignUp: 'Sign up',
|
||||||
|
@ -71,12 +113,9 @@ export const lang: LangFormat = {
|
||||||
signUpStepUsername: {
|
signUpStepUsername: {
|
||||||
title: "Let's get started, what's your name?",
|
title: "Let's get started, what's your name?",
|
||||||
description: 'The name will be displayed on your profil overview',
|
description: 'The name will be displayed on your profil overview',
|
||||||
inputUsername: 'Username',
|
|
||||||
error: 'At least ${minLength} characters are required',
|
|
||||||
},
|
},
|
||||||
signUpStepPhoneNumber: {
|
signUpStepPhoneNumber: {
|
||||||
title: 'Create your account using your phone number',
|
title: 'Create your account using your phone number',
|
||||||
inputPhoneNumber: 'PHONE NUMBER',
|
|
||||||
},
|
},
|
||||||
signUpStepVerifyPhoneNumber: {
|
signUpStepVerifyPhoneNumber: {
|
||||||
title: 'We sent you a code',
|
title: 'We sent you a code',
|
||||||
|
@ -86,10 +125,6 @@ export const lang: LangFormat = {
|
||||||
signUpStepPassword: {
|
signUpStepPassword: {
|
||||||
title: "You'll need a password",
|
title: "You'll need a password",
|
||||||
description: 'Make sure it’s ${minLength} characters or more.',
|
description: 'Make sure it’s ${minLength} characters or more.',
|
||||||
inputPassword: 'PASSWORD',
|
|
||||||
errorLength: 'Password must be at least ${minLength} characters long',
|
|
||||||
errorPasswordInvalid:
|
|
||||||
'Must include at least on uppercase letter, one lowercase letter, one number and one special character',
|
|
||||||
},
|
},
|
||||||
signUpStepAccountName: {
|
signUpStepAccountName: {
|
||||||
title: 'Next, create your account name',
|
title: 'Next, create your account name',
|
||||||
|
@ -97,9 +132,6 @@ export const lang: LangFormat = {
|
||||||
'Your account name is unique and is used for friends to find you.',
|
'Your account name is unique and is used for friends to find you.',
|
||||||
inputAccountName: 'ACCOUNT NAME',
|
inputAccountName: 'ACCOUNT NAME',
|
||||||
buttonGetStarted: 'Get Started',
|
buttonGetStarted: 'Get Started',
|
||||||
errorLength: 'Account name must be at least ${minLength} characters long',
|
|
||||||
errorAccountNameInvalid:
|
|
||||||
'Account name can only contain \n20a-z, 0-9, underscores and dots',
|
|
||||||
signUpError: {
|
signUpError: {
|
||||||
400: 'Invalid account name',
|
400: 'Invalid account name',
|
||||||
401: 'Invalid credentials',
|
401: 'Invalid credentials',
|
||||||
|
|
|
@ -2,6 +2,7 @@ import Stack from '@pages/globalStackManager';
|
||||||
import {
|
import {
|
||||||
NavigatorScreenParams,
|
NavigatorScreenParams,
|
||||||
getFocusedRouteNameFromRoute,
|
getFocusedRouteNameFromRoute,
|
||||||
|
useNavigation,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
import {
|
import {
|
||||||
BottomTabBarProps,
|
BottomTabBarProps,
|
||||||
|
@ -16,7 +17,7 @@ import ProfileTab, {
|
||||||
ProfileStackNavigatorParamList,
|
ProfileStackNavigatorParamList,
|
||||||
} from './tabs/main/ProfileTab';
|
} from './tabs/main/ProfileTab';
|
||||||
import {FadeInView} from '@helper/animations';
|
import {FadeInView} from '@helper/animations';
|
||||||
import {Animated, AppState, View} from 'react-native';
|
import {Animated, View} from 'react-native';
|
||||||
import LinearGradient from 'react-native-linear-gradient';
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
import {
|
import {
|
||||||
RegistrationScreenAnim,
|
RegistrationScreenAnim,
|
||||||
|
@ -29,8 +30,9 @@ import {RootState, store as reduxStore} from '@redux/store';
|
||||||
import {Text} from '@gluestack-ui/themed';
|
import {Text} from '@gluestack-ui/themed';
|
||||||
import {MyTouchableOpacity} from '@components/MyTouchableOpacity';
|
import {MyTouchableOpacity} from '@components/MyTouchableOpacity';
|
||||||
import {useEffect, useRef} from 'react';
|
import {useEffect, useRef} from 'react';
|
||||||
import {animated, useSpring} from '@react-spring/native';
|
|
||||||
import {apiBackendRequest, makeRequest} from '@helper/request';
|
import {apiBackendRequest, makeRequest} from '@helper/request';
|
||||||
|
import {appVarActions} from '@configs/appVarReducer';
|
||||||
|
import MyUserManager from '@user/MyUserManager';
|
||||||
|
|
||||||
export type RootStackNavigatorParamList = {
|
export type RootStackNavigatorParamList = {
|
||||||
Home: NavigatorScreenParams<HomeStackNavigatorParamList>;
|
Home: NavigatorScreenParams<HomeStackNavigatorParamList>;
|
||||||
|
@ -44,9 +46,13 @@ export default function Navigation() {
|
||||||
const currentUser =
|
const currentUser =
|
||||||
reduxStore.getState().appVariables.preferences.selectedAccount;
|
reduxStore.getState().appVariables.preferences.selectedAccount;
|
||||||
|
|
||||||
|
const rootNavigation = useNavigation<RootScreenNavigationProp>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('APP NAVIGATION');
|
console.log('APP NAVIGATION');
|
||||||
|
|
||||||
|
if (currentUser === 'none') return;
|
||||||
|
|
||||||
makeRequest({
|
makeRequest({
|
||||||
path: apiBackendRequest.APP_START,
|
path: apiBackendRequest.APP_START,
|
||||||
response: {
|
response: {
|
||||||
|
@ -65,8 +71,30 @@ export default function Navigation() {
|
||||||
Events: {},
|
Events: {},
|
||||||
TokenValid: false, */
|
TokenValid: false, */
|
||||||
},
|
},
|
||||||
}).then(response => {
|
})
|
||||||
console.log(response);
|
.then(resp => {
|
||||||
|
if (resp.response.accountName !== undefined) {
|
||||||
|
reduxStore.dispatch(
|
||||||
|
appVarActions.setAccountName({
|
||||||
|
userId: currentUser,
|
||||||
|
name: resp.response.accountName,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.response.username !== undefined) {
|
||||||
|
reduxStore.dispatch(
|
||||||
|
appVarActions.setUsername({
|
||||||
|
userId: currentUser,
|
||||||
|
username: resp.response.username,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (err.status === 401) {
|
||||||
|
MyUserManager.logoutMyUser(rootNavigation);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,10 @@ import {Map} from '@pages/map/map';
|
||||||
|
|
||||||
import {EventID} from '@components/map/types';
|
import {EventID} from '@components/map/types';
|
||||||
import EventPage from '@pages/event/EventPage';
|
import EventPage from '@pages/event/EventPage';
|
||||||
|
import CreateEventPage, {
|
||||||
|
EventCreationNavigatorParamList,
|
||||||
|
} from '@pages/event/CreateEventNavigation';
|
||||||
|
import {NavigatorScreenParams} from '@react-navigation/native';
|
||||||
|
|
||||||
export const MapTabName = 'Map';
|
export const MapTabName = 'Map';
|
||||||
|
|
||||||
|
@ -19,6 +23,7 @@ export type MapStackNavigatorParamList = {
|
||||||
Overview: undefined;
|
Overview: undefined;
|
||||||
Event: {eventID: EventID};
|
Event: {eventID: EventID};
|
||||||
EventStore: {eventID: EventID};
|
EventStore: {eventID: EventID};
|
||||||
|
CreateEvent: NavigatorScreenParams<EventCreationNavigatorParamList>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const MapStack = createNativeStackNavigator<MapStackNavigatorParamList>();
|
const MapStack = createNativeStackNavigator<MapStackNavigatorParamList>();
|
||||||
|
@ -27,9 +32,7 @@ export type MapScreenNavigationProp =
|
||||||
NativeStackNavigationProp<MapStackNavigatorParamList>;
|
NativeStackNavigationProp<MapStackNavigatorParamList>;
|
||||||
|
|
||||||
function MapTab() {
|
function MapTab() {
|
||||||
const lang = useSelector(
|
const lang = useSelector((state: RootState) => state.appVariables.lang);
|
||||||
(state: RootState) => state.appVariables.lang.navigation.home.map,
|
|
||||||
);
|
|
||||||
const currentTheme = useSelector(
|
const currentTheme = useSelector(
|
||||||
(state: RootState) => state.nonSaveVariables.theme.colors,
|
(state: RootState) => state.nonSaveVariables.theme.colors,
|
||||||
);
|
);
|
||||||
|
@ -63,6 +66,13 @@ function MapTab() {
|
||||||
options={{headerShown: true}}
|
options={{headerShown: true}}
|
||||||
component={EventPage}
|
component={EventPage}
|
||||||
/>
|
/>
|
||||||
|
<MapStack.Screen
|
||||||
|
name="CreateEvent"
|
||||||
|
options={{
|
||||||
|
headerShown: false,
|
||||||
|
}}
|
||||||
|
component={CreateEventPage}
|
||||||
|
/>
|
||||||
</MapStack.Navigator>
|
</MapStack.Navigator>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,6 @@ const events: ArrayLike<any> | null | undefined = [];
|
||||||
for (let i = 1; i <= 100; i++) {
|
for (let i = 1; i <= 100; i++) {
|
||||||
const randomUrlIndex = Math.floor(Math.random() * baseUrls.length);
|
const randomUrlIndex = Math.floor(Math.random() * baseUrls.length);
|
||||||
|
|
||||||
// hello world
|
|
||||||
|
|
||||||
events.push({
|
events.push({
|
||||||
id: i,
|
id: i,
|
||||||
url: baseUrls[randomUrlIndex],
|
url: baseUrls[randomUrlIndex],
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import {MyIconButton} from '@components/MyButton';
|
||||||
|
import {MyScreenContainer} from '@components/MyScreenContainer';
|
||||||
|
import {ButtonText, VStack, HStack} from '@gluestack-ui/themed';
|
||||||
|
import {RootState} from '@redux/store';
|
||||||
|
import {View, Text, Button, Pressable} from 'react-native';
|
||||||
|
import {useSelector} from 'react-redux';
|
||||||
|
|
||||||
|
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||||
|
|
||||||
|
function Overview() {
|
||||||
|
const lang = useSelector(
|
||||||
|
(state: RootState) => state.appVariables.lang.eventCreateion,
|
||||||
|
);
|
||||||
|
const currentTheme = useSelector(
|
||||||
|
(state: RootState) => state.nonSaveVariables.theme.colors,
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MyScreenContainer>
|
||||||
|
<VStack space={'sm'} alignItems="center">
|
||||||
|
<EventType MyIconProps={{name: 'public', size: 28}} />
|
||||||
|
<EventType MyIconProps={{name: 'public', size: 28}} />
|
||||||
|
</VStack>
|
||||||
|
</MyScreenContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function EventType({
|
||||||
|
MyIconProps,
|
||||||
|
}: {
|
||||||
|
MyIconProps: {name: string; size: number; color?: string};
|
||||||
|
}) {
|
||||||
|
const currentTheme = useSelector(
|
||||||
|
(state: RootState) => state.nonSaveVariables.theme.colors,
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Pressable
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: 50,
|
||||||
|
backgroundColor: currentTheme.backgroundDark300,
|
||||||
|
borderRadius: 10,
|
||||||
|
}}>
|
||||||
|
<HStack>
|
||||||
|
<MaterialIcon
|
||||||
|
name={MyIconProps.name}
|
||||||
|
size={MyIconProps.size}
|
||||||
|
color={MyIconProps.color}
|
||||||
|
/>
|
||||||
|
<Text>Event Type</Text>
|
||||||
|
</HStack>
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Overview;
|
|
@ -0,0 +1,53 @@
|
||||||
|
import {MapStackNavigatorParamList} from '@navigation/tabs/main/MapTab';
|
||||||
|
import {
|
||||||
|
createNativeStackNavigator,
|
||||||
|
NativeStackNavigationProp,
|
||||||
|
} from '@react-navigation/native-stack';
|
||||||
|
import {RootState} from '@redux/store';
|
||||||
|
import {View, Text} from 'react-native';
|
||||||
|
import {useSelector} from 'react-redux';
|
||||||
|
import EventPage from './EventPage';
|
||||||
|
|
||||||
|
import Overview from './CreateEvent/Overview';
|
||||||
|
|
||||||
|
export type EventCreationNavigatorParamList = {
|
||||||
|
Overview: undefined;
|
||||||
|
PublicEvent: undefined;
|
||||||
|
PrivateEvent: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const EventCreationStack =
|
||||||
|
createNativeStackNavigator<MapStackNavigatorParamList>();
|
||||||
|
|
||||||
|
export type EventCreationScreenNavigationProp =
|
||||||
|
NativeStackNavigationProp<MapStackNavigatorParamList>;
|
||||||
|
|
||||||
|
function CreateEventPage() {
|
||||||
|
const lang = useSelector((state: RootState) => state.appVariables.lang);
|
||||||
|
const currentTheme = useSelector(
|
||||||
|
(state: RootState) => state.nonSaveVariables.theme.colors,
|
||||||
|
);
|
||||||
|
|
||||||
|
const headerStyle = {
|
||||||
|
backgroundColor: currentTheme.backgroundDark400,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EventCreationStack.Navigator initialRouteName="Overview">
|
||||||
|
<EventCreationStack.Screen
|
||||||
|
name="Overview"
|
||||||
|
options={{
|
||||||
|
animation: 'simple_push',
|
||||||
|
title: lang.eventCreateion.newEventTitle,
|
||||||
|
headerShown: true,
|
||||||
|
headerStyle: headerStyle,
|
||||||
|
headerShadowVisible: false,
|
||||||
|
headerTitleAlign: 'center',
|
||||||
|
}}
|
||||||
|
component={Overview}
|
||||||
|
/>
|
||||||
|
</EventCreationStack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CreateEventPage;
|
|
@ -1,4 +1,4 @@
|
||||||
import {StyleSheet, View, Text, Image} from 'react-native';
|
import {StyleSheet, View, Text, Image, ViewStyle} from 'react-native';
|
||||||
import Mapbox, {MarkerView} from '@rnmapbox/maps';
|
import Mapbox, {MarkerView} from '@rnmapbox/maps';
|
||||||
|
|
||||||
import React, {useState} from 'react'; // Add useState import
|
import React, {useState} from 'react'; // Add useState import
|
||||||
|
@ -11,14 +11,17 @@ import {RootState, store} from '@redux/store';
|
||||||
import {appNonSaveVarActions} from '@configs/appNonSaveVarReducer';
|
import {appNonSaveVarActions} from '@configs/appNonSaveVarReducer';
|
||||||
import {Position} from '@rnmapbox/maps/src/types/Position';
|
import {Position} from '@rnmapbox/maps/src/types/Position';
|
||||||
|
|
||||||
import {Dimensions} from 'react-native';
|
import {Dimensions, Pressable} from 'react-native';
|
||||||
import {MyIconButton} from '@components/MyButton';
|
import {MyIconButton} from '@components/MyButton';
|
||||||
import {MyTouchableOpacity} from '@components/MyTouchableOpacity';
|
import {MyTouchableOpacity} from '@components/MyTouchableOpacity';
|
||||||
import {MyIcon} from '@components/MyIcon';
|
import {MyIcon} from '@components/MyIcon';
|
||||||
import {useSelector} from 'react-redux';
|
import {useSelector} from 'react-redux';
|
||||||
import {Button, ButtonIcon} from '@gluestack-ui/themed';
|
import {Button, ButtonIcon} from '@gluestack-ui/themed';
|
||||||
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
|
|
||||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||||
|
import {MapScreenNavigationProp} from '@navigation/tabs/main/MapTab';
|
||||||
|
import {useNavigation} from '@react-navigation/native';
|
||||||
|
|
||||||
Mapbox.setAccessToken(
|
Mapbox.setAccessToken(
|
||||||
'pk.eyJ1IjoidGl0YW5pdW1iYWNoIiwiYSI6ImNscGgzZGJxMDAwbHQyaXA2N3BtOWUxbWkifQ.x-f8JJxwQHWmPFI3P6Qn-w',
|
'pk.eyJ1IjoidGl0YW5pdW1iYWNoIiwiYSI6ImNscGgzZGJxMDAwbHQyaXA2N3BtOWUxbWkifQ.x-f8JJxwQHWmPFI3P6Qn-w',
|
||||||
|
@ -27,6 +30,11 @@ Mapbox.setAccessToken(
|
||||||
let lastCameraChange = 0;
|
let lastCameraChange = 0;
|
||||||
let isRerenderData = 0;
|
let isRerenderData = 0;
|
||||||
|
|
||||||
|
const IconButtonSize = 28;
|
||||||
|
const IconButtonCircleSize = IconButtonSize * 1.75;
|
||||||
|
|
||||||
|
const IconMarginRight = 15;
|
||||||
|
|
||||||
export const Map = () => {
|
export const Map = () => {
|
||||||
const mapRef = React.useRef<Mapbox.MapView | null>(null);
|
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
|
||||||
|
@ -36,6 +44,8 @@ export const Map = () => {
|
||||||
(state: RootState) => state.nonSaveVariables.theme.colors,
|
(state: RootState) => state.nonSaveVariables.theme.colors,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const navigation = useNavigation<MapScreenNavigationProp>();
|
||||||
|
|
||||||
const getVisibleBounds = async () => {
|
const getVisibleBounds = async () => {
|
||||||
// return when lastDataRerender is 300ms ago
|
// return when lastDataRerender is 300ms ago
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
@ -132,16 +142,63 @@ export const Map = () => {
|
||||||
attributionPosition={{top: 10, left: 100}}
|
attributionPosition={{top: 10, left: 100}}
|
||||||
logoPosition={{top: 10, left: 10}}
|
logoPosition={{top: 10, left: 10}}
|
||||||
styleURL="mapbox://styles/titaniumbach/clpij5uoo00o301pg2dj23j0m"
|
styleURL="mapbox://styles/titaniumbach/clpij5uoo00o301pg2dj23j0m"
|
||||||
projection="globe">
|
projection="globe"
|
||||||
|
compassPosition={{top: 10, right: IconMarginRight}}
|
||||||
|
compassImage={'mycompassimagekey'}>
|
||||||
<DisplayMarkerList />
|
<DisplayMarkerList />
|
||||||
</Mapbox.MapView>
|
</Mapbox.MapView>
|
||||||
<MapIconButton
|
<MapIconButton
|
||||||
MyIconProps={{
|
MyIconProps={{
|
||||||
name: 'close',
|
name: 'group',
|
||||||
size: 24,
|
size: IconButtonSize,
|
||||||
backgroundColor: colors.backgroundDark300,
|
backgroundColor: colors.backgroundDark300,
|
||||||
}}
|
}}
|
||||||
onPress={() => {}}
|
onPress={() => {}}
|
||||||
|
style={{
|
||||||
|
top: 70,
|
||||||
|
right: IconMarginRight,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MapIconButton
|
||||||
|
MyIconProps={{
|
||||||
|
name: 'tune',
|
||||||
|
size: IconButtonSize,
|
||||||
|
backgroundColor: colors.backgroundDark300,
|
||||||
|
}}
|
||||||
|
onPress={() => {}}
|
||||||
|
style={{
|
||||||
|
top: 70 + IconButtonCircleSize + 10,
|
||||||
|
right: IconMarginRight,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MapIconButton
|
||||||
|
MyIconProps={{
|
||||||
|
name: 'add',
|
||||||
|
size: IconButtonSize,
|
||||||
|
color: colors.backgroundLight300,
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
navigation.navigate('CreateEvent', {screen: 'Overview'});
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
bottom: 90 + 10 + IconButtonCircleSize,
|
||||||
|
right: IconMarginRight,
|
||||||
|
}}
|
||||||
|
type="primary"
|
||||||
|
/>
|
||||||
|
<MapIconButton
|
||||||
|
MyIconProps={{
|
||||||
|
name: 'search',
|
||||||
|
size: IconButtonSize,
|
||||||
|
backgroundColor: colors.backgroundDark300,
|
||||||
|
}}
|
||||||
|
onPress={() => {}}
|
||||||
|
style={{
|
||||||
|
bottom: 90,
|
||||||
|
right: IconMarginRight,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
@ -166,6 +223,8 @@ const styles = StyleSheet.create({
|
||||||
function MapIconButton({
|
function MapIconButton({
|
||||||
onPress,
|
onPress,
|
||||||
MyIconProps,
|
MyIconProps,
|
||||||
|
style,
|
||||||
|
type,
|
||||||
}: {
|
}: {
|
||||||
onPress: () => void;
|
onPress: () => void;
|
||||||
MyIconProps: {
|
MyIconProps: {
|
||||||
|
@ -174,18 +233,73 @@ function MapIconButton({
|
||||||
size: number;
|
size: number;
|
||||||
backgroundColor?: string;
|
backgroundColor?: string;
|
||||||
};
|
};
|
||||||
|
style?: ViewStyle;
|
||||||
|
type?: 'primary' | 'secondary';
|
||||||
}) {
|
}) {
|
||||||
|
const currentTheme = useSelector(
|
||||||
|
(state: RootState) => state.nonSaveVariables.theme,
|
||||||
|
);
|
||||||
|
|
||||||
|
const viewStyle: ViewStyle = {
|
||||||
|
position: 'absolute',
|
||||||
|
|
||||||
|
width: IconButtonCircleSize,
|
||||||
|
height: IconButtonCircleSize,
|
||||||
|
borderRadius: MyIconProps.size, // This will make the View circular
|
||||||
|
justifyContent: 'center', // Center the icon vertically
|
||||||
|
alignItems: 'center', // Center the icon horizontally
|
||||||
|
elevation: 5,
|
||||||
|
overflow: 'hidden',
|
||||||
|
...style,
|
||||||
|
};
|
||||||
|
|
||||||
|
const pressableStyle: ViewStyle = {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
justifyContent: 'center', // Center the icon vertically
|
||||||
|
alignItems: 'center', // Center the icon horizontally
|
||||||
|
};
|
||||||
|
|
||||||
|
if (type === 'primary') {
|
||||||
|
return (
|
||||||
|
<LinearGradient
|
||||||
|
colors={[
|
||||||
|
currentTheme.colors.secondary200,
|
||||||
|
currentTheme.colors.primary400,
|
||||||
|
]}
|
||||||
|
start={{x: 0, y: 1}}
|
||||||
|
end={{x: 1, y: 0}}
|
||||||
|
style={{elevation: 50, ...viewStyle}}>
|
||||||
|
<Pressable
|
||||||
|
android_ripple={{color: '#3e00a8'}}
|
||||||
|
style={pressableStyle}
|
||||||
|
onPress={onPress}>
|
||||||
|
<MaterialIcon
|
||||||
|
name={MyIconProps.name}
|
||||||
|
size={MyIconProps.size}
|
||||||
|
color={MyIconProps.color}
|
||||||
|
/>
|
||||||
|
</Pressable>
|
||||||
|
</LinearGradient>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
backgroundColor: MyIconProps.backgroundColor, // Set the background color
|
||||||
top: 60,
|
...viewStyle,
|
||||||
right: 10,
|
|
||||||
|
|
||||||
width: MyIconProps.size * 2,
|
|
||||||
height: MyIconProps.size * 2,
|
|
||||||
}}>
|
}}>
|
||||||
<MaterialIcon.Button name="facebook" backgroundColor="#3b5998" />
|
<Pressable
|
||||||
|
android_ripple={{color: '#fff2', foreground: false}}
|
||||||
|
style={pressableStyle}
|
||||||
|
onPress={onPress}>
|
||||||
|
<MaterialIcon
|
||||||
|
name={MyIconProps.name}
|
||||||
|
size={MyIconProps.size}
|
||||||
|
color={MyIconProps.color}
|
||||||
|
/>
|
||||||
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {MyVerticalDivider} from '@components/MyDivider';
|
||||||
import {MyIcon} from '@components/MyIcon';
|
import {MyIcon} from '@components/MyIcon';
|
||||||
import {useNavigation} from '@react-navigation/native';
|
import {useNavigation} from '@react-navigation/native';
|
||||||
import {ProfileScreenNavigationProp} from '@navigation/tabs/main/ProfileTab';
|
import {ProfileScreenNavigationProp} from '@navigation/tabs/main/ProfileTab';
|
||||||
import {MyIconInput} from '@components/MyInput';
|
import {MyIconInput, MyInputError} from '@components/MyInput';
|
||||||
import {useEffect, useState} from 'react';
|
import {useEffect, useState} from 'react';
|
||||||
import {RootScreenNavigationProp} from '@navigation/navigation';
|
import {RootScreenNavigationProp} from '@navigation/navigation';
|
||||||
import {useSelector} from 'react-redux';
|
import {useSelector} from 'react-redux';
|
||||||
|
@ -19,6 +19,12 @@ import MyUserManager from '@user/MyUserManager';
|
||||||
import {apiBackendRequest, makeRequest} from '@helper/request';
|
import {apiBackendRequest, makeRequest} from '@helper/request';
|
||||||
import reactStringReplace from 'react-string-replace';
|
import reactStringReplace from 'react-string-replace';
|
||||||
import {passwordOptions, userNameOptions} from '@configs/types';
|
import {passwordOptions, userNameOptions} from '@configs/types';
|
||||||
|
import {
|
||||||
|
MyPasswordInput,
|
||||||
|
MyUsernameInput,
|
||||||
|
passwordValid,
|
||||||
|
usernameValid,
|
||||||
|
} from '@components/MyCommonInputs';
|
||||||
|
|
||||||
function UserAvatar() {
|
function UserAvatar() {
|
||||||
return (
|
return (
|
||||||
|
@ -137,7 +143,9 @@ export function ProfileSettings() {
|
||||||
<SettingsItem
|
<SettingsItem
|
||||||
icon="person"
|
icon="person"
|
||||||
title={lang.accountData.accountName}
|
title={lang.accountData.accountName}
|
||||||
value={user.AccountName === undefined ? '' : user.AccountName}
|
value={
|
||||||
|
user.AccountName.data === undefined ? '' : user.AccountName.data
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingsItem
|
<SettingsItem
|
||||||
|
@ -182,12 +190,7 @@ export function ProfileSettings() {
|
||||||
console.log('logout failed, err: ', reason);
|
console.log('logout failed, err: ', reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
MyUserManager.logoutMyUser();
|
MyUserManager.logoutMyUser(rootNavigation);
|
||||||
rootNavigation.navigate('Registration', {screen: 'LoginPreview'});
|
|
||||||
rootNavigation.reset({
|
|
||||||
index: 0,
|
|
||||||
routes: [{name: 'Registration'}],
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SettingsItemContainer>
|
</SettingsItemContainer>
|
||||||
|
@ -256,9 +259,7 @@ function SettingsItem({icon, title, value, onPress}: SettingsItemProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function UpdateUsername() {
|
export function UpdateUsername() {
|
||||||
const lang = useSelector(
|
const lang = useSelector((state: RootState) => state.appVariables.lang);
|
||||||
(state: RootState) => state.appVariables.lang.profile.settings,
|
|
||||||
);
|
|
||||||
const currentTheme = useSelector(
|
const currentTheme = useSelector(
|
||||||
(state: RootState) => state.nonSaveVariables.theme.colors,
|
(state: RootState) => state.nonSaveVariables.theme.colors,
|
||||||
);
|
);
|
||||||
|
@ -273,7 +274,7 @@ export function UpdateUsername() {
|
||||||
const [newUsername, setNewUsername] = useState(user.Username.data || '');
|
const [newUsername, setNewUsername] = useState(user.Username.data || '');
|
||||||
|
|
||||||
const info2Text = reactStringReplace(
|
const info2Text = reactStringReplace(
|
||||||
lang.changeUsername.info2,
|
lang.profile.settings.changeUsername.info2,
|
||||||
'${minLength}',
|
'${minLength}',
|
||||||
() => userNameOptions.minLength.toString(),
|
() => userNameOptions.minLength.toString(),
|
||||||
);
|
);
|
||||||
|
@ -283,7 +284,7 @@ export function UpdateUsername() {
|
||||||
|
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
headerRight: () =>
|
headerRight: () =>
|
||||||
changed ? (
|
changed && usernameValid(newUsername) ? (
|
||||||
<MyTouchableOpacity onPress={() => navigation.goBack()}>
|
<MyTouchableOpacity onPress={() => navigation.goBack()}>
|
||||||
<MyIcon
|
<MyIcon
|
||||||
name="done"
|
name="done"
|
||||||
|
@ -299,16 +300,14 @@ export function UpdateUsername() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MyScreenContainer style={{paddingTop: 20}}>
|
<MyScreenContainer style={{paddingTop: 20}}>
|
||||||
<MyIconInput
|
<MyUsernameInput
|
||||||
iconName="person"
|
username={newUsername}
|
||||||
text={lang.changeUsername.username}
|
setUsername={value => {
|
||||||
value={newUsername}
|
setNewUsername(value);
|
||||||
onChangeText={text => {
|
|
||||||
setNewUsername(text);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Text color={currentTheme.textLight100} style={{marginTop: 12}}>
|
<Text color={currentTheme.textLight100} style={{marginTop: 12}}>
|
||||||
{lang.changeUsername.info}
|
{lang.profile.settings.changeUsername.info}
|
||||||
</Text>
|
</Text>
|
||||||
<Text color={currentTheme.textLight100}>{info2Text}</Text>
|
<Text color={currentTheme.textLight100}>{info2Text}</Text>
|
||||||
</MyScreenContainer>
|
</MyScreenContainer>
|
||||||
|
@ -335,9 +334,9 @@ export function UpdatePassword() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const passwordChanged =
|
const passwordChanged =
|
||||||
currentPassword.length > 0 &&
|
passwordValid(currentPassword) &&
|
||||||
newPassword.length > 0 &&
|
passwordValid(newPassword) &&
|
||||||
repeatNewPassword.length > 0 &&
|
passwordValid(repeatNewPassword) &&
|
||||||
newPassword === repeatNewPassword;
|
newPassword === repeatNewPassword;
|
||||||
|
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
|
@ -363,28 +362,19 @@ export function UpdatePassword() {
|
||||||
backgroundColor: currentTheme.backgroundDark300,
|
backgroundColor: currentTheme.backgroundDark300,
|
||||||
marginTop: 4,
|
marginTop: 4,
|
||||||
}}>
|
}}>
|
||||||
<MyIconInput
|
<MyPasswordInput
|
||||||
iconName="lock"
|
password={currentPassword}
|
||||||
text={lang.currentPassword}
|
setPassword={value => setCurrentPassword(value)}
|
||||||
secureTextEntry={true}
|
|
||||||
value={currentPassword}
|
|
||||||
onChangeText={text => setCurrentPassword(text)}
|
|
||||||
disableContainer
|
disableContainer
|
||||||
/>
|
/>
|
||||||
<MyIconInput
|
<MyPasswordInput
|
||||||
iconName="lock"
|
password={newPassword}
|
||||||
text={lang.newPassword}
|
setPassword={value => setNewPassword(value)}
|
||||||
secureTextEntry={true}
|
|
||||||
value={newPassword}
|
|
||||||
onChangeText={text => setNewPassword(text)}
|
|
||||||
disableContainer
|
disableContainer
|
||||||
/>
|
/>
|
||||||
<MyIconInput
|
<MyPasswordInput
|
||||||
iconName="lock"
|
password={repeatNewPassword}
|
||||||
text={lang.repeatNewPassword}
|
setPassword={value => setRepeatNewPassword(value)}
|
||||||
secureTextEntry={true}
|
|
||||||
value={repeatNewPassword}
|
|
||||||
onChangeText={text => setRepeatNewPassword(text)}
|
|
||||||
disableContainer
|
disableContainer
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import {MyButton} from '@components/MyButton';
|
import {MyButton} from '@components/MyButton';
|
||||||
import {MyIconInput} from '@components/MyInput';
|
|
||||||
import {MyScreenContainer} from '@components/MyScreenContainer';
|
import {MyScreenContainer} from '@components/MyScreenContainer';
|
||||||
import {MyTitle} from '@components/MyTitle';
|
import {MyTitle} from '@components/MyTitle';
|
||||||
import {apiBackendRequest, makeRequest} from '@helper/request';
|
import {apiBackendRequest, makeRequest} from '@helper/request';
|
||||||
|
@ -17,6 +16,12 @@ import {useSelector} from 'react-redux';
|
||||||
import {ToBase64} from '@helper/base64';
|
import {ToBase64} from '@helper/base64';
|
||||||
import showToast from '@components/MyToast';
|
import showToast from '@components/MyToast';
|
||||||
import {useToast} from '@gluestack-ui/themed';
|
import {useToast} from '@gluestack-ui/themed';
|
||||||
|
import {
|
||||||
|
MyAccountNameInput,
|
||||||
|
MyPasswordInput,
|
||||||
|
accountNameValid,
|
||||||
|
passwordValid,
|
||||||
|
} from '@components/MyCommonInputs';
|
||||||
|
|
||||||
export function Login() {
|
export function Login() {
|
||||||
const lang = useSelector(
|
const lang = useSelector(
|
||||||
|
@ -29,7 +34,7 @@ export function Login() {
|
||||||
const [accountName, setAccountName] = useState('anna');
|
const [accountName, setAccountName] = useState('anna');
|
||||||
const [password, setPassword] = useState('testtesttest1#S');
|
const [password, setPassword] = useState('testtesttest1#S');
|
||||||
|
|
||||||
const loginEnabled = accountName.length > 0 && password.length > 0;
|
const loginEnabled = accountNameValid(accountName) && passwordValid(password);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MyScreenContainer
|
<MyScreenContainer
|
||||||
|
@ -40,18 +45,14 @@ export function Login() {
|
||||||
<MyTitle text={lang.login.title} />
|
<MyTitle text={lang.login.title} />
|
||||||
|
|
||||||
<View style={{gap: 12}}>
|
<View style={{gap: 12}}>
|
||||||
<MyIconInput
|
<MyAccountNameInput
|
||||||
text={lang.login.inputPhoneNumberOrAccountName}
|
accountName={accountName}
|
||||||
iconName="person"
|
setAccountName={value => setAccountName(value)}
|
||||||
value={accountName}
|
|
||||||
onChangeText={text => setAccountName(text)}
|
|
||||||
/>
|
/>
|
||||||
<MyIconInput
|
|
||||||
text={lang.login.inputPassword}
|
<MyPasswordInput
|
||||||
iconName="lock"
|
password={password}
|
||||||
secureTextEntry
|
setPassword={value => setPassword(value)}
|
||||||
value={password}
|
|
||||||
onChangeText={text => setPassword(text)}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MyButton
|
<MyButton
|
||||||
|
@ -70,6 +71,7 @@ export function Login() {
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
XAuthorization: '',
|
XAuthorization: '',
|
||||||
|
UserId: '',
|
||||||
Username: '',
|
Username: '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -77,6 +79,7 @@ export function Login() {
|
||||||
console.log('resp', resp);
|
console.log('resp', resp);
|
||||||
|
|
||||||
MyUserManager.createNewMyUser(
|
MyUserManager.createNewMyUser(
|
||||||
|
resp.response.UserId,
|
||||||
accountName,
|
accountName,
|
||||||
resp.response.Username,
|
resp.response.Username,
|
||||||
resp.response.XAuthorization,
|
resp.response.XAuthorization,
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
import {MyButton, MyIconButton} from '@components/MyButton';
|
import {MyButton} from '@components/MyButton';
|
||||||
import {MyIcon} from '@components/MyIcon';
|
import {
|
||||||
import {MyIconInput, MyInputError} from '@components/MyInput';
|
AccountNameAvailable,
|
||||||
|
MyAccountNameInput,
|
||||||
|
MyPasswordInput,
|
||||||
|
MyUsernameInput,
|
||||||
|
accountNameValid,
|
||||||
|
passwordValid,
|
||||||
|
usernameValid,
|
||||||
|
} from '@components/MyCommonInputs';
|
||||||
import {MyScreenContainer} from '@components/MyScreenContainer';
|
import {MyScreenContainer} from '@components/MyScreenContainer';
|
||||||
import {MyTitle} from '@components/MyTitle';
|
import {MyTitle} from '@components/MyTitle';
|
||||||
import showToast from '@components/MyToast';
|
import showToast from '@components/MyToast';
|
||||||
import {appVarActions} from '@configs/appVarReducer';
|
import {appVarActions} from '@configs/appVarReducer';
|
||||||
import {
|
import {passwordOptions} from '@configs/types';
|
||||||
accountNameOptions,
|
import {useToast} from '@gluestack-ui/themed';
|
||||||
passwordOptions,
|
|
||||||
userNameOptions,
|
|
||||||
} from '@configs/types';
|
|
||||||
import {Spinner, set, useToast} from '@gluestack-ui/themed';
|
|
||||||
import {ToBase64} from '@helper/base64';
|
import {ToBase64} from '@helper/base64';
|
||||||
import {apiBackendRequest, makeRequest} from '@helper/request';
|
import {apiBackendRequest, makeRequest} from '@helper/request';
|
||||||
import {RootScreenNavigationProp} from '@navigation/navigation';
|
import {RootScreenNavigationProp} from '@navigation/navigation';
|
||||||
|
@ -21,7 +24,7 @@ import {
|
||||||
import {useNavigation} from '@react-navigation/native';
|
import {useNavigation} from '@react-navigation/native';
|
||||||
import {RootState, store} from '@redux/store';
|
import {RootState, store} from '@redux/store';
|
||||||
import MyUserManager from '@user/MyUserManager';
|
import MyUserManager from '@user/MyUserManager';
|
||||||
import {useEffect, useState} from 'react';
|
import {useState} from 'react';
|
||||||
import {Text} from 'react-native';
|
import {Text} from 'react-native';
|
||||||
import {View} from 'react-native';
|
import {View} from 'react-native';
|
||||||
import {useSelector} from 'react-redux';
|
import {useSelector} from 'react-redux';
|
||||||
|
@ -47,17 +50,6 @@ export function SignUpStepUsername() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
const [inputTouched, setInputTouched] = useState(false);
|
|
||||||
|
|
||||||
const usernameValid = username.length < userNameOptions.minLength;
|
|
||||||
|
|
||||||
const errorText = reactStringReplace(
|
|
||||||
lang.signUpStepUsername.error,
|
|
||||||
'${minLength}',
|
|
||||||
(match, i) => {
|
|
||||||
return userNameOptions.minLength.toString();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MyScreenContainer
|
<MyScreenContainer
|
||||||
|
@ -71,26 +63,16 @@ export function SignUpStepUsername() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<View style={{gap: 12, marginTop: 20}}>
|
<View style={{gap: 12, marginTop: 20}}>
|
||||||
<MyIconInput
|
<MyUsernameInput
|
||||||
text={lang.signUpStepUsername.inputUsername}
|
username={username}
|
||||||
iconName="person"
|
setUsername={value => setUsername(value)}
|
||||||
value={username}
|
|
||||||
onChangeText={text => {
|
|
||||||
setUsername(text);
|
|
||||||
setInputTouched(true);
|
|
||||||
}}
|
|
||||||
maxLength={userNameOptions.maxLength}
|
|
||||||
helper={
|
|
||||||
inputTouched &&
|
|
||||||
usernameValid && <MyInputError text={errorText.join('')} />
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MyButton
|
<MyButton
|
||||||
type="secondary"
|
type="secondary"
|
||||||
text={lang.buttonNext}
|
text={lang.buttonNext}
|
||||||
style={{marginBottom: 20}}
|
style={{marginBottom: 20}}
|
||||||
disabled={username.length < userNameOptions.minLength}
|
disabled={!usernameValid(username)}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
let rp = {...registerProcess};
|
let rp = {...registerProcess};
|
||||||
|
|
||||||
|
@ -202,23 +184,6 @@ export function SignUpStepPassword() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [inputTouched, setInputTouched] = useState(false);
|
|
||||||
|
|
||||||
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
|
||||||
|
|
||||||
const togglePasswordVisibility = () => {
|
|
||||||
setIsPasswordVisible(!isPasswordVisible);
|
|
||||||
};
|
|
||||||
|
|
||||||
const passwordValid = () => {
|
|
||||||
if (password.length < passwordOptions.minLength) {
|
|
||||||
return false;
|
|
||||||
} else if (!passwordOptions.isAllowed(password)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const descriptionText = reactStringReplace(
|
const descriptionText = reactStringReplace(
|
||||||
lang.signUpStepPassword.description,
|
lang.signUpStepPassword.description,
|
||||||
|
@ -228,24 +193,6 @@ export function SignUpStepPassword() {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const errorLengthText = reactStringReplace(
|
|
||||||
lang.signUpStepPassword.errorLength,
|
|
||||||
'${minLength}',
|
|
||||||
() => {
|
|
||||||
return passwordOptions.minLength.toString();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const errorText = () => {
|
|
||||||
if (password.length < passwordOptions.minLength) {
|
|
||||||
return errorLengthText.join('');
|
|
||||||
} else if (!passwordOptions.isAllowed(password)) {
|
|
||||||
return lang.signUpStepPassword.errorPasswordInvalid;
|
|
||||||
} else {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MyScreenContainer
|
<MyScreenContainer
|
||||||
style={{
|
style={{
|
||||||
|
@ -258,36 +205,16 @@ export function SignUpStepPassword() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<View style={{gap: 12, marginTop: 20}}>
|
<View style={{gap: 12, marginTop: 20}}>
|
||||||
<MyIconInput
|
<MyPasswordInput
|
||||||
text={lang.signUpStepPassword.inputPassword}
|
password={password}
|
||||||
iconName="lock"
|
setPassword={value => setPassword(value)}
|
||||||
secureTextEntry={!isPasswordVisible}
|
|
||||||
value={password}
|
|
||||||
maxLength={passwordOptions.maxLength}
|
|
||||||
onChangeText={text => {
|
|
||||||
setPassword(text);
|
|
||||||
setInputTouched(true);
|
|
||||||
}}
|
|
||||||
rightComponent={
|
|
||||||
<MyIconButton
|
|
||||||
MyIconProps={{
|
|
||||||
name: isPasswordVisible ? 'visibility-off' : 'visibility',
|
|
||||||
size: 24,
|
|
||||||
}}
|
|
||||||
onPress={togglePasswordVisibility}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
helper={
|
|
||||||
inputTouched &&
|
|
||||||
!passwordValid() && <MyInputError text={errorText()} />
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MyButton
|
<MyButton
|
||||||
type="secondary"
|
type="secondary"
|
||||||
text={lang.buttonNext}
|
text={lang.buttonNext}
|
||||||
style={{marginBottom: 2}}
|
style={{marginBottom: 2}}
|
||||||
disabled={!passwordValid()}
|
disabled={!passwordValid(password)}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
let rp = {...registerProcess};
|
let rp = {...registerProcess};
|
||||||
|
|
||||||
|
@ -306,19 +233,10 @@ export function SignUpStepPassword() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AccountNameAvailable {
|
|
||||||
Loading,
|
|
||||||
Available,
|
|
||||||
NotAvailable,
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SignUpStepAccountName() {
|
export function SignUpStepAccountName() {
|
||||||
const lang = useSelector(
|
const lang = useSelector(
|
||||||
(state: RootState) => state.appVariables.lang.registration,
|
(state: RootState) => state.appVariables.lang.registration,
|
||||||
);
|
);
|
||||||
const currentTheme = useSelector(
|
|
||||||
(state: RootState) => state.nonSaveVariables.theme.colors,
|
|
||||||
);
|
|
||||||
|
|
||||||
const navigation = useNavigation<RootScreenNavigationProp>();
|
const navigation = useNavigation<RootScreenNavigationProp>();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
@ -329,72 +247,10 @@ export function SignUpStepAccountName() {
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [accountName, setAccountName] = useState('');
|
const [accountName, setAccountName] = useState('');
|
||||||
|
|
||||||
const [isAccountNameAvailable, setIsAccountNameAvailable] = useState(
|
const [isAccountNameAvailable, setIsAccountNameAvailable] = useState(
|
||||||
AccountNameAvailable.Loading,
|
AccountNameAvailable.Loading,
|
||||||
);
|
);
|
||||||
const [inputTouched, setInputTouched] = useState(false);
|
|
||||||
|
|
||||||
const accountNameValid = () => {
|
|
||||||
if (accountName.length < accountNameOptions.minLength) {
|
|
||||||
return false;
|
|
||||||
} else if (!accountNameOptions.isAllowed(accountName)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const errorText = () => {
|
|
||||||
if (accountName.length < accountNameOptions.minLength) {
|
|
||||||
return reactStringReplace(
|
|
||||||
lang.signUpStepAccountName.errorLength,
|
|
||||||
'${minLength}',
|
|
||||||
() => {
|
|
||||||
return accountNameOptions.minLength.toString();
|
|
||||||
},
|
|
||||||
).join('');
|
|
||||||
} else if (!accountNameOptions.isAllowed(accountName)) {
|
|
||||||
return lang.signUpStepAccountName.errorAccountNameInvalid;
|
|
||||||
} else {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const rightComponent = () => {
|
|
||||||
const closeIcon = (
|
|
||||||
<MyIcon name="close" size={24} color={currentTheme.red600} />
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!accountNameValid()) {
|
|
||||||
return closeIcon;
|
|
||||||
} else if (isAccountNameAvailable === AccountNameAvailable.Loading) {
|
|
||||||
return <Spinner />;
|
|
||||||
} else if (isAccountNameAvailable === AccountNameAvailable.Available) {
|
|
||||||
return <MyIcon name="check" size={24} color={currentTheme.green400} />;
|
|
||||||
} else {
|
|
||||||
return closeIcon;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!accountNameValid()) return;
|
|
||||||
|
|
||||||
const delay = 400;
|
|
||||||
const timeoutId = setTimeout(() => {
|
|
||||||
makeRequest({
|
|
||||||
path: apiBackendRequest.CHECK_ACCOUNT_NAME,
|
|
||||||
requestGET: {':accountName': accountName},
|
|
||||||
response: {},
|
|
||||||
})
|
|
||||||
.then(() => setIsAccountNameAvailable(AccountNameAvailable.Available))
|
|
||||||
.catch(() =>
|
|
||||||
setIsAccountNameAvailable(AccountNameAvailable.NotAvailable),
|
|
||||||
);
|
|
||||||
}, delay);
|
|
||||||
|
|
||||||
// Cleanup the timeout on component unmount or when inputValue changes
|
|
||||||
return () => clearTimeout(timeoutId);
|
|
||||||
}, [accountName]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MyScreenContainer
|
<MyScreenContainer
|
||||||
|
@ -409,21 +265,14 @@ export function SignUpStepAccountName() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<View style={{gap: 12, marginTop: 20}}>
|
<View style={{gap: 12, marginTop: 20}}>
|
||||||
<MyIconInput
|
<MyAccountNameInput
|
||||||
text={lang.signUpStepAccountName.inputAccountName}
|
accountName={accountName}
|
||||||
iconName="person"
|
setAccountName={value => setAccountName(value)}
|
||||||
value={accountName}
|
isAccountNameAvailable={isAccountNameAvailable}
|
||||||
onChangeText={text => {
|
setIsAccountNameAvailable={value =>
|
||||||
setAccountName(text);
|
setIsAccountNameAvailable(value)
|
||||||
setInputTouched(true);
|
|
||||||
setIsAccountNameAvailable(AccountNameAvailable.Loading);
|
|
||||||
}}
|
|
||||||
maxLength={accountNameOptions.maxLength}
|
|
||||||
rightComponent={rightComponent()}
|
|
||||||
helper={
|
|
||||||
inputTouched &&
|
|
||||||
!accountNameValid() && <MyInputError text={errorText()} />
|
|
||||||
}
|
}
|
||||||
|
checkAccountNameAvailability
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MyButton
|
<MyButton
|
||||||
|
@ -432,7 +281,7 @@ export function SignUpStepAccountName() {
|
||||||
style={{marginBottom: 2}}
|
style={{marginBottom: 2}}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
disabled={
|
disabled={
|
||||||
!accountNameValid() ||
|
!accountNameValid(accountName) ||
|
||||||
isAccountNameAvailable !== AccountNameAvailable.Available
|
isAccountNameAvailable !== AccountNameAvailable.Available
|
||||||
}
|
}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
|
@ -450,11 +299,13 @@ export function SignUpStepAccountName() {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
response: {
|
response: {
|
||||||
XAuthorization: '',
|
XAuthorization: '',
|
||||||
|
UserId: '',
|
||||||
Username: '',
|
Username: '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
MyUserManager.createNewMyUser(
|
MyUserManager.createNewMyUser(
|
||||||
|
resp.response.UserId,
|
||||||
accountName,
|
accountName,
|
||||||
resp.response.Username,
|
resp.response.Username,
|
||||||
resp.response.XAuthorization,
|
resp.response.XAuthorization,
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
import {appVarActions} from '@configs/appVarReducer';
|
import {appVarActions} from '@configs/appVarReducer';
|
||||||
import {AccountName, XAuthorization, Username} from '@configs/types';
|
import {AccountName, XAuthorization, Username, UserId} from '@configs/types';
|
||||||
import {saveVarChanges} from '@helper/appData';
|
import {saveVarChanges} from '@helper/appData';
|
||||||
import {apiBackendRequest, makeRequest} from '@helper/request';
|
import {apiBackendRequest, makeRequest} from '@helper/request';
|
||||||
import BigDataManager from '@helper/storage/BigDataManager';
|
import BigDataManager from '@helper/storage/BigDataManager';
|
||||||
import {RootState, store} from '@redux/store';
|
import {RootState, store} from '@redux/store';
|
||||||
import {useSelector} from 'react-redux';
|
import {useSelector} from 'react-redux';
|
||||||
import {MyUserAccount, createUserProp, SourceProp} from './types';
|
import {MyUserAccount, createUserProp, SourceProp} from './types';
|
||||||
|
import {RootScreenNavigationProp} from '@navigation/navigation';
|
||||||
|
|
||||||
function createNewMyUser(
|
function createNewMyUser(
|
||||||
|
UserId: UserId,
|
||||||
AccountName: AccountName,
|
AccountName: AccountName,
|
||||||
Username: Username,
|
Username: Username,
|
||||||
SessionId: XAuthorization,
|
SessionId: XAuthorization,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let user: MyUserAccount = {
|
let user: MyUserAccount = {
|
||||||
AccountName /*: createUserProp(SourceProp.offline, AccountName)*/,
|
UserId,
|
||||||
|
AccountName: createUserProp(SourceProp.offline, AccountName),
|
||||||
Username: createUserProp(SourceProp.offline, Username),
|
Username: createUserProp(SourceProp.offline, Username),
|
||||||
/* Description: createUserProp(SourceProp.online),
|
/* Description: createUserProp(SourceProp.online),
|
||||||
FollowersCount: createUserProp(SourceProp.online),
|
FollowersCount: createUserProp(SourceProp.online),
|
||||||
|
@ -101,7 +104,7 @@ function createNewMyUser(
|
||||||
|
|
||||||
function createMyUser(user: MyUserAccount) {
|
function createMyUser(user: MyUserAccount) {
|
||||||
store.dispatch(appVarActions.setAccount(user));
|
store.dispatch(appVarActions.setAccount(user));
|
||||||
store.dispatch(appVarActions.setCurrentAccount(user.AccountName));
|
store.dispatch(appVarActions.setCurrentAccount(user.UserId));
|
||||||
saveVarChanges();
|
saveVarChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,9 +117,17 @@ function setMyUser(user: MyUserAccount) {
|
||||||
saveVarChanges();
|
saveVarChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
function logoutMyUser() {
|
function logoutMyUser(rootNavigation?: RootScreenNavigationProp) {
|
||||||
store.dispatch(appVarActions.setCurrentAccount('none'));
|
store.dispatch(appVarActions.setCurrentAccount('none'));
|
||||||
saveVarChanges();
|
saveVarChanges();
|
||||||
|
|
||||||
|
if (rootNavigation === undefined) return;
|
||||||
|
|
||||||
|
rootNavigation.navigate('Registration', {screen: 'LoginPreview'});
|
||||||
|
rootNavigation.reset({
|
||||||
|
index: 0,
|
||||||
|
routes: [{name: 'Registration'}],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelectedUserAccount(): AccountName {
|
function getSelectedUserAccount(): AccountName {
|
||||||
|
|
|
@ -1,26 +1,19 @@
|
||||||
import {maxCachedUsers} from '@configs/appNonSaveVar';
|
import {maxCachedUsers} from '@configs/appNonSaveVar';
|
||||||
import {appNonSaveVarActions} from '@configs/appNonSaveVarReducer';
|
import {appNonSaveVarActions} from '@configs/appNonSaveVarReducer';
|
||||||
import {AccountName, XAuthorization} from '@configs/types';
|
import {AccountName, UserId} from '@configs/types';
|
||||||
import {makeRequest, apiBackendRequest} from '@helper/request';
|
import {makeRequest, apiBackendRequest} from '@helper/request';
|
||||||
import BigDataManager from '@helper/storage/BigDataManager';
|
import BigDataManager from '@helper/storage/BigDataManager';
|
||||||
import {RootState, store} from '@redux/store';
|
import {RootState, store} from '@redux/store';
|
||||||
import {useSelector} from 'react-redux';
|
import {useSelector} from 'react-redux';
|
||||||
import {
|
import {createUserProp, ProfilePicture, SourceProp, User} from './types';
|
||||||
BasicUserProp,
|
|
||||||
createUserProp,
|
|
||||||
ProfilePicture,
|
|
||||||
ProfilePictureType,
|
|
||||||
SourceProp,
|
|
||||||
User,
|
|
||||||
} from './types';
|
|
||||||
|
|
||||||
let cachedUserList: AccountName[] = [];
|
let cachedUserList: AccountName[] = [];
|
||||||
|
|
||||||
async function getUser(
|
async function getUser(
|
||||||
AccountName: AccountName,
|
UserId: UserId,
|
||||||
save?: boolean,
|
save?: boolean,
|
||||||
): Promise<User | undefined> {
|
): Promise<User | undefined> {
|
||||||
if (AccountName === 'none') {
|
if (UserId === 'none') {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,18 +23,19 @@ async function getUser(
|
||||||
let userIsInCache = false;
|
let userIsInCache = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
const usr = state.nonSaveVariables.cachedUsers[AccountName];
|
const usr = state.nonSaveVariables.cachedUsers[UserId];
|
||||||
if (usr !== undefined) {
|
if (usr !== undefined) {
|
||||||
user = usr;
|
user = usr;
|
||||||
userIsInCache = true;
|
userIsInCache = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AccountName === state.appVariables.preferences.selectedAccount) {
|
if (UserId === state.appVariables.preferences.selectedAccount) {
|
||||||
const usr = state.appVariables.preferences.accounts[AccountName];
|
const usr = state.appVariables.preferences.accounts[UserId];
|
||||||
|
|
||||||
if (usr !== undefined) {
|
if (usr !== undefined) {
|
||||||
user = {
|
user = {
|
||||||
|
UserId,
|
||||||
AccountName: usr.AccountName,
|
AccountName: usr.AccountName,
|
||||||
/*Description: usr.Description,
|
/*Description: usr.Description,
|
||||||
FollowersCount: usr.FollowersCount,
|
FollowersCount: usr.FollowersCount,
|
||||||
|
@ -57,7 +51,7 @@ async function getUser(
|
||||||
|
|
||||||
if (user === undefined) {
|
if (user === undefined) {
|
||||||
const usrDBKeys = BigDataManager.databases.users.keys;
|
const usrDBKeys = BigDataManager.databases.users.keys;
|
||||||
const usr = await BigDataManager.databases.users.getEntry(AccountName);
|
const usr = await BigDataManager.databases.users.getEntry(UserId);
|
||||||
|
|
||||||
if (usr !== undefined && usr !== null) {
|
if (usr !== undefined && usr !== null) {
|
||||||
let ProfilePicture = {
|
let ProfilePicture = {
|
||||||
|
@ -88,7 +82,11 @@ async function getUser(
|
||||||
};
|
};
|
||||||
|
|
||||||
user = {
|
user = {
|
||||||
AccountName,
|
UserId,
|
||||||
|
AccountName: createUserProp(
|
||||||
|
SourceProp.offline,
|
||||||
|
usr[usrDBKeys.AccountName],
|
||||||
|
),
|
||||||
Description: createUserProp(
|
Description: createUserProp(
|
||||||
SourceProp.offline,
|
SourceProp.offline,
|
||||||
usr[usrDBKeys.Description],
|
usr[usrDBKeys.Description],
|
||||||
|
@ -114,7 +112,7 @@ async function getUser(
|
||||||
try {
|
try {
|
||||||
const resp = await makeRequest({
|
const resp = await makeRequest({
|
||||||
path: apiBackendRequest.GET_USER_PROFILE,
|
path: apiBackendRequest.GET_USER_PROFILE,
|
||||||
requestGET: {':accountName': AccountName},
|
requestGET: {':userId': UserId},
|
||||||
response: {
|
response: {
|
||||||
Description: '',
|
Description: '',
|
||||||
FollowersCount: 0,
|
FollowersCount: 0,
|
||||||
|
@ -127,7 +125,11 @@ async function getUser(
|
||||||
});
|
});
|
||||||
|
|
||||||
user = {
|
user = {
|
||||||
AccountName: AccountName,
|
UserId,
|
||||||
|
AccountName: createUserProp(
|
||||||
|
SourceProp.cached,
|
||||||
|
resp.response.AccountName,
|
||||||
|
),
|
||||||
Description: createUserProp(
|
Description: createUserProp(
|
||||||
SourceProp.cached,
|
SourceProp.cached,
|
||||||
resp.response.Description,
|
resp.response.Description,
|
||||||
|
@ -162,7 +164,7 @@ async function getUser(
|
||||||
if (userIsInCache === false && user !== undefined) {
|
if (userIsInCache === false && user !== undefined) {
|
||||||
console.log('save in cache');
|
console.log('save in cache');
|
||||||
store.dispatch(appNonSaveVarActions.setCachedUser(user));
|
store.dispatch(appNonSaveVarActions.setCachedUser(user));
|
||||||
cachedUserList.push(user.AccountName);
|
cachedUserList.push(user.UserId);
|
||||||
|
|
||||||
if (cachedUserList.length > maxCachedUsers) {
|
if (cachedUserList.length > maxCachedUsers) {
|
||||||
let usrId = cachedUserList[0];
|
let usrId = cachedUserList[0];
|
||||||
|
@ -181,47 +183,47 @@ enum GetParam {
|
||||||
SAVE,
|
SAVE,
|
||||||
}
|
}
|
||||||
|
|
||||||
let getUserList: {[key: AccountName]: GetParam} = {};
|
let getUserList: {[key: UserId]: GetParam} = {};
|
||||||
|
|
||||||
async function refreshUsers() {
|
async function refreshUsers() {
|
||||||
for (let AccountName in getUserList) {
|
for (let UserId in getUserList) {
|
||||||
const param = getUserList[AccountName];
|
const param = getUserList[UserId];
|
||||||
delete getUserList[AccountName];
|
delete getUserList[UserId];
|
||||||
|
|
||||||
await getUser(AccountName);
|
await getUser(UserId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(refreshUsers, 500);
|
setInterval(refreshUsers, 500);
|
||||||
|
|
||||||
function addUserToGetQueue(AccountName: AccountName, param: GetParam) {
|
function addUserToGetQueue(UserId: UserId, param: GetParam) {
|
||||||
if (getUserList[AccountName] === undefined) {
|
if (getUserList[UserId] === undefined) {
|
||||||
getUserList[AccountName] = param;
|
getUserList[UserId] = param;
|
||||||
} else if (getUserList[AccountName] < param) {
|
} else if (getUserList[UserId] < param) {
|
||||||
getUserList[AccountName] = param;
|
getUserList[UserId] = param;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUserSelector(AccountName: AccountName) {
|
function getUserSelector(UserId: UserId) {
|
||||||
addUserToGetQueue(AccountName, GetParam.CACHE);
|
addUserToGetQueue(UserId, GetParam.CACHE);
|
||||||
|
|
||||||
const myUser = useSelector(
|
const myUser = useSelector(
|
||||||
(state: RootState) => state.nonSaveVariables.cachedUsers[AccountName],
|
(state: RootState) => state.nonSaveVariables.cachedUsers[UserId],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (myUser === undefined) {
|
if (myUser === undefined) {
|
||||||
return initUndefinedUser(AccountName);
|
return initUndefinedUser(UserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return myUser;
|
return myUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUserSelectorPicture(AccountName: AccountName): ProfilePicture {
|
function getUserSelectorPicture(UserId: UserId): ProfilePicture {
|
||||||
addUserToGetQueue(AccountName, GetParam.CACHE);
|
addUserToGetQueue(UserId, GetParam.CACHE);
|
||||||
|
|
||||||
const myUser = useSelector(
|
const myUser = useSelector(
|
||||||
(state: RootState) =>
|
(state: RootState) =>
|
||||||
state.nonSaveVariables.cachedUsers[AccountName]?.ProfilePicture,
|
state.nonSaveVariables.cachedUsers[UserId]?.ProfilePicture,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (myUser === undefined) {
|
if (myUser === undefined) {
|
||||||
|
@ -251,9 +253,10 @@ function getUserSelectorAccountName(
|
||||||
return myUser;
|
return myUser;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
function initUndefinedUser(AccountName: AccountName): User {
|
function initUndefinedUser(UserId: UserId): User {
|
||||||
return {
|
return {
|
||||||
AccountName: AccountName,
|
UserId,
|
||||||
|
AccountName: createUserProp(SourceProp.online),
|
||||||
/* Description: createUserProp(SourceProp.online),
|
/* Description: createUserProp(SourceProp.online),
|
||||||
FollowersCount: createUserProp(SourceProp.online),
|
FollowersCount: createUserProp(SourceProp.online),
|
||||||
FollowingCount: createUserProp(SourceProp.online),
|
FollowingCount: createUserProp(SourceProp.online),
|
||||||
|
|
|
@ -3,8 +3,8 @@ import {
|
||||||
AccountName,
|
AccountName,
|
||||||
langCode,
|
langCode,
|
||||||
XAuthorization,
|
XAuthorization,
|
||||||
timestamp,
|
|
||||||
Username,
|
Username,
|
||||||
|
UserId,
|
||||||
} from '@configs/types';
|
} from '@configs/types';
|
||||||
|
|
||||||
export enum SourceProp {
|
export enum SourceProp {
|
||||||
|
@ -27,8 +27,8 @@ export interface ProfilePicture {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
//UserId: UserId;
|
UserId: UserId;
|
||||||
AccountName: AccountName;
|
AccountName: BasicUserProp<AccountName>;
|
||||||
|
|
||||||
/* ProfilePicture: ProfilePicture;
|
/* ProfilePicture: ProfilePicture;
|
||||||
lastUpdateTimestamp: timestamp; */
|
lastUpdateTimestamp: timestamp; */
|
||||||
|
|
Reference in New Issue