mirror of
https://github.com/tooot-app/app
synced 2025-02-21 14:20:50 +01:00
Fixed #566
This commit is contained in:
parent
3691b19a87
commit
c59690fcb9
@ -1,10 +1 @@
|
||||
Enjoy toooting! This version includes following improvements and fixes:
|
||||
- Added Ukrainian (Slava Ukraini)
|
||||
- Automatic setting detected language when tooting
|
||||
- Remember public timeline type selection
|
||||
- Show diffing of edit history
|
||||
- Allow hiding boosts and replies in home timeline
|
||||
- Support toot in RTL languages
|
||||
- Added notification for admins
|
||||
- Fix whole word filter matching
|
||||
- Fix tablet cannot delete toot drafts
|
||||
|
@ -1,10 +1 @@
|
||||
toooting愉快!此版本包括以下改进和修复:
|
||||
- 增加乌克兰语(Slava Ukraini)
|
||||
- 自动识别发嘟语言
|
||||
- 记住上次公共时间轴选项
|
||||
- 显示编辑历史的差异
|
||||
- 关注列表可隐藏转嘟和回复
|
||||
- 新增管理员推送通知
|
||||
- 支持嘟文右到左文字
|
||||
- 修复过滤整词功能
|
||||
- 修复平板不能删除草稿
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tooot",
|
||||
"version": "4.7.0",
|
||||
"version": "4.7.1",
|
||||
"description": "tooot for Mastodon",
|
||||
"author": "xmflsct <me@xmflsct.com>",
|
||||
"license": "GPL-3.0-or-later",
|
||||
|
@ -64,6 +64,7 @@ const TimelineDefault: React.FC<Props> = ({
|
||||
content: '',
|
||||
complete: false
|
||||
})
|
||||
const detectedLanguage = useRef<string>(status.language || '')
|
||||
|
||||
const filtered = queryKey && shouldFilter({ copiableContent, status, queryKey })
|
||||
if (queryKey && filtered && !highlighted) {
|
||||
@ -139,6 +140,7 @@ const TimelineDefault: React.FC<Props> = ({
|
||||
ownAccount,
|
||||
spoilerHidden,
|
||||
copiableContent,
|
||||
detectedLanguage,
|
||||
highlighted,
|
||||
inThread: queryKey?.[1].page === 'Toot',
|
||||
disableDetails,
|
||||
|
@ -14,6 +14,7 @@ type ContextType = {
|
||||
content: string
|
||||
complete: boolean
|
||||
}>
|
||||
detectedLanguage?: React.MutableRefObject<string>
|
||||
|
||||
highlighted?: boolean
|
||||
inThread?: boolean
|
||||
|
@ -11,7 +11,7 @@ import { StyleSheet, View } from 'react-native'
|
||||
import StatusContext from './Context'
|
||||
|
||||
const TimelineFeedback = () => {
|
||||
const { status, highlighted } = useContext(StatusContext)
|
||||
const { status, highlighted, detectedLanguage } = useContext(StatusContext)
|
||||
if (!status || !highlighted) return null
|
||||
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
@ -80,7 +80,12 @@ const TimelineFeedback = () => {
|
||||
accessibilityHint={t('shared.actionsUsers.history.accessibilityHint')}
|
||||
accessibilityRole='button'
|
||||
style={[styles.text, { marginRight: 0, color: colors.blue }]}
|
||||
onPress={() => navigation.push('Tab-Shared-History', { id: status.id })}
|
||||
onPress={() =>
|
||||
navigation.push('Tab-Shared-History', {
|
||||
id: status.id,
|
||||
detectedLanguage: detectedLanguage?.current || status.language || ''
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('shared.actionsUsers.history.text', {
|
||||
count: data.length - 1
|
||||
|
@ -13,7 +13,7 @@ import { Circle } from 'react-native-animated-spinkit'
|
||||
import StatusContext from './Context'
|
||||
|
||||
const TimelineTranslate = () => {
|
||||
const { status, highlighted, copiableContent } = useContext(StatusContext)
|
||||
const { status, highlighted, copiableContent, detectedLanguage } = useContext(StatusContext)
|
||||
if (!status || !highlighted) return null
|
||||
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
@ -38,14 +38,19 @@ const TimelineTranslate = () => {
|
||||
? [copiableContent?.current.content]
|
||||
: backupTextProcessing()
|
||||
|
||||
const [detectedLanguage, setDetectedLanguage] = useState<{
|
||||
const [detected, setDetected] = useState<{
|
||||
language: string
|
||||
confidence: number
|
||||
}>({ language: status.language || '', confidence: 0 })
|
||||
useEffect(() => {
|
||||
const detect = async () => {
|
||||
const result = await detectLanguage(text.join('\n\n'))
|
||||
result && setDetectedLanguage(result)
|
||||
if (result) {
|
||||
setDetected(result)
|
||||
if (detectedLanguage) {
|
||||
detectedLanguage.current = result.language
|
||||
}
|
||||
}
|
||||
}
|
||||
detect()
|
||||
}, [])
|
||||
@ -57,7 +62,7 @@ const TimelineTranslate = () => {
|
||||
|
||||
const [enabled, setEnabled] = useState(false)
|
||||
const { refetch, data, isFetching, isSuccess, isError } = useTranslateQuery({
|
||||
source: detectedLanguage.language,
|
||||
source: detected.language,
|
||||
target: targetLanguage,
|
||||
text,
|
||||
options: { enabled }
|
||||
@ -66,9 +71,9 @@ const TimelineTranslate = () => {
|
||||
const devView = () => {
|
||||
return __DEV__ ? (
|
||||
<CustomText fontStyle='S' style={{ color: colors.secondary }}>{` Source: ${
|
||||
detectedLanguage?.language
|
||||
detected?.language
|
||||
}; Confidence: ${
|
||||
detectedLanguage?.confidence.toString().slice(0, 5) || 'null'
|
||||
detected?.confidence.toString().slice(0, 5) || 'null'
|
||||
}; Target: ${targetLanguage}`}</CustomText>
|
||||
) : null
|
||||
}
|
||||
@ -78,13 +83,13 @@ const TimelineTranslate = () => {
|
||||
}
|
||||
if (
|
||||
Platform.OS === 'ios' &&
|
||||
Localization.locale.slice(0, 2).includes(detectedLanguage.language.slice(0, 2))
|
||||
Localization.locale.slice(0, 2).includes(detected.language.slice(0, 2))
|
||||
) {
|
||||
return devView()
|
||||
}
|
||||
if (
|
||||
Platform.OS === 'android' &&
|
||||
settingsLanguage?.slice(0, 2).includes(detectedLanguage.language.slice(0, 2))
|
||||
settingsLanguage?.slice(0, 2).includes(detected.language.slice(0, 2))
|
||||
) {
|
||||
return devView()
|
||||
}
|
||||
|
@ -11,25 +11,45 @@ import { TabSharedStackScreenProps } from '@utils/navigation/navigators'
|
||||
import { useStatusHistory } from '@utils/queryHooks/statusesHistory'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import { diffWords } from 'diff'
|
||||
import { diffChars, diffWords } from 'diff'
|
||||
import React, { useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { FlatList, View } from 'react-native'
|
||||
|
||||
const SCRIPTS_WITHOUT_BOUNDARIES = [
|
||||
'my',
|
||||
'zh',
|
||||
'ja',
|
||||
'kar',
|
||||
'km',
|
||||
'lp',
|
||||
'phag',
|
||||
'pwo',
|
||||
'kar',
|
||||
'lana',
|
||||
'th',
|
||||
'bo'
|
||||
]
|
||||
|
||||
const ContentView: React.FC<{
|
||||
withoutBoundary: boolean
|
||||
item: Mastodon.StatusHistory
|
||||
prevItem?: Mastodon.StatusHistory
|
||||
}> = ({ item, prevItem }) => {
|
||||
}> = ({ withoutBoundary, item, prevItem }) => {
|
||||
const { colors } = useTheme()
|
||||
|
||||
const changesSpoiler = diffWords(
|
||||
removeHTML(prevItem?.spoiler_text || item.spoiler_text || ''),
|
||||
removeHTML(item.spoiler_text || '')
|
||||
)
|
||||
const changesContent = diffWords(
|
||||
removeHTML(prevItem?.content || item.content),
|
||||
removeHTML(item.content)
|
||||
)
|
||||
const changesSpoiler = withoutBoundary
|
||||
? diffChars(
|
||||
removeHTML(prevItem?.spoiler_text || item.spoiler_text || ''),
|
||||
removeHTML(item.spoiler_text || '')
|
||||
)
|
||||
: diffWords(
|
||||
removeHTML(prevItem?.spoiler_text || item.spoiler_text || ''),
|
||||
removeHTML(item.spoiler_text || '')
|
||||
)
|
||||
const changesContent = withoutBoundary
|
||||
? diffChars(removeHTML(prevItem?.content || item.content), removeHTML(item.content))
|
||||
: diffWords(removeHTML(prevItem?.content || item.content), removeHTML(item.content))
|
||||
|
||||
return (
|
||||
// @ts-ignore
|
||||
@ -91,7 +111,7 @@ const ContentView: React.FC<{
|
||||
const TabSharedHistory: React.FC<TabSharedStackScreenProps<'Tab-Shared-History'>> = ({
|
||||
navigation,
|
||||
route: {
|
||||
params: { id }
|
||||
params: { id, detectedLanguage }
|
||||
}
|
||||
}) => {
|
||||
const { t } = useTranslation('screenTabs')
|
||||
@ -106,12 +126,20 @@ const TabSharedHistory: React.FC<TabSharedStackScreenProps<'Tab-Shared-History'>
|
||||
|
||||
const dataReversed = data ? [...data].reverse() : []
|
||||
|
||||
const withoutBoundary = !!SCRIPTS_WITHOUT_BOUNDARIES.filter(script =>
|
||||
detectedLanguage?.toLocaleLowerCase().startsWith(script)
|
||||
).length
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
style={{ flex: 1, minHeight: '100%' }}
|
||||
data={dataReversed}
|
||||
renderItem={({ item, index }) => (
|
||||
<ContentView item={item} prevItem={dataReversed[index + 1]} />
|
||||
<ContentView
|
||||
withoutBoundary={withoutBoundary}
|
||||
item={item}
|
||||
prevItem={dataReversed[index + 1]}
|
||||
/>
|
||||
)}
|
||||
ItemSeparatorComponent={ComponentSeparator}
|
||||
/>
|
||||
|
@ -103,6 +103,7 @@ export type TabSharedStackParamList = {
|
||||
}
|
||||
'Tab-Shared-History': {
|
||||
id: Mastodon.Status['id']
|
||||
detectedLanguage: string
|
||||
}
|
||||
'Tab-Shared-Search': undefined
|
||||
'Tab-Shared-Toot': {
|
||||
|
Loading…
x
Reference in New Issue
Block a user