1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00

Merge branch 'main' into release

This commit is contained in:
xmflsct
2023-07-16 23:10:35 +02:00
63 changed files with 4403 additions and 3693 deletions

View File

@@ -20,7 +20,7 @@ jobs:
- run: bundle install - run: bundle install
- run: yarn app:build ios - run: yarn app:build ios
env: env:
DEVELOPER_DIR: /Applications/Xcode_14.3.app/Contents/Developer DEVELOPER_DIR: /Applications/Xcode_14.3.1.app/Contents/Developer
ENVIRONMENT: ${{ steps.branch.outputs.current_branch }} ENVIRONMENT: ${{ steps.branch.outputs.current_branch }}
SENTRY_ENVIRONMENT: ${{ steps.branch.outputs.current_branch }} SENTRY_ENVIRONMENT: ${{ steps.branch.outputs.current_branch }}
LC_ALL: en_US.UTF-8 LC_ALL: en_US.UTF-8

View File

@@ -0,0 +1,50 @@
diff --git a/src/android.js b/src/android.js
index fbf09855771f985c5edfc53c22cf6cfe828f45f9..7751d456e08e2dc4c78601fc9430fdbf1373e0d4 100644
--- a/src/android.js
+++ b/src/android.js
@@ -16,7 +16,7 @@ import TextAncestor from 'react-native/Libraries/Text/TextAncestor';
import TextInputState from 'react-native/Libraries/Components/TextInput/TextInputState';
import invariant from 'invariant';
import nullthrows from 'nullthrows';
-import setAndForwardRef from 'react-native/Libraries/Utilities/setAndForwardRef';
+import setAndForwardRef from './setAndForwardRef';
import usePressability from 'react-native/Libraries/Pressability/usePressability';
diff --git a/src/ios.tsx b/src/ios.tsx
index b9ed28bbf9fca6fb44c27096e771d8d2b65b858f..588a75c82b2ee1123d3e48acb984bcbc8b293cc8 100644
--- a/src/ios.tsx
+++ b/src/ios.tsx
@@ -11,7 +11,7 @@ import {
} from 'react-native';
import TextInputState from 'react-native/Libraries/Components/TextInput/TextInputState';
import TextAncestor from 'react-native/Libraries/Text/TextAncestor';
-import setAndForwardRef from 'react-native/Libraries/Utilities/setAndForwardRef';
+import setAndForwardRef from './setAndForwardRef';
import { getTextInputExtraProps } from './extra_props';
import type {
diff --git a/src/setAndForwardRef.js b/src/setAndForwardRef.js
new file mode 100644
index 0000000000000000000000000000000000000000..ad7777e271b945c7123953f7578a8d1208ca9e48
--- /dev/null
+++ b/src/setAndForwardRef.js
@@ -0,0 +1,17 @@
+function setAndForwardRef({ getForwardedRef, setLocalRef }) {
+ return function forwardRef(ref) {
+ 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;
+ }
+ };
+}
+export default setAndForwardRef;
\ No newline at end of file

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" source "https://rubygems.org"
gem "fastlane" gem "fastlane"
gem 'cocoapods' gem 'cocoapods', '~> 1.12'
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path) eval_gemfile(plugins_path) if File.exist?(plugins_path)

View File

@@ -8,7 +8,7 @@ GEM
i18n (>= 1.6, < 2) i18n (>= 1.6, < 2)
minitest (>= 5.1) minitest (>= 5.1)
tzinfo (~> 2.0) tzinfo (~> 2.0)
addressable (2.8.1) addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0) public_suffix (>= 2.0.2, < 6.0)
algoliasearch (1.27.5) algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3) httpclient (~> 2.8, >= 2.8.3)
@@ -16,20 +16,20 @@ GEM
artifactory (3.0.15) artifactory (3.0.15)
atomos (0.1.3) atomos (0.1.3)
aws-eventstream (1.2.0) aws-eventstream (1.2.0)
aws-partitions (1.722.0) aws-partitions (1.785.0)
aws-sdk-core (3.170.0) aws-sdk-core (3.178.0)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0) aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5) aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1) jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.63.0) aws-sdk-kms (1.71.0)
aws-sdk-core (~> 3, >= 3.165.0) aws-sdk-core (~> 3, >= 3.177.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.119.1) aws-sdk-s3 (1.129.0)
aws-sdk-core (~> 3, >= 3.165.0) aws-sdk-core (~> 3, >= 3.177.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4) aws-sigv4 (~> 1.6)
aws-sigv4 (1.5.2) aws-sigv4 (1.6.0)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4) babosa (1.0.4)
claide (1.1.0) claide (1.1.0)
@@ -76,7 +76,7 @@ GEM
highline (~> 2.0.0) highline (~> 2.0.0)
concurrent-ruby (1.2.2) concurrent-ruby (1.2.2)
declarative (0.0.20) declarative (0.0.20)
digest-crc (0.6.4) digest-crc (0.6.5)
rake (>= 12.0.0, < 14.0.0) rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
@@ -85,7 +85,7 @@ GEM
escape (0.0.4) escape (0.0.4)
ethon (0.16.0) ethon (0.16.0)
ffi (>= 1.15.0) ffi (>= 1.15.0)
excon (0.99.0) excon (0.100.0)
faraday (1.10.3) faraday (1.10.3)
faraday-em_http (~> 1.0) faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0) faraday-em_synchrony (~> 1.0)
@@ -114,8 +114,8 @@ GEM
faraday-retry (1.0.3) faraday-retry (1.0.3)
faraday_middleware (1.2.0) faraday_middleware (1.2.0)
faraday (~> 1.0) faraday (~> 1.0)
fastimage (2.2.6) fastimage (2.2.7)
fastlane (2.212.1) fastlane (2.213.0)
CFPropertyList (>= 2.3, < 4.0.0) CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0) addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0) artifactory (~> 3.0)
@@ -139,7 +139,7 @@ GEM
json (< 3.0.0) json (< 3.0.0)
jwt (>= 2.1.0, < 3) jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0) mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0) multipart-post (>= 2.0.0, < 3.0.0)
naturally (~> 2.2) naturally (~> 2.2)
optparse (~> 0.1.1) optparse (~> 0.1.1)
plist (>= 3.1.0, < 4.0.0) plist (>= 3.1.0, < 4.0.0)
@@ -163,7 +163,7 @@ GEM
fourflusher (2.3.1) fourflusher (2.3.1)
fuzzy_match (2.0.4) fuzzy_match (2.0.4)
gh_inspector (1.1.3) gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.35.0) google-apis-androidpublisher_v3 (0.45.0)
google-apis-core (>= 0.11.0, < 2.a) google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.0) google-apis-core (0.11.0)
addressable (~> 2.5, >= 2.5.1) addressable (~> 2.5, >= 2.5.1)
@@ -194,7 +194,7 @@ GEM
google-cloud-core (~> 1.6) google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a) googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0) mini_mime (~> 1.0)
googleauth (1.3.0) googleauth (1.6.0)
faraday (>= 0.17.3, < 3.a) faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0) jwt (>= 1.4, < 3.0)
memoist (~> 0.16) memoist (~> 0.16)
@@ -209,14 +209,14 @@ GEM
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
jmespath (1.6.2) jmespath (1.6.2)
json (2.6.3) json (2.6.3)
jwt (2.7.0) jwt (2.7.1)
memoist (0.16.2) memoist (0.16.2)
mini_magick (4.12.0) mini_magick (4.12.0)
mini_mime (1.1.2) mini_mime (1.1.2)
minitest (5.18.0) minitest (5.18.0)
molinillo (0.8.0) molinillo (0.8.0)
multi_json (1.15.0) multi_json (1.15.0)
multipart-post (2.0.0) multipart-post (2.3.0)
nanaimo (0.3.0) nanaimo (0.3.0)
nap (1.1.0) nap (1.1.0)
naturally (2.2.1) naturally (2.2.1)
@@ -280,7 +280,7 @@ PLATFORMS
arm64-darwin-22 arm64-darwin-22
DEPENDENCIES DEPENDENCIES
cocoapods cocoapods (~> 1.12)
fastlane fastlane
fastlane-plugin-json fastlane-plugin-json
fastlane-plugin-sentry fastlane-plugin-sentry

