mirror of
https://github.com/tooot-app/app
synced 2025-02-18 04:40:57 +01:00
Fixed #119 and translation
This commit is contained in:
parent
0517d2fae2
commit
0190b35b57
@ -1,5 +1,5 @@
|
||||
# [tooot](https://tooot.app/) app for Mastodon
|
||||
|
||||
[![GPL-3.0](https://img.shields.io/github/license/tooot-app/push?style=flat-square)](LICENSE) ![GitHub issues](https://img.shields.io/github/issues/tooot-app/app?style=flat-square) ![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/tooot-app/app?include_prereleases&style=flat-square) ![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/tooot-app/app?style=flat-square) [![Crowdin](https://badges.crowdin.net/tooot/localized.svg)](https://crowdin.tooot.app/project/tooot)
|
||||
[![GPL-3.0](https://img.shields.io/github/license/tooot-app/push)](LICENSE) ![GitHub issues](https://img.shields.io/github/issues/tooot-app/app) ![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/tooot-app/app?include_prereleases&style=flat-square) ![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/tooot-app/app) [![Crowdin](https://badges.crowdin.net/tooot/localized.svg)](https://crowdin.tooot.app/project/tooot)
|
||||
|
||||
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/tooot-app/app/build?style=flat-square) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/tooot-app/app/build/candidate?label=build%20candidate&style=flat-square) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/tooot-app/app/build/release?label=build%20release&style=flat-square)
|
||||
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/tooot-app/app/build) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/tooot-app/app/build/candidate?label=build%20candidate&style=flat-square) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/tooot-app/app/build/release?label=build%20release&style=flat-square)
|
||||
|
@ -19,6 +19,7 @@ public class BasePackageList {
|
||||
new expo.modules.font.FontLoaderPackage(),
|
||||
new expo.modules.haptics.HapticsPackage(),
|
||||
new expo.modules.imageloader.ImageLoaderPackage(),
|
||||
new expo.modules.imagemanipulator.ImageManipulatorPackage(),
|
||||
new expo.modules.imagepicker.ImagePickerPackage(),
|
||||
new expo.modules.keepawake.KeepAwakePackage(),
|
||||
new expo.modules.localization.LocalizationPackage(),
|
||||
|
@ -825,7 +825,7 @@ SPEC CHECKSUMS:
|
||||
EXVideoThumbnails: cd257fc6e07884a704a5674d362a6410933acb68
|
||||
EXWebBrowser: 0b466c50e5ff61c9758095d49d5081e3229d77ac
|
||||
FBLazyVector: 7b423f9e248eae65987838148c36eec1dbfe0b53
|
||||
FBReactNativeSpec: be55984d4a593b4ef281ead81139cdfb1812d259
|
||||
FBReactNativeSpec: 5058d1917c80dca4b9ed89bdf94385315939ab80
|
||||
Firebase: cd2ab85eec8170dc260186159f21072ecb679ad5
|
||||
FirebaseAnalytics: f3f8f75de34fe04141a69bb1c4bd7e24a80178e1
|
||||
FirebaseCore: ac35d680a0bf32319a59966a1478e0741536b97b
|
||||
|
@ -346,7 +346,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = tooot/tooot.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 2102022230;
|
||||
DEVELOPMENT_TEAM = 8EGBLQ2MA6;
|
||||
@ -366,7 +366,7 @@
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.xmflsct.app.tooot;
|
||||
PRODUCT_NAME = tooot;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "match Development com.xmflsct.app.tooot";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "match AdHoc com.xmflsct.app.tooot";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "tooot-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
15
src/@types/translate.d.ts
vendored
15
src/@types/translate.d.ts
vendored
@ -1,15 +0,0 @@
|
||||
declare namespace Translate {
|
||||
type Detect = {
|
||||
confidence: number
|
||||
language: string
|
||||
}
|
||||
|
||||
type Language = {
|
||||
code: string
|
||||
name: string
|
||||
}
|
||||
|
||||
type Translate = {
|
||||
translatedText: string
|
||||
}
|
||||
}
|
@ -74,7 +74,11 @@ const apiGeneral = async <T = unknown>({
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
console.error(ctx.bold(' API general '), ctx.bold('request'), error)
|
||||
console.error(
|
||||
ctx.bold(' API general '),
|
||||
ctx.bold('request'),
|
||||
error.request
|
||||
)
|
||||
return Promise.reject()
|
||||
} else {
|
||||
console.error(
|
||||
|
@ -76,7 +76,7 @@ const MenuRow: React.FC<Props> = ({
|
||||
}
|
||||
}}
|
||||
>
|
||||
<View>
|
||||
<View style={{ flex: 1 }}>
|
||||
<View style={styles.core}>
|
||||
<View style={styles.front}>
|
||||
{iconFront && (
|
||||
|
@ -164,6 +164,7 @@ export interface Props {
|
||||
expandHint?: string
|
||||
highlighted?: boolean
|
||||
disableDetails?: boolean
|
||||
selectable?: boolean
|
||||
}
|
||||
|
||||
const ParseHTML = React.memo(
|
||||
@ -178,7 +179,8 @@ const ParseHTML = React.memo(
|
||||
numberOfLines = 10,
|
||||
expandHint,
|
||||
highlighted = false,
|
||||
disableDetails = false
|
||||
disableDetails = false,
|
||||
selectable = false
|
||||
}: Props) => {
|
||||
const adaptiveFontsize = useSelector(getSettingsFontsize)
|
||||
const adaptedFontsize = adaptiveScale(
|
||||
@ -255,6 +257,7 @@ const ParseHTML = React.memo(
|
||||
numberOfLines={
|
||||
expandAllow ? (expanded ? 999 : numberOfLines) : undefined
|
||||
}
|
||||
selectable={selectable}
|
||||
/>
|
||||
{expandAllow ? (
|
||||
<Pressable
|
||||
|
@ -32,6 +32,7 @@ const TimelineContent = React.memo(
|
||||
numberOfLines={999}
|
||||
highlighted={highlighted}
|
||||
disableDetails={disableDetails}
|
||||
selectable={highlighted}
|
||||
/>
|
||||
<ParseHTML
|
||||
content={status.content}
|
||||
@ -44,6 +45,7 @@ const TimelineContent = React.memo(
|
||||
expandHint={t('shared.content.expandHint')}
|
||||
highlighted={highlighted}
|
||||
disableDetails={disableDetails}
|
||||
selectable={highlighted}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
@ -56,6 +58,7 @@ const TimelineContent = React.memo(
|
||||
tags={status.tags}
|
||||
numberOfLines={highlighted ? 999 : numberOfLines}
|
||||
disableDetails={disableDetails}
|
||||
selectable={highlighted}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
@ -1,32 +1,16 @@
|
||||
import analytics from '@components/analytics'
|
||||
import { ParseHTML } from '@components/Parse'
|
||||
import { useTranslateQuery } from '@utils/queryHooks/translate'
|
||||
import { getInstanceUri } from '@utils/slices/instancesSlice'
|
||||
import { getSettingsLanguage } from '@utils/slices/settingsSlice'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import htmlparser2 from 'htmlparser2-without-node-native'
|
||||
import React, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Pressable, StyleSheet, Text } from 'react-native'
|
||||
import { Circle } from 'react-native-animated-spinkit'
|
||||
import { useSelector } from 'react-redux'
|
||||
|
||||
const availableLanguages = [
|
||||
'en',
|
||||
'ar',
|
||||
'zh',
|
||||
'fr',
|
||||
'de',
|
||||
'hi',
|
||||
'ga',
|
||||
'it',
|
||||
'ja',
|
||||
'ko',
|
||||
'pl',
|
||||
'pt',
|
||||
'ru',
|
||||
'es',
|
||||
'tr'
|
||||
]
|
||||
|
||||
export interface Props {
|
||||
highlighted: boolean
|
||||
status: Mastodon.Status
|
||||
@ -45,48 +29,31 @@ const TimelineTranslate = React.memo(
|
||||
const { theme } = useTheme()
|
||||
|
||||
const tootLanguage = status.language.slice(0, 2)
|
||||
if (!availableLanguages.includes(tootLanguage)) {
|
||||
return (
|
||||
<Text
|
||||
style={{
|
||||
...StyleConstants.FontStyle.M,
|
||||
color: theme.disabled
|
||||
}}
|
||||
>
|
||||
{t('shared.translate.unavailable')}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
|
||||
const settingsLanguage = useSelector(getSettingsLanguage, () => true)
|
||||
const settingsLanguage = useSelector(getSettingsLanguage)
|
||||
|
||||
if (settingsLanguage.includes(tootLanguage)) {
|
||||
return null
|
||||
}
|
||||
|
||||
let emojisRemoved = status.spoiler_text
|
||||
? status.spoiler_text.concat(status.content)
|
||||
: status.content
|
||||
if (status.emojis) {
|
||||
let text = status.spoiler_text
|
||||
? [status.spoiler_text, status.content]
|
||||
: [status.content]
|
||||
|
||||
for (const i in text) {
|
||||
for (const emoji of status.emojis) {
|
||||
emojisRemoved = emojisRemoved.replaceAll(`:${emoji.shortcode}:`, '')
|
||||
text[i] = text[i].replaceAll(`:${emoji.shortcode}:`, '')
|
||||
}
|
||||
}
|
||||
|
||||
let cleaned = ''
|
||||
const parser = new htmlparser2.Parser({
|
||||
ontext (text: string) {
|
||||
cleaned = cleaned.concat(text)
|
||||
}
|
||||
})
|
||||
parser.write(emojisRemoved)
|
||||
parser.end()
|
||||
|
||||
const instanceUri = useSelector(getInstanceUri)
|
||||
const [enabled, setEnabled] = useState(false)
|
||||
const { refetch, data, isLoading, isSuccess, isError } = useTranslateQuery({
|
||||
toot: cleaned,
|
||||
instance: instanceUri!,
|
||||
id: status.id,
|
||||
source: status.language,
|
||||
target: settingsLanguage.slice(0, 2),
|
||||
target: settingsLanguage,
|
||||
text,
|
||||
options: { enabled }
|
||||
})
|
||||
|
||||
@ -97,9 +64,15 @@ const TimelineTranslate = React.memo(
|
||||
onPress={() => {
|
||||
if (enabled) {
|
||||
if (!isSuccess) {
|
||||
analytics('timeline_shared_translate_retry', {
|
||||
language: status.language
|
||||
})
|
||||
refetch()
|
||||
}
|
||||
} else {
|
||||
analytics('timeline_shared_translate', {
|
||||
language: status.language
|
||||
})
|
||||
setEnabled(true)
|
||||
}
|
||||
}}
|
||||
@ -109,15 +82,21 @@ const TimelineTranslate = React.memo(
|
||||
...StyleConstants.FontStyle.M,
|
||||
color:
|
||||
isLoading || isSuccess
|
||||
? theme.disabled
|
||||
? theme.secondary
|
||||
: isError
|
||||
? theme.red
|
||||
: theme.blue
|
||||
}}
|
||||
>
|
||||
{isError
|
||||
? t('shared.translate.error')
|
||||
? t('shared.translate.failed')
|
||||
: isSuccess
|
||||
? t('shared.translate.succeed', {
|
||||
provider: data?.provider,
|
||||
source: data?.sourceLanguage
|
||||
})
|
||||
: t('shared.translate.default')}
|
||||
{__DEV__ ? ` Source: ${status.language}` : undefined}
|
||||
</Text>
|
||||
{isLoading ? (
|
||||
<Circle
|
||||
@ -127,15 +106,17 @@ const TimelineTranslate = React.memo(
|
||||
/>
|
||||
) : null}
|
||||
</Pressable>
|
||||
{data ? (
|
||||
<Text
|
||||
style={{
|
||||
...StyleConstants.FontStyle.M,
|
||||
color: theme.primaryDefault
|
||||
}}
|
||||
children={data}
|
||||
/>
|
||||
) : null}
|
||||
{data
|
||||
? data.text.map((d, i) => (
|
||||
<ParseHTML
|
||||
key={i}
|
||||
content={d}
|
||||
size={'M'}
|
||||
numberOfLines={999}
|
||||
selectable
|
||||
/>
|
||||
))
|
||||
: null}
|
||||
</>
|
||||
)
|
||||
},
|
||||
|
@ -76,8 +76,8 @@
|
||||
"fullConversation": "Read conversations",
|
||||
"translate": {
|
||||
"default": "Translate",
|
||||
"error": "Try to translate again",
|
||||
"unavailable": "Language not supported"
|
||||
"succeed": "Translated by {{provider}} from {{source}}",
|
||||
"failed": "Translation failed"
|
||||
},
|
||||
"header": {
|
||||
"shared": {
|
||||
|
@ -87,6 +87,7 @@ const ScreenAnnouncements: React.FC<ScreenAnnouncementsProp> = ({
|
||||
emojis={item.emojis}
|
||||
mentions={item.mentions}
|
||||
numberOfLines={999}
|
||||
selectable
|
||||
/>
|
||||
</ScrollView>
|
||||
{item.reactions?.length ? (
|
||||
|
@ -1,3 +1,4 @@
|
||||
import analytics from '@components/analytics'
|
||||
import { MenuContainer, MenuRow } from '@components/Menu'
|
||||
import { displayMessage } from '@components/Message'
|
||||
import { useActionSheet } from '@expo/react-native-action-sheet'
|
||||
@ -40,6 +41,12 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
||||
async buttonIndex => {
|
||||
switch (buttonIndex) {
|
||||
case 0:
|
||||
analytics('me_profile_visibility', {
|
||||
current: t(
|
||||
`me.profile.root.visibility.options.${data?.source.privacy}`
|
||||
),
|
||||
new: 'public'
|
||||
})
|
||||
mutateAsync({ type: 'source[privacy]', data: 'public' })
|
||||
.then(() => dispatch(updateAccountPreferences()))
|
||||
.catch(err =>
|
||||
@ -55,6 +62,12 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
||||
)
|
||||
break
|
||||
case 1:
|
||||
analytics('me_profile_visibility', {
|
||||
current: t(
|
||||
`me.profile.root.visibility.options.${data?.source.privacy}`
|
||||
),
|
||||
new: 'unlisted'
|
||||
})
|
||||
mutateAsync({ type: 'source[privacy]', data: 'unlisted' })
|
||||
.then(() => dispatch(updateAccountPreferences()))
|
||||
.catch(err =>
|
||||
@ -70,6 +83,12 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
||||
)
|
||||
break
|
||||
case 2:
|
||||
analytics('me_profile_visibility', {
|
||||
current: t(
|
||||
`me.profile.root.visibility.options.${data?.source.privacy}`
|
||||
),
|
||||
new: 'unlisted'
|
||||
})
|
||||
mutateAsync({ type: 'source[privacy]', data: 'private' })
|
||||
.then(() => dispatch(updateAccountPreferences()))
|
||||
.catch(err =>
|
||||
@ -87,10 +106,14 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
||||
}
|
||||
}
|
||||
)
|
||||
}, [])
|
||||
}, [data?.source.privacy])
|
||||
|
||||
const onPressSensitive = useCallback(() => {
|
||||
if (data?.source.sensitive === undefined) {
|
||||
analytics('me_profile_sensitive', {
|
||||
current: undefined,
|
||||
new: true
|
||||
})
|
||||
mutateAsync({ type: 'source[sensitive]', data: true })
|
||||
.then(() => dispatch(updateAccountPreferences()))
|
||||
.catch(err =>
|
||||
@ -105,6 +128,10 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
||||
})
|
||||
)
|
||||
} else {
|
||||
analytics('me_profile_sensitive', {
|
||||
current: data.source.sensitive,
|
||||
new: !data.source.sensitive
|
||||
})
|
||||
mutateAsync({
|
||||
type: 'source[sensitive]',
|
||||
data: !data.source.sensitive
|
||||
@ -126,6 +153,10 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
||||
|
||||
const onPressLock = useCallback(() => {
|
||||
if (data?.locked === undefined) {
|
||||
analytics('me_profile_lock', {
|
||||
current: undefined,
|
||||
new: true
|
||||
})
|
||||
mutateAsync({ type: 'locked', data: true }).catch(err =>
|
||||
displayMessage({
|
||||
ref: messageRef,
|
||||
@ -138,6 +169,10 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
||||
})
|
||||
)
|
||||
} else {
|
||||
analytics('me_profile_lock', {
|
||||
current: data.locked,
|
||||
new: !data.locked
|
||||
})
|
||||
mutateAsync({ type: 'locked', data: !data.locked }).catch(err =>
|
||||
displayMessage({
|
||||
ref: messageRef,
|
||||
@ -154,6 +189,10 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
||||
|
||||
const onPressBot = useCallback(() => {
|
||||
if (data?.bot === undefined) {
|
||||
analytics('me_profile_bot', {
|
||||
current: undefined,
|
||||
new: true
|
||||
})
|
||||
mutateAsync({ type: 'bot', data: true }).catch(err =>
|
||||
displayMessage({
|
||||
ref: messageRef,
|
||||
@ -166,6 +205,10 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
||||
})
|
||||
)
|
||||
} else {
|
||||
analytics('me_profile_bot', {
|
||||
current: data.bot,
|
||||
new: !data.bot
|
||||
})
|
||||
mutateAsync({ type: 'bot', data: !data?.bot }).catch(err =>
|
||||
displayMessage({
|
||||
ref: messageRef,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import analytics from '@components/analytics'
|
||||
import Button from '@components/Button'
|
||||
import { MenuContainer, MenuRow } from '@components/Menu'
|
||||
import { updateInstancePush } from '@utils/slices/instances/updatePush'
|
||||
@ -67,7 +68,11 @@ const TabMePush: React.FC = () => {
|
||||
!pushEnabled || !instancePush.global.value || isLoading
|
||||
}
|
||||
switchValue={instancePush?.alerts[alert].value}
|
||||
switchOnValueChange={() =>
|
||||
switchOnValueChange={() => {
|
||||
analytics(`me_push_${alert}`, {
|
||||
current: instancePush?.alerts[alert].value,
|
||||
new: !instancePush?.alerts[alert].value
|
||||
})
|
||||
dispatch(
|
||||
updateInstancePushAlert({
|
||||
changed: alert,
|
||||
@ -80,7 +85,7 @@ const TabMePush: React.FC = () => {
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))
|
||||
: null
|
||||
@ -103,10 +108,12 @@ const TabMePush: React.FC = () => {
|
||||
}}
|
||||
onPress={async () => {
|
||||
if (pushCanAskAgain) {
|
||||
analytics('me_push_enabled_dialogue')
|
||||
const result = await Notifications.requestPermissionsAsync()
|
||||
setPushEnabled(result.granted)
|
||||
setPushCanAskAgain(result.canAskAgain)
|
||||
} else {
|
||||
analytics('me_push_enabled_setting')
|
||||
Linking.openSettings()
|
||||
}
|
||||
}}
|
||||
@ -124,9 +131,13 @@ const TabMePush: React.FC = () => {
|
||||
switchValue={
|
||||
pushEnabled === false ? false : instancePush?.global.value
|
||||
}
|
||||
switchOnValueChange={() =>
|
||||
switchOnValueChange={() => {
|
||||
analytics('me_push_global', {
|
||||
current: instancePush?.global.value,
|
||||
new: !instancePush?.global.value
|
||||
})
|
||||
dispatch(updateInstancePush(!instancePush?.global.value))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</MenuContainer>
|
||||
<MenuContainer>
|
||||
@ -138,16 +149,21 @@ const TabMePush: React.FC = () => {
|
||||
!pushEnabled || !instancePush?.global.value || isLoading
|
||||
}
|
||||
switchValue={instancePush?.decode.value}
|
||||
switchOnValueChange={() =>
|
||||
switchOnValueChange={() => {
|
||||
analytics('me_push_decode', {
|
||||
current: instancePush?.decode.value,
|
||||
new: !instancePush?.decode.value
|
||||
})
|
||||
dispatch(updateInstancePushDecode(!instancePush?.decode.value))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<MenuRow
|
||||
title={t('me.push.howitworks')}
|
||||
iconBack='ExternalLink'
|
||||
onPress={() =>
|
||||
onPress={() => {
|
||||
analytics('me_push_howitworks')
|
||||
WebBrowser.openBrowserAsync('https://tooot.app/how-push-works')
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</MenuContainer>
|
||||
<MenuContainer>{alerts}</MenuContainer>
|
||||
|
@ -34,6 +34,7 @@ const AccountInformationFields = React.memo(
|
||||
emojis={account.emojis}
|
||||
showFullLink
|
||||
numberOfLines={5}
|
||||
selectable
|
||||
/>
|
||||
{field.verified_at ? (
|
||||
<Icon
|
||||
@ -51,6 +52,7 @@ const AccountInformationFields = React.memo(
|
||||
emojis={account.emojis}
|
||||
showFullLink
|
||||
numberOfLines={5}
|
||||
selectable
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
@ -28,7 +28,7 @@ const AccountInformationNote = React.memo(
|
||||
|
||||
return (
|
||||
<View style={styles.note}>
|
||||
<ParseHTML content={account.note!} size={'M'} emojis={account.emojis} />
|
||||
<ParseHTML content={account.note!} size={'M'} emojis={account.emojis} selectable />
|
||||
</View>
|
||||
)
|
||||
},
|
||||
|
@ -1,39 +1,55 @@
|
||||
import apiGeneral from '@api/general'
|
||||
import { AxiosError } from 'axios'
|
||||
import { Constants } from 'react-native-unimodules'
|
||||
import { Buffer } from 'buffer'
|
||||
import Constants from 'expo-constants'
|
||||
import { useQuery, UseQueryOptions } from 'react-query'
|
||||
|
||||
type Translations = {
|
||||
provider: string
|
||||
sourceLanguage: string
|
||||
text: string[]
|
||||
}
|
||||
|
||||
export type QueryKeyTranslate = [
|
||||
'Translate',
|
||||
{ toot: string; source: string; target: string }
|
||||
{
|
||||
instance: string
|
||||
id: string
|
||||
source: string
|
||||
target: string
|
||||
text: string[]
|
||||
}
|
||||
]
|
||||
|
||||
const queryFunction = async ({ queryKey }: { queryKey: QueryKeyTranslate }) => {
|
||||
const { toot, source, target } = queryKey[1]
|
||||
export const TRANSLATE_SERVER = __DEV__
|
||||
? 'testtranslate.tooot.app'
|
||||
: 'translate.tooot.app'
|
||||
|
||||
const res = await apiGeneral<Translate.Translate>({
|
||||
domain: 'translate.tooot.app',
|
||||
method: 'post',
|
||||
url: 'translate',
|
||||
params: {
|
||||
api_key: Constants.manifest?.extra?.translateKey,
|
||||
q: toot,
|
||||
source,
|
||||
target
|
||||
const queryFunction = async ({ queryKey }: { queryKey: QueryKeyTranslate }) => {
|
||||
const key = Constants.manifest.extra?.translateKey
|
||||
if (!key) {
|
||||
return Promise.reject()
|
||||
}
|
||||
|
||||
const { instance, id, source, target, text } = queryKey[1]
|
||||
|
||||
const res = await apiGeneral<Translations>({
|
||||
domain: TRANSLATE_SERVER,
|
||||
method: 'get',
|
||||
url: `v1/translate/${instance}/${id}/${target}`,
|
||||
headers: {
|
||||
key,
|
||||
original: Buffer.from(JSON.stringify({ source, text })).toString('base64')
|
||||
}
|
||||
})
|
||||
return res.body.translatedText
|
||||
return res.body
|
||||
}
|
||||
|
||||
const useTranslateQuery = ({
|
||||
options,
|
||||
...queryKeyParams
|
||||
}: QueryKeyTranslate[1] & {
|
||||
options?: UseQueryOptions<
|
||||
Translate.Translate['translatedText'],
|
||||
AxiosError,
|
||||
Translate.Translate['translatedText']
|
||||
>
|
||||
options?: UseQueryOptions<Translations, AxiosError, Translations>
|
||||
}) => {
|
||||
const queryKey: QueryKeyTranslate = ['Translate', { ...queryKeyParams }]
|
||||
return useQuery(queryKey, queryFunction, options)
|
||||
|
Loading…
x
Reference in New Issue
Block a user