mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	Fixed #538
This commit is contained in:
		| @@ -1,5 +1,6 @@ | ||||
| Enjoy toooting! This version includes following improvements and fixes: | ||||
| - Automatic setting detected language when tooting | ||||
| - Remember public timeline type selection | ||||
| - Added notification for admins | ||||
| - Fix whole word filter matching | ||||
| - Fix tablet cannot delete toot drafts | ||||
| @@ -1,5 +1,6 @@ | ||||
| toooting愉快!此版本包括以下改进和修复: | ||||
| - 自动识别发嘟语言 | ||||
| - 记住上次公共时间轴选项 | ||||
| - 新增管理员推送通知 | ||||
| - 修复过滤整词功能 | ||||
| - 修复平板不能删除草稿 | ||||
| @@ -3,14 +3,18 @@ import Timeline from '@components/Timeline' | ||||
| import TimelineDefault from '@components/Timeline/Default' | ||||
| import SegmentedControl from '@react-native-community/segmented-control' | ||||
| import { NativeStackScreenProps } from '@react-navigation/native-stack' | ||||
| import { useAppDispatch } from '@root/store' | ||||
| import { ContextsLatest } from '@utils/migrations/contexts/migration' | ||||
| import { TabPublicStackParamList } from '@utils/navigation/navigators' | ||||
| import usePopToTop from '@utils/navigation/usePopToTop' | ||||
| import { QueryKeyTimeline } from '@utils/queryHooks/timeline' | ||||
| import { getPreviousSegment, updatePreviousSegment } from '@utils/slices/contextsSlice' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import { useEffect, useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { Dimensions } from 'react-native' | ||||
| import { SceneMap, TabView } from 'react-native-tab-view' | ||||
| import { useSelector } from 'react-redux' | ||||
|  | ||||
| const Route = ({ route: { key: page } }: { route: any }) => { | ||||
|   const queryKey: QueryKeyTimeline = ['Timeline', { page }] | ||||
| @@ -37,7 +41,12 @@ const Root: React.FC<NativeStackScreenProps<TabPublicStackParamList, 'Tab-Public | ||||
|   const { mode } = useTheme() | ||||
|   const { t } = useTranslation('screenTabs') | ||||
|  | ||||
|   const [segment, setSegment] = useState(0) | ||||
|   const dispatch = useAppDispatch() | ||||
|   const previousSegment = useSelector(getPreviousSegment, () => true) | ||||
|   const segments: ContextsLatest['previousSegment'][] = ['Local', 'LocalPublic', 'Trending'] | ||||
|   const [segment, setSegment] = useState<number>( | ||||
|     segments.findIndex(segment => segment === previousSegment) | ||||
|   ) | ||||
|   const [routes] = useState([ | ||||
|     { key: 'Local', title: t('tabs.public.segments.local') }, | ||||
|     { key: 'LocalPublic', title: t('tabs.public.segments.federated') }, | ||||
| @@ -51,7 +60,10 @@ const Root: React.FC<NativeStackScreenProps<TabPublicStackParamList, 'Tab-Public | ||||
|           appearance={mode} | ||||
|           values={routes.map(({ title }) => title)} | ||||
|           selectedIndex={segment} | ||||
|           onChange={({ nativeEvent }) => setSegment(nativeEvent.selectedSegmentIndex)} | ||||
|           onChange={({ nativeEvent }) => { | ||||
|             setSegment(nativeEvent.selectedSegmentIndex) | ||||
|             dispatch(updatePreviousSegment(segments[nativeEvent.selectedSegmentIndex])) | ||||
|           }} | ||||
|           style={{ flexBasis: '65%' }} | ||||
|         /> | ||||
|       ), | ||||
|   | ||||
| @@ -1,8 +1,3 @@ | ||||
| /// <reference types="@welldone-software/why-did-you-render" /> | ||||
|  | ||||
| import React from 'react' | ||||
| import log from './log' | ||||
|  | ||||
| const dev = () => { | ||||
|   if (__DEV__) { | ||||
|     // log('log', 'devs', 'initializing wdyr') | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| import createSecureStore from '@neverdull-agency/expo-unlimited-secure-store' | ||||
| import AsyncStorage from '@react-native-async-storage/async-storage' | ||||
| import { AnyAction, configureStore, Reducer } from '@reduxjs/toolkit' | ||||
| import contextsMigration from '@utils/migrations/contexts/migration' | ||||
| import contextsMigration, { ContextsLatest } from '@utils/migrations/contexts/migration' | ||||
| import instancesMigration from '@utils/migrations/instances/migration' | ||||
| import settingsMigration from '@utils/migrations/settings/migration' | ||||
| import appSlice, { AppState } from '@utils/slices/appSlice' | ||||
| import contextsSlice, { ContextsState } from '@utils/slices/contextsSlice' | ||||
| import contextsSlice from '@utils/slices/contextsSlice' | ||||
| import instancesSlice, { InstancesState } from '@utils/slices/instancesSlice' | ||||
| import settingsSlice, { SettingsState } from '@utils/slices/settingsSlice' | ||||
| import { Platform } from 'react-native' | ||||
| @@ -37,7 +37,7 @@ const contextsPersistConfig = { | ||||
|   key: 'contexts', | ||||
|   prefix, | ||||
|   storage: AsyncStorage, | ||||
|   version: 2, | ||||
|   version: 3, | ||||
|   // @ts-ignore | ||||
|   migrate: createMigrate(contextsMigration) | ||||
| } | ||||
| @@ -64,7 +64,7 @@ const store = configureStore({ | ||||
|   reducer: { | ||||
|     app: persistReducer(appPersistConfig, appSlice) as Reducer<AppState, AnyAction>, | ||||
|     contexts: persistReducer(contextsPersistConfig, contextsSlice) as Reducer< | ||||
|       ContextsState, | ||||
|       ContextsLatest, | ||||
|       AnyAction | ||||
|     >, | ||||
|     instances: persistReducer(instancesPersistConfig, instancesSlice) as Reducer< | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| import { ContextsV0 } from './v0' | ||||
| import { ContextsV1 } from './v1' | ||||
| import { ContextsV2 } from './v2' | ||||
| import { ContextsV3 } from './v3' | ||||
|  | ||||
| const contextsMigration = { | ||||
|   1: (state: ContextsV0): ContextsV1 => { | ||||
| @@ -15,7 +16,12 @@ const contextsMigration = { | ||||
|   2: (state: ContextsV1): ContextsV2 => { | ||||
|     const { mePage, ...rest } = state | ||||
|     return rest | ||||
|   }, | ||||
|   3: (state: ContextsV2): ContextsV3 => { | ||||
|     return { ...state, previousSegment: 'Local' } | ||||
|   } | ||||
| } | ||||
|  | ||||
| export { ContextsV3 as ContextsLatest } | ||||
|  | ||||
| export default contextsMigration | ||||
|   | ||||
							
								
								
									
										19
									
								
								src/utils/migrations/contexts/v3.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/utils/migrations/contexts/v3.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| import { ScreenTabsStackParamList } from '@utils/navigation/navigators' | ||||
|  | ||||
| export type ContextsV3 = { | ||||
|   storeReview: { | ||||
|     context: Readonly<number> | ||||
|     current: number | ||||
|     shown: boolean | ||||
|   } | ||||
|   publicRemoteNotice: { | ||||
|     context: Readonly<number> | ||||
|     current: number | ||||
|     hidden: boolean | ||||
|   } | ||||
|   previousTab: Extract< | ||||
|     keyof ScreenTabsStackParamList, | ||||
|     'Tab-Local' | 'Tab-Public' | 'Tab-Notifications' | 'Tab-Me' | ||||
|   > | ||||
|   previousSegment: Extract<App.Pages, 'Local' | 'LocalPublic' | 'Trending'> | ||||
| } | ||||
| @@ -1,23 +1,10 @@ | ||||
| import { createSlice, PayloadAction } from '@reduxjs/toolkit' | ||||
| import { RootState } from '@root/store' | ||||
| import { ContextsLatest } from '@utils/migrations/contexts/migration' | ||||
| import Constants from 'expo-constants' | ||||
| import * as StoreReview from 'expo-store-review' | ||||
|  | ||||
| export type ContextsState = { | ||||
|   storeReview: { | ||||
|     context: Readonly<number> | ||||
|     current: number | ||||
|     shown: boolean | ||||
|   } | ||||
|   publicRemoteNotice: { | ||||
|     context: Readonly<number> | ||||
|     current: number | ||||
|     hidden: boolean | ||||
|   } | ||||
|   previousTab: 'Tab-Local' | 'Tab-Public' | 'Tab-Notifications' | 'Tab-Me' | ||||
| } | ||||
|  | ||||
| export const contextsInitialState = { | ||||
| export const contextsInitialState: ContextsLatest = { | ||||
|   // After 10 successful postings | ||||
|   storeReview: { | ||||
|     context: 10, | ||||
| @@ -30,49 +17,46 @@ export const contextsInitialState = { | ||||
|     current: 0, | ||||
|     hidden: false | ||||
|   }, | ||||
|   previousTab: 'Tab-Me' | ||||
|   previousTab: 'Tab-Me', | ||||
|   previousSegment: 'Local' | ||||
| } | ||||
|  | ||||
| const contextsSlice = createSlice({ | ||||
|   name: 'contexts', | ||||
|   initialState: contextsInitialState as ContextsState, | ||||
|   initialState: contextsInitialState, | ||||
|   reducers: { | ||||
|     updateStoreReview: (state, action: PayloadAction<1>) => { | ||||
|       if (Constants.expoConfig?.extra?.environment === 'release') { | ||||
|         state.storeReview.current = state.storeReview.current + action.payload | ||||
|         if (state.storeReview.current === state.storeReview.context) { | ||||
|           StoreReview?.isAvailableAsync().then(() => | ||||
|             StoreReview.requestReview() | ||||
|           ) | ||||
|           StoreReview?.isAvailableAsync().then(() => StoreReview.requestReview()) | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     updatePublicRemoteNotice: (state, action: PayloadAction<1>) => { | ||||
|       state.publicRemoteNotice.current = | ||||
|         state.publicRemoteNotice.current + action.payload | ||||
|       if ( | ||||
|         state.publicRemoteNotice.current === state.publicRemoteNotice.context | ||||
|       ) { | ||||
|       state.publicRemoteNotice.current = state.publicRemoteNotice.current + action.payload | ||||
|       if (state.publicRemoteNotice.current === state.publicRemoteNotice.context) { | ||||
|         state.publicRemoteNotice.hidden = true | ||||
|       } | ||||
|     }, | ||||
|     updatePreviousTab: ( | ||||
|       state, | ||||
|       action: PayloadAction<ContextsState['previousTab']> | ||||
|     ) => { | ||||
|     updatePreviousTab: (state, action: PayloadAction<ContextsLatest['previousTab']>) => { | ||||
|       state.previousTab = action.payload | ||||
|     }, | ||||
|     updatePreviousSegment: (state, action: PayloadAction<ContextsLatest['previousSegment']>) => { | ||||
|       state.previousSegment = action.payload | ||||
|     } | ||||
|   } | ||||
| }) | ||||
|  | ||||
| export const getPublicRemoteNotice = (state: RootState) => | ||||
|   state.contexts.publicRemoteNotice | ||||
| export const getPublicRemoteNotice = (state: RootState) => state.contexts.publicRemoteNotice | ||||
| export const getPreviousTab = (state: RootState) => state.contexts.previousTab | ||||
| export const getPreviousSegment = (state: RootState) => state.contexts.previousSegment | ||||
| export const getContexts = (state: RootState) => state.contexts | ||||
|  | ||||
| export const { | ||||
|   updateStoreReview, | ||||
|   updatePublicRemoteNotice, | ||||
|   updatePreviousTab | ||||
|   updatePreviousTab, | ||||
|   updatePreviousSegment | ||||
| } = contextsSlice.actions | ||||
| export default contextsSlice.reducer | ||||
|   | ||||
		Reference in New Issue
	
	Block a user