Merge branch 'main' into candidate

This commit is contained in:
xmflsct 2023-06-22 00:07:27 +02:00
commit 4a60d81e45
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
29 changed files with 2077 additions and 1890 deletions

View File

@ -0,0 +1,74 @@
diff --git a/Libraries/Utilities/setAndForwardRef.js b/Libraries/Utilities/setAndForwardRef.js
new file mode 100644
index 0000000000000000000000000000000000000000..e67b530b9a933b68e219e2b8cec2a66dc8f51323
--- /dev/null
+++ b/Libraries/Utilities/setAndForwardRef.js
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @format
+ * @flow
+ */
+
+'use strict'
+
+import type { ElementRef, Ref } from 'react'
+
+type Args = $ReadOnly<{|
+ getForwardedRef: () => ?Ref<any>,
+ setLocalRef: (ref: ElementRef<any>) => mixed
+|}>
+
+/**
+ * This is a helper function for when a component needs to be able to forward a ref
+ * to a child component, but still needs to have access to that component as part of
+ * its implementation.
+ *
+ * Its main use case is in wrappers for native components.
+ *
+ * Usage:
+ *
+ * class MyView extends React.Component {
+ * _nativeRef = null;
+ *
+ * _setNativeRef = setAndForwardRef({
+ * getForwardedRef: () => this.props.forwardedRef,
+ * setLocalRef: ref => {
+ * this._nativeRef = ref;
+ * },
+ * });
+ *
+ * render() {
+ * return <View ref={this._setNativeRef} />;
+ * }
+ * }
+ *
+ * const MyViewWithRef = React.forwardRef((props, ref) => (
+ * <MyView {...props} forwardedRef={ref} />
+ * ));
+ *
+ * module.exports = MyViewWithRef;
+ */
+
+function setAndForwardRef({ getForwardedRef, setLocalRef }: Args): (ref: ElementRef<any>) => void {
+ return function forwardRef(ref: ElementRef<any>) {
+ const forwardedRef = getForwardedRef()
+
+ setLocalRef(ref)
+
+ // Forward to user ref prop (if one has been specified)
+ if (typeof forwardedRef === 'function') {
+ // Handle function-based refs. String-based refs are handled as functions.
+ forwardedRef(ref)
+ } else if (typeof forwardedRef === 'object' && forwardedRef != null) {
+ // Handle createRef-based refs
+ forwardedRef.current = ref
+ }
+ }
+}
+
+module.exports = setAndForwardRef

View File

@ -1,6 +1,6 @@
source "https://rubygems.org"
gem "fastlane"
gem 'cocoapods'
gem 'cocoapods', '~> 1.12'
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)

View File

@ -2,8 +2,6 @@ apply plugin: "com.android.application"
apply plugin: "com.facebook.react"
apply plugin: 'com.google.gms.google-services'
import com.android.build.OutputFile
/**
* This is the configuration block to customize your React Native Android app.
* By default you don't need to apply any configuration, just uncomment the lines you need.
@ -15,8 +13,8 @@ react {
// root = file("../")
// The folder where the react-native NPM package is. Default is ../node_modules/react-native
// reactNativeDir = file("../node_modules/react-native")
// The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen
// codegenDir = file("../node_modules/react-native-codegen")
// The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
// codegenDir = file("../node_modules/@react-native/codegen")
// The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
// cliFile = file("../node_modules/react-native/cli.js")
/* Variants */
@ -51,14 +49,6 @@ react {
// hermesFlags = ["-O", "-output-source-map"]
}
/**
* Set this to true to create four separate APKs instead of one,
* one for each native architecture. This is useful if you don't
* use App Bundles (https://developer.android.com/guide/app-bundle/)
* and want to have separate APKs to upload to the Play Store.
*/
def enableSeparateBuildPerCPUArchitecture = false
/**
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
*/
@ -77,16 +67,6 @@ def enableProguardInReleaseBuilds = false
*/
def jscFlavor = 'org.webkit:android-jsc:+'
/**
* Private function to get the list of Native Architectures you want to build.
* This reads the value from reactNativeArchitectures in your gradle.properties
* file and works together with the --active-arch-only flag of react-native run-android.
*/
def reactNativeArchitectures() {
def value = project.getProperties().get("reactNativeArchitectures")
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}
android {
ndkVersion rootProject.ext.ndkVersion
@ -105,14 +85,6 @@ android {
versionCode 50
versionName "0.2"
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include (*reactNativeArchitectures())
}
}
signingConfigs {
debug {
storeFile file('debug.keystore')
@ -133,28 +105,9 @@ android {
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// https://developer.android.com/studio/build/configure-apk-splits.html
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
defaultConfig.versionCode * 1000 + versionCodes.get(abi)
}
}
}
}
dependencies {
implementation ("androidx.lifecycle:lifecycle-runtime-ktx:2.3.0") {
force = true
}
def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true";
def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true";
@ -182,7 +135,6 @@ dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.squareup.okhttp3', module:'okhttp'

View File

@ -34,9 +34,6 @@ public class MainActivity extends ReactActivity {
this,
getMainComponentName(),
// If you opted-in for the New Architecture, we enable the Fabric Renderer.
DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled
// If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18).
DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled
);
DefaultNewArchitectureEntryPoint.getFabricEnabled());
}
}

