Skip to content

Commit

Permalink
Merge branch 'main' into candidate
Browse files Browse the repository at this point in the history
  • Loading branch information
xmflsct committed Mar 13, 2023
2 parents a336658 + 4e620f8 commit 6e316f0
Show file tree
Hide file tree
Showing 18 changed files with 298 additions and 87 deletions.
1 change: 0 additions & 1 deletion fastlane/metadata/en-US/release_notes.txt
@@ -1,2 +1 @@
Enjoy toooting! This version includes following improvements and fixes:
- Added Belarusian language
1 change: 0 additions & 1 deletion fastlane/metadata/zh-Hans/release_notes.txt
@@ -1,2 +1 @@
toooting愉快!此版本包括以下改进和修复:
- 新增白俄罗斯语
4 changes: 1 addition & 3 deletions ios/tooot/AppDelegate.h
@@ -1,9 +1,7 @@
#import <Foundation/Foundation.h>
#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>

#import <Expo/Expo.h>

@interface AppDelegate : RCTAppDelegate
@interface AppDelegate : EXAppDelegateWrapper

@end
18 changes: 18 additions & 0 deletions ios/tooot/AppDelegate.mm
Expand Up @@ -51,4 +51,22 @@ - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull N
restorationHandler:restorationHandler];
}

// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
return [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
}

// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