View File

@@ -2,8 +2,6 @@ apply plugin: "com.android.application"
apply plugin: "com.facebook.react" apply plugin: "com.facebook.react"
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'
import com.android.build.OutputFile
/** /**
* This is the configuration block to customize your React Native Android app. * 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. * By default you don't need to apply any configuration, just uncomment the lines you need.
@@ -15,8 +13,8 @@ react {
// root = file("../") // root = file("../")
// The folder where the react-native NPM package is. Default is ../node_modules/react-native // The folder where the react-native NPM package is. Default is ../node_modules/react-native
// reactNativeDir = file("../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 // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
// codegenDir = file("../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 // 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") // cliFile = file("../node_modules/react-native/cli.js")
/* Variants */ /* Variants */
@@ -51,14 +49,6 @@ react {
// hermesFlags = ["-O", "-output-source-map"] // 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. * 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:+' 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 { android {
ndkVersion rootProject.ext.ndkVersion ndkVersion rootProject.ext.ndkVersion
@@ -105,14 +85,6 @@ android {
versionCode 50 versionCode 50
versionName "0.2" versionName "0.2"
} }
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include (*reactNativeArchitectures())
}
}
signingConfigs { signingConfigs {
debug { debug {
storeFile file('debug.keystore') storeFile file('debug.keystore')
@@ -133,28 +105,9 @@ android {
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 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 { dependencies {
implementation ("androidx.lifecycle:lifecycle-runtime-ktx:2.3.0") {
force = true
}
def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true"; def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true"; def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true";
def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "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 // The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android") 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:${FLIPPER_VERSION}")
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.squareup.okhttp3', module:'okhttp' exclude group:'com.squareup.okhttp3', module:'okhttp'

View File

@@ -1,4 +1,5 @@
package com.xmflsct.app.tooot; package com.xmflsct.app.tooot;
import expo.modules.ReactActivityDelegateWrapper;
import android.os.Bundle; import android.os.Bundle;
import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivity;
@@ -30,13 +31,10 @@ public class MainActivity extends ReactActivity {
*/ */
@Override @Override
protected ReactActivityDelegate createReactActivityDelegate() { protected ReactActivityDelegate createReactActivityDelegate() {
return new DefaultReactActivityDelegate( return new ReactActivityDelegateWrapper(this, BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, new DefaultReactActivityDelegate(
this, this,
getMainComponentName(), getMainComponentName(),
// If you opted-in for the New Architecture, we enable the Fabric Renderer. // If you opted-in for the New Architecture, we enable the Fabric Renderer.
DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled DefaultNewArchitectureEntryPoint.getFabricEnabled()));
// If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18).
DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled
);
} }
} }

View File

@@ -20,7 +20,7 @@ import java.util.List;
public class MainApplication extends Application implements ReactApplication { public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHostWrapper( private final ReactNativeHost mReactNativeHost = new ReactNativeHostWrapper(
this, this,
new DefaultReactNativeHost(this) { new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) {
@Override @Override
public boolean getUseDeveloperSupport() { public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG; return BuildConfig.DEBUG;
@@ -48,7 +48,7 @@ public class MainApplication extends Application implements ReactApplication {
protected Boolean isHermesEnabled() { protected Boolean isHermesEnabled() {
return BuildConfig.IS_HERMES_ENABLED; return BuildConfig.IS_HERMES_ENABLED;
} }
}); }));
@Override @Override
public ReactNativeHost getReactNativeHost() { public ReactNativeHost getReactNativeHost() {
@@ -65,5 +65,12 @@ public class MainApplication extends Application implements ReactApplication {
DefaultNewArchitectureEntryPoint.load(); DefaultNewArchitectureEntryPoint.load();
} }
// ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); // ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
ApplicationLifecycleDispatcher.onApplicationCreate(this);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig);
} }
} }

View File

@@ -7,6 +7,7 @@ buildscript {
compileSdkVersion = 33 compileSdkVersion = 33
targetSdkVersion = 33 targetSdkVersion = 33
kotlinVersion = '1.8.21' kotlinVersion = '1.8.21'
frescoVersion = '2.5.0'
// We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
ndkVersion = "23.1.7779620" ndkVersion = "23.1.7779620"
@@ -17,7 +18,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { 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.facebook.react:react-native-gradle-plugin")
classpath 'com.google.gms:google-services:4.3.14' classpath 'com.google.gms:google-services:4.3.14'
} }

View File

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

Binary file not shown.

View File

@@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists 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 zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

62
android/gradlew vendored
View File

@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright 2015 the original author or authors. # Copyright © 2015-2021 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -17,14 +17,56 @@
# #
############################################################################## ##############################################################################
## #
## Gradle start up script for UN*X # Gradle start up script for POSIX generated by Gradle.
## #
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
############################################################################## ##############################################################################
# Attempt to set APP_HOME # Attempt to set APP_HOME
# Resolve links: $0 may be a link # Resolve links: $0 may be a link
app_path=$0 app_path=$0
# Need this for daisy-chained symlinks. # Need this for daisy-chained symlinks.
while while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
@@ -37,6 +79,7 @@ do
*) app_path=$APP_HOME$link ;; *) app_path=$APP_HOME$link ;;
esac esac
done done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle" APP_NAME="Gradle"
@@ -73,6 +116,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -122,7 +166,9 @@ fi
if "$cygwin" || "$msys" ; then if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" ) JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh # Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do for arg do
if if
@@ -152,11 +198,19 @@ fi
# shell script including quotes and variable substitutions, so put them in # shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and # double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded. # * put everything else in single quotes, so that it's not re-expanded.
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \ -classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \ 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. # Use "xargs" to parse quoted args.
# #
# With -n1 it outputs one arg per line, with the quotes and backslashes removed. # 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 limitations under the License.
@rem @rem
@if "%DEBUG%" == "" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@rem Gradle startup script for Windows @rem Gradle startup script for Windows
@@ -25,7 +25,7 @@
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -69,18 +69,21 @@ goto fail
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if %ERRORLEVEL% equ 0 goto mainEnd
:fail :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 set EXIT_CODE=%ERRORLEVEL%
exit /b 1 if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal

View File

@@ -1,11 +1,10 @@
rootProject.name = 'tooot' rootProject.name = 'tooot'
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute().text.trim(), "../scripts/autolinking.gradle"); apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
useExpoModules() useExpoModules()
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute().text.trim(), "../native_modules.gradle"); apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
applyNativeModulesSettingsGradle(settings) applyNativeModulesSettingsGradle(settings)
include ':app' include ':app'
includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json')"].execute(null, rootDir).text.trim()).getParentFile())
includeBuild('../node_modules/react-native-gradle-plugin')

