Browse Source

feature/update-app (#2)

Reviewed-on: #2
Co-authored-by: Oksana Stepanenko <oksana.stepanenko@jetup.team>
Co-committed-by: Oksana Stepanenko <oksana.stepanenko@jetup.team>
pull/4/head
Oksana Stepanenko 1 year ago committed by Vitalik Yatsenko
parent
commit
f21a2fc7a8
  1. 3
      src/api/index.ts
  2. 11
      src/api/system/requests.ts
  3. 3
      src/api/system/responses.interfaces.ts
  4. 8
      src/config/index.ts
  5. 29
      src/managers/factory.manager.ts
  6. 21
      src/modules/settings/hooks/use-setting-navigation-list.hook.ts
  7. 9
      src/modules/settings/screens/settings.screen.tsx
  8. 31
      src/services/domain/auth.service.ts
  9. 6
      src/services/domain/factories.service.ts
  10. 55
      src/services/system/app-info.service.ts
  11. 1
      src/services/system/index.ts
  12. 10
      src/store/shared/reducer.ts
  13. 5
      src/store/shared/selectors.ts
  14. 22
      src/store/shared/types.ts

3
src/api/index.ts

@ -10,4 +10,5 @@ export * from './notifications/requests' @@ -10,4 +10,5 @@ export * from './notifications/requests'
export * from './chats-members/requests'
export * from './chat-messages/requests'
export * from './tasks-documents/requests'
export * from './configs/requests'
export * from './configs/requests'
export * from './system/requests'

11
src/api/system/requests.ts

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
import { ApiResponse } from '../http.types'
import { IActualAppVersionResp } from './responses.interfaces'
import http from '../http.service'
export const fetchActualAppVersionReq = (
platform: string,
): ApiResponse<IActualAppVersionResp> => {
return http.get<IActualAppVersionResp>('system/app-version', {
params: { platform },
})
}

3
src/api/system/responses.interfaces.ts

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
export interface IActualAppVersionResp {
version: string
}

8
src/config/index.ts

@ -6,6 +6,9 @@ export const dynamicConfig = { @@ -6,6 +6,9 @@ export const dynamicConfig = {
// baseUrl: 'http://localhost:3000',
// socketUrl: 'http://localhost:3000',
// baseUrl: 'https://5763-46-63-4-20.ngrok.io',
// socketUrl: 'https://5763-46-63-4-20.ngrok.io',
// baseUrl: 'http://46.101.170.206:5000/app/',
// socketUrl: 'http://46.101.170.206:5000',
@ -18,8 +21,11 @@ export const dynamicConfig = { @@ -18,8 +21,11 @@ export const dynamicConfig = {
baseUrl: 'https://tasks-api.rwsbank.com.ua',
socketUrl: 'https://tasks-api.rwsbank.com.ua',
// oneSignalKey: '8b9066f5-8c3f-49f7-bef4-c5ab621f9d27', stage
// oneSignalKey: '8b9066f5-8c3f-49f7-bef4-c5ab621f9d27', //stage
oneSignalKey: '5e1a5e18-33e5-4ed3-8423-45b1abc354c6',
appStoreUrl: 'https://apps.apple.com/ua/app/task-me/id1482240685?l=uk',
googlePlayUrl:
'https://play.google.com/store/apps/details?id=com.app.task_me',
}
export const config = {

29
src/managers/factory.manager.ts

@ -1,12 +1,12 @@ @@ -1,12 +1,12 @@
import { ApiFactoryRepository, DbFactoryRepository } from "@/repositories"
import { Manager } from "@/shared/abstract"
import { ApiFactoryRepository, DbFactoryRepository } from '@/repositories'
import { Manager } from '@/shared/abstract'
export class FactoryManager extends Manager {
private factoryRepository = new ApiFactoryRepository()
private dbFactoryRepository = new DbFactoryRepository()
public async loadFactories() {
if (this.isConnected === 'online') {
public async loadFactories() {
if (this.isConnected === 'online') {
const { data } = await this.factoryRepository.getFactoriesReq()
if (data) {
try {
@ -14,12 +14,27 @@ export class FactoryManager extends Manager { @@ -14,12 +14,27 @@ export class FactoryManager extends Manager {
} catch (e) {
console.log('SAVE FACTORIES TO LOCAL DB FAILED', e)
}
}
}
return data
} else {
const dbFactories = await this.dbFactoryRepository.fetchFactories()
console.log('no connection, load factories from local db', dbFactories)
console.log(
'no connection, load factories from local db',
dbFactories,
)
return dbFactories
}
}
}
// ******************************
static instance: FactoryManager
static getInstance() {
if (!FactoryManager.instance)
FactoryManager.instance = new FactoryManager()
return FactoryManager.instance
}
}
export const factoryManager = FactoryManager.getInstance()

21
src/modules/settings/hooks/use-setting-navigation-list.hook.ts

@ -5,10 +5,14 @@ import { Alert } from 'react-native' @@ -5,10 +5,14 @@ import { Alert } from 'react-native'
import { SettingsItemActionType } from '../enums'
// import ClearCache from 'oa-react-native-clear-cache'
import { chatMembersService, chatMessagesService } from '@/services/domain'
import { appInfoService } from '@/services/system'
export const useSettingNavigationList = (navigation: {
navigate: (to: string, params?: any) => any
}) => {
export const useSettingNavigationList = (
navigation: {
navigate: (to: string, params?: any) => any
},
needUpdateApp: boolean,
) => {
const { toggleTheme, themeTitle } = useContext(ThemeContext)
const onClearChats = () => {
@ -85,9 +89,18 @@ export const useSettingNavigationList = (navigation: { @@ -85,9 +89,18 @@ export const useSettingNavigationList = (navigation: {
icon: 'bin',
onPress: onDeleteChats,
actionType: SettingsItemActionType.none,
lastItem: true,
lastItem: !needUpdateApp,
},
]
if (needUpdateApp)
settingListConfig.push({
title: 'Оновити додаток',
icon: 'gear-1',
onPress: appInfoService.updateApp,
actionType: SettingsItemActionType.none,
lastItem: true,
})
return settingListConfig
}

9
src/modules/settings/screens/settings.screen.tsx

@ -7,6 +7,8 @@ import { IRouteParams } from '@/shared' @@ -7,6 +7,8 @@ import { IRouteParams } from '@/shared'
import { PartialTheme } from '@/shared/themes/interfaces'
import { useTheme } from '@/shared/hooks/use-theme.hook'
import { DeviceInfoService } from '@/services/system'
import { useSelector } from 'react-redux'
import { selectActualAppVersion } from '@/store/shared'
const appLogo = {
light: require('@/assets/images/light-logo.png'),
@ -18,10 +20,15 @@ interface IProps extends IRouteParams {} @@ -18,10 +20,15 @@ interface IProps extends IRouteParams {}
export const SettingsScreen: FC<IProps> = ({ navigation }) => {
const { styles, themeTitle } = useTheme(createStyles)
const settingListConfig = useSettingNavigationList(navigation)
const actualAppVersion = useSelector(selectActualAppVersion)
const appVersion = DeviceInfoService.getAppVersion()
const settingListConfig = useSettingNavigationList(
navigation,
appVersion !== actualAppVersion,
)
const items = useMemo(() => {
return settingListConfig.map(item => {
return (

31
src/services/domain/auth.service.ts

@ -2,15 +2,11 @@ import { @@ -2,15 +2,11 @@ import {
notificationService,
setAppIsReady,
} from './../system/notification.service'
import {
requestConfirmationCode,
finishLogin,
signOut,
resetSessionReq,
} from '@/api'
import { requestConfirmationCode, finishLogin, resetSessionReq } from '@/api'
import { SaveTokens } from '@/store/auth'
import { simpleDispatch } from '@/store/store-helpers'
import {
appInfoService,
DeviceInfoService,
NavigationService,
skeletonDataService,
@ -109,8 +105,9 @@ const loadNotImportantData = async ( @@ -109,8 +105,9 @@ const loadNotImportantData = async (
await contactsService.fetchBirthdayCountToday().catch(() => {})
await tasksService.getUnreadTasksCount().catch(() => {})
await chatsService.getUnreadMessagesCount().catch(() => {})
await notificationService.initAndSaveDevice().catch(() => { })
await configsService.loadFilesLimitsConfig();
await notificationService.initAndSaveDevice().catch(() => {})
await configsService.loadFilesLimitsConfig()
await appInfoService.loadActualAppVersion()
}
const onReconnect = async () => {
@ -132,18 +129,20 @@ const onLogout = async () => { @@ -132,18 +129,20 @@ const onLogout = async () => {
const logout = async (refreshToken: string) => {
try {
const isSignedOutOnline = await accManager.signOutOnline.bind(accManager)({refreshToken})
const isSignedOutOnline = await accManager.signOutOnline.bind(
accManager,
)({ refreshToken })
await onLogout()
if (!isSignedOutOnline)
await accManager.signOutOffline.bind(accManager)({refreshToken})
await accManager.signOutOffline.bind(accManager)({ refreshToken })
} catch (e) {
console.log("LOGOUT ERROR", e)
if (getErrorCode(e) === 401) {
await refreshSession(refreshToken);
const { refreshToken: refresh } = await getTokensFromStore();
await logout(refresh);
}
console.log('LOGOUT ERROR', e)
if (getErrorCode(e) === 401) {
await refreshSession(refreshToken)
const { refreshToken: refresh } = await getTokensFromStore()
await logout(refresh)
}
}
}

6
src/services/domain/factories.service.ts

@ -1,16 +1,14 @@ @@ -1,16 +1,14 @@
import { fetchMyFactoriesReq } from '@/api/factories/requests'
import { FactoryManager } from '@/managers'
import { factoryManager } from '@/managers/factory.manager'
import { Service } from '@/shared/abstract'
import { SaveFactories } from '@/store/account'
import { simpleDispatch } from '@/store/store-helpers'
class FactoriesService extends Service {
protected prefix = 'fcs'
protected factoryManager = new FactoryManager()
public async loadFactories() {
try {
const factories = await this.factoryManager.loadFactories()
const factories = await factoryManager.loadFactories()
simpleDispatch(new SaveFactories({ factories }))
} catch (e) {
console.log(e)

55
src/services/system/app-info.service.ts

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
import { fetchActualAppVersionReq } from '@/api'
import { appEvents } from '@/shared'
import { DeviceInfoService } from './device-info.service'
import { Linking, Platform } from 'react-native'
import { config } from '@/config'
import { simpleDispatch } from '@/store/store-helpers'
import { SetActualAppVersion } from '@/store/shared'
const updateApp = () => {
const link = Platform.select({
ios: config.appStoreUrl,
android: config.googlePlayUrl,
})
Linking.canOpenURL(link)
.then(supported => supported && Linking.openURL(link))
.catch(() =>
appEvents.emit('openInfoModal', {
title: 'Сталась помилка!',
message: 'Спробуйте будь-ласка пізніше.',
onPressOk: () => {},
}),
)
}
const loadActualAppVersion = async () => {
try {
const { data } = await fetchActualAppVersionReq(Platform.OS)
if (data) {
const currentAppVersion = DeviceInfoService.getAppVersion()
simpleDispatch(new SetActualAppVersion(data))
if (data.version !== currentAppVersion)
setTimeout(() => {
appEvents.emit('openConfirmModal', {
title: 'Доступна нова версія додатку. Бажаєте оновити зараз?',
buttonToHighlight: 'notAllow',
allowBtnAction: () => {
setTimeout(() => {
updateApp()
}, 300)
},
notAllowBtnAction: () => {},
})
}, 1500)
}
} catch (e) {
console.log('Error on load actual app version', e)
}
}
export const appInfoService = {
loadActualAppVersion,
updateApp,
}

1
src/services/system/index.ts

@ -9,3 +9,4 @@ export * from './fs.service' @@ -9,3 +9,4 @@ export * from './fs.service'
export * from './converter.service'
export * from './skeleton-data.service'
export * from './synchronization.service'
export * from './app-info.service'

10
src/store/shared/reducer.ts

@ -9,6 +9,7 @@ export interface ISharedState { @@ -9,6 +9,7 @@ export interface ISharedState {
isForbidden: ConstrainBoolean
isNetConnect: boolean
filesConfig: IFilesConfig
actualAppVersion: string
}
const filesConfigInitState = {
@ -28,6 +29,7 @@ const initialState: ISharedState = { @@ -28,6 +29,7 @@ const initialState: ISharedState = {
isForbidden: false,
isNetConnect: true,
filesConfig: filesConfigInitState,
actualAppVersion: null,
}
export const sharedReducer = createReducer<ISharedState, TAuthActions>(
@ -62,6 +64,7 @@ export const sharedReducer = createReducer<ISharedState, TAuthActions>( @@ -62,6 +64,7 @@ export const sharedReducer = createReducer<ISharedState, TAuthActions>(
isForbidden: false,
isNetConnect: true,
filesConfig: filesConfigInitState,
actualAppVersion: null,
}
},
@ -74,5 +77,12 @@ export const sharedReducer = createReducer<ISharedState, TAuthActions>( @@ -74,5 +77,12 @@ export const sharedReducer = createReducer<ISharedState, TAuthActions>(
},
}
},
SET_ACTUAL_APP_VERSION: (state, action) => {
return {
...state,
actualAppVersion: action.payload.version,
}
},
},
)

5
src/store/shared/selectors.ts

@ -10,4 +10,7 @@ export const selectIsForbidden = (store: RootState) => store.shared.isForbidden @@ -10,4 +10,7 @@ export const selectIsForbidden = (store: RootState) => store.shared.isForbidden
export const selectNetConnect = (store: RootState) => store.shared.isNetConnect
export const getFilesConfig = (state: RootState) => state.shared.filesConfig;
export const getFilesConfig = (state: RootState) => state.shared.filesConfig
export const selectActualAppVersion = (state: RootState) =>
state.shared.actualAppVersion

22
src/store/shared/types.ts

@ -30,12 +30,21 @@ export class Reset { @@ -30,12 +30,21 @@ export class Reset {
}
export class SetFilesConfig {
readonly type = "SET_FILES_CONFIG";
constructor(
public readonly payload: {
config: Partial<IFilesConfig>;
}
) {}
readonly type = 'SET_FILES_CONFIG'
constructor(
public readonly payload: {
config: Partial<IFilesConfig>
},
) {}
}
export class SetActualAppVersion {
readonly type = 'SET_ACTUAL_APP_VERSION'
constructor(
public readonly payload: {
version: string
},
) {}
}
export type TAuthActions =
@ -44,3 +53,4 @@ export type TAuthActions = @@ -44,3 +53,4 @@ export type TAuthActions =
| Reset
| SetNetConnect
| SetFilesConfig
| SetActualAppVersion

Loading…
Cancel
Save