mirror of https://github.com/tooot-app/app
commit
495449184c
|
@ -25,7 +25,7 @@ jobs:
|
||||||
run: bundle install
|
run: bundle install
|
||||||
- name: -- Step 5 -- Run fastlane
|
- name: -- Step 5 -- Run fastlane
|
||||||
env:
|
env:
|
||||||
DEVELOPER_DIR: /Applications/Xcode_14.0.1.app/Contents/Developer
|
DEVELOPER_DIR: /Applications/Xcode_14.1.app/Contents/Developer
|
||||||
ENVIRONMENT: ${{ steps.branch.outputs.branch }}
|
ENVIRONMENT: ${{ steps.branch.outputs.branch }}
|
||||||
SENTRY_ENVIRONMENT: ${{ steps.branch.outputs.branch }}
|
SENTRY_ENVIRONMENT: ${{ steps.branch.outputs.branch }}
|
||||||
LC_ALL: en_US.UTF-8
|
LC_ALL: en_US.UTF-8
|
||||||
|
|
|
@ -23,4 +23,6 @@ Please **do not** create a pull request to update translation. tooot's translati
|
||||||
|
|
||||||
[@duy@mas.to](https://mas.to/@duy) for Vietnamese translation
|
[@duy@mas.to](https://mas.to/@duy) for Vietnamese translation
|
||||||
|
|
||||||
|
[@jimmyorz](https://github.com/jimmyorz) for Traditional Chinese translation
|
||||||
|
|
||||||
[@jk@mastodon.social](https://mastodon.social/@jk) for the famous Mastodon boop sound
|
[@jk@mastodon.social](https://mastodon.social/@jk) for the famous Mastodon boop sound
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "tooot",
|
"name": "tooot",
|
||||||
"version": "4.5.0",
|
"version": "4.5.1",
|
||||||
"description": "tooot for Mastodon",
|
"description": "tooot for Mastodon",
|
||||||
"author": "xmflsct <me@xmflsct.com>",
|
"author": "xmflsct <me@xmflsct.com>",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { ActionSheetProvider } from '@expo/react-native-action-sheet'
|
import { ActionSheetProvider } from '@expo/react-native-action-sheet'
|
||||||
|
import getLanguage from '@helpers/getLanguage'
|
||||||
import queryClient from '@helpers/queryClient'
|
import queryClient from '@helpers/queryClient'
|
||||||
import i18n from '@root/i18n/i18n'
|
import i18n from '@root/i18n/i18n'
|
||||||
import Screens from '@root/Screens'
|
import Screens from '@root/Screens'
|
||||||
|
@ -12,7 +13,7 @@ import timezone from '@root/startup/timezone'
|
||||||
import { persistor, store } from '@root/store'
|
import { persistor, store } from '@root/store'
|
||||||
import * as Sentry from '@sentry/react-native'
|
import * as Sentry from '@sentry/react-native'
|
||||||
import AccessibilityManager from '@utils/accessibility/AccessibilityManager'
|
import AccessibilityManager from '@utils/accessibility/AccessibilityManager'
|
||||||
import { changeLanguage, getSettingsLanguage } from '@utils/slices/settingsSlice'
|
import { changeLanguage } from '@utils/slices/settingsSlice'
|
||||||
import ThemeManager from '@utils/styles/ThemeManager'
|
import ThemeManager from '@utils/styles/ThemeManager'
|
||||||
import * as Localization from 'expo-localization'
|
import * as Localization from 'expo-localization'
|
||||||
import * as SplashScreen from 'expo-splash-screen'
|
import * as SplashScreen from 'expo-splash-screen'
|
||||||
|
@ -83,10 +84,7 @@ const App: React.FC = () => {
|
||||||
if (bootstrapped) {
|
if (bootstrapped) {
|
||||||
log('log', 'App', 'loading actual app :)')
|
log('log', 'App', 'loading actual app :)')
|
||||||
log('log', 'App', `Locale: ${Localization.locale}`)
|
log('log', 'App', `Locale: ${Localization.locale}`)
|
||||||
const language =
|
const language = getLanguage()
|
||||||
Platform.OS === 'ios'
|
|
||||||
? Localization.locale
|
|
||||||
: getSettingsLanguage(store.getState())
|
|
||||||
if (!language) {
|
if (!language) {
|
||||||
if (Platform.OS !== 'ios') {
|
if (Platform.OS !== 'ios') {
|
||||||
store.dispatch(changeLanguage('en'))
|
store.dispatch(changeLanguage('en'))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import Constants from 'expo-constants'
|
|
||||||
import handleError, { ctx } from './handleError'
|
import handleError, { ctx } from './handleError'
|
||||||
|
import { userAgent } from './helpers'
|
||||||
|
|
||||||
export type Params = {
|
export type Params = {
|
||||||
method: 'get' | 'post' | 'put' | 'delete'
|
method: 'get' | 'post' | 'put' | 'delete'
|
||||||
|
@ -44,8 +44,8 @@ const apiGeneral = async <T = unknown>({
|
||||||
body && body instanceof FormData
|
body && body instanceof FormData
|
||||||
? 'multipart/form-data'
|
? 'multipart/form-data'
|
||||||
: 'application/json',
|
: 'application/json',
|
||||||
'User-Agent': `tooot/${Constants.expoConfig?.version}`,
|
|
||||||
Accept: '*/*',
|
Accept: '*/*',
|
||||||
|
...userAgent,
|
||||||
...headers
|
...headers
|
||||||
},
|
},
|
||||||
...(body && { data: body })
|
...(body && { data: body })
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import Constants from "expo-constants"
|
||||||
|
import { Platform } from "react-native"
|
||||||
|
|
||||||
|
const userAgent = { 'User-Agent': `tooot/${Constants.expoConfig?.version} ${Platform.OS}/${Platform.Version}` }
|
||||||
|
|
||||||
|
export { userAgent }
|
|
@ -1,8 +1,8 @@
|
||||||
import { RootState } from '@root/store'
|
import { RootState } from '@root/store'
|
||||||
import axios, { AxiosRequestConfig } from 'axios'
|
import axios, { AxiosRequestConfig } from 'axios'
|
||||||
import Constants from 'expo-constants'
|
|
||||||
import li from 'li'
|
import li from 'li'
|
||||||
import handleError, { ctx } from './handleError'
|
import handleError, { ctx } from './handleError'
|
||||||
|
import { userAgent } from './helpers'
|
||||||
|
|
||||||
export type Params = {
|
export type Params = {
|
||||||
method: 'get' | 'post' | 'put' | 'delete' | 'patch'
|
method: 'get' | 'post' | 'put' | 'delete' | 'patch'
|
||||||
|
@ -53,13 +53,13 @@ const apiInstance = async <T = unknown>({
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
ctx.bgGreen.bold(' API instance ') +
|
ctx.bgGreen.bold(' API instance ') +
|
||||||
' ' +
|
' ' +
|
||||||
domain +
|
domain +
|
||||||
' ' +
|
' ' +
|
||||||
method +
|
method +
|
||||||
ctx.green(' -> ') +
|
ctx.green(' -> ') +
|
||||||
`/${url}` +
|
`/${url}` +
|
||||||
(params ? ctx.green(' -> ') : ''),
|
(params ? ctx.green(' -> ') : ''),
|
||||||
params ? params : ''
|
params ? params : ''
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -74,8 +74,8 @@ const apiInstance = async <T = unknown>({
|
||||||
body && body instanceof FormData
|
body && body instanceof FormData
|
||||||
? 'multipart/form-data'
|
? 'multipart/form-data'
|
||||||
: 'application/json',
|
: 'application/json',
|
||||||
'User-Agent': `tooot/${Constants.expoConfig?.version}`,
|
|
||||||
Accept: '*/*',
|
Accept: '*/*',
|
||||||
|
...userAgent,
|
||||||
...headers,
|
...headers,
|
||||||
...(token && {
|
...(token && {
|
||||||
Authorization: `Bearer ${token}`
|
Authorization: `Bearer ${token}`
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import * as Sentry from '@sentry/react-native'
|
import * as Sentry from '@sentry/react-native'
|
||||||
import { mapEnvironment } from '@utils/checkEnvironment'
|
import { mapEnvironment } from '@utils/checkEnvironment'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import Constants from 'expo-constants'
|
|
||||||
import handleError, { ctx } from './handleError'
|
import handleError, { ctx } from './handleError'
|
||||||
|
import { userAgent } from './helpers'
|
||||||
|
|
||||||
export type Params = {
|
export type Params = {
|
||||||
method: 'get' | 'post' | 'put' | 'delete'
|
method: 'get' | 'post' | 'put' | 'delete'
|
||||||
|
@ -50,13 +50,11 @@ const apiTooot = async <T = unknown>({
|
||||||
body && body instanceof FormData
|
body && body instanceof FormData
|
||||||
? 'multipart/form-data'
|
? 'multipart/form-data'
|
||||||
: 'application/json',
|
: 'application/json',
|
||||||
'User-Agent': `tooot/${Constants.expoConfig?.version}`,
|
|
||||||
Accept: '*/*',
|
Accept: '*/*',
|
||||||
|
...userAgent,
|
||||||
...headers
|
...headers
|
||||||
},
|
},
|
||||||
...(body && { data: body }),
|
...(body && { data: body })
|
||||||
validateStatus: status =>
|
|
||||||
url.includes('translate') ? status < 500 : status === 200
|
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
|
|
|
@ -174,6 +174,12 @@ const contextMenuAccount = ({
|
||||||
id: accountId,
|
id: accountId,
|
||||||
payload: { property: 'reports' }
|
payload: { property: 'reports' }
|
||||||
})
|
})
|
||||||
|
mutation.mutate({
|
||||||
|
type: 'updateAccountProperty',
|
||||||
|
queryKey,
|
||||||
|
id: accountId,
|
||||||
|
payload: { property: 'block', currentValue: false }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import analytics from '@components/analytics'
|
import analytics from '@components/analytics'
|
||||||
import { ParseHTML } from '@components/Parse'
|
import { ParseHTML } from '@components/Parse'
|
||||||
import CustomText from '@components/Text'
|
import CustomText from '@components/Text'
|
||||||
|
import getLanguage from '@helpers/getLanguage'
|
||||||
import { useTranslateQuery } from '@utils/queryHooks/translate'
|
import { useTranslateQuery } from '@utils/queryHooks/translate'
|
||||||
import { getSettingsLanguage } from '@utils/slices/settingsSlice'
|
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import * as Localization from 'expo-localization'
|
import * as Localization from 'expo-localization'
|
||||||
|
@ -11,14 +11,10 @@ import { useTranslation } from 'react-i18next'
|
||||||
import { Pressable } from 'react-native'
|
import { Pressable } from 'react-native'
|
||||||
import { Circle } from 'react-native-animated-spinkit'
|
import { Circle } from 'react-native-animated-spinkit'
|
||||||
import detectLanguage from 'react-native-language-detection'
|
import detectLanguage from 'react-native-language-detection'
|
||||||
import { useSelector } from 'react-redux'
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
highlighted: boolean
|
highlighted: boolean
|
||||||
status: Pick<
|
status: Pick<Mastodon.Status, 'language' | 'spoiler_text' | 'content' | 'emojis'>
|
||||||
Mastodon.Status,
|
|
||||||
'language' | 'spoiler_text' | 'content' | 'emojis'
|
|
||||||
>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimelineTranslate = React.memo(
|
const TimelineTranslate = React.memo(
|
||||||
|
@ -30,9 +26,7 @@ const TimelineTranslate = React.memo(
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const text = status.spoiler_text
|
const text = status.spoiler_text ? [status.spoiler_text, status.content] : [status.content]
|
||||||
? [status.spoiler_text, status.content]
|
|
||||||
: [status.content]
|
|
||||||
|
|
||||||
for (const i in text) {
|
for (const i in text) {
|
||||||
for (const emoji of status.emojis) {
|
for (const emoji of status.emojis) {
|
||||||
|
@ -56,7 +50,7 @@ const TimelineTranslate = React.memo(
|
||||||
detect()
|
detect()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const settingsLanguage = useSelector(getSettingsLanguage)
|
const settingsLanguage = getLanguage()
|
||||||
const targetLanguage = settingsLanguage?.startsWith('en')
|
const targetLanguage = settingsLanguage?.startsWith('en')
|
||||||
? Localization.locale || settingsLanguage || 'en'
|
? Localization.locale || settingsLanguage || 'en'
|
||||||
: settingsLanguage || Localization.locale || 'en'
|
: settingsLanguage || Localization.locale || 'en'
|
||||||
|
@ -107,12 +101,7 @@ const TimelineTranslate = React.memo(
|
||||||
<CustomText
|
<CustomText
|
||||||
fontStyle='M'
|
fontStyle='M'
|
||||||
style={{
|
style={{
|
||||||
color:
|
color: isLoading || isSuccess ? colors.secondary : isError ? colors.red : colors.blue
|
||||||
isLoading || isSuccess
|
|
||||||
? colors.secondary
|
|
||||||
: isError
|
|
||||||
? colors.red
|
|
||||||
: colors.blue
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isError
|
{isError
|
||||||
|
@ -127,9 +116,7 @@ const TimelineTranslate = React.memo(
|
||||||
: t('shared.translate.default')}
|
: t('shared.translate.default')}
|
||||||
</CustomText>
|
</CustomText>
|
||||||
<CustomText>
|
<CustomText>
|
||||||
{__DEV__
|
{__DEV__ ? ` Source: ${detectedLanguage}; Target: ${targetLanguage}` : undefined}
|
||||||
? ` Source: ${detectedLanguage}; Target: ${targetLanguage}`
|
|
||||||
: undefined}
|
|
||||||
</CustomText>
|
</CustomText>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Circle
|
<Circle
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { store } from '@root/store'
|
||||||
|
import { getSettingsLanguage } from '@utils/slices/settingsSlice'
|
||||||
|
import * as Localization from 'expo-localization'
|
||||||
|
import { Platform } from "react-native"
|
||||||
|
|
||||||
|
const getLanguage = (): string => {
|
||||||
|
return Platform.OS === 'ios'
|
||||||
|
? Localization.locale
|
||||||
|
: getSettingsLanguage(store.getState())
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getLanguage
|
|
@ -2,7 +2,7 @@
|
||||||
"HTML": {
|
"HTML": {
|
||||||
"accessibilityHint": "Nhấn để mở rộng hoặc thu gọn nội dung",
|
"accessibilityHint": "Nhấn để mở rộng hoặc thu gọn nội dung",
|
||||||
"expanded": "{{hint}}{{moreLines}}",
|
"expanded": "{{hint}}{{moreLines}}",
|
||||||
"moreLines": "",
|
"moreLines": " ({{count}} dòng nữa)",
|
||||||
"defaultHint": "Tút dài"
|
"defaultHint": "Tút dài"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -40,9 +40,9 @@
|
||||||
"accessibilityLabel": "Đăng lại tút này",
|
"accessibilityLabel": "Đăng lại tút này",
|
||||||
"function": "Đăng lại tút",
|
"function": "Đăng lại tút",
|
||||||
"options": {
|
"options": {
|
||||||
"title": "",
|
"title": "Kiểu đăng lại",
|
||||||
"public": "",
|
"public": "Đăng lại công khai",
|
||||||
"unlisted": ""
|
"unlisted": "Đăng lại hạn chế"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"favourited": {
|
"favourited": {
|
||||||
|
|
|
@ -14,13 +14,13 @@
|
||||||
"base": "將使用系統內建的瀏覽器來登入,tooot 無法讀取您的帳號資訊。"
|
"base": "將使用系統內建的瀏覽器來登入,tooot 無法讀取您的帳號資訊。"
|
||||||
},
|
},
|
||||||
"terms": {
|
"terms": {
|
||||||
"base": "登入則表示您同意<0>隱私條款</0>和<1>服務條款</1>。"
|
"base": "登入則表示您同意<0>隱私政策</0>和<1>使用條款</1>。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"update": {
|
"update": {
|
||||||
"alert": {
|
"alert": {
|
||||||
"title": "已登入站點",
|
"title": "已登入站點",
|
||||||
"message": "您可以多登入其他的帳號,已登入的帳號會被保留",
|
"message": "您可以登入其它的帳號,已登入的帳號會被保留",
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"cancel": "$t(common:buttons.cancel)",
|
"cancel": "$t(common:buttons.cancel)",
|
||||||
"continue": "繼續"
|
"continue": "繼續"
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"title": "選擇媒體來源",
|
"title": "選擇媒體來源",
|
||||||
"message": "媒體 EXIF 資料不會被上傳",
|
"message": "媒體 Exif 資訊不會被上傳",
|
||||||
"options": {
|
"options": {
|
||||||
"image": "上傳圖片",
|
"image": "上傳圖片",
|
||||||
"image_max": "上傳圖片(最多 {{max}})",
|
"image_max": "上傳圖片(最多 {{max}} 張)",
|
||||||
"video": "上傳影片",
|
"video": "上傳影片",
|
||||||
"video_max": "上傳影片(最多 {{max}})"
|
"video_max": "上傳影片(最多 {{max}} 個)"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,9 +22,9 @@
|
||||||
"actioned": {
|
"actioned": {
|
||||||
"pinned": "置頂",
|
"pinned": "置頂",
|
||||||
"favourite": "{{name}} 把您的嘟文加入了最愛",
|
"favourite": "{{name}} 把您的嘟文加入了最愛",
|
||||||
"status": "{{name}} 正發了嘟",
|
"status": "{{name}} 剛剛嘟文",
|
||||||
"follow": "{{name}} 追隨您了",
|
"follow": "{{name}} 跟隨了您",
|
||||||
"follow_request": "{{name}} 要求您允許他的追隨",
|
"follow_request": "{{name}} 要求跟隨您",
|
||||||
"poll": "您曾投過的投票已經結束",
|
"poll": "您曾投過的投票已經結束",
|
||||||
"reblog": {
|
"reblog": {
|
||||||
"default": "{{name}} 轉嘟了",
|
"default": "{{name}} 轉嘟了",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"tabs": {
|
"tabs": {
|
||||||
"local": {
|
"local": {
|
||||||
"name": "追隨中"
|
"name": "跟隨中"
|
||||||
},
|
},
|
||||||
"public": {
|
"public": {
|
||||||
"name": "",
|
"name": "",
|
||||||
|
@ -47,16 +47,16 @@
|
||||||
"name": "語言"
|
"name": "語言"
|
||||||
},
|
},
|
||||||
"lists": {
|
"lists": {
|
||||||
"name": "清單"
|
"name": "列表"
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"name": "清單: {{list}}"
|
"name": "列表:{{list}}"
|
||||||
},
|
},
|
||||||
"push": {
|
"push": {
|
||||||
"name": "推播通知"
|
"name": "推播通知"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"name": "編輯個人資料"
|
"name": "編輯個人檔案"
|
||||||
},
|
},
|
||||||
"profileName": {
|
"profileName": {
|
||||||
"name": "編輯顯示名稱"
|
"name": "編輯顯示名稱"
|
||||||
|
@ -71,20 +71,20 @@
|
||||||
"name": "App 設定"
|
"name": "App 設定"
|
||||||
},
|
},
|
||||||
"webSettings": {
|
"webSettings": {
|
||||||
"name": "更多的帳號設定"
|
"name": "更多帳號設定"
|
||||||
},
|
},
|
||||||
"switch": {
|
"switch": {
|
||||||
"name": "切換帳號"
|
"name": "切換帳號"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fontSize": {
|
"fontSize": {
|
||||||
"demo": "<p>這是一條測試用的嘟文😊。以下是可供選擇的字體大小,從小至超大。<br /><br />這個設定僅會調整嘟文的本身字體大小,不影響其它字體大小。</p>",
|
"demo": "<p>這是一條測試用的嘟文😊。以下是可供選擇的字體大小,從小到超大。<br /><br />這個設定僅會調整嘟文本身的字體大小,不影響其它介面的字體大小。</p>",
|
||||||
"sizes": {
|
"sizes": {
|
||||||
"S": "小",
|
"S": "小",
|
||||||
"M": "M - 預設",
|
"M": "中 (預設)",
|
||||||
"L": "大",
|
"L": "大",
|
||||||
"XL": "超大",
|
"XL": "特大",
|
||||||
"XXL": "特大"
|
"XXL": "超大"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
|
@ -277,7 +277,7 @@
|
||||||
},
|
},
|
||||||
"analytics": {
|
"analytics": {
|
||||||
"heading": "幫助我們改善",
|
"heading": "幫助我們改善",
|
||||||
"description": "僅收集不與使用者關聯的資料"
|
"description": "僅收集不與使用者相關聯的資料"
|
||||||
},
|
},
|
||||||
"version": "Version v{{version}}",
|
"version": "Version v{{version}}",
|
||||||
"instanceVersion": "Mastodon version v{{version}}"
|
"instanceVersion": "Mastodon version v{{version}}"
|
||||||
|
|
|
@ -387,7 +387,7 @@ const mutationFunction = async (params: MutationVarsTimeline) => {
|
||||||
url: `statuses/${params.id}/${
|
url: `statuses/${params.id}/${
|
||||||
params.payload.currentValue ? 'un' : ''
|
params.payload.currentValue ? 'un' : ''
|
||||||
}${MapPropertyToUrl[params.payload.property]}`,
|
}${MapPropertyToUrl[params.payload.property]}`,
|
||||||
body
|
...(params.payload.property === 'reblogged' && { body })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case 'updateAccountProperty':
|
case 'updateAccountProperty':
|
||||||
|
|
Loading…
Reference in New Issue