View File

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

View File

@@ -1,2 +1,4 @@
Enjoy toooting! This version includes following improvements and fixes: Enjoy toooting! This version includes following improvements and fixes:
- Fixed functionality version check (e.g. cannot edit own toots) - Supports mute duration
- Long press to copy toot
- Button to fetch latest on load

View File

@@ -1,2 +1,5 @@
tooot-ing愉快此版本包括以下改进和修复 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('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' platform :ios, '13.0'
prepare_react_native_project! prepare_react_native_project!
@@ -33,8 +38,7 @@ target 'tooot' do
post_install do |installer| post_install do |installer|
react_native_post_install( react_native_post_install(
installer, installer,
# Set `mac_catalyst_enabled` to `true` in order to apply patches config[:reactNativePath],
# necessary for Mac Catalyst builds
:mac_catalyst_enabled => false :mac_catalyst_enabled => false
) )
__apply_Xcode_12_5_M1_post_install_workaround(installer) __apply_Xcode_12_5_M1_post_install_workaround(installer)

File diff suppressed because it is too large Load Diff

View File

@@ -225,6 +225,7 @@
buildPhases = ( buildPhases = (
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */, 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */,
FD10A7F022414F080027D42C /* Start Packager */, FD10A7F022414F080027D42C /* Start Packager */,
395686AEA3960C8699AE1CAD /* [Expo] Configure project */,
13B07F871A680F5B00A75B9A /* Sources */, 13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */, 13B07F8E1A680F5B00A75B9A /* Resources */,
@@ -385,6 +386,25 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
395686AEA3960C8699AE1CAD /* [Expo] Configure project */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "[Expo] Configure project";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-tooot/expo-configure-project.sh\"\n";
};
49D30A53634620EF2A5C6692 /* [CP] Embed Pods Frameworks */ = { 49D30A53634620EF2A5C6692 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@@ -697,6 +717,8 @@
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"\""; LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"\"";
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
}; };
@@ -753,6 +775,8 @@
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"\""; LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"\"";
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
ONLY_ACTIVE_ARCH = NO; ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;

View File

@@ -22,16 +22,6 @@
#endif #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 // Linking API
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSString *urlString = url.absoluteString; NSString *urlString = url.absoluteString;

View File

@@ -1,3 +1,11 @@
module.exports = { const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config')
transformer: { inlineRequires: true }
} /**
* 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", "name": "tooot",
"version": "4.9.6", "version": "4.10.0",
"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",
@@ -19,95 +19,96 @@
}, },
"dependencies": { "dependencies": {
"@expo/react-native-action-sheet": "^4.0.1", "@expo/react-native-action-sheet": "^4.0.1",
"@formatjs/intl-datetimeformat": "^6.8.0", "@formatjs/intl-datetimeformat": "^6.10.0",
"@formatjs/intl-getcanonicallocales": "^2.2.0", "@formatjs/intl-getcanonicallocales": "^2.2.1",
"@formatjs/intl-locale": "^3.3.0", "@formatjs/intl-locale": "^3.3.2",
"@formatjs/intl-numberformat": "^8.5.0", "@formatjs/intl-numberformat": "^8.7.0",
"@formatjs/intl-pluralrules": "^5.2.2", "@formatjs/intl-pluralrules": "^5.2.4",
"@formatjs/intl-relativetimeformat": "^11.2.2", "@formatjs/intl-relativetimeformat": "^11.2.4",
"@mattermost/react-native-paste-input": "^0.6.2", "@mattermost/react-native-paste-input": "^0.6.2",
"@neverdull-agency/expo-unlimited-secure-store": "^1.0.10", "@neverdull-agency/expo-unlimited-secure-store": "^1.0.10",
"@react-native-async-storage/async-storage": "~1.17.11", "@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.7.2",
"@react-native-clipboard/clipboard": "^1.11.2", "@react-native-clipboard/clipboard": "^1.11.2",
"@react-native-community/blur": "^4.3.2", "@react-native-community/blur": "^4.3.2",
"@react-native-community/netinfo": "9.3.10", "@react-native-community/netinfo": "^9.4.1",
"@react-native-firebase/app": "^17.5.0", "@react-native-firebase/app": "^18.1.0",
"@react-native-menu/menu": "^0.7.3", "@react-native-menu/menu": "^0.8.0",
"@react-native-segmented-control/segmented-control": "^2.4.1", "@react-native-segmented-control/segmented-control": "^2.4.2",
"@react-navigation/bottom-tabs": "^6.5.7", "@react-navigation/bottom-tabs": "^6.5.8",
"@react-navigation/native": "^6.1.6", "@react-navigation/native": "^6.1.7",
"@react-navigation/native-stack": "^6.9.12", "@react-navigation/native-stack": "^6.9.13",
"@react-navigation/stack": "^6.3.16", "@react-navigation/stack": "^6.3.17",
"@sentry/react-native": "5.5.0", "@sentry/react-native": "^5.7.1",
"@sharcoux/slider": "^6.1.2", "@sharcoux/slider": "^7.0.1",
"@tanstack/react-query": "^4.29.7", "@tanstack/react-query": "^4.29.19",
"axios": "^1.4.0", "axios": "^1.4.0",
"diff": "^5.1.0", "diff": "^5.1.0",
"expo": "48.0.17", "expo": "^49.0.3",
"expo-auth-session": "^4.1.0", "expo-auth-session": "^5.0.2",
"expo-av": "^13.3.0", "expo-av": "^13.4.1",
"expo-constants": "^14.3.0", "expo-constants": "^14.4.2",
"expo-crypto": "^12.3.0", "expo-crypto": "^12.4.1",
"expo-file-system": "^15.3.0", "expo-file-system": "^15.4.2",
"expo-haptics": "^12.3.0", "expo-haptics": "^12.4.0",
"expo-image": "^1.2.3", "expo-image": "^1.3.2",
"expo-linking": "^4.1.0", "expo-linking": "^5.0.2",
"expo-localization": "^14.2.0", "expo-localization": "^14.3.0",
"expo-notifications": "^0.18.1", "expo-notifications": "^0.20.1",
"expo-screen-capture": "5.1.1", "expo-screen-capture": "^5.3.0",
"expo-screen-orientation": "^5.2.0", "expo-screen-orientation": "^6.0.3",
"expo-secure-store": "^12.1.1", "expo-secure-store": "^12.3.1",
"expo-splash-screen": "^0.18.2", "expo-splash-screen": "^0.20.4",
"expo-store-review": "^6.3.0", "expo-store-review": "^6.4.0",
"expo-video-thumbnails": "^7.3.0", "expo-video-thumbnails": "^7.4.0",
"expo-web-browser": "~12.1.1", "expo-web-browser": "^12.3.2",
"htmlparser2": "^9.0.0", "htmlparser2": "^9.0.0",
"i18next": "^22.5.0", "i18next": "^23.2.11",
"linkify-it": "^4.0.1", "linkify-it": "^4.0.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-i18next": "^12.3.1", "react-i18next": "^13.0.2",
"react-intl": "^6.4.2", "react-intl": "^6.4.4",
"react-native": "^0.71.8", "react-native": "^0.72.3",
"react-native-flash-message": "^0.4.1", "react-native-flash-message": "^0.4.1",
"react-native-gesture-handler": "~2.10.1", "react-native-gesture-handler": "~2.12.0",
"react-native-image-picker": "^5.3.1", "react-native-image-picker": "^5.6.0",
"react-native-ios-context-menu": "^1.15.3", "react-native-ios-context-menu": "^1.15.3",
"react-native-language-detection": "^0.2.2", "react-native-language-detection": "^0.2.2",
"react-native-mmkv": "~2.8.0", "react-native-mmkv": "^2.10.1",
"react-native-pager-view": "^6.2.0", "react-native-pager-view": "^6.2.0",
"react-native-quick-base64": "^2.0.6", "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-reanimated-zoom": "^0.3.3",
"react-native-safe-area-context": "^4.5.3", "react-native-safe-area-context": "^4.7.1",
"react-native-screens": "^3.20.0", "react-native-screens": "^3.22.1",
"react-native-share-menu": "^6.0.0", "react-native-share-menu": "^6.0.0",
"react-native-svg": "^13.9.0", "react-native-svg": "^13.10.0",
"react-native-swipe-list-view": "^3.2.9", "react-native-swipe-list-view": "^3.2.9",
"react-native-tab-view": "^3.5.1", "react-native-tab-view": "^3.5.2",
"rn-placeholder": "^3.0.3", "rn-placeholder": "^3.0.3",
"zeego": "^1.6.1" "zeego": "^1.6.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.21.8", "@babel/core": "^7.22.8",
"@babel/plugin-proposal-optional-chaining": "^7.21.0", "@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", "@expo/config": "^8.1.2",
"@react-native/metro-config": "^0.72.9",
"@types/diff": "^5.0.3", "@types/diff": "^5.0.3",
"@types/linkify-it": "^3.0.2", "@types/linkify-it": "^3.0.2",
"@types/lodash": "^4.14.194", "@types/lodash": "^4.14.195",
"@types/react": "^18.2.6", "@types/react": "^18.2.14",
"@types/react-dom": "^18.2.4", "@types/react-dom": "^18.2.7",
"@types/react-native-share-menu": "^5.0.2", "@types/react-native-share-menu": "^5.0.2",
"babel-plugin-module-resolver": "^5.0.0", "babel-plugin-module-resolver": "^5.0.0",
"babel-plugin-transform-remove-console": "^6.9.4", "babel-plugin-transform-remove-console": "^6.9.4",
"chalk": "^4.1.2", "chalk": "^4.1.2",
"deprecated-react-native-prop-types": "^4.1.0", "deprecated-react-native-prop-types": "^4.1.0",
"dotenv": "^16.0.3", "dotenv": "^16.3.1",
"react-native-clean-project": "^4.0.1", "react-native-clean-project": "^4.0.1",
"typescript": "^5.0.4" "typescript": "^5.1.6"
}, },
"packageManager": "yarn@3.3.1", "packageManager": "yarn@3.3.1",
"resolutions": { "resolutions": {
@@ -115,6 +116,8 @@
"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", "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", "@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-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",
"@mattermost/react-native-paste-input@^0.6.2": "patch:@mattermost/react-native-paste-input@npm%3A0.6.2#./.yarn/patches/@mattermost-react-native-paste-input-npm-0.6.2-e109419dfb.patch"
} }
} }

View File

@@ -17,6 +17,7 @@ export type Props = {
loading?: boolean loading?: boolean
disabled?: boolean disabled?: boolean
destructive?: boolean destructive?: boolean
destructiveColor?: string
onPress: () => void onPress: () => void
} & ({ type?: undefined; content: IconName } | { type: 'text'; content: string }) } & ({ type?: undefined; content: IconName } | { type: 'text'; content: string })
@@ -34,6 +35,7 @@ const HeaderRight: React.FC<Props> = ({
loading, loading,
disabled, disabled,
destructive = false, destructive = false,
destructiveColor,
onPress onPress
}) => { }) => {
const { colors } = useTheme() const { colors } = useTheme()
@@ -57,7 +59,7 @@ const HeaderRight: React.FC<Props> = ({
color: disabled color: disabled
? colors.secondary ? colors.secondary
: destructive : destructive
? colors.red ? destructiveColor || colors.red
: colors.primaryDefault, : colors.primaryDefault,
opacity: loading ? 0 : 1 opacity: loading ? 0 : 1
}} }}

View File

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

View File

@@ -36,6 +36,7 @@ const TimelineContent: React.FC<Props> = ({ notificationOwnToot = false, setSpoi
adaptiveSize adaptiveSize
numberOfLines={999} numberOfLines={999}
color={suppressSpoiler ? colors.disabled : undefined} color={suppressSpoiler ? colors.disabled : undefined}
selectable
/> />
{inThread ? ( {inThread ? (
<CustomText <CustomText
@@ -62,6 +63,7 @@ const TimelineContent: React.FC<Props> = ({ notificationOwnToot = false, setSpoi
} }
expandHint={t('shared.content.expandHint')} expandHint={t('shared.content.expandHint')}
setSpoilerExpanded={setSpoilerExpanded} setSpoilerExpanded={setSpoilerExpanded}
selectable
/> />
</> </>
) : ( ) : (
@@ -70,6 +72,7 @@ const TimelineContent: React.FC<Props> = ({ notificationOwnToot = false, setSpoi
size={highlighted ? 'L' : 'M'} size={highlighted ? 'L' : 'M'}
adaptiveSize adaptiveSize
numberOfLines={highlighted || inThread ? 999 : notificationOwnToot ? 2 : undefined} numberOfLines={highlighted || inThread ? 999 : notificationOwnToot ? 2 : undefined}
selectable
/> />
)} )}
</View> </View>

View File

@@ -1,3 +1,4 @@
import Icon from '@components/Icon'
import ComponentSeparator from '@components/Separator' import ComponentSeparator from '@components/Separator'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import TimelineDefault from '@components/Timeline/Default' import TimelineDefault from '@components/Timeline/Default'
@@ -10,12 +11,20 @@ import {
setAccountStorage, setAccountStorage,
useGlobalStorageListener useGlobalStorageListener
} from '@utils/storage/actions' } from '@utils/storage/actions'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import { StyleConstants } from '@utils/styles/constants'
import { throttle } from 'lodash' import { throttle } from 'lodash'
import React, { RefObject, useCallback, useEffect, useRef, useState } from 'react' import React, { RefObject, useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { FlatList, FlatListProps, Platform, RefreshControl } from 'react-native' import {
FlatList,
FlatListProps,
Platform,
Pressable,
RefreshControl,
StyleProp,
ViewStyle
} from 'react-native'
import Animated, { import Animated, {
Easing, Easing,
runOnJS, runOnJS,
@@ -127,6 +136,27 @@ const Timeline: React.FC<Props> = ({
transform: [{ translateY: fetchedNoticeTop.value }] transform: [{ translateY: fetchedNoticeTop.value }]
})) }))
const refetchedNoticeBottom = useDerivedValue(() => {
if (firstLoad.value) {
return withSequence(
withTiming(0),
withDelay(
3000,
withTiming(fetchedNoticeHeight.value + 32, { easing: Easing.out(Easing.ease) })
)
)
} else {
return fetchedNoticeHeight.value + 32
}
}, [])
const refetchedNoticeAnimate = useAnimatedStyle(() => ({
transform: [
{
translateY: refetchedNoticeBottom.value
}
]
}))
const scrollY = useSharedValue(0) const scrollY = useSharedValue(0)
const fetchingType = useSharedValue<0 | 1 | 2>(0) const fetchingType = useSharedValue<0 | 1 | 2>(0)
@@ -169,10 +199,9 @@ const Timeline: React.FC<Props> = ({
throttle(() => { throttle(() => {
if (readMarker) { if (readMarker) {
const currentMarker = getAccountStorage.string(readMarker) || '0' const currentMarker = getAccountStorage.string(readMarker) || '0'
// setAccountStorage([{ key: readMarker, value: '108425743226508521' }])
if (latestMarker.current > currentMarker) { if (latestMarker.current > currentMarker) {
setAccountStorage([{ key: readMarker, value: latestMarker.current }]) setAccountStorage([{ key: readMarker, value: latestMarker.current }])
} else {
// setAccountStorage([{ key: readMarker, value: '105250709762254246' }])
} }
} }
}, 1000 * 15), }, 1000 * 15),
@@ -242,6 +271,18 @@ const Timeline: React.FC<Props> = ({
flRef.current?.scrollToOffset({ offset: 0, animated: false }) flRef.current?.scrollToOffset({ offset: 0, animated: false })
) )
const noticeDefaults: StyleProp<Animated.AnimateStyle<StyleProp<ViewStyle>>> = {
position: 'absolute',
alignSelf: 'center',
borderRadius: 99,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: colors.backgroundDefault,
shadowColor: colors.primaryDefault,
shadowOffset: { width: 0, height: 0 },
shadowOpacity: theme === 'light' ? 0.16 : 0.24
}
return ( return (
<> <>
<TimelineRefresh <TimelineRefresh
@@ -286,42 +327,78 @@ const Timeline: React.FC<Props> = ({
{...customProps} {...customProps}
/> />
{!disableRefresh ? ( {!disableRefresh ? (
<Animated.View <>
style={[ <Animated.View
{ style={[
position: 'absolute', {
alignSelf: 'center', top: -fetchedNoticeHeight.value - 16,
top: -fetchedNoticeHeight.value - 16, paddingVertical: StyleConstants.Spacing.S,
paddingVertical: StyleConstants.Spacing.S, paddingHorizontal: StyleConstants.Spacing.M,
paddingHorizontal: StyleConstants.Spacing.M, ...noticeDefaults
backgroundColor: colors.backgroundDefault, },
shadowColor: colors.primaryDefault, fetchedNoticeAnimate
shadowOffset: { width: 0, height: 0 }, ]}
shadowOpacity: theme === 'light' ? 0.16 : 0.24, onLayout={({
borderRadius: 99, nativeEvent: {
justifyContent: 'center', layout: { height }
alignItems: 'center' }
}, }) => (fetchedNoticeHeight.value = height)}
fetchedNoticeAnimate >
]} <CustomText
onLayout={({ fontStyle='S'
nativeEvent: { style={{ color: colors.primaryDefault }}
layout: { height } children={
} fetchedCount !== null
}) => (fetchedNoticeHeight.value = height)} ? fetchedCount > 0
> ? t('refresh.fetched.found', { count: fetchedCount })
<CustomText : t('refresh.fetched.none')
fontStyle='S' : t('refresh.fetching')
style={{ color: colors.primaryDefault }} }
children={ />
fetchedCount !== null </Animated.View>
? fetchedCount > 0 {readMarker ? (
? t('refresh.fetched.found', { count: fetchedCount }) <Animated.View
: t('refresh.fetched.none') style={[
: t('refresh.fetching') {
} bottom: 16,
/> borderColor: colors.primaryDefault,
</Animated.View> borderWidth: 0.5,
...noticeDefaults
},
refetchedNoticeAnimate
]}
>
<Pressable
style={{
flexDirection: 'row',
alignItems: 'center',
gap: StyleConstants.Spacing.S,
paddingVertical: StyleConstants.Spacing.S,
paddingHorizontal: StyleConstants.Spacing.M
}}
onPress={async () => {
if (readMarker) {
setAccountStorage([{ key: readMarker, value: undefined }])
}
flRef.current?.scrollToOffset({ offset: 0 })
await refetch()
}}
>
<CustomText
fontStyle='M'
style={{ color: colors.primaryDefault }}
children={t('refresh.refetch')}
/>
<Icon
name='log-in'
color={colors.primaryDefault}
size={StyleConstants.Font.Size.M}
style={{ transform: [{ rotate: '-90deg' }] }}
/>
</Pressable>
</Animated.View>
) : null}
</>
) : null} ) : null}
</> </>
) )

View File

@@ -4,6 +4,7 @@ import { useNavigation } from '@react-navigation/native'
import { NativeStackNavigationProp } from '@react-navigation/native-stack' import { NativeStackNavigationProp } from '@react-navigation/native-stack'
import { useQueryClient } from '@tanstack/react-query' import { useQueryClient } from '@tanstack/react-query'
import apiInstance from '@utils/api/instance' import apiInstance from '@utils/api/instance'
import { featureCheck } from '@utils/helpers/featureCheck'
import { checkIsMyAccount } from '@utils/helpers/isMyAccount' import { checkIsMyAccount } from '@utils/helpers/isMyAccount'
import { TabSharedStackParamList, useNavState } from '@utils/navigation/navigators' import { TabSharedStackParamList, useNavState } from '@utils/navigation/navigators'
import { useAccountQuery } from '@utils/queryHooks/account' import { useAccountQuery } from '@utils/queryHooks/account'
@@ -203,13 +204,22 @@ const menuAccount = ({
type: 'item', type: 'item',
key: 'account-mute', key: 'account-mute',
props: { props: {
onSelect: () => onSelect: () => {
actualAccount && if (actualAccount) {
timelineMutation.mutate({ if (data?.muting !== true) {
type: 'updateAccountProperty', if (featureCheck('mute_duration')) {
id: actualAccount.id, navigation.navigate('Tab-Shared-Mute', { account: actualAccount })
payload: { property: 'mute', currentValue: data?.muting } return
}), }
}
timelineMutation.mutate({
type: 'updateAccountProperty',
id: actualAccount.id,
payload: { property: 'mute', currentValue: data?.muting }
})
}
},
disabled: Platform.OS !== 'android' ? !data || !isFetched : false, disabled: Platform.OS !== 'android' ? !data || !isFetched : false,
destructive: false, destructive: false,
hidden: false hidden: false

View File

@@ -390,8 +390,8 @@
"accessibilityHint": "Вы можаце ігнараваць, блакіраваць або абагуліць гэтага карыстальніка" "accessibilityHint": "Вы можаце ігнараваць, блакіраваць або абагуліць гэтага карыстальніка"
}, },
"followed_by": " падпісаны на вас", "followed_by": " падпісаны на вас",
"privateNote": "", "privateNote": "Задаць прыватную нататку",
"moved": "", "moved": "Карыстальнік перанесены",
"created_at": "Далучыўся: {{date}}", "created_at": "Далучыўся: {{date}}",
"summary": { "summary": {
"statuses_count": "{{count}} допісаў" "statuses_count": "{{count}} допісаў"
@@ -412,11 +412,25 @@
}, },
"filter": { "filter": {
"name": "Дадаць у фільтр", "name": "Дадаць у фільтр",
"existed": "" "existed": "Існаваў у гэтых фільтрах"
}, },
"history": { "history": {
"name": "Гісторыя рэдагавання" "name": "Гісторыя рэдагавання"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "Бестэрмінова",
"1800": "30 хвілін",
"3600": "1 гадзіна",
"86400": "1 дзень",
"604800": "1 тыдзень"
}
},
"report": { "report": {
"name": "Паскардзіцца на {{acct}}", "name": "Паскардзіцца на {{acct}}",
"report": "Скарга", "report": "Скарга",
@@ -468,7 +482,7 @@
"name": "Абмеркаванні", "name": "Абмеркаванні",
"remoteFetch": { "remoteFetch": {
"title": "Змяшчае аддаленае змесціва", "title": "Змяшчае аддаленае змесціва",
"message": "" "message": "Федэратыўны кантэнт не заўсёды даступны на лакальным серверы. Гэты кантэнт атрымліваецца з аддаленага сервера і мае пазнаку. Вы можаце ўзаемадзейнічаць з гэтым кантэнтам як звычайна."
} }
}, },
"users": { "users": {

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Edita l'historial" "name": "Edita l'historial"
}, },
"mute": {
"name": "Silencia {{acct}}",
"mute": "Silencia",
"description": "Amaga publicacions i mencions d'aquest usuari, però encara podrà veure les teves publicacions i seguir-te.",
"notification": "També amaga notificacions d'aquest usuari",
"duration": {
"heading": "D'una durada",
"0": "Indefinida",
"1800": "30 minuts",
"3600": "1 hora",
"86400": "1 dia",
"604800": "1 setmana"
}
},
"report": { "report": {
"name": "Denúncia a {{acct}}", "name": "Denúncia a {{acct}}",
"report": "Denúncia", "report": "Denúncia",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "" "name": ""
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "", "name": "",
"report": "", "report": "",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Bearbeitungsverlauf" "name": "Bearbeitungsverlauf"
}, },
"mute": {
"name": "@{{acct}} stummschalten",
"mute": "Stummschalten",
"description": "Verstecke Tröts des Users und solche, in denen das Konto erwähnt wird. Die Person wird weiterhin deine Beiträge lesen und dir folgen können.",
"notification": "Benachrichtigungen dieses Profils ebenfalls ausblenden",
"duration": {
"heading": "Für die Dauer",
"0": "Dauerhaft",
"1800": "30 Minuten",
"3600": "1 Stunde",
"86400": "1 Tag",
"604800": "1 Woche"
}
},
"report": { "report": {
"name": "{{acct}} melden", "name": "{{acct}} melden",
"report": "Melden", "report": "Melden",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Ιστορικό επεξεργασίας" "name": "Ιστορικό επεξεργασίας"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "Αναφορά {{acct}}", "name": "Αναφορά {{acct}}",
"report": "Αναφορά", "report": "Αναφορά",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Edit History" "name": "Edit History"
}, },
"mute": {
"name": "Mute {{acct}}",
"mute": "Mute",
"description": "Hide posts from this user and posts mentioning them, but it will still allow them to see your posts and follow you.",
"notification": "Also hide notifications from this user",
"duration": {
"heading": "For duration",
"0": "Indefinitely",
"1800": "30 minutes",
"3600": "1 hour",
"86400": "1 day",
"604800": "1 week"
}
},
"report": { "report": {
"name": "Report {{acct}}", "name": "Report {{acct}}",
"report": "Report", "report": "Report",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Historial de ediciones" "name": "Historial de ediciones"
}, },
"mute": {
"name": "Silenciar a {{acct}}",
"mute": "Silenciar",
"description": "Oculta publicaciones y menciones a este usuario, pero podrá ver tus publicaciones y seguirte.",
"notification": "También oculta notificaciones de este usuario",
"duration": {
"heading": "Durante",
"0": "Indefinidamente",
"1800": "30 minutos",
"3600": "1 hora",
"86400": "1 día",
"604800": "1 semana"
}
},
"report": { "report": {
"name": "Denuncia {{acct}}", "name": "Denuncia {{acct}}",
"report": "Denuncia", "report": "Denuncia",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "" "name": ""
}, },
"mute": {
"name": "Mututu {{acct}}",
"mute": "Mututu",
"description": "Ezkutatu erabiltzaile honen argitalpenak berari aipatzen dieten argitalpenak, hala ere, berak zure argitalpenak irakurri ahal izango ditu eta zuri jarraitu ere.",
"notification": "Baita ere, ezkutatu erabiltzaile honen jakinarazpenak",
"duration": {
"heading": "Iraupena",
"0": "Mugagabe",
"1800": "30 minutu",
"3600": "Ordu 1",
"86400": "Egun 1",
"604800": "Aste 1"
}
},
"report": { "report": {
"name": "", "name": "",
"report": "", "report": "",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Modifier l'historique" "name": "Modifier l'historique"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "", "name": "",
"report": "", "report": "",

View File

@@ -5,11 +5,11 @@
"cancel": "Annulla", "cancel": "Annulla",
"discard": "Scarta", "discard": "Scarta",
"continue": "Continua", "continue": "Continua",
"create": "", "create": "Crea",
"delete": "", "delete": "Elimina",
"done": "", "done": "Fatto",
"confirm": "Ho capito", "confirm": "Ho capito",
"add": "" "add": "Aggiungi"
}, },
"customEmoji": { "customEmoji": {
"accessibilityLabel": "Emoji personalizzata {{emoji}}" "accessibilityLabel": "Emoji personalizzata {{emoji}}"

View File

@@ -1,13 +1,13 @@
{ {
"server": { "server": {
"textInput": { "textInput": {
"placeholder": "" "placeholder": "Dominio dell'istanza"
}, },
"whitelisted": "", "whitelisted": "Questa potrebbe essere un'istanza nella whitelist nella quale tooot non può accedere ai dati di essa prima di fare il log-in.",
"button": "Accedi", "button": "Accedi",
"information": { "information": {
"name": "Nome", "name": "Nome",
"description": "" "description": "Descrizione"
}, },
"disclaimer": { "disclaimer": {
"base": "Per accedere, verrà aperta una pagina del browser di sistema. I dati di accesso del tuo account sono protetti." "base": "Per accedere, verrà aperta una pagina del browser di sistema. I dati di accesso del tuo account sono protetti."

View File

@@ -17,10 +17,10 @@
"refresh": { "refresh": {
"fetchPreviousPage": "Più recenti da qui", "fetchPreviousPage": "Più recenti da qui",
"refetch": "Al più recente", "refetch": "Al più recente",
"fetching": "", "fetching": "Recupero nuovi toot ...",
"fetched": { "fetched": {
"none": "", "none": "Nessun nuovo toot",
"found": "" "found": "{{count}} toot recuperati"
} }
}, },
"shared": { "shared": {

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Cronologia delle modifiche" "name": "Cronologia delle modifiche"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "", "name": "",
"report": "", "report": "",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "編集履歴" "name": "編集履歴"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "{{acct}} の違反報告", "name": "{{acct}} の違反報告",
"report": "報告", "report": "報告",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "수정 이력" "name": "수정 이력"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "@{{acct}} 신고", "name": "@{{acct}} 신고",
"report": "신고", "report": "신고",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Geschiedenis bewerken" "name": "Geschiedenis bewerken"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "Voor duur",
"0": "Onbepaalde tijd",
"1800": "30 minuten",
"3600": "1 uur",
"86400": "1 dag",
"604800": "1 week"
}
},
"report": { "report": {
"name": "Rapporteer {{acct}}", "name": "Rapporteer {{acct}}",
"report": "Rapporteer", "report": "Rapporteer",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Rediger historikk" "name": "Rediger historikk"
}, },
"mute": {
"name": "Demp {{acct}}",
"mute": "Demp",
"description": "Skjul innlegg fra denne brukeren og innleggene som nevner brukeren, men det vil fortsatt la brukeren se dine innlegg og følge deg.",
"notification": "Skjul varsler også for denne brukeren",
"duration": {
"heading": "For varighet",
"0": "På ubestemt tid",
"1800": "30 minutter",
"3600": "Én time",
"86400": "Én dag",
"604800": "én uke"
}
},
"report": { "report": {
"name": "Rapporter {{acct}}", "name": "Rapporter {{acct}}",
"report": "Rapporter", "report": "Rapporter",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Historia edycji" "name": "Historia edycji"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "Zgłoś {{acct}}", "name": "Zgłoś {{acct}}",
"report": "Zgłoś", "report": "Zgłoś",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Histórico de Edição" "name": "Histórico de Edição"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "Denuncia {{acct}}", "name": "Denuncia {{acct}}",
"report": "Denunciar", "report": "Denunciar",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "" "name": ""
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "", "name": "",
"report": "", "report": "",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Redigeringshistorik" "name": "Redigeringshistorik"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "Rapportera {{acct}}", "name": "Rapportera {{acct}}",
"report": "Rapport", "report": "Rapport",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Редагувати історію" "name": "Редагувати історію"
}, },
"mute": {
"name": "Ігнорувати {{acct}}",
"mute": "Ігнорувати",
"description": "Сховає дописи від цього користувача і дописи зі згадками про них, проте вони все одно матимуть змогу бачити ваші дописи та слідкувати за вами.",
"notification": "Також сховати сповіщення цього користувача",
"duration": {
"heading": "На час",
"0": "Безтерміново",
"1800": "30 хвилин",
"3600": "1 годину",
"86400": "1 день",
"604800": "1 тиждень"
}
},
"report": { "report": {
"name": "Скарга на {{acct}}", "name": "Скарга на {{acct}}",
"report": "Скарга", "report": "Скарга",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "Lịch sử chỉnh sửa" "name": "Lịch sử chỉnh sửa"
}, },
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "",
"1800": "",
"3600": "",
"86400": "",
"604800": ""
}
},
"report": { "report": {
"name": "Báo cáo @{{acct}}", "name": "Báo cáo @{{acct}}",
"report": "Báo cáo", "report": "Báo cáo",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "编辑历史" "name": "编辑历史"
}, },
"mute": {
"name": "隐藏{{acct}}",
"mute": "隐藏",
"description": "此用户的嘟文及提到此用户的嘟文都会隐藏,但他们仍可以看到你的嘟文,也可以关注你。",
"notification": "同时隐藏来自此用户的通知",
"duration": {
"heading": "时限",
"0": "无限期",
"1800": "30分钟",
"3600": "一小时",
"86400": "一天",
"604800": "一周"
}
},
"report": { "report": {
"name": "举报 {{acct}}", "name": "举报 {{acct}}",
"report": "举报", "report": "举报",

View File

@@ -417,6 +417,20 @@
"history": { "history": {
"name": "編輯歷史" "name": "編輯歷史"
}, },
"mute": {
"name": "禁音{{acct}}",
"mute": "禁音",
"description": "該使用者的嘟文及提到該使用者的嘟文都會被隱藏,但他們仍然可以看到你的嘟文,也可以關注你。",
"notification": "同時隱藏來自該使用者的通知",
"duration": {
"heading": "時限",
"0": "無限期",
"1800": "30分鐘",
"3600": "一小時",
"86400": "一天",
"604800": "一週"
}
},
"report": { "report": {
"name": "檢舉 {{acct}}", "name": "檢舉 {{acct}}",
"report": "檢舉", "report": "檢舉",

View File

@@ -374,7 +374,10 @@ const Explore = ({ route: { key: page } }: { route: { key: 'Explore' } }) => {
<DropdownMenu.ItemTitle children={item.title} /> <DropdownMenu.ItemTitle children={item.title} />
<DropdownMenu.ItemSubtitle children={item.domain} /> <DropdownMenu.ItemSubtitle children={item.domain} />
{index === remotes?.findIndex(r => r.domain === remoteActive) ? ( {index === remotes?.findIndex(r => r.domain === remoteActive) ? (
<DropdownMenu.ItemIcon ios={{ name: 'trash' }} /> <DropdownMenu.ItemIcon
ios={{ name: 'trash' }}
androidIconName='ic_menu_delete'
/>
) : null} ) : null}
</DropdownMenu.CheckboxItem> </DropdownMenu.CheckboxItem>
))} ))}
@@ -391,7 +394,7 @@ const Explore = ({ route: { key: page } }: { route: { key: 'Explore' } }) => {
<DropdownMenu.ItemTitle <DropdownMenu.ItemTitle
children={t('screenTabs:tabs.public.exploring.followRemote')} children={t('screenTabs:tabs.public.exploring.followRemote')}
/> />
<DropdownMenu.ItemIcon ios={{ name: 'plus' }} /> <DropdownMenu.ItemIcon ios={{ name: 'plus' }} androidIconName='ic_menu_add' />
</DropdownMenu.Item> </DropdownMenu.Item>
</DropdownMenu.Group> </DropdownMenu.Group>
</DropdownMenu.Content> </DropdownMenu.Content>

View File

@@ -71,7 +71,7 @@ const AccountInformationActions: React.FC = () => {
round round
type='icon' type='icon'
content='at-sign' content='at-sign'
style={{ flex: 1, marginRight: StyleConstants.Spacing.S }} style={{ marginRight: StyleConstants.Spacing.S }}
onPress={() => {}} onPress={() => {}}
/> />
</DropdownMenu.Trigger> </DropdownMenu.Trigger>
@@ -129,7 +129,7 @@ const styles = StyleSheet.create({
base: { base: {
alignSelf: 'flex-end', alignSelf: 'flex-end',
flexDirection: 'row', flexDirection: 'row',
alignItems: 'stretch' alignItems: 'center'
} }
}) })

View File

@@ -0,0 +1,130 @@
import ComponentAccount from '@components/Account'
import { HeaderLeft, HeaderRight } from '@components/Header'
import Icon from '@components/Icon'
import { displayMessage } from '@components/Message'
import { ModalScrollView } from '@components/ModalScrollView'
import Selections from '@components/Selections'
import CustomText from '@components/Text'
import { TabSharedStackScreenProps } from '@utils/navigation/navigators'
import { useTimelineMutation } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, View } from 'react-native'
const TabSharedMute: React.FC<TabSharedStackScreenProps<'Tab-Shared-Report'>> = ({
navigation,
route: {
params: { account }
}
}) => {
const { colors, theme } = useTheme()
const { t } = useTranslation(['common', 'screenTabs'])
const { mutateAsync, isLoading } = useTimelineMutation({
onSuccess: () =>
displayMessage({
type: 'success',
message: t('common:message.success.message', {
function: t('componentContextMenu:account.mute.action', {
defaultValue: 'false',
context: 'false'
})
})
})
})
const [durations, setDurations] = useState<{ selected: boolean; content: string }[]>(
(['0', '1800', '3600', '86400', '604800'] as ['0', '1800', '3600', '86400', '604800']).map(
duration => ({
selected: duration === '0',
content: t(`screenTabs:shared.mute.duration.${duration}`)
})
)
)
const [notification, setNotification] = useState(false)
useEffect(() => {
navigation.setOptions({
title: t('screenTabs:shared.mute.name', { acct: `@${account.acct}` }),
headerLeft: () => (
<HeaderLeft
type='text'
content={t('common:buttons.cancel')}
onPress={() => navigation.goBack()}
/>
),
headerRight: () => (
<HeaderRight
type='text'
content={t('screenTabs:shared.mute.mute')}
destructive
destructiveColor={colors.yellow}
onPress={async () => {
await mutateAsync({
type: 'updateAccountProperty',
id: account.id,
payload: { property: 'mute', currentValue: false }
})
navigation.pop(1)
}}
loading={isLoading}
/>
)
})
}, [theme, isLoading, durations, notification, account.id])
return (
<ModalScrollView>
<View
style={{
margin: StyleConstants.Spacing.Global.PagePadding,
borderWidth: 1,
borderColor: colors.yellow,
borderRadius: StyleConstants.BorderRadius
}}
>
<ComponentAccount account={account} props={{}} />
</View>
<View
style={{
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding
}}
>
<CustomText
fontStyle='M'
style={{ color: colors.primaryDefault, marginBottom: StyleConstants.Spacing.M }}
>
{t('screenTabs:shared.mute.description')}
</CustomText>
<Selections
title={t('screenTabs:shared.mute.duration.heading')}
options={durations}
setOptions={setDurations}
/>
<Pressable
style={{ flex: 1, flexDirection: 'row', marginTop: StyleConstants.Spacing.M }}
onPress={() => setNotification(!notification)}
>
<Icon
style={{
marginTop: (StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M) / 2,
marginRight: StyleConstants.Spacing.S
}}
name={notification ? 'check-square' : 'square'}
size={StyleConstants.Font.Size.M}
color={colors.primaryDefault}
/>
<CustomText fontStyle='M' style={{ color: colors.primaryDefault }}>
{t('screenTabs:shared.mute.notification')}
</CustomText>
</Pressable>
</View>
</ModalScrollView>
)
}
export default TabSharedMute

View File

@@ -21,7 +21,6 @@ const TabSharedReport: React.FC<TabSharedStackScreenProps<'Tab-Shared-Report'>>
params: { account, status } params: { account, status }
} }
}) => { }) => {
console.log('account', account.id)
const { colors } = useTheme() const { colors } = useTheme()
const { t } = useTranslation(['common', 'screenTabs']) const { t } = useTranslation(['common', 'screenTabs'])

View File

@@ -9,6 +9,7 @@ import TabSharedToot from '@screens/Tabs/Shared/Toot'
import TabSharedUsers from '@screens/Tabs/Shared/Users' import TabSharedUsers from '@screens/Tabs/Shared/Users'
import React from 'react' import React from 'react'
import TabSharedFilter from './Filter' import TabSharedFilter from './Filter'
import TabSharedMute from './Mute'
const TabShared = ({ Stack }: { Stack: any }) => { const TabShared = ({ Stack }: { Stack: any }) => {
return ( return (
@@ -44,6 +45,12 @@ const TabShared = ({ Stack }: { Stack: any }) => {
name='Tab-Shared-History' name='Tab-Shared-History'
component={TabSharedHistory} component={TabSharedHistory}
/> />
<Stack.Screen
key='Tab-Shared-Mute'
name='Tab-Shared-Mute'
component={TabSharedMute}
options={{ presentation: 'modal' }}
/>
<Stack.Screen <Stack.Screen
key='Tab-Shared-Report' key='Tab-Shared-Report'
name='Tab-Shared-Report' name='Tab-Shared-Report'

View File

@@ -4,6 +4,7 @@ type Features =
| 'account_follow_notify' | 'account_follow_notify'
| 'notification_type_status' | 'notification_type_status'
| 'account_return_suspended' | 'account_return_suspended'
| 'mute_duration'
| 'edit_post' | 'edit_post'
| 'deprecate_auth_follow' | 'deprecate_auth_follow'
| 'notification_type_update' | 'notification_type_update'
@@ -20,6 +21,7 @@ const features: { feature: Features; version: number }[] = [
{ feature: 'account_follow_notify', version: 3.3 }, { feature: 'account_follow_notify', version: 3.3 },
{ feature: 'notification_type_status', version: 3.3 }, { feature: 'notification_type_status', version: 3.3 },
{ feature: 'account_return_suspended', version: 3.3 }, { feature: 'account_return_suspended', version: 3.3 },
{ feature: 'mute_duration', version: 3.3 },
{ feature: 'edit_post', version: 3.5 }, { feature: 'edit_post', version: 3.5 },
{ feature: 'deprecate_auth_follow', version: 3.5 }, { feature: 'deprecate_auth_follow', version: 3.5 },
{ feature: 'notification_type_update', version: 3.5 }, { feature: 'notification_type_update', version: 3.5 },

View File

@@ -104,6 +104,9 @@ export type TabSharedStackParamList = {
| { source: 'hashtag'; tag_name: Mastodon.Tag['name'] } | { source: 'hashtag'; tag_name: Mastodon.Tag['name'] }
'Tab-Shared-Hashtag': { tag_name: Mastodon.Tag['name']; queryKey?: QueryKeyTimeline } 'Tab-Shared-Hashtag': { tag_name: Mastodon.Tag['name']; queryKey?: QueryKeyTimeline }
'Tab-Shared-History': { status: Mastodon.Status; detectedLanguage: string } 'Tab-Shared-History': { status: Mastodon.Status; detectedLanguage: string }
'Tab-Shared-Mute': {
account: Pick<Mastodon.Account, 'id' | 'acct' | 'username' | 'url'>
}
'Tab-Shared-Report': { 'Tab-Shared-Report': {
account: Pick<Mastodon.Account, 'id' | 'acct' | 'username' | 'url'> account: Pick<Mastodon.Account, 'id' | 'acct' | 'username' | 'url'>
status?: Pick<Mastodon.Status, 'id' | '_remote' | 'uri'> status?: Pick<Mastodon.Status, 'id' | '_remote' | 'uri'>

View File

@@ -25,10 +25,7 @@ const useAppsQuery = (
type MutationVarsApps = { domain: string; scopes: string[] } type MutationVarsApps = { domain: string; scopes: string[] }
export const redirectUri = AuthSession.makeRedirectUri({ export const redirectUri = AuthSession.makeRedirectUri({ native: 'tooot://instance-auth' })
native: 'tooot://instance-auth',
useProxy: false
})
const mutationFunctionApps = async ({ domain, scopes }: MutationVarsApps) => { const mutationFunctionApps = async ({ domain, scopes }: MutationVarsApps) => {
return apiGeneral<Mastodon.Apps>({ return apiGeneral<Mastodon.Apps>({
method: 'post', method: 'post',
@@ -49,4 +46,5 @@ const useAppsMutation = (
return useMutation(mutationFunctionApps, options) return useMutation(mutationFunctionApps, options)
} }
export { useAppsQuery, useAppsMutation } export { useAppsMutation, useAppsQuery }

6047
yarn.lock

File diff suppressed because it is too large Load Diff