Add static emoji option

This commit is contained in:
Zhiyuan Zheng 2022-05-13 00:04:15 +02:00
parent 9c3e8f58b0
commit dde33ad1ad
9 changed files with 131 additions and 59 deletions

View File

@ -166,7 +166,7 @@ const styles = StyleSheet.create({
core: {
flex: 1,
flexDirection: 'row',
paddingVertical: StyleConstants.Spacing.S
paddingTop: StyleConstants.Spacing.S
},
front: {
flex: 2,

View File

@ -130,7 +130,9 @@ const Timeline: React.FC<Props> = ({
}
ListEmptyComponent={<TimelineEmpty queryKey={queryKey} />}
ItemSeparatorComponent={ItemSeparatorComponent}
maintainVisibleContentPosition={{ minIndexForVisible: 0 }}
{...(isFetchingPreviousPage && {
maintainVisibleContentPosition: { minIndexForVisible: 0 }
})}
refreshing={isFetchingPreviousPage}
onRefresh={() => {
if (!disableRefresh && !isFetchingPreviousPage) {

View File

@ -251,6 +251,10 @@
"cancel": "$t(common:buttons.cancel)"
}
},
"staticEmoji": {
"heading": "Use static emoji",
"description": "If you encounter frequent app crash when viewing emoji list, you can try to use static emoji instead."
},
"feedback": {
"heading": "Feature Requests"
},

View File

@ -3,6 +3,7 @@ import CustomText from '@components/Text'
import { useAppDispatch } from '@root/store'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { countInstanceEmoji } from '@utils/slices/instancesSlice'
import { getSettingsStaticEmoji } from '@utils/slices/settingsSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { RefObject, useCallback, useContext, useEffect } from 'react'
@ -10,11 +11,13 @@ import { useTranslation } from 'react-i18next'
import {
AccessibilityInfo,
findNodeHandle,
Image,
Pressable,
SectionList,
View
} from 'react-native'
import FastImage from 'react-native-fast-image'
import { useSelector } from 'react-redux'
import validUrl from 'valid-url'
import updateText from '../../updateText'
import ComposeContext from '../../utils/createContext'
@ -30,6 +33,8 @@ const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
const { t } = useTranslation()
const dispatch = useAppDispatch()
const staticEmoji = useSelector(getSettingsStaticEmoji)
useEffect(() => {
const tagEmojis = findNodeHandle(accessibleRefEmojis.current)
if (composeState.emoji.active) {
@ -82,6 +87,26 @@ const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
dispatch(countInstanceEmoji(emoji))
}}
>
{staticEmoji ? (
<Image
accessibilityLabel={t(
'common:customEmoji.accessibilityLabel',
{
emoji: emoji.shortcode
}
)}
accessibilityHint={t(
'screenCompose:content.root.footer.emojis.accessibilityHint'
)}
source={{ uri }}
style={{
width: 32,
height: 32,
padding: StyleConstants.Spacing.S,
margin: StyleConstants.Spacing.S
}}
/>
) : (
<FastImage
accessibilityLabel={t(
'common:customEmoji.accessibilityLabel',
@ -100,6 +125,7 @@ const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
margin: StyleConstants.Spacing.S
}}
/>
)}
</Pressable>
)
} else {

View File

@ -22,6 +22,7 @@ const SettingsAnalytics: React.FC = () => {
const instanceVersion = useSelector(getInstanceVersion, () => true)
return (
<>
<MenuContainer>
<MenuRow
title={t('me.settings.analytics.heading')}
@ -31,6 +32,8 @@ const SettingsAnalytics: React.FC = () => {
dispatch(changeAnalytics(!settingsAnalytics))
}
/>
</MenuContainer>
<MenuContainer>
<CustomText
fontStyle='S'
style={{
@ -51,6 +54,7 @@ const SettingsAnalytics: React.FC = () => {
{t('me.settings.instanceVersion', { version: instanceVersion })}
</CustomText>
</MenuContainer>
</>
)
}

View File

@ -15,7 +15,9 @@ import {
getSettingsBrowser,
getSettingsFontsize,
getSettingsDarkTheme,
changeDarkTheme
changeDarkTheme,
getSettingsStaticEmoji,
changeStaticEmoji
} from '@utils/slices/settingsSlice'
import { useTheme } from '@utils/styles/ThemeManager'
import * as Notifications from 'expo-notifications'
@ -37,6 +39,7 @@ const SettingsApp: React.FC = () => {
const settingsTheme = useSelector(getSettingsTheme)
const settingsDarkTheme = useSelector(getSettingsDarkTheme)
const settingsBrowser = useSelector(getSettingsBrowser)
const settingsStaticEmoji = useSelector(getSettingsStaticEmoji)
return (
<MenuContainer>
@ -266,6 +269,18 @@ const SettingsApp: React.FC = () => {
)
}
/>
<MenuRow
title={t('me.settings.staticEmoji.heading')}
description={t('me.settings.staticEmoji.description')}
switchValue={settingsStaticEmoji}
switchOnValueChange={() => {
analytics('settings_staticemoji_press', {
current: settingsStaticEmoji.toString(),
new: !settingsStaticEmoji.toString()
})
dispatch(changeStaticEmoji(!settingsStaticEmoji))
}}
/>
</MenuContainer>
)
}

View File

@ -1,5 +1,6 @@
import { SettingsV0 } from './v0'
import { SettingsV1 } from './v1'
import { SettingsV2 } from './v2'
const settingsMigration = {
1: (state: SettingsV0): SettingsV1 => {
@ -7,6 +8,13 @@ const settingsMigration = {
...state,
darkTheme: 'lighter'
}
},
2: (state: SettingsV1): SettingsV2 => {
return {
...state,
darkTheme: 'lighter',
staticEmoji: false
}
}
}

View File

@ -0,0 +1,9 @@
export type SettingsV2 = {
fontsize: -1 | 0 | 1 | 2 | 3
language: string
theme: 'light' | 'dark' | 'auto'
darkTheme: 'lighter' | 'darker'
browser: 'internal' | 'external'
staticEmoji: boolean
analytics: boolean
}

View File

@ -1,6 +1,7 @@
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'
import { LOCALES } from '@root/i18n/locales'
import { RootState } from '@root/store'
import { SettingsV2 } from '@utils/migrations/settings/v2'
import * as Analytics from 'expo-firebase-analytics'
import * as Localization from 'expo-localization'
import { pickBy } from 'lodash'
@ -13,14 +14,7 @@ export const changeAnalytics = createAsyncThunk(
}
)
export type SettingsState = {
fontsize: -1 | 0 | 1 | 2 | 3
language: string
theme: 'light' | 'dark' | 'auto'
darkTheme: 'lighter' | 'darker'
browser: 'internal' | 'external'
analytics: boolean
}
export type SettingsState = SettingsV2
export const settingsInitialState = {
fontsize: 0,
@ -37,6 +31,7 @@ export const settingsInitialState = {
theme: 'auto',
darkTheme: 'lighter',
browser: 'internal',
staticEmoji: false,
analytics: true
}
@ -73,6 +68,12 @@ const settingsSlice = createSlice({
action: PayloadAction<NonNullable<SettingsState['browser']>>
) => {
state.browser = action.payload
},
changeStaticEmoji: (
state,
action: PayloadAction<NonNullable<SettingsState['staticEmoji']>>
) => {
state.staticEmoji = action.payload
}
},
extraReducers: builder => {
@ -89,6 +90,8 @@ export const getSettingsTheme = (state: RootState) => state.settings.theme
export const getSettingsDarkTheme = (state: RootState) =>
state.settings.darkTheme
export const getSettingsBrowser = (state: RootState) => state.settings.browser
export const getSettingsStaticEmoji = (state: RootState) =>
state.settings.staticEmoji
export const getSettingsAnalytics = (state: RootState) =>
state.settings.analytics
@ -97,6 +100,7 @@ export const {
changeLanguage,
changeTheme,
changeDarkTheme,
changeBrowser
changeBrowser,
changeStaticEmoji
} = settingsSlice.actions
export default settingsSlice.reducer