View File

@ -17,7 +17,7 @@ buildscript {
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle:7.4.1")
classpath("com.android.tools.build:gradle")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath 'com.google.gms:google-services:4.3.14'
}

View File

@ -26,7 +26,7 @@ android.useAndroidX=true
android.enableJetifier=true
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.176.1
FLIPPER_VERSION=0.182.0
# Use this property to specify which architecture you want to build.
# You can also override it from the CLI using

Binary file not shown.

View File

@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

16
android/gradlew vendored
View File

@ -37,10 +37,11 @@ do
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
@ -99,12 +100,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -157,6 +162,13 @@ set -- \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.

15
android/gradlew.bat vendored
View File

@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -74,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal

View File

@ -8,4 +8,4 @@ applyNativeModulesSettingsGradle(settings)
include ':app'
includeBuild('../node_modules/react-native-gradle-plugin')
includeBuild('../node_modules/@react-native/gradle-plugin')

View File

@ -1,26 +1,27 @@
module.exports = function (api) {
api.cache(false)
const plugins = [
'@babel/plugin-proposal-optional-chaining',
[
'module-resolver',
{
root: ['./'],
alias: {
'@components': './src/components',
'@i18n': './src/i18n',
'@screens': './src/screens',
'@utils': './src/utils'
return {
presets: ['babel-preset-expo'],
plugins: [
'@babel/plugin-proposal-optional-chaining',
[
'module-resolver',
{
root: ['./'],
alias: {
'@components': './src/components',
'@i18n': './src/i18n',
'@screens': './src/screens',
'@utils': './src/utils'
}
}
}
],
'react-native-reanimated/plugin'
]
if (process.env.NODE_ENV === 'production' || process.env.BABEL_ENV === 'production') {
plugins.push('transform-remove-console')
]
].concat(
process.env.NODE_ENV === 'production' || process.env.BABEL_ENV === 'production'
? ['transform-remove-console']
: [],
['react-native-reanimated/plugin']
)
}
return { presets: ['babel-preset-expo'], plugins }
}

View File

@ -1,3 +1 @@
Enjoy toooting! This version includes following improvements and fixes:
- Long press avatar in tab bar to quickly switch to another account
- Fix poll notifications wrongly greyed out

View File

@ -1,3 +1,2 @@
tooot-ing愉快此版本包括以下改进和修复
- 长按底部菜单头像快速切换账户
- 修复投票通知显示
- 新增neodb.social演出卡片

View File

@ -1,6 +1,11 @@
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
require File.join(File.dirname(`node --print "require.resolve('@react-native-community/cli-platform-ios/package.json')"`), "native_modules")
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip
platform :ios, '13.0'
prepare_react_native_project!
@ -33,8 +38,7 @@ target 'tooot' do
post_install do |installer|
react_native_post_install(
installer,
# Set `mac_catalyst_enabled` to `true` in order to apply patches
# necessary for Mac Catalyst builds
config[:reactNativePath],
:mac_catalyst_enabled => false
)
__apply_Xcode_12_5_M1_post_install_workaround(installer)

File diff suppressed because it is too large Load Diff

View File

@ -697,6 +697,8 @@
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"\"";
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
};
@ -753,6 +755,8 @@
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"\"";
MTL_ENABLE_DEBUG_INFO = NO;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;

View File

@ -22,16 +22,6 @@
#endif
}
/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
///
/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`.
- (BOOL)concurrentRootEnabled
{
return true;
}
// Linking API
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSString *urlString = url.absoluteString;

View File

@ -1,3 +1,11 @@
module.exports = {
transformer: { inlineRequires: true }
}
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config')
/**
* Metro configuration
* https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
const config = {};
module.exports = mergeConfig(getDefaultConfig(__dirname), config)

View File

@ -1,6 +1,6 @@
{
"name": "tooot",
"version": "4.9.5",
"version": "4.9.7",
"description": "tooot for Mastodon",
"author": "xmflsct <me@xmflsct.com>",
"license": "GPL-3.0-or-later",
@ -19,43 +19,43 @@
},
"dependencies": {
"@expo/react-native-action-sheet": "^4.0.1",
"@formatjs/intl-datetimeformat": "^6.8.0",
"@formatjs/intl-getcanonicallocales": "^2.2.0",
"@formatjs/intl-locale": "^3.3.0",
"@formatjs/intl-numberformat": "^8.5.0",
"@formatjs/intl-pluralrules": "^5.2.2",
"@formatjs/intl-relativetimeformat": "^11.2.2",
"@formatjs/intl-datetimeformat": "^6.10.0",
"@formatjs/intl-getcanonicallocales": "^2.2.1",
"@formatjs/intl-locale": "^3.3.2",
"@formatjs/intl-numberformat": "^8.7.0",
"@formatjs/intl-pluralrules": "^5.2.4",
"@formatjs/intl-relativetimeformat": "^11.2.4",
"@mattermost/react-native-paste-input": "^0.6.2",
"@neverdull-agency/expo-unlimited-secure-store": "^1.0.10",
"@react-native-async-storage/async-storage": "~1.17.11",
"@react-native-camera-roll/camera-roll": "^5.4.0",
"@react-native-camera-roll/camera-roll": "^5.6.0",
"@react-native-clipboard/clipboard": "^1.11.2",
"@react-native-community/blur": "^4.3.2",
"@react-native-community/netinfo": "9.3.10",
"@react-native-firebase/app": "^17.5.0",
"@react-native-menu/menu": "^0.7.3",
"@react-native-firebase/app": "^18.0.0",
"@react-native-menu/menu": "^0.8.0",
"@react-native-segmented-control/segmented-control": "^2.4.1",
"@react-navigation/bottom-tabs": "^6.5.7",
"@react-navigation/native": "^6.1.6",
"@react-navigation/native-stack": "^6.9.12",
"@react-navigation/stack": "^6.3.16",
"@sentry/react-native": "5.4.2",
"@sentry/react-native": "5.6.0",
"@sharcoux/slider": "^6.1.2",
"@tanstack/react-query": "^4.29.7",
"@tanstack/react-query": "^4.29.15",
"axios": "^1.4.0",
"diff": "^5.1.0",
"expo": "48.0.16",
"expo": "48.0.19",
"expo-auth-session": "^4.1.0",
"expo-av": "^13.3.0",
"expo-constants": "^14.3.0",
"expo-crypto": "^12.3.0",
"expo-file-system": "^15.3.0",
"expo-constants": "^14.4.0",
"expo-crypto": "^12.4.0",
"expo-file-system": "^15.4.0",
"expo-haptics": "^12.3.0",
"expo-image": "^1.2.2",
"expo-image": "^1.3.0",
"expo-linking": "^4.1.0",
"expo-localization": "^14.2.0",
"expo-notifications": "^0.18.1",
"expo-screen-capture": "5.1.1",
"expo-screen-capture": "5.2.0",
"expo-screen-orientation": "^5.2.0",
"expo-secure-store": "^12.1.1",
"expo-splash-screen": "^0.18.2",
@ -63,51 +63,52 @@
"expo-video-thumbnails": "^7.3.0",
"expo-web-browser": "~12.1.1",
"htmlparser2": "^9.0.0",
"i18next": "^22.4.15",
"i18next": "^23.2.2",
"linkify-it": "^4.0.1",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^12.2.2",
"react-intl": "^6.4.2",
"react-native": "^0.71.8",
"react-i18next": "^13.0.0",
"react-intl": "^6.4.4",
"react-native": "^0.72.0",
"react-native-flash-message": "^0.4.1",
"react-native-gesture-handler": "~2.10.0",
"react-native-image-picker": "^5.3.1",
"react-native-gesture-handler": "~2.12.0",
"react-native-image-picker": "^5.6.0",
"react-native-ios-context-menu": "^1.15.3",
"react-native-language-detection": "^0.2.2",
"react-native-mmkv": "~2.8.0",
"react-native-mmkv": "~2.9.0",
"react-native-pager-view": "^6.2.0",
"react-native-quick-base64": "^2.0.6",
"react-native-reanimated": "^3.1.0",
"react-native-reanimated": "^3.3.0",
"react-native-reanimated-zoom": "^0.3.3",
"react-native-safe-area-context": "^4.5.2",
"react-native-screens": "^3.20.0",
"react-native-safe-area-context": "^4.6.2",
"react-native-screens": "^3.21.1",
"react-native-share-menu": "^6.0.0",
"react-native-svg": "^13.9.0",
"react-native-swipe-list-view": "^3.2.9",
"react-native-tab-view": "^3.5.1",
"rn-placeholder": "^3.0.3",
"zeego": "^1.6.0"
"zeego": "^1.6.2"
},
"devDependencies": {
"@babel/core": "^7.21.8",
"@babel/core": "^7.22.5",
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
"@babel/preset-typescript": "^7.21.5",
"@babel/preset-typescript": "^7.22.5",
"@expo/config": "^8.0.4",
"@react-native/metro-config": "^0.72.6",
"@types/diff": "^5.0.3",
"@types/linkify-it": "^3.0.2",
"@types/lodash": "^4.14.194",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"@types/lodash": "^4.14.195",
"@types/react": "^18.2.13",
"@types/react-dom": "^18.2.6",
"@types/react-native-share-menu": "^5.0.2",
"babel-plugin-module-resolver": "^5.0.0",
"babel-plugin-transform-remove-console": "^6.9.4",
"chalk": "^4.1.2",
"deprecated-react-native-prop-types": "^4.1.0",
"dotenv": "^16.0.3",
"dotenv": "^16.3.1",
"react-native-clean-project": "^4.0.1",
"typescript": "^5.0.4"
"typescript": "^5.1.3"
},
"packageManager": "yarn@3.3.1",
"resolutions": {
@ -115,6 +116,7 @@
"react-native-share-menu@^6.0.0": "patch:react-native-share-menu@npm%3A6.0.0#./.yarn/patches/react-native-share-menu-npm-6.0.0-f1094c3204.patch",
"@types/react-native-share-menu@^5.0.2": "patch:@types/react-native-share-menu@npm%3A5.0.2#./.yarn/patches/@types-react-native-share-menu-npm-5.0.2-373df17ecc.patch",
"react-native-ios-context-menu@^1.15.1": "patch:react-native-ios-context-menu@npm%3A1.15.1#./.yarn/patches/react-native-ios-context-menu-npm-1.15.1-0034bfa5ba.patch",
"react-native-reanimated-zoom@^0.3.3": "patch:react-native-reanimated-zoom@npm%3A0.3.3#./.yarn/patches/react-native-reanimated-zoom-npm-0.3.3-bbb8d84109.patch"
"react-native-reanimated-zoom@^0.3.3": "patch:react-native-reanimated-zoom@npm%3A0.3.3#./.yarn/patches/react-native-reanimated-zoom-npm-0.3.3-bbb8d84109.patch",
"react-native@^0.72.0": "patch:react-native@npm%3A0.72.0#./.yarn/patches/react-native-npm-0.72.0-66f5fd62b3.patch"
}
}

View File

@ -52,7 +52,7 @@ const ComponentInstance: React.FC<Props> = ({
!!domain.length &&
!!errorCode &&
!!(Linking.parse(`https://${domain}/`).hostname === domain) &&
errorCode === 401
(errorCode === 401 || errorCode === 500)
const instanceQuery = useInstanceQuery({
domain,
@ -80,7 +80,7 @@ const ComponentInstance: React.FC<Props> = ({
clientSecret,
scopes: variables.scopes,
redirectUri,
usePKCE: !['pawoo.net', 'mao.mastodonhub.com'].includes(domain)
usePKCE: !['pawoo.net'].includes(domain)
})
await request.makeAuthUrlAsync(discovery)
@ -131,7 +131,8 @@ const ComponentInstance: React.FC<Props> = ({
((instanceQuery.data as Mastodon.Instance_V1)?.uri
? Linking.parse((instanceQuery.data as Mastodon.Instance_V1).uri).hostname
: undefined) ||
(instanceQuery.data as Mastodon.Instance_V1)?.uri,
(instanceQuery.data as Mastodon.Instance_V1)?.uri ||
domain,
'auth.account.avatar_static': avatar_static,
version: instanceQuery.data?.version || '0',
preferences: undefined,

View File

@ -10,6 +10,7 @@ import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, StyleSheet, View } from 'react-native'
import StatusContext from './Context'
import GracefullyImage from '@components/GracefullyImage'
export interface Props {
action: Mastodon.Notification['type'] | 'reblog' | 'pinned'
@ -34,11 +35,30 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
content={content}
emojis={account.emojis}
size='S'
style={{ color: action === 'admin.report' ? colors.red : colors.primaryDefault }}
style={{ flex: 1, color: action === 'admin.report' ? colors.red : colors.primaryDefault }}
/>
)
const onPress = () => navigation.push('Tab-Shared-Account', { account })
const miniAvatar = (
<GracefullyImage
sources={{
default: { uri: account.avatar },
static: { uri: account.avatar_static }
}}
dimension={{
width: StyleConstants.Avatar.XS / 1.5,
height: StyleConstants.Avatar.XS / 1.5
}}
style={{
borderRadius: 99,
overflow: 'hidden',
marginRight: StyleConstants.Spacing.S
}}
dim
withoutTransition
/>
)
const children = () => {
switch (action) {
@ -63,7 +83,8 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
color={iconColor}
style={styles.icon}
/>
<Pressable onPress={onPress}>
<Pressable onPress={onPress} style={{ flexDirection: 'row', alignItems: 'center' }}>
{miniAvatar}
{content(t('shared.actioned.favourite', { name }))}
</Pressable>
</>
@ -77,7 +98,8 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
color={iconColor}
style={styles.icon}
/>
<Pressable onPress={onPress}>
<Pressable onPress={onPress} style={{ flexDirection: 'row', alignItems: 'center' }}>
{miniAvatar}
{content(t('shared.actioned.follow', { name }))}
</Pressable>
</>
@ -91,7 +113,8 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
color={iconColor}
style={styles.icon}
/>
<Pressable onPress={onPress}>
<Pressable onPress={onPress} style={{ flexDirection: 'row', alignItems: 'center' }}>
{miniAvatar}
{content(t('shared.actioned.follow_request', { name }))}
</Pressable>
</>
@ -118,7 +141,8 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
color={iconColor}
style={styles.icon}
/>
<Pressable onPress={onPress}>
<Pressable onPress={onPress} style={{ flexDirection: 'row', alignItems: 'center' }}>
{!myself ? miniAvatar : null}
{content(
isNotification
? t('shared.actioned.reblog.notification', { name })
@ -138,7 +162,8 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
color={iconColor}
style={styles.icon}
/>
<Pressable onPress={onPress}>
<Pressable onPress={onPress} style={{ flexDirection: 'row', alignItems: 'center' }}>
{miniAvatar}
{content(t('shared.actioned.status', { name }))}
</Pressable>
</>

View File

@ -16,18 +16,19 @@ export type Props = {
export const CardNeodb: React.FC<Props> = ({ card }) => {
const { colors } = useTheme()
const segments = Linking.parse(card.url).path?.split('/')
if (!segments || !['movie', 'book', 'tv', 'game', 'album', 'podcast'].includes(segments[0]))
const path = Linking.parse(card.url).path
if (!path) return null
const segments = path?.split('/')
if (
!segments ||
!['movie', 'book', 'tv', 'game', 'album', 'podcast', 'performance'].includes(segments[0])
)
return null
const [headingLines, setHeadingLines] = useState(3)
const { data } = useNeodbQuery({
path:
segments[0] === 'tv' && segments[1] === 'season'
? `${segments[0]}${segments[1]}/${segments[2]}`
: `${segments[0]}/${segments[1]}`
})
const { data } = useNeodbQuery({ path })
if (!data) return null
@ -44,7 +45,13 @@ export const CardNeodb: React.FC<Props> = ({ card }) => {
>
{data.cover_image_url ? (
<GracefullyImage
sources={{ default: { uri: data.cover_image_url } }}
sources={{
default: {
uri: data.cover_image_url.startsWith('/')
? `https://neodb.social${data.cover_image_url}`
: data.cover_image_url
}
}}
dimension={{
width: StyleConstants.Font.LineHeight.M * 4,
height: StyleConstants.Font.LineHeight.M * 5
@ -162,6 +169,27 @@ export const CardNeodb: React.FC<Props> = ({ card }) => {
return (
<Content heading={[data.title]} details={[data.hosts.join(' '), data.genre.join(' ')]} />
)
case 'performance':
if (segments[1] === 'production') {
return (
<Content
heading={[data.display_title]}
details={[
data.opening_date,
data.director.join(' '),
data.playwright.join(' '),
data.composer.join(' ')
]}
/>
)
} else {
return (
<Content
heading={[data.title, data.orig_title]}
details={[data.genre.join(' '), data.playwright.join(' '), data.director.join(' ')]}
/>
)
}
default:
return null
}

View File

@ -39,6 +39,7 @@ const TimelineHeaderAndroid: React.FC = () => {
<View
style={{
padding: StyleConstants.Spacing.L,
paddingBottom: StyleConstants.Spacing.S,
backgroundColor: colors.backgroundDefault
}}
>

View File

@ -4,7 +4,7 @@
"title": "Hành động người dùng",
"following": {
"action_false": "Theo dõi người này",
"action_true": "Ngưng theo dõi người này"
"action_true": "Bỏ theo dõi người này"
},
"inLists": "Danh sách người ...",
"showBoosts": {
@ -57,7 +57,7 @@
"hashtag": {
"follow": {
"action_false": "Theo dõi",
"action_true": "Ngưng theo dõi"
"action_true": "Bỏ theo dõi"
},
"filter": {
"action": "Lọc hashtag..."

View File

@ -9,7 +9,7 @@
"error": "Xảy ra lỗi khi tải",
"blocked_by": "Đã chặn",
"blocking": "Bỏ chặn",
"following": "Ngưng theo dõi",
"following": "Bỏ theo dõi",
"requested": "Yêu cầu theo dõi",
"default": "Theo dõi"
}

View File

@ -59,7 +59,7 @@ const ScreenTabs = () => {
case 'Tab-Me':
return (
<>
<ContextMenu.Root onOpenChange={() => haptics('Light')}>
<ContextMenu.Root>
<ContextMenu.Trigger>
<View
key={avatarStatic}
@ -112,7 +112,6 @@ const ScreenTabs = () => {
onValueChange={async () => {
if (!account.active) {
await setAccount(account.key)
haptics('Light')
}
}}
>
@ -144,17 +143,7 @@ const ScreenTabs = () => {
{() => null}
</Tab.Screen>
<Tab.Screen name='Tab-Notifications' component={TabNotifications} />
<Tab.Screen
name='Tab-Me'
component={TabMe}
// listeners={({ navigation }) => ({
// tabLongPress: () => {
// haptics('Light')
// navigation.navigate('Tab-Me', { screen: 'Tab-Me-Root' })
// navigation.navigate('Tab-Me', { screen: 'Tab-Me-Switch' })
// }
// })}
/>
<Tab.Screen name='Tab-Me' component={TabMe} />
</Tab.Navigator>
)
}

View File

@ -34,5 +34,7 @@ const features: { feature: Features; version: number }[] = [
]
export const featureCheck = (feature: Features, v?: string): boolean =>
(features.find(f => f.feature === feature)?.version || 999) <=
parseFloat(v || getAccountStorage.string('version'))
v || getAccountStorage.string('version')
? (features.find(f => f.feature === feature)?.version || 999) <=
parseFloat(v || getAccountStorage.string('version'))
: false

2828
yarn.lock

File diff suppressed because it is too large Load Diff