@end
4 changes: 1 addition & 3 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "tooot",
"version": "4.9.1",
"version": "4.9.2",
"description": "tooot for Mastodon",
"author": "xmflsct <[email protected]>",
"license": "GPL-3.0-or-later",
Expand Down Expand Up @@ -88,7 +88,6 @@
"react-native-swipe-list-view": "^3.2.9",
"react-native-tab-view": "^3.5.1",
"rn-placeholder": "^3.0.3",
"url-parse": "^1.5.10",
"zeego": "^1.3.1"
},
"devDependencies": {
Expand All @@ -102,7 +101,6 @@
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@types/react-native-share-menu": "^5.0.2",
"@types/url-parse": "^1.4.8",
"babel-plugin-module-resolver": "^5.0.0",
"babel-plugin-transform-remove-console": "^6.9.4",
"chalk": "^4.1.2",
Expand Down
6 changes: 3 additions & 3 deletions src/components/Instance/index.tsx
Expand Up @@ -21,14 +21,14 @@ import { useTheme } from '@utils/styles/ThemeManager'
import * as AuthSession from 'expo-auth-session'
import * as Crypto from 'expo-crypto'
import { Image } from 'expo-image'
import * as Linking from 'expo-linking'
import * as WebBrowser from 'expo-web-browser'
import { debounce } from 'lodash'
import React, { RefObject, useCallback, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { Alert, KeyboardAvoidingView, Platform, TextInput, View } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
import { fromByteArray } from 'react-native-quick-base64'
import parse from 'url-parse'
import CustomText from '../Text'

export interface Props {
Expand All @@ -51,7 +51,7 @@ const ComponentInstance: React.FC<Props> = ({
const whitelisted: boolean =
!!domain.length &&
!!errorCode &&
!!(parse(`https://${domain}/`).hostname === domain) &&
!!(Linking.parse(`https://${domain}/`).hostname === domain) &&
errorCode === 401

const instanceQuery = useInstanceQuery({
Expand Down Expand Up @@ -129,7 +129,7 @@ const ComponentInstance: React.FC<Props> = ({
(instanceQuery.data as Mastodon.Instance_V2)?.domain ||
instanceQuery.data?.account_domain ||
((instanceQuery.data as Mastodon.Instance_V1)?.uri
? parse((instanceQuery.data as Mastodon.Instance_V1).uri).hostname
? Linking.parse((instanceQuery.data as Mastodon.Instance_V1).uri).hostname
: undefined) ||
(instanceQuery.data as Mastodon.Instance_V1)?.uri,
'auth.account.avatar_static': avatar_static,
Expand Down
125 changes: 125 additions & 0 deletions src/components/Timeline/Shared/Card/Neodb.tsx
@@ -0,0 +1,125 @@
import GracefullyImage from '@components/GracefullyImage'
import openLink from '@components/openLink'
import CustomText from '@components/Text'
import { useNeodbQuery } from '@utils/queryHooks/neodb'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import * as Linking from 'expo-linking'
import { Pressable, View } from 'react-native'

export const CardNeodb = ({ card }: { card: Mastodon.Card }) => {
const { colors } = useTheme()

const segments = Linking.parse(card.url).path?.split('/')
if (!segments || !(segments[0] === 'movie' || segments[0] === 'book')) return null

const { data } = useNeodbQuery({ path: `${segments[0]}/${segments[1]}` })

if (!data) return null

switch (segments[0]) {
case 'movie':
return (
<Pressable
style={{
marginTop: StyleConstants.Spacing.S,
backgroundColor: colors.shimmerDefault,
borderRadius: StyleConstants.BorderRadius,
padding: StyleConstants.Spacing.S,
flexDirection: 'row'
}}
onPress={() => openLink(card.url)}
>
<GracefullyImage
sources={{ default: { uri: `https://neodb.social${data.image}` } }}
dimension={{
width: StyleConstants.Font.LineHeight.M * 4,
height: StyleConstants.Font.LineHeight.M * 5
}}
style={{ marginRight: StyleConstants.Spacing.S }}
imageStyle={{ borderRadius: StyleConstants.BorderRadius / 2 }}
dim
/>
<View style={{ flex: 1, gap: StyleConstants.Spacing.S }}>
<CustomText
fontStyle='S'
fontWeight='Bold'
style={{ color: colors.primaryDefault }}
numberOfLines={3}
>
{[
data.data.title,
data.data.orig_title,
data.data.year ? `(${data.data.year})` : null
]
.filter(d => d)
.join(' ')}
</CustomText>
<CustomText fontStyle='S' style={{ color: colors.secondary }} numberOfLines={2}>
{[
data.data.duration ? `${data.data.duration}分钟` : null,
data.data.area?.join(' '),
data.data.genre?.join(' '),
data.data.director?.join(' ')
]
.filter(d => d)
.join(' / ')}
</CustomText>
</View>
</Pressable>
)
case 'book':
return (
<Pressable
style={{
marginTop: StyleConstants.Spacing.S,
backgroundColor: colors.shimmerDefault,
borderRadius: StyleConstants.BorderRadius,
padding: StyleConstants.Spacing.S,
flexDirection: 'row'
}}
onPress={() => openLink(card.url)}
>
<GracefullyImage
sources={{ default: { uri: `https://neodb.social${data.image}` } }}
dimension={{
width: StyleConstants.Font.LineHeight.M * 4,
height: StyleConstants.Font.LineHeight.M * 5
}}
style={{ marginRight: StyleConstants.Spacing.S }}
imageStyle={{ borderRadius: StyleConstants.BorderRadius / 2 }}
dim
/>
<View style={{ flex: 1, gap: StyleConstants.Spacing.S }}>
<CustomText
fontStyle='S'
fontWeight='Bold'
style={{ color: colors.primaryDefault }}
numberOfLines={3}
>
{[
data.data.title,
data.data.pub_year && data.data.pub_month
? `(${data.data.pub_year}${data.data.pub_month}月)`
: null
]
.filter(d => d)
.join(' ')}
</CustomText>
<CustomText fontStyle='S' style={{ color: colors.secondary }} numberOfLines={2}>
{[
data.data.author?.join(' '),
data.data.language,
data.data.pages ? `${data.data.pages}页` : null,
data.data.pub_house
]
.filter(d => d)
.join(' / ')}
</CustomText>
</View>
</Pressable>
)
default:
return null
}
}
Expand Up @@ -11,14 +11,21 @@ import { useStatusQuery } from '@utils/queryHooks/status'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, View } from 'react-native'
import TimelineDefault from '../Default'
import StatusContext from './Context'
import TimelineDefault from '../../Default'
import StatusContext from '../Context'
import { CardNeodb } from './Neodb'

const TimelineCard: React.FC = () => {
const { status, spoilerHidden, disableDetails, inThread } = useContext(StatusContext)
if (!status || !status.card) return null

const { i18n } = useTranslation()
if (status.card.url.includes('://neodb.social/') && i18n.language === 'zh-hans') {
return <CardNeodb card={status.card} />
}

const { colors } = useTheme()
const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()

Expand Down
6 changes: 3 additions & 3 deletions src/components/contextMenu/instance.ts
Expand Up @@ -2,9 +2,9 @@ import { displayMessage } from '@components/Message'
import { useQueryClient } from '@tanstack/react-query'
import { QueryKeyTimeline, useTimelineMutation } from '@utils/queryHooks/timeline'
import { getAccountStorage } from '@utils/storage/actions'
import * as Linking from 'expo-linking'
import { useTranslation } from 'react-i18next'
import { Alert } from 'react-native'
import parse from 'url-parse'

const menuInstance = ({
status,
Expand Down Expand Up @@ -32,9 +32,9 @@ const menuInstance = ({

const menus: ContextMenu = []

const instance = parse(status.uri).hostname
const instance = Linking.parse(status.uri).hostname

if (instance !== getAccountStorage.string('auth.domain')) {
if (instance && instance !== getAccountStorage.string('auth.domain')) {
menus.push([
{
type: 'item',
Expand Down
4 changes: 2 additions & 2 deletions src/screens/Tabs/Me/FollowedTags.tsx
Expand Up @@ -60,8 +60,8 @@ const TabMeFollowedTags: React.FC<TabMeStackScreenProps<'Tab-Me-FollowedTags'>>
<Button
type='text'
content={t('componentContextMenu:hashtag.follow.action', {
defaultValue: 'fase',
context: 'false'
defaultValue: 'true',
context: 'true'
})}
onPress={() => mutation.mutate({ tag_name: item.name, to: !item.following })}
/>
Expand Down
29 changes: 3 additions & 26 deletions src/screens/index.tsx
Expand Up @@ -7,6 +7,7 @@ import ScreenAnnouncements from '@screens/Announcements'
import ScreenCompose from '@screens/Compose'
import ScreenImagesViewer from '@screens/ImageViewer'
import ScreenTabs from '@screens/Tabs'
import { useLinking } from '@utils/linking'
import navigationRef from '@utils/navigation/navigationRef'
import { RootStackParamList } from '@utils/navigation/navigators'
import pushUseConnect from '@utils/push/useConnect'
Expand Down Expand Up @@ -78,32 +79,8 @@ const Screens: React.FC = () => {
}
}

// Deep linking for compose
const [deeplinked, setDeeplinked] = useState(false)
useEffect(() => {
const getUrlAsync = async () => {
setDeeplinked(true)

const initialUrl = await Linking.parseInitialURLAsync()

if (initialUrl.path) {
const paths = initialUrl.path.split('/')

if (paths.length) {
if (accountActive && !accounts?.includes(accountActive)) {
setAccount(accountActive)
}
}
}

if (initialUrl.hostname === 'compose') {
navigationRef.navigate('Screen-Compose')
}
}
if (!deeplinked) {
getUrlAsync()
}
}, [accounts, accountActive, deeplinked])
// Deep linking
useLinking()

// Share Extension
const handleShare = (
Expand Down
34 changes: 18 additions & 16 deletions src/utils/api/helpers/connect.ts
Expand Up @@ -2,7 +2,7 @@ import { mapEnvironment } from '@utils/helpers/checkEnvironment'
import { GLOBAL } from '@utils/storage'
import { setGlobalStorage } from '@utils/storage/actions'
import axios from 'axios'
import parse from 'url-parse'
import * as Linking from 'expo-linking'
import { userAgent } from '.'

const list = [
Expand Down Expand Up @@ -86,21 +86,23 @@ export const connectMedia = (args?: {
}): { uri?: string; headers?: { 'x-tooot-domain': string } } => {
if (GLOBAL.connect) {
if (args?.uri) {
const host = parse(args.uri).host
return {
...args,
uri: args.uri.replace(
host,
CONNECT_DOMAIN(
args.uri
.split('')
.map(i => i.charCodeAt(0))
.reduce((a, b) => a + b, 0) %
(list.length + 1)
)
),
headers: { 'x-tooot-domain': host }
}
const host = Linking.parse(args.uri).hostname
return host
? {
...args,
uri: args.uri.replace(
host,
CONNECT_DOMAIN(
args.uri
.split('')
.map(i => i.charCodeAt(0))
.reduce((a, b) => a + b, 0) %
(list.length + 1)
)
),
headers: { 'x-tooot-domain': host }
}
: { ...args }
} else {
return { ...args }
}
Expand Down

0 comments on commit 6e316f0

Please sign in to comment.