Compare commits

..

66 Commits
main ... v4.9.0

Author SHA1 Message Date
xmflsct 2a376b3d92 Merge branch 'main' into release 2023-02-27 18:57:24 +01:00
xmflsct c46f03ed37 Merge branch 'main' into release 2023-02-09 14:37:12 +01:00
xmflsct 22db1b8fad Merge branch 'main' into release 2023-02-03 16:06:31 +01:00
xmflsct c05554746f Merge branch 'main' into release 2023-02-03 14:54:28 +01:00
xmflsct 61ec9d68f6
Merge pull request #689 from tooot-app/main
Update name.txt
2023-01-30 15:37:33 +01:00
xmflsct d4178af0d7
Merge pull request #688 from tooot-app/main
Update connect.ts
2023-01-30 14:53:25 +01:00
xmflsct af5bfecb06
Merge pull request #687 from tooot-app/main
Release v4.8.6
2023-01-30 14:35:31 +01:00
xmflsct 2d72218446 Merge branch 'main' into release 2023-01-29 00:41:54 +01:00
xmflsct 6bdf53d4dc Merge branch 'main' into release 2023-01-27 23:11:40 +01:00
xmflsct f694ccda08 Merge branch 'main' into release 2023-01-17 15:35:45 +01:00
xmflsct ebee060580 Merge branch 'main' into release 2023-01-17 13:00:02 +01:00
xmflsct 6a8315e1e0 Merge branch 'main' into release 2023-01-12 21:49:28 +01:00
xmflsct 5a78a56185 Merge branch 'main' into release 2023-01-12 00:13:44 +01:00
xmflsct 3312ceaa05 Merge branch 'main' into release 2023-01-11 22:56:03 +01:00
xmflsct f401f5fcb7 Merge branch 'main' into release 2023-01-11 22:54:44 +01:00
xmflsct 9c0b33fb4e Merge branch 'main' into release 2023-01-10 14:56:21 +01:00
xmflsct 54749ddc18 Merge branch 'main' into release 2023-01-10 00:52:56 +01:00
xmflsct 0a795e427d Merge branch 'main' into release 2023-01-10 00:29:33 +01:00
xmflsct 36e61e9f95
Merge pull request #645 from tooot-app/main
Release v4.8.0
2023-01-09 22:55:52 +01:00
xmflsct 1687e5f439 Merge branch 'main' into release 2022-12-21 15:34:33 +01:00
xmflsct 176b073d27
Merge pull request #592 from tooot-app/main
Update subtitle.txt
2022-12-20 12:12:28 +01:00
xmflsct d15587797b Merge branch 'main' into release 2022-12-20 10:51:26 +01:00
xmflsct 2d365e4a39 Merge branch 'main' into release 2022-12-20 00:46:57 +01:00
xmflsct ca1e09920b Merge branch 'main' into release 2022-12-16 22:00:39 +01:00
xmflsct 5e12c1e001 Merge branch 'main' into release 2022-12-16 17:00:14 +01:00
xmflsct 67cd386117 Merge branch 'main' into release 2022-12-16 13:16:34 +01:00
xmflsct 3f8d969517 Merge branch 'main' into release 2022-12-16 10:47:34 +01:00
xmflsct 1917fbf510
Merge pull request #560 from tooot-app/main
Fix Apple emoji error
2022-12-16 01:03:25 +01:00
xmflsct 49c4b86b6a
Merge pull request #559 from tooot-app/main
Release v4.7.0
2022-12-16 00:26:36 +01:00
xmflsct 884419ef76 Merge branch 'main' into release 2022-12-05 23:21:25 +01:00
xmflsct 73fa1a81cd Merge branch 'main' into release 2022-12-05 21:31:09 +01:00
xmflsct 168218e5b1
Merge pull request #521 from tooot-app/main
Emergency release v4.6.6
2022-12-05 20:00:23 +01:00
xmflsct 21f17280af
Merge pull request #511 from tooot-app/main
Release v4.6.5
2022-12-04 21:50:32 +01:00
xmflsct ce0c14b22a Merge branch 'main' into release 2022-11-23 22:09:46 +01:00
xmflsct 354050c4ed
Merge pull request #486 from tooot-app/main
Release v4.6.3
2022-11-22 22:47:20 +01:00
xmflsct c89115b58c
Merge pull request #478 from tooot-app/main
Release v4.6.2
2022-11-20 23:36:35 +01:00
xmflsct 9cf7b2f0a8
Merge pull request #467 from tooot-app/main
Release v4.6.1
2022-11-18 00:03:16 +01:00
xmflsct eedeb6394f
Merge pull request #461 from tooot-app/main
Release 4.6
2022-11-14 19:00:04 +01:00
xmflsct 0229fc25e1 Merge branch 'main' into release 2022-11-05 23:43:53 +01:00
xmflsct e28ff17bac Merge branch 'main' into release 2022-11-05 23:24:05 +01:00
xmflsct 495449184c
Merge pull request #435 from tooot-app/main
Start building v4.5.1
2022-11-05 01:56:41 +01:00
xmflsct 7837bde155
Merge pull request #430 from tooot-app/main
Release v4.5.0
2022-11-01 00:41:07 +01:00
xmflsct 91a3f4b5d0
Merge pull request #406 from tooot-app/main
Update package.json
2022-10-12 14:57:27 +02:00
xmflsct 1ef186ec5d
Merge pull request #405 from tooot-app/main
Release v4.3.4
2022-10-11 23:23:41 +02:00
xmflsct 29fe0dc2e3 Merge branch 'main' into release 2022-09-28 23:59:07 +02:00
xmflsct 47a0cb4696 Merge branch 'main' into release 2022-09-28 23:32:10 +02:00
xmflsct 98b2f49912 Merge branch 'main' into release 2022-09-26 19:04:36 +02:00
xmflsct cd3b45f330 Merge branch 'main' into release 2022-09-25 23:50:51 +02:00
xmflsct a69e795b80
Merge pull request #396 from tooot-app/main
Release v4.3.3
2022-09-25 17:17:29 +02:00
xmflsct 6bca34cb1a
Merge pull request #393 from tooot-app/main
Release v4.3.2
2022-09-23 01:26:38 +02:00
xmflsct 48c690b782
Merge pull request #383 from tooot-app/main
Release v4.3.1
2022-09-14 23:44:05 +02:00
xmflsct 7ec6a0792a
Merge pull request #377 from tooot-app/main
Release v4.3
2022-08-19 18:28:48 +02:00
xmflsct b0064a8f70
Merge pull request #375 from tooot-app/main
Release v4.3
2022-08-19 12:23:55 +02:00
xmflsct ec67666629
Merge pull request #370 from tooot-app/main
Release v4.2
2022-08-18 00:25:42 +02:00
xmflsct 5a19009e48
Merge pull request #368 from tooot-app/main
Release v4.2
2022-08-17 15:50:23 +02:00
xmflsct ced75ba168
Merge pull request #351 from tooot-app/main
Release v4.1.6
2022-06-26 23:07:19 +02:00
xmflsct e53a1a753f
Merge pull request #349 from tooot-app/main
Release v4.1.5
2022-06-21 23:57:19 +02:00
xmflsct 033be89145
Merge pull request #345 from tooot-app/main
Release v4.1.4
2022-06-19 12:53:07 +02:00
xmflsct c116e2aeb2
Merge pull request #342 from tooot-app/main
Release v4.1.3
2022-06-17 00:15:08 +02:00
Zhiyuan Zheng 13c1dbd8bd Merge branch 'main' into release 2022-06-15 00:57:25 +02:00
Zhiyuan Zheng 61f5585dea Merge branch 'main' into release 2022-06-15 00:39:52 +02:00
xmflsct 264fe23d22
Merge pull request #341 from tooot-app/main
Release v4.1.2
2022-06-15 00:21:34 +02:00
xmflsct 77e0f32260
Merge pull request #339 from tooot-app/main
Release v4.1.2
2022-06-15 00:01:48 +02:00
Zhiyuan Zheng 31f25af66b Merge branch 'main' into release 2022-06-12 12:31:01 +02:00
xmflsct ac18abcb47
Merge pull request #335 from tooot-app/main
Release v4.1
2022-06-11 23:36:13 +02:00
xmflsct 0d1b5b9a7d
Merge pull request #333 from tooot-app/main
Release v4.1
2022-06-11 06:54:31 +02:00
181 changed files with 9172 additions and 11181 deletions

View File

@ -7,12 +7,12 @@ on:
jobs:
build-ios:
runs-on: macos-14
runs-on: macos-12
steps:
- uses: tj-actions/branch-names@v8
- uses: tj-actions/branch-names@v6
id: branch
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- run: corepack enable
@ -20,7 +20,7 @@ jobs:
- run: bundle install
- run: yarn app:build ios
env:
DEVELOPER_DIR: /Applications/Xcode_15.2.app/Contents/Developer
DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer
ENVIRONMENT: ${{ steps.branch.outputs.current_branch }}
SENTRY_ENVIRONMENT: ${{ steps.branch.outputs.current_branch }}
LC_ALL: en_US.UTF-8
@ -38,18 +38,18 @@ jobs:
GH_PAT_GET_RELEASE: ${{ secrets.GITHUB_TOKEN }}
build-android:
runs-on: macos-14
runs-on: macos-12
steps:
- uses: tj-actions/branch-names@v8
- uses: tj-actions/branch-names@v6
id: branch
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- uses: actions/setup-java@v4
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '17'
java-version: '11'
- run: corepack enable
- run: yarn install
- run: bundle install
@ -67,19 +67,19 @@ jobs:
GH_PAT_GET_RELEASE: ${{ secrets.GITHUB_TOKEN }}
create-release:
runs-on: macos-14
runs-on: macos-12
needs: [build-ios, build-android]
steps:
- uses: tj-actions/branch-names@v8
- uses: tj-actions/branch-names@v6
id: branch
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- uses: actions/setup-java@v4
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '17'
java-version: '11'
- run: corepack enable
- run: yarn install
- run: bundle install

2
.nvmrc
View File

@ -1 +1 @@
20
18

View File

@ -0,0 +1,13 @@
diff --git a/ios/EXAV/EXAudioSessionManager.m b/ios/EXAV/EXAudioSessionManager.m
index 81dce13366c3947b12c863f7b39c0237882a6c36..fa27e0a354d48a994ca46e19642a5e224d42d9a8 100644
--- a/ios/EXAV/EXAudioSessionManager.m
+++ b/ios/EXAV/EXAudioSessionManager.m
@@ -170,7 +170,7 @@ - (void)moduleDidBackground:(id)backgroundingModule
[_foregroundedModules compact];
// Any possible failures are silent
- [self _updateSessionConfiguration];
+ // [self _updateSessionConfiguration];
}
- (void)moduleDidForeground:(id)module

View File

@ -0,0 +1,14 @@
diff --git a/src/functions/Helpers.ts b/src/functions/Helpers.ts
index e04486540494891ab07ec130b686dc4acddf2d0c..265e6ac11439276a1c52c222dfc4c50daf1689ae 100644
--- a/src/functions/Helpers.ts
+++ b/src/functions/Helpers.ts
@@ -77,7 +77,8 @@ export function getNativeNodeHandle(nativeRef: React.Component){
const nodeHandle = findNodeHandle(nativeRef);
if(nodeHandle == null){
- throw new Error('Unable to get the node handle for the native ref.');
+ return 0
+ // throw new Error('Unable to get the node handle for the native ref.');
};
return nodeHandle;

View File

@ -1,64 +0,0 @@
diff --git a/ios/Sources/Common/AutoLayoutWrapperView.swift b/ios/Sources/Common/AutoLayoutWrapperView.swift
index e2b9be9c129c66eed3eaebb4e33f5456ce98f5da..ef6a0087f524c8d228b7fee31e54fc3dba769ffa 100644
--- a/ios/Sources/Common/AutoLayoutWrapperView.swift
+++ b/ios/Sources/Common/AutoLayoutWrapperView.swift
@@ -18,7 +18,11 @@ class AutoLayoutWrapperView: UIView {
override func addSubview(_ view: UIView) {
if let detachedView = view as? RNIDetachedView {
- detachedView.updateBounds(newSize: self.bounds.size);
+ do {
+ try detachedView.updateBounds(newSize: self.bounds.size);
+ } catch {
+ print("Error: \(error)");
+ };
};
super.addSubview(view);
@@ -37,7 +41,11 @@ class AutoLayoutWrapperView: UIView {
func updateSizeOfSubviews(newSize: CGSize? = nil){
self.subviews.forEach {
guard let detachedView = $0 as? RNIDetachedView else { return };
- detachedView.updateBounds(newSize: newSize ?? self.bounds.size);
+ do {
+ try detachedView.updateBounds(newSize: newSize ?? self.bounds.size);
+ } catch {
+ print("Error: \(error)");
+ };
};
};
};
diff --git a/ios/Sources/RNIContextMenuView/RNIContextMenuPreviewController.swift b/ios/Sources/RNIContextMenuView/RNIContextMenuPreviewController.swift
index 2b4dc6287c68c88d6652b963ac2cc5f59251ffa9..7c8472e90dac8359f6b40ce2c096323fcf388249 100644
--- a/ios/Sources/RNIContextMenuView/RNIContextMenuPreviewController.swift
+++ b/ios/Sources/RNIContextMenuView/RNIContextMenuPreviewController.swift
@@ -63,7 +63,11 @@ class RNIContextMenuPreviewController: UIViewController {
case .STRETCH:
guard let menuCustomPreviewView = self.menuCustomPreviewView else { return };
- menuCustomPreviewView.updateBounds(newSize: self.view.bounds.size);
+ do {
+ try menuCustomPreviewView.updateBounds(newSize: self.view.bounds.size);
+ } catch {
+ print("Error: \(error)");
+ };
self.preferredContentSize = .zero;
case .INHERIT:
diff --git a/ios/Sources/RNIContextMenuView/RNIContextMenuView.swift b/ios/Sources/RNIContextMenuView/RNIContextMenuView.swift
index affabcdee8303681f1438c6cfdb9d90d6a105ba6..7c470229e06250f4bd80d3133e381b91ff4f61c5 100644
--- a/ios/Sources/RNIContextMenuView/RNIContextMenuView.swift
+++ b/ios/Sources/RNIContextMenuView/RNIContextMenuView.swift
@@ -307,7 +307,11 @@ public class RNIContextMenuView:
.init(with: detachedView)
);
- detachedView.detach();
+ do {
+ try detachedView.detach();
+ } catch {
+ print("Error: \(error)");
+ };
};
#if DEBUG

View File

@ -1,38 +0,0 @@
diff --git a/src/zoom.tsx b/src/zoom.tsx
index 70ce1c8d6a43e711f06b93d1eda3b44a3ad9a659..cdc2713470f2d332b8bf3e9c97e38fd9b78281df 100644
--- a/src/zoom.tsx
+++ b/src/zoom.tsx
@@ -4,6 +4,7 @@ import Animated, {
useSharedValue,
useAnimatedStyle,
useDerivedValue,
+ withDecay,
withTiming,
cancelAnimation,
runOnJS,
@@ -120,11 +121,22 @@ export function Zoom(props: Props) {
}
}
})
- .onEnd(() => {
+ .onEnd((event) => {
if (isPinching.value || !isZoomed.value) return;
- panTranslateX.value = 0;
- panTranslateY.value = 0;
+ const maxTranslateX = (viewWidth.value / 2) * scale.value - viewWidth.value / 2;
+ const minTranslateX = -maxTranslateX;
+ translationX.value = withDecay({
+ velocity: event.velocityX,
+ clamp: [minTranslateX, maxTranslateX]
+ });
+
+ const maxTranslateY = (viewHeight.value / 2) * scale.value - viewHeight.value / 2;
+ const minTranslateY = -maxTranslateY;
+ translationY.value = withDecay({
+ velocity: event.velocityY,
+ clamp: [minTranslateY, maxTranslateY]
+ });
});
const pinch = Gesture.Pinch()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
compressionLevel: mixed
enableGlobalCache: false
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-4.1.0.cjs
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs
spec: "@yarnpkg/plugin-typescript"
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"

View File

@ -1,13 +1,6 @@
source "https://rubygems.org"
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.6.10"
# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
# bound in the template on Cocoapods with next React Native release.
gem 'cocoapods', '>= 1.13', '< 1.15'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
gem "fastlane"
gem 'cocoapods'
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)

View File

@ -1,47 +1,48 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.6)
CFPropertyList (3.0.5)
rexml
activesupport (7.0.4.2)
activesupport (6.1.7)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
addressable (2.8.6)
zeitwerk (~> 2.3)
addressable (2.8.1)
public_suffix (>= 2.0.2, < 6.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.3.0)
aws-partitions (1.887.0)
aws-sdk-core (3.191.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-eventstream (1.2.0)
aws-partitions (1.687.0)
aws-sdk-core (3.168.4)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.8)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.77.0)
aws-sdk-core (~> 3, >= 3.191.0)
aws-sdk-kms (1.61.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.143.0)
aws-sdk-core (~> 3, >= 3.191.0)
aws-sdk-s3 (1.117.2)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.8)
aws-sigv4 (1.8.0)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.5.2)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.1.0)
cocoapods (1.14.3)
cocoapods (1.11.3)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.14.3)
cocoapods-core (= 1.11.3)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 2.1, < 3.0)
cocoapods-downloader (>= 1.4.0, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.6.0, < 2.0)
cocoapods-trunk (>= 1.4.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
@ -49,10 +50,10 @@ GEM
gh_inspector (~> 1.0)
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 2.3.0, < 3.0)
xcodeproj (>= 1.23.0, < 2.0)
cocoapods-core (1.14.3)
activesupport (>= 5.0, < 8)
ruby-macho (>= 1.0, < 3.0)
xcodeproj (>= 1.21.0, < 2.0)
cocoapods-core (1.11.3)
activesupport (>= 5.0, < 7)
addressable (~> 2.8)
algoliasearch (~> 1.0)
concurrent-ruby (~> 1.1)
@ -62,7 +63,7 @@ GEM
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (2.1)
cocoapods-downloader (1.6.3)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
@ -74,18 +75,19 @@ GEM
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
concurrent-ruby (1.2.2)
concurrent-ruby (1.1.10)
declarative (0.0.20)
digest-crc (0.6.5)
digest-crc (0.6.4)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.6.20240107)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.8.1)
emoji_regex (3.2.3)
escape (0.0.4)
ethon (0.16.0)
ethon (0.15.0)
ffi (>= 1.15.0)
excon (0.109.0)
faraday (1.10.3)
excon (0.95.0)
faraday (1.10.2)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
@ -113,8 +115,8 @@ GEM
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.3.0)
fastlane (2.219.0)
fastimage (2.2.6)
fastlane (2.211.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
@ -133,22 +135,20 @@ GEM
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-env (>= 1.6.0, < 2.0.0)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
multipart-post (~> 2.0.0)
naturally (~> 2.2)
optparse (>= 0.1.1)
optparse (~> 0.1.1)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (~> 3)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
@ -158,15 +158,15 @@ GEM
fastlane-plugin-json (1.1.0)
fastlane-plugin-sentry (1.15.0)
os (~> 1.1, >= 1.1.4)
fastlane-plugin-versioning_android (0.1.1)
fastlane-plugin-versioning_android (0.1.0)
fastlane-plugin-yarn (1.2)
ffi (1.16.3)
ffi (1.15.5)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.54.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.3)
google-apis-androidpublisher_v3 (0.32.0)
google-apis-core (>= 0.9.1, < 2.a)
google-apis-core (0.9.2)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
@ -174,29 +174,31 @@ GEM
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
rexml
google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.31.0)
google-apis-core (>= 0.11.0, < 2.a)
google-cloud-core (1.6.1)
google-cloud-env (>= 1.0, < 3.a)
webrick
google-apis-iamcredentials_v1 (0.16.0)
google-apis-core (>= 0.9.1, < 2.a)
google-apis-playcustomapp_v1 (0.12.0)
google-apis-core (>= 0.9.1, < 2.a)
google-apis-storage_v1 (0.19.0)
google-apis-core (>= 0.9.0, < 2.a)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.3.1)
google-cloud-storage (1.47.0)
google-cloud-errors (1.3.0)
google-cloud-storage (1.44.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.31.0)
google-apis-storage_v1 (~> 0.19.0)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.8.1)
googleauth (1.3.0)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
@ -207,58 +209,63 @@ GEM
i18n (1.12.0)
concurrent-ruby (~> 1.0)
jmespath (1.6.2)
json (2.7.1)
jwt (2.7.1)
json (2.6.3)
jwt (2.6.0)
memoist (0.16.2)
mini_magick (4.12.0)
mini_mime (1.1.5)
minitest (5.18.0)
mini_mime (1.1.2)
minitest (5.16.3)
molinillo (0.8.0)
multi_json (1.15.0)
multipart-post (2.3.0)
multipart-post (2.0.0)
nanaimo (0.3.0)
nap (1.1.0)
naturally (2.2.1)
netrc (0.11.0)
optparse (0.4.0)
optparse (0.1.1)
os (1.1.4)
plist (3.7.1)
plist (3.6.0)
public_suffix (4.0.7)
rake (13.1.0)
rake (13.0.6)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.6)
rexml (3.2.5)
rouge (2.0.7)
ruby-macho (2.5.1)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
security (0.1.3)
signet (0.18.0)
signet (0.17.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.10)
simctl (1.6.8)
CFPropertyList
naturally
terminal-notifier (2.0.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.2)
tty-screen (0.8.1)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
typhoeus (1.4.1)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (2.0.6)
tzinfo (2.0.5)
concurrent-ruby (~> 1.0)
uber (0.1.0)
unicode-display_width (2.5.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
webrick (1.7.0)
word_wrap (1.0.0)
xcodeproj (1.24.0)
xcodeproj (1.22.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
@ -269,21 +276,18 @@ GEM
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
zeitwerk (2.6.1)
PLATFORMS
arm64-darwin-22
DEPENDENCIES
activesupport (>= 6.1.7.5, < 7.1.0)
cocoapods (>= 1.13, < 1.15)
cocoapods
fastlane
fastlane-plugin-json
fastlane-plugin-sentry
fastlane-plugin-versioning_android
fastlane-plugin-yarn
RUBY VERSION
ruby 3.1.2p20
BUNDLED WITH
2.3.24

View File

@ -8,20 +8,17 @@
Please **do not** create a pull request to update translation. tooot's translation is managed through [https://crowdin.tooot.app/](https://crowdin.tooot.app/) and Crowdin struggles to properly sync two ways. If there is a minor update and you do not want to register an account on Crowdin, please open an issue.
## Special thanks
- [@a_mento](https://crowdin.com/profile/a_mento) for Basques translation
- [@dzmitry.zubialevich](https://crowdin.com/profile/dzmitry.zubialevich) for Belarusian translation
- [@amrtf](https://crowdin.com/profile/amrtf) for Catalan and Spanish translation
- [@pat](https://piaille.fr/@pat) for French translation
- [@forenta](https://github.com/forenta) for German translation
- [@heracl.es](https://heracl.es/) for Greek translation
- [@pat](https://piaille.fr/@pat) for French translation
- [@andrigamerita](https://github.com/andrigamerita) for Italian translation
- [@Hikaru](https://github.com/Hikali-47041) and [@la_la](https://mstdn.jp/@la_la_la) for Japanese translation
- [@hellojaccc](https://github.com/hellojaccc) for Korean translation
- [@jan-vandenberg](https://crowdin.com/profile/jan-vandenberg) for Dutch translation
- [@gaute](https://gauteweb.net/) for Norwegian translation
- [@MStankiewiczOfficial](https://crowdin.com/profile/MStankiewiczOfficial) for Polish translation
- [@luizpicolo](https://github.com/luizpicolo) for Brazilian Portuguese
- [@janlindblom](https://github.com/janlindblom) for Swedish
- [@ihoryan](https://crowdin.com/profile/ihoryan) for Ukrainian

View File

@ -1,8 +1,9 @@
apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
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.
@ -14,8 +15,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 */
@ -50,6 +51,14 @@ 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.
*/
@ -68,11 +77,20 @@ 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
buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
@ -87,6 +105,14 @@ 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')
@ -107,9 +133,28 @@ 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";
@ -137,8 +182,13 @@ dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
implementation("com.facebook.react:flipper-integration")
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'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {

View File

@ -1,9 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application
android:usesCleartextTraffic="true"
tools:targetApi="28"
tools:ignore="GoogleAppIndexingWarning"/>
</manifest>
tools:ignore="GoogleAppIndexingWarning">
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false" />
</application>
</manifest>

View File

@ -0,0 +1,72 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package com.tooot;
import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;
import com.facebook.flipper.android.utils.FlipperUtils;
import com.facebook.flipper.core.FlipperClient;
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
import com.facebook.react.ReactInstanceEventListener;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.NetworkingModule;
import okhttp3.OkHttpClient;
/**
* Class responsible of loading Flipper inside your React Native application. This is the debug
* flavor of it. Here you can add your own plugins and customize the Flipper setup.
*/
public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
if (FlipperUtils.shouldEnableFlipper(context)) {
final FlipperClient client = AndroidFlipperClient.getInstance(context);
client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
client.addPlugin(new DatabasesFlipperPlugin(context));
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
client.addPlugin(CrashReporterPlugin.getInstance());
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
@Override
public void apply(OkHttpClient.Builder builder) {
builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
}
});
client.addPlugin(networkFlipperPlugin);
client.start();
// Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
// Hence we run if after all native modules have been initialized
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
reactInstanceManager.addReactInstanceEventListener(
new ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext reactContext) {
reactInstanceManager.removeReactInstanceEventListener(this);
reactContext.runOnNativeModulesQueueThread(
new Runnable() {
@Override
public void run() {
client.addPlugin(new FrescoFlipperPlugin());
}
});
}
});
} else {
client.addPlugin(new FrescoFlipperPlugin());
}
}
}
}

View File

@ -13,7 +13,7 @@
<!-- [Custom] Expo Notifications -->
<meta-data android:name="expo.modules.notifications.default_notification_icon" android:resource="@drawable/ic_stat_notifications" />
<!-- [Custom] End Expo Notifications -->
<activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:exported="true" android:theme="@style/Theme.App.SplashScreen" android:documentLaunchMode="never">
<activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:exported="true" android:theme="@style/Theme.App.SplashScreen" android:screenOrientation="portrait" android:documentLaunchMode="never">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>

View File

@ -0,0 +1,42 @@
package com.xmflsct.app.tooot;
import android.os.Bundle;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactActivityDelegate;
import expo.modules.ReactActivityDelegateWrapper;
public class MainActivity extends ReactActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
}
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "main";
}
/**
* Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
* DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
* (aka React 18) with two boolean flags.
*/
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new DefaultReactActivityDelegate(
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
);
}
}

View File

@ -1,61 +0,0 @@
package com.xmflsct.app.tooot;
import android.os.Build
import android.os.Bundle
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
import expo.modules.ReactActivityDelegateWrapper
class MainActivity : ReactActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Set the theme to AppTheme BEFORE onCreate to support
// coloring the background, status bar, and navigation bar.
// This is required for expo-splash-screen.
setTheme(R.style.AppTheme);
super.onCreate(null)
}
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
override fun getMainComponentName(): String = "main"
/**
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
*/
override fun createReactActivityDelegate(): ReactActivityDelegate {
return ReactActivityDelegateWrapper(
this,
BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
object : DefaultReactActivityDelegate(
this,
mainComponentName,
fabricEnabled
){})
}
/**
* Align the back button behavior with Android S
* where moving root activities to background instead of finishing activities.
* @see <a href="https://developer.android.com/reference/android/app/Activity#onBackPressed()">onBackPressed</a>
*/
override fun invokeDefaultOnBackPressed() {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
if (!moveTaskToBack(false)) {
// For non-root activities, use the default implementation to finish them.
super.invokeDefaultOnBackPressed()
}
return
}
// Use the default back button implementation on Android S
// because it's doing more than [Activity.moveTaskToBack] in fact.
super.invokeDefaultOnBackPressed()
}
}

View File

@ -0,0 +1,69 @@
package com.xmflsct.app.tooot;
import android.app.Application;
import android.content.res.Configuration;
import androidx.annotation.NonNull;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.soloader.SoLoader;
import expo.modules.ApplicationLifecycleDispatcher;
import expo.modules.ReactNativeHostWrapper;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHostWrapper(
this,
new DefaultReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@Override
protected boolean isNewArchEnabled() {
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
}
@Override
protected Boolean isHermesEnabled() {
return BuildConfig.IS_HERMES_ENABLED;
}
});
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
DefaultNewArchitectureEntryPoint.load();
}
// ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
}

View File

@ -1,58 +0,0 @@
package com.xmflsct.app.tooot;
import android.app.Application
import android.content.res.Configuration
import androidx.annotation.NonNull
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.flipper.ReactNativeFlipper
import com.facebook.soloader.SoLoader
import expo.modules.ApplicationLifecycleDispatcher
import expo.modules.ReactNativeHostWrapper
class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper(
this,
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> {
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
return PackageList(this).packages
}
override fun getJSMainModuleName(): String = "index"
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}
)
override val reactHost: ReactHost
get() = getDefaultReactHost(this.applicationContext, reactNativeHost)
override fun onCreate() {
super.onCreate()
SoLoader.init(this, false)
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
load()
}
ApplicationLifecycleDispatcher.onApplicationCreate(this)
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig)
}
}

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package com.rndiffapp;
import android.content.Context;
import com.facebook.react.ReactInstanceManager;
/**
* Class responsible of loading Flipper inside your React Native application. This is the release
* flavor of it so it's empty as we don't want to load Flipper.
*/
public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
// Do nothing as we don't want to initialize Flipper on Release.
}
}

View File

@ -1,11 +1,15 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
buildToolsVersion = "34.0.0"
buildToolsVersion = "33.0.0"
minSdkVersion = 21
compileSdkVersion = 34
targetSdkVersion = 34
ndkVersion = "25.1.8937393"
kotlinVersion = '1.8.0'
compileSdkVersion = 33
targetSdkVersion = 33
kotlinVersion = '1.8.10'
// We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
ndkVersion = "23.1.7779620"
}
repositories {
google()
@ -13,11 +17,8 @@ buildscript {
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle")
classpath("com.android.tools.build:gradle:7.4.1")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath 'com.google.gms:google-services:4.3.14'
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
}
}
apply plugin: "com.facebook.react.rootproject"

View File

@ -25,6 +25,9 @@ android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.176.1
# Use this property to specify which architecture you want to build.
# You can also override it from the CLI using
# ./gradlew <task> -PreactNativeArchitectures=x86_64
@ -40,10 +43,10 @@ newArchEnabled=false
# If set to false, you will be using JSC instead.
hermesEnabled=true
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
# org.gradle.daemon=true
# org.gradle.parallel=true
# org.gradle.configureondemand=true
org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.configureondemand=true
# The hosted JavaScript engine
# Supported values: expo.jsEngine = "hermes" | "jsc"

Binary file not shown.

View File

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

81
android/gradlew vendored
View File

@ -1,7 +1,7 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -17,56 +17,14 @@
#
##############################################################################
#
# 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/.
#
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
@ -79,11 +37,13 @@ do
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && 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"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@ -113,7 +73,6 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@ -130,29 +89,22 @@ location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
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
@ -170,9 +122,7 @@ fi
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
@ -197,27 +147,16 @@ if "$cygwin" || "$msys" ; then
done
fi
# 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"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-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.
@ -244,4 +183,4 @@ eval "set -- $(
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
exec "$JAVACMD" "$@"

17
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,7 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -69,23 +69,20 @@ goto fail
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
if "%ERRORLEVEL%"=="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!
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%
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
:omega

View File

@ -1,10 +1,11 @@
rootProject.name = 'tooot'
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute().text.trim(), "../scripts/autolinking.gradle");
useExpoModules()
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute().text.trim(), "../native_modules.gradle");
applyNativeModulesSettingsGradle(settings)
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,27 +1,26 @@
module.exports = function (api) {
api.cache(false)
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'
}
const plugins = [
'@babel/plugin-proposal-optional-chaining',
[
'module-resolver',
{
root: ['./'],
alias: {
'@components': './src/components',
'@i18n': './src/i18n',
'@screens': './src/screens',
'@utils': './src/utils'
}
]
].concat(
process.env.NODE_ENV === 'production' || process.env.BABEL_ENV === 'production'
? ['transform-remove-console']
: [],
['react-native-reanimated/plugin']
)
}
],
'react-native-reanimated/plugin'
]
if (process.env.NODE_ENV === 'production' || process.env.BABEL_ENV === 'production') {
plugins.push('transform-remove-console')
}
return { presets: ['babel-preset-expo'], plugins }
}

View File

@ -1 +1,4 @@
Enjoy toooting! This version includes improvements and fixes.
Enjoy toooting! This version includes following improvements and fixes:
- Added following remote instance
- Added set note of followed users
- Best effort load remote user's toots

View File

@ -1 +1,4 @@
tooot-ing愉快此版本包括改进和修复。
toooting愉快此版本包括以下改进和修复
- 新增关注远程实例功能
- 新增关注用户备注功能
- 加载远程用户的嘟文

View File

@ -1,13 +1,8 @@
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.4'
platform :ios, '13.0'
prepare_react_native_project!
flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
linkage = ENV['USE_FRAMEWORKS']
@ -23,8 +18,13 @@ target 'tooot' do
use_expo_modules!
config = use_native_modules!
# Flags change depending on the env values.
flags = get_default_flags()
use_react_native!(
:path => config[:reactNativePath],
:hermes_enabled => true,
:fabric_enabled => flags[:fabric_enabled],
:flipper_configuration => FlipperConfiguration.disabled,
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
@ -33,9 +33,11 @@ target 'tooot' do
post_install do |installer|
react_native_post_install(
installer,
config[:reactNativePath],
# Set `mac_catalyst_enabled` to `true` in order to apply patches
# necessary for Mac Catalyst builds
:mac_catalyst_enabled => false
)
__apply_Xcode_12_5_M1_post_install_workaround(installer)
# For share extension
installer.pods_project.targets.each do |target|
@ -43,6 +45,15 @@ target 'tooot' do
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'No'
end
end
# For Xcode 14
installer.generated_projects.each do |project|
project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end
end
end
post_integrate do |installer|
@ -56,6 +67,7 @@ end
target 'ShareExtension' do
use_react_native!(
:hermes_enabled => true,
:flipper_configuration => FlipperConfiguration.disabled
)

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +0,0 @@
"NSPhotoLibraryAddUsageDescription" = "Дазвольце tooot захоўваць выявы ў папку камеры";
"NSPhotoLibraryUsageDescription" = "Дазвольце tooot захоўваць выявы ў папку камеры";

View File

@ -1,2 +0,0 @@
"NSPhotoLibraryAddUsageDescription" = "Επιτρέψτε στο tooot να αποθηκεύει εικόνες στο ρολό της κάμερας";
"NSPhotoLibraryUsageDescription" = "Επιτρέψτε στο tooot να αποθηκεύει εικόνες στο ρολό της κάμερας";

View File

@ -1,2 +0,0 @@
"NSPhotoLibraryAddUsageDescription" = "Baimendu tooot-i irudiak zure kameraren rollean gordetzeko";
"NSPhotoLibraryUsageDescription" = "Baimendu tooot-i irudiak zure kameraren rollean gordetzeko";

View File

@ -1,2 +0,0 @@
"NSPhotoLibraryAddUsageDescription" = "Zezwól toootowi na zapisywanie zdjęć w rolce z aparatu";
"NSPhotoLibraryUsageDescription" = "Zezwól toootowi na zapisywanie zdjęć w rolce z aparatu";

View File

@ -70,17 +70,14 @@
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = tooot/SplashScreen.storyboard; sourceTree = "<group>"; };
DF8133F098604A10B0D94952 /* boop.mp3 */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = boop.mp3; path = tooot/boop.mp3; sourceTree = "<group>"; };
E613A80A28282A01003C97D6 /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = tooot/AppDelegate.mm; sourceTree = "<group>"; };
E6179D6E29B94551001930D5 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E6217B7E293C1EBF00B1755E /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E633A420281EAEAB000E540F /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
E633A427281EAEAB000E540F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E633A42F281EAF38000E540F /* ShareViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShareViewController.swift; path = "../../node_modules/react-native-share-menu/ios/ShareViewController.swift"; sourceTree = "<group>"; };
E633A431281EB55C000E540F /* ShareExtension-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ShareExtension-Bridging-Header.h"; sourceTree = "<group>"; };
E63E7FF0292A828100C76FD4 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E65BA25629EDEF8C008E0BBC /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E66C0842291F095800DFFF60 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E671BDF8290EAFB800287BD0 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
E690907B29C1133000489554 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E690AF692926B737002C38A8 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E69EBACA28DF282D0057EDEC /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E69EBACB28DF283A0057EDEC /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -88,7 +85,6 @@
E69EBACD28DF284D0057EDEC /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
E69EBACE28DF28560057EDEC /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E6A4895D293C1F740047951A /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E6B76A1E29C1147B00187ABB /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E6C8B26628F5F9FC0062CF2E /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E6D64C7A294A90840098F3AC /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E6FD3AA7299EE8A900774C18 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -225,7 +221,6 @@
buildPhases = (
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */,
FD10A7F022414F080027D42C /* Start Packager */,
395686AEA3960C8699AE1CAD /* [Expo] Configure project */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
@ -307,10 +302,6 @@
ca,
uk,
nb,
be,
eu,
pl,
el,
);
mainGroup = 83CBB9F61A601CBA00E9B192;
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
@ -386,25 +377,6 @@
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;
};
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 */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -431,14 +403,12 @@
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-tooot/Pods-tooot-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle",
"${PODS_ROOT}/Sentry/Sources/Resources/PrivacyInfo.xcprivacy",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/PrivacyInfo.xcprivacy",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@ -474,11 +444,11 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ShareExtension/Pods-ShareExtension-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@ -566,10 +536,6 @@
E6A4895D293C1F740047951A /* ca */,
E6D64C7A294A90840098F3AC /* uk */,
E6FD3AA7299EE8A900774C18 /* nb */,
E6179D6E29B94551001930D5 /* be */,
E690907B29C1133000489554 /* eu */,
E6B76A1E29C1147B00187ABB /* pl */,
E65BA25629EDEF8C008E0BBC /* el */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
@ -596,7 +562,7 @@
);
INFOPLIST_FILE = tooot/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -611,8 +577,8 @@
PRODUCT_NAME = tooot;
PROVISIONING_PROFILE_SPECIFIER = "match AdHoc com.xmflsct.app.tooot";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "tooot-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_PRECOMPILE_BRIDGING_HEADER = YES;
@ -636,7 +602,7 @@
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
INFOPLIST_FILE = tooot/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -651,8 +617,8 @@
PRODUCT_NAME = tooot;
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.xmflsct.app.tooot";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "tooot-Bridging-Header.h";
SWIFT_PRECOMPILE_BRIDGING_HEADER = YES;
SWIFT_VERSION = 5.0;
@ -666,7 +632,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
@ -703,7 +669,6 @@
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION,
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@ -720,12 +685,8 @@
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"\"";
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;
};
name = Debug;
};
@ -734,7 +695,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
@ -766,10 +727,6 @@
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION,
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
@ -784,13 +741,9 @@
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"\"";
MTL_ENABLE_DEBUG_INFO = NO;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
USE_HERMES = true;
VALIDATE_PRODUCT = YES;
};
name = Release;
@ -817,7 +770,8 @@
INFOPLIST_FILE = ShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -832,8 +786,7 @@
PROVISIONING_PROFILE_SPECIFIER = "match AdHoc com.xmflsct.app.tooot.ShareExtension";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "match AdHoc com.xmflsct.app.tooot.ShareExtension";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MACCATALYST = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "ShareExtension/ShareExtension-Bridging-Header.h";
@ -867,7 +820,8 @@
INFOPLIST_FILE = ShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -881,8 +835,7 @@
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.xmflsct.app.tooot.ShareExtension";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "match AppStore com.xmflsct.app.tooot.ShareExtension";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MACCATALYST = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "ShareExtension/ShareExtension-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-O";

View File

@ -1,7 +1,9 @@
#import <Foundation/Foundation.h>
#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>
#import <Expo/Expo.h>
@interface AppDelegate : EXAppDelegateWrapper
@interface AppDelegate : RCTAppDelegate
@end

View File

@ -14,10 +14,6 @@
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [self getBundleURL];
}
- (NSURL *)getBundleURL
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
@ -26,6 +22,16 @@
#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;
@ -45,22 +51,4 @@
restorationHandler:restorationHandler];
}
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
return [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
}
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
@end

View File

@ -35,7 +35,6 @@
<array>
<string>tooot-share</string>
<string>tooot</string>
<string>https</string>
</array>
</dict>
</array>
@ -49,11 +48,14 @@
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSAllowsLocalNetworking</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>

View File

@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>production</string>
<string>development</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>

View File

@ -1,11 +1,3 @@
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)
module.exports = {
transformer: { inlineRequires: true }
}

View File

@ -1,6 +1,6 @@
{
"name": "tooot",
"version": "4.11.0",
"version": "4.9.0",
"description": "tooot for Mastodon",
"author": "xmflsct <me@xmflsct.com>",
"license": "GPL-3.0-or-later",
@ -12,110 +12,110 @@
"start": "react-native start",
"android": "react-native run-android",
"phone": "react-native run-ios --device",
"iphone": "react-native run-ios --simulator 'iPhone 15 Pro'",
"iphone": "react-native run-ios --simulator 'iPhone 14 Pro'",
"ipad": "react-native run-ios --simulator 'iPad Pro (11-inch) (4th generation)'",
"app:build": "bundle exec fastlane",
"clean": "react-native-clean-project"
},
"dependencies": {
"@expo/react-native-action-sheet": "^4.0.1",
"@formatjs/intl-datetimeformat": "^6.12.2",
"@formatjs/intl-getcanonicallocales": "^2.3.0",
"@formatjs/intl-locale": "^3.4.5",
"@formatjs/intl-numberformat": "^8.10.0",
"@formatjs/intl-pluralrules": "^5.2.12",
"@formatjs/intl-relativetimeformat": "^11.2.12",
"@mattermost/react-native-paste-input": "^0.7.0",
"@formatjs/intl-datetimeformat": "^6.5.1",
"@formatjs/intl-getcanonicallocales": "^2.1.0",
"@formatjs/intl-locale": "^3.1.1",
"@formatjs/intl-numberformat": "^8.3.5",
"@formatjs/intl-pluralrules": "^5.1.10",
"@formatjs/intl-relativetimeformat": "^11.1.10",
"@mattermost/react-native-paste-input": "^0.6.2",
"@neverdull-agency/expo-unlimited-secure-store": "^1.0.10",
"@react-native-async-storage/async-storage": "~1.21.0",
"@react-native-camera-roll/camera-roll": "^7.4.0",
"@react-native-clipboard/clipboard": "^1.13.2",
"@react-native-community/blur": "^4.4.0",
"@react-native-community/netinfo": "^11.2.1",
"@react-native-firebase/app": "^18.8.0",
"@react-native-menu/menu": "^0.9.1",
"@react-native-segmented-control/segmented-control": "^2.5.0",
"@react-navigation/bottom-tabs": "^6.5.11",
"@react-navigation/native": "^6.1.9",
"@react-navigation/native-stack": "^6.9.17",
"@react-navigation/stack": "^6.3.20",
"@sentry/react-native": "^5.18.0",
"@sharcoux/slider": "^7.1.1",
"@tanstack/react-query": "^4.36.1",
"axios": "^1.6.7",
"@react-native-async-storage/async-storage": "~1.17.11",
"@react-native-camera-roll/camera-roll": "^5.2.4",
"@react-native-clipboard/clipboard": "^1.11.1",
"@react-native-community/blur": "^4.3.0",
"@react-native-community/netinfo": "9.3.7",
"@react-native-firebase/app": "^17.3.1",
"@react-native-menu/menu": "^0.7.3",
"@react-native-segmented-control/segmented-control": "^2.4.0",
"@react-navigation/bottom-tabs": "^6.5.6",
"@react-navigation/native": "^6.1.5",
"@react-navigation/native-stack": "^6.9.11",
"@react-navigation/stack": "^6.3.15",
"@sentry/react-native": "5.0.0",
"@sharcoux/slider": "^6.1.1",
"@tanstack/react-query": "^4.24.10",
"axios": "^1.3.4",
"diff": "^5.1.0",
"expo": "^50.0.6",
"expo-auth-session": "^5.4.0",
"expo-av": "^13.10.5",
"expo-constants": "^15.4.5",
"expo-crypto": "^12.8.0",
"expo-file-system": "^16.0.6",
"expo-haptics": "^12.8.1",
"expo-image": "^1.11.0",
"expo-linking": "^6.2.2",
"expo-localization": "^14.8.3",
"expo-notifications": "^0.27.6",
"expo-screen-capture": "^5.8.1",
"expo-screen-orientation": "^6.4.1",
"expo-secure-store": "^12.8.1",
"expo-splash-screen": "^0.26.4",
"expo-store-review": "^6.8.3",
"expo-video-thumbnails": "^7.9.0",
"expo-web-browser": "^12.8.2",
"htmlparser2": "^9.1.0",
"i18next": "^23.8.2",
"linkify-it": "^5.0.0",
"expo": "48.0.0-beta.2",
"expo-auth-session": "^4.0.3",
"expo-av": "^13.2.1",
"expo-constants": "^14.2.1",
"expo-crypto": "^12.2.1",
"expo-file-system": "^15.2.2",
"expo-haptics": "^12.2.1",
"expo-image": "^1.0.0",
"expo-linking": "^4.0.1",
"expo-localization": "^14.1.1",
"expo-notifications": "^0.18.1",
"expo-screen-capture": "^5.1.1",
"expo-screen-orientation": "^5.1.1",
"expo-secure-store": "^12.1.1",
"expo-splash-screen": "^0.18.1",
"expo-store-review": "^6.2.1",
"expo-video-thumbnails": "^7.2.1",
"expo-web-browser": "~12.1.1",
"htmlparser2": "^8.0.1",
"i18next": "^22.4.10",
"linkify-it": "^4.0.1",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^14.0.5",
"react-intl": "^6.6.2",
"react-native": "^0.73.4",
"react-native-flash-message": "^0.4.2",
"react-native-gesture-handler": "^2.15.0",
"react-native-image-picker": "^7.1.0",
"react-native-ios-context-menu": "^2.3.2",
"react-native-ios-utilities": "^4.3.0",
"react-i18next": "^12.2.0",
"react-intl": "^6.2.10",
"react-native": "^0.71.3",
"react-native-flash-message": "^0.4.0",
"react-native-gesture-handler": "~2.9.0",
"react-native-image-picker": "^5.1.0",
"react-native-ios-context-menu": "^1.15.3",
"react-native-language-detection": "^0.2.2",
"react-native-mmkv": "^2.11.0",
"react-native-pager-view": "^6.2.3",
"react-native-quick-base64": "^2.0.8",
"react-native-reanimated": "^3.6.2",
"react-native-mmkv": "~2.7.0",
"react-native-pager-view": "^6.1.4",
"react-native-quick-base64": "^2.0.5",
"react-native-reanimated": "^3.0.0-rc.10",
"react-native-reanimated-zoom": "^0.3.3",
"react-native-safe-area-context": "^4.9.0",
"react-native-screens": "^3.29.0",
"react-native-safe-area-context": "^4.5.0",
"react-native-screens": "^3.20.0",
"react-native-share-menu": "^6.0.0",
"react-native-svg": "^14.1.0",
"react-native-svg": "^13.8.0",
"react-native-swipe-list-view": "^3.2.9",
"react-native-tab-view": "^3.5.2",
"react-native-tab-view": "^3.5.0",
"rn-placeholder": "^3.0.3",
"zeego": "^1.7.2"
"url-parse": "^1.5.10",
"zeego": "^1.0.2"
},
"devDependencies": {
"@babel/core": "^7.23.9",
"@babel/core": "^7.21.0",
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
"@babel/preset-typescript": "^7.23.3",
"@expo/config": "^8.5.4",
"@react-native/metro-config": "^0.73.5",
"@react-native/typescript-config": "^0.74.0",
"@types/diff": "^5.0.9",
"@types/linkify-it": "^3.0.5",
"@types/lodash": "^4.14.202",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.18",
"@types/react-native-share-menu": "^5.0.5",
"@babel/preset-typescript": "^7.21.0",
"@expo/config": "^8.0.2",
"@types/diff": "^5.0.2",
"@types/linkify-it": "^3.0.2",
"@types/lodash": "^4.14.191",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@types/react-native-share-menu": "^5.0.2",
"@types/url-parse": "^1.4.8",
"babel-plugin-module-resolver": "^5.0.0",
"babel-plugin-transform-remove-console": "^6.9.4",
"chalk": "^4.1.2",
"dotenv": "^16.4.1",
"react-native-clean-project": "^4.0.3",
"typescript": "^5.3.3"
"deprecated-react-native-prop-types": "^4.0.0",
"dotenv": "^16.0.3",
"react-native-clean-project": "^4.0.1",
"typescript": "^4.9.5"
},
"packageManager": "yarn@4.1.0",
"packageManager": "yarn@3.3.1",
"resolutions": {
"expo-av@^13.0.2": "patch:expo-av@npm%3A13.0.2#./.yarn/patches/expo-av-npm-13.0.2-7a651776f1.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",
"react-native-ios-context-menu@^2.3.2": "patch:react-native-ios-context-menu@npm%3A2.3.2#~/.yarn/patches/react-native-ios-context-menu-npm-2.3.2-9099ed7858.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-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"
}
}

View File

@ -1,7 +1,7 @@
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { connectMedia } from '@utils/api/helpers/connect'
import { useTheme } from '@utils/styles/ThemeManager'
import { Image, ImageContentFit, ImageSource, ImageStyle } from 'expo-image'
import { Image, ImageSource, ImageStyle } from 'expo-image'
import React, { useState } from 'react'
import { AccessibilityProps, Pressable, StyleProp, View, ViewStyle } from 'react-native'
@ -21,7 +21,6 @@ export interface Props {
onPress?: () => void
style?: StyleProp<ViewStyle>
imageStyle?: ImageStyle
contentFit?: ImageContentFit
dim?: boolean
withoutTransition?: boolean
@ -37,7 +36,6 @@ const GracefullyImage = ({
onPress,
style,
imageStyle,
contentFit,
dim,
withoutTransition = false,
enableLiveTextInteraction = false
@ -65,7 +63,6 @@ const GracefullyImage = ({
source={hidden ? sources.blurhash : connectMedia(source)}
{...(!withoutTransition && !reduceMotionEnabled && { transition: { duration: 120 } })}
style={{ flex: 1, ...imageStyle }}
contentFit={contentFit}
onError={() => {
if (
sources.default?.uri &&

View File

@ -4,10 +4,9 @@ import { TabLocalStackParamList } from '@utils/navigation/navigators'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { PropsWithChildren, useState } from 'react'
import { Dimensions, Pressable, Text, View } from 'react-native'
import { Dimensions, Pressable, View } from 'react-native'
import Sparkline from './Sparkline'
import CustomText from './Text'
import { sumBy } from 'lodash'
export interface Props {
hashtag: Mastodon.Tag
@ -30,8 +29,6 @@ const ComponentHashtag: React.FC<PropsWithChildren & Props> = ({
const width = Dimensions.get('window').width / 4
const [height, setHeight] = useState<number>(0)
const sum = sumBy(hashtag.history, h => parseInt(h.uses))
return (
<Pressable
accessibilityRole='button'
@ -44,24 +41,17 @@ const ComponentHashtag: React.FC<PropsWithChildren & Props> = ({
}}
onPress={customOnPress || onPress}
>
<View
<CustomText
fontStyle='M'
style={{
flexShrink: 1,
color: colors.primaryDefault,
paddingRight: StyleConstants.Spacing.M
}}
numberOfLines={1}
>
<CustomText fontStyle='M' style={{ color: colors.primaryDefault }} numberOfLines={1}>
#{hashtag.name}
{sum ? (
<>
{' '}
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
({sumBy(hashtag.history, h => parseInt(h.uses))})
</CustomText>
</>
) : null}
</CustomText>
</View>
#{hashtag.name}
</CustomText>
{hashtag.history?.length ? (
<View
style={{ flexDirection: 'row', alignItems: 'center', alignSelf: 'stretch' }}
@ -76,7 +66,6 @@ const ComponentHashtag: React.FC<PropsWithChildren & Props> = ({
width={width}
height={height}
margin={children ? StyleConstants.Spacing.S : undefined}
color={!sum ? colors.disabled : undefined}
/>
{children}
</View>

View File

@ -1,6 +1,5 @@
import Icon, { IconName } from '@components/Icon'
import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
@ -10,7 +9,7 @@ export type Props = {
native?: boolean
background?: boolean
onPress?: () => void
onPress: () => void
} & ({ type?: undefined; content?: IconName } | { type: 'text'; content: string })
const HeaderLeft: React.FC<Props> = ({
@ -20,7 +19,6 @@ const HeaderLeft: React.FC<Props> = ({
background = false,
onPress
}) => {
const navigation = useNavigation()
const { colors } = useTheme()
const children = () => {
@ -42,7 +40,7 @@ const HeaderLeft: React.FC<Props> = ({
return (
<Pressable
onPress={onPress ? onPress : () => navigation.goBack()}
onPress={onPress}
children={children()}
style={{
flexDirection: 'row',

View File

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

View File

@ -21,15 +21,15 @@ import { useTheme } from '@utils/styles/ThemeManager'
import * as AuthSession from 'expo-auth-session'
import * as Crypto from 'expo-crypto'
import { Image } from 'expo-image'
import * as Linking from 'expo-linking'
import * as WebBrowser from 'expo-web-browser'
import { debounce } from 'lodash'
import React, { RefObject, useCallback, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { Alert, KeyboardAvoidingView, Platform, TextInput, View } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
import { fromByteArray } from 'react-native-quick-base64'
import parse from 'url-parse'
import CustomText from '../Text'
import openLink from '@components/openLink'
export interface Props {
scrollViewRef?: RefObject<ScrollView>
@ -51,8 +51,8 @@ const ComponentInstance: React.FC<Props> = ({
const whitelisted: boolean =
!!domain.length &&
!!errorCode &&
!!(Linking.parse(`https://${domain}/`).hostname === domain) &&
(errorCode === 401 || errorCode === 500)
!!(parse(`https://${domain}/`).hostname === domain) &&
errorCode === 401
const instanceQuery = useInstanceQuery({
domain,
@ -129,10 +129,9 @@ const ComponentInstance: React.FC<Props> = ({
(instanceQuery.data as Mastodon.Instance_V2)?.domain ||
instanceQuery.data?.account_domain ||
((instanceQuery.data as Mastodon.Instance_V1)?.uri
? Linking.parse((instanceQuery.data as Mastodon.Instance_V1).uri).hostname
? parse((instanceQuery.data as Mastodon.Instance_V1).uri).hostname
: undefined) ||
(instanceQuery.data as Mastodon.Instance_V1)?.uri ||
domain,
(instanceQuery.data as Mastodon.Instance_V1)?.uri,
'auth.account.avatar_static': avatar_static,
version: instanceQuery.data?.version || '0',
preferences: undefined,
@ -387,12 +386,20 @@ const ComponentInstance: React.FC<Props> = ({
<CustomText
accessible
style={{ color: colors.blue }}
onPress={async () => openLink('https://tooot.app/privacy-policy')}
onPress={async () =>
WebBrowser.openBrowserAsync('https://tooot.app/privacy-policy', {
...(await browserPackage())
})
}
/>,
<CustomText
accessible
style={{ color: colors.blue }}
onPress={async () => openLink('https://tooot.app/terms-of-service')}
onPress={async () =>
WebBrowser.openBrowserAsync('https://tooot.app/terms-of-service', {
...(await browserPackage())
})
}
/>
]}
/>

View File

@ -223,7 +223,7 @@ const ParseHTML: React.FC<Props> = ({
key={index}
style={{ lineHeight: adaptedLineheight ? adaptedLineheight / 2 : undefined }}
>
{'\n\n'}
{'\n'}
</Text>
)
case 'p':

View File

@ -1,18 +1,18 @@
import { useTheme } from '@utils/styles/ThemeManager'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { Pressable, View } from 'react-native'
import haptics from './haptics'
import Icon from './Icon'
import { ParseEmojis } from './Parse'
import CustomText from './Text'
import haptics from './haptics'
export interface Props {
title?: string
multiple?: boolean
options: { selected: boolean; content: string }[]
setOptions: React.Dispatch<React.SetStateAction<any>>
setOptions: React.Dispatch<React.SetStateAction<{ selected: boolean; content: string }[]>>
disabled?: boolean
invalid?: boolean
}

View File

@ -22,7 +22,7 @@ const ComponentSeparator: React.FC<Props> = ({
style,
{
backgroundColor: colors.backgroundDefault,
borderTopColor: colors.separator,
borderTopColor: colors.border,
borderTopWidth: 1,
marginLeft: StyleConstants.Spacing.Global.PagePadding + extraMarginLeft,
marginRight: StyleConstants.Spacing.Global.PagePadding + extraMarginRight

View File

@ -8,10 +8,9 @@ export interface Props {
width: number
height: number
margin?: number
color?: string
}
const Sparkline: React.FC<Props> = ({ data, width, height, margin = 0, color }) => {
const Sparkline: React.FC<Props> = ({ data, width, height, margin = 0 }) => {
const { colors } = useTheme()
const dataToPoints = ({
@ -71,10 +70,10 @@ const Sparkline: React.FC<Props> = ({ data, width, height, margin = 0, color })
return (
<Svg height={height} width={width} style={{ marginRight: margin }} fill='none'>
<G>
<Path d={'M' + fillPoints.join(' ')} fill={color || colors.blue} fillOpacity={0.1} />
<Path d={'M' + fillPoints.join(' ')} fill={colors.blue} fillOpacity={0.1} />
<Path
d={'M' + linePoints.join(' ')}
stroke={color || colors.blue}
stroke={colors.blue}
strokeWidth={1}
strokeLinejoin='round'
strokeLinecap='round'

View File

@ -1,3 +1,6 @@
import menuInstance from '@components/contextMenu/instance'
import menuShare from '@components/contextMenu/share'
import menuStatus from '@components/contextMenu/status'
import TimelineActioned from '@components/Timeline/Shared/Actioned'
import TimelineActions from '@components/Timeline/Shared/Actions'
import TimelineAttachment from '@components/Timeline/Shared/Attachment'
@ -16,8 +19,9 @@ import { usePreferencesQuery } from '@utils/queryHooks/preferences'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useRef, useState } from 'react'
import React, { Fragment, useRef, useState } from 'react'
import { Pressable, StyleProp, View, ViewStyle } from 'react-native'
import * as ContextMenu from 'zeego/context-menu'
import StatusContext from './Shared/Context'
import TimelineFeedback from './Shared/Feedback'
import TimelineFiltered, { FilteredProps, shouldFilter } from './Shared/Filtered'
@ -122,6 +126,15 @@ const TimelineDefault: React.FC<Props> = ({
</>
)
const mShare = menuShare({
visibility: status.visibility,
type: 'status',
url: status.url || status.uri,
rawContent
})
const mStatus = menuStatus({ status, queryKey })
const mInstance = menuInstance({ status, queryKey })
if (!isMyAccount) {
let filterResults: FilteredProps['filterResults'] = []
const [filterRevealed, setFilterRevealed] = useState(false)
@ -170,14 +183,67 @@ const TimelineDefault: React.FC<Props> = ({
<View style={mainStyle}>{main()}</View>
) : (
<>
<Pressable
accessible={highlighted ? false : true}
style={mainStyle}
disabled={highlighted}
onPress={() => navigation.push('Tab-Shared-Toot', { toot: status })}
onLongPress={() => {}}
children={main()}
/>
<ContextMenu.Root>
<ContextMenu.Trigger>
<Pressable
accessible={highlighted ? false : true}
style={mainStyle}
disabled={highlighted}
onPress={() => navigation.push('Tab-Shared-Toot', { toot: status })}
onLongPress={() => {}}
children={main()}
/>
</ContextMenu.Trigger>
<ContextMenu.Content>
{[mShare, mStatus, mInstance].map((menu, i) => (
<Fragment key={i}>
{menu.map((group, index) => (
<ContextMenu.Group key={index}>
{group.map(item => {
switch (item.type) {
case 'item':
return (
<ContextMenu.Item key={item.key} {...item.props}>
<ContextMenu.ItemTitle children={item.title} />
{item.icon ? (
<ContextMenu.ItemIcon ios={{ name: item.icon }} />
) : null}
</ContextMenu.Item>
)
case 'sub':
return (
// @ts-ignore
<ContextMenu.Sub key={item.key}>
<ContextMenu.SubTrigger
key={item.trigger.key}
{...item.trigger.props}
>
<ContextMenu.ItemTitle children={item.trigger.title} />
{item.trigger.icon ? (
<ContextMenu.ItemIcon ios={{ name: item.trigger.icon }} />
) : null}
</ContextMenu.SubTrigger>
<ContextMenu.SubContent>
{item.items.map(sub => (
<ContextMenu.Item key={sub.key} {...sub.props}>
<ContextMenu.ItemTitle children={sub.title} />
{sub.icon ? (
<ContextMenu.ItemIcon ios={{ name: sub.icon }} />
) : null}
</ContextMenu.Item>
))}
</ContextMenu.SubContent>
</ContextMenu.Sub>
)
}
})}
</ContextMenu.Group>
))}
</Fragment>
))}
</ContextMenu.Content>
</ContextMenu.Root>
<TimelineHeaderAndroid />
</>
)}

View File

@ -1,3 +1,6 @@
import menuInstance from '@components/contextMenu/instance'
import menuShare from '@components/contextMenu/share'
import menuStatus from '@components/contextMenu/status'
import TimelineActioned from '@components/Timeline/Shared/Actioned'
import TimelineActions from '@components/Timeline/Shared/Actions'
import TimelineAttachment from '@components/Timeline/Shared/Attachment'
@ -15,8 +18,9 @@ import { usePreferencesQuery } from '@utils/queryHooks/preferences'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useState } from 'react'
import React, { Fragment, useState } from 'react'
import { Pressable, View } from 'react-native'
import * as ContextMenu from 'zeego/context-menu'
import StatusContext from './Shared/Context'
import TimelineFiltered, { FilteredProps, shouldFilter } from './Shared/Filtered'
import TimelineFullConversation from './Shared/FullConversation'
@ -62,16 +66,14 @@ const TimelineNotifications: React.FC<Props> = ({ notification, queryKey }) => {
<View
style={{
opacity: [
'follow',
'follow_request',
'mention',
'status',
'poll',
'admin.sign_up'
].includes(notification.type)
? 1
: 0.5
opacity:
notification.type === 'follow' ||
notification.type === 'follow_request' ||
notification.type === 'mention' ||
notification.type === 'status' ||
notification.type === 'admin.sign_up'
? 1
: 0.5
}}
>
<View style={{ flex: 1, width: '100%', flexDirection: 'row' }}>
@ -98,6 +100,14 @@ const TimelineNotifications: React.FC<Props> = ({ notification, queryKey }) => {
)
}
const mShare = menuShare({
visibility: notification.status?.visibility,
type: 'status',
url: notification.status?.url || notification.status?.uri
})
const mStatus = menuStatus({ status: notification.status, queryKey })
const mInstance = menuInstance({ status: notification.status, queryKey })
if (!isMyAccount) {
let filterResults: FilteredProps['filterResults'] = []
const [filterRevealed, setFilterRevealed] = useState(false)
@ -133,18 +143,67 @@ const TimelineNotifications: React.FC<Props> = ({ notification, queryKey }) => {
spoilerHidden
}}
>
<Pressable
style={{
padding: StyleConstants.Spacing.Global.PagePadding,
backgroundColor: colors.backgroundDefault,
paddingBottom: notification.status ? 0 : StyleConstants.Spacing.Global.PagePadding
}}
onPress={() =>
notification.status && navigation.push('Tab-Shared-Toot', { toot: notification.status })
}
onLongPress={() => {}}
children={main()}
/>
<ContextMenu.Root>
<ContextMenu.Trigger>
<Pressable
style={{
padding: StyleConstants.Spacing.Global.PagePadding,
backgroundColor: colors.backgroundDefault,
paddingBottom: notification.status ? 0 : StyleConstants.Spacing.Global.PagePadding
}}
onPress={() =>
notification.status &&
navigation.push('Tab-Shared-Toot', { toot: notification.status })
}
onLongPress={() => {}}
children={main()}
/>
</ContextMenu.Trigger>
<ContextMenu.Content>
{[mShare, mStatus, mInstance].map((menu, i) => (
<Fragment key={i}>
{menu.map((group, index) => (
<ContextMenu.Group key={index}>
{group.map(item => {
switch (item.type) {
case 'item':
return (
<ContextMenu.Item key={item.key} {...item.props}>
<ContextMenu.ItemTitle children={item.title} />
{item.icon ? <ContextMenu.ItemIcon ios={{ name: item.icon }} /> : null}
</ContextMenu.Item>
)
case 'sub':
return (
// @ts-ignore
<ContextMenu.Sub key={item.key}>
<ContextMenu.SubTrigger key={item.trigger.key} {...item.trigger.props}>
<ContextMenu.ItemTitle children={item.trigger.title} />
{item.trigger.icon ? (
<ContextMenu.ItemIcon ios={{ name: item.trigger.icon }} />
) : null}
</ContextMenu.SubTrigger>
<ContextMenu.SubContent>
{item.items.map(sub => (
<ContextMenu.Item key={sub.key} {...sub.props}>
<ContextMenu.ItemTitle children={sub.title} />
{sub.icon ? (
<ContextMenu.ItemIcon ios={{ name: sub.icon }} />
) : null}
</ContextMenu.Item>
))}
</ContextMenu.SubContent>
</ContextMenu.Sub>
)
}
})}
</ContextMenu.Group>
))}
</Fragment>
))}
</ContextMenu.Content>
</ContextMenu.Root>
<TimelineHeaderAndroid />
</StatusContext.Provider>
)

View File

@ -218,7 +218,6 @@ const TimelineRefresh: React.FC<Props> = ({
}
isFetchingPrev.value = false
})
.catch(() => (isFetchingPrev.value = false))
}
const runFetchLatest = async () => {

View File

@ -10,7 +10,6 @@ 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'
@ -35,30 +34,11 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
content={content}
emojis={account.emojis}
size='S'
style={{ flex: 1, color: action === 'admin.report' ? colors.red : colors.primaryDefault }}
style={{ 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) {
@ -83,8 +63,7 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
color={iconColor}
style={styles.icon}
/>
<Pressable onPress={onPress} style={{ flexDirection: 'row', alignItems: 'center' }}>
{miniAvatar}
<Pressable onPress={onPress}>
{content(t('shared.actioned.favourite', { name }))}
</Pressable>
</>
@ -98,8 +77,7 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
color={iconColor}
style={styles.icon}
/>
<Pressable onPress={onPress} style={{ flexDirection: 'row', alignItems: 'center' }}>
{miniAvatar}
<Pressable onPress={onPress}>
{content(t('shared.actioned.follow', { name }))}
</Pressable>
</>
@ -113,8 +91,7 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
color={iconColor}
style={styles.icon}
/>
<Pressable onPress={onPress} style={{ flexDirection: 'row', alignItems: 'center' }}>
{miniAvatar}
<Pressable onPress={onPress}>
{content(t('shared.actioned.follow_request', { name }))}
</Pressable>
</>
@ -141,8 +118,7 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
color={iconColor}
style={styles.icon}
/>
<Pressable onPress={onPress} style={{ flexDirection: 'row', alignItems: 'center' }}>
{!myself ? miniAvatar : null}
<Pressable onPress={onPress}>
{content(
isNotification
? t('shared.actioned.reblog.notification', { name })
@ -162,8 +138,7 @@ const TimelineActioned: React.FC<Props> = ({ action, isNotification, ...rest })
color={iconColor}
style={styles.icon}
/>
<Pressable onPress={onPress} style={{ flexDirection: 'row', alignItems: 'center' }}>
{miniAvatar}
<Pressable onPress={onPress}>
{content(t('shared.actioned.status', { name }))}
</Pressable>
</>

View File

@ -1,40 +1,24 @@
import ComponentAccount from '@components/Account'
import GracefullyImage from '@components/GracefullyImage'
import CustomText from '@components/Text'
import openLink from '@components/openLink'
import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
import { isDevelopment } from '@utils/helpers/checkEnvironment'
import { urlMatcher } from '@utils/helpers/urlMatcher'
import { TabLocalStackParamList } from '@utils/navigation/navigators'
import { useAccountQuery } from '@utils/queryHooks/account'
import { useStatusQuery } from '@utils/queryHooks/status'
import { useTheme } from '@utils/styles/ThemeManager'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, View } from 'react-native'
import TimelineDefault from '../../Default'
import StatusContext from '../Context'
import { CardNeodb } from './Neodb'
const CARD_URL_BLACKLISTS = ['weibo.com', 'weibo.cn']
import TimelineDefault from '../Default'
import StatusContext from './Context'
const TimelineCard: React.FC = () => {
const { status, spoilerHidden, disableDetails, inThread } = useContext(StatusContext)
if (!status || !status.card) return null
if (CARD_URL_BLACKLISTS.find(domain => status.card?.url.includes(`${domain}/`))) return null
const { i18n } = useTranslation()
if (
(status.card.url.includes('://neodb.social/') &&
i18n.language.toLowerCase().startsWith('zh-hans')) ||
isDevelopment
) {
return <CardNeodb />
}
const { colors } = useTheme()
const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()

View File

@ -1,196 +0,0 @@
import GracefullyImage from '@components/GracefullyImage'
import CustomText from '@components/Text'
import openLink from '@components/openLink'
import { useNeodbQuery } from '@utils/queryHooks/neodb'
import { useTheme } from '@utils/styles/ThemeManager'
import { StyleConstants } from '@utils/styles/constants'
import * as Linking from 'expo-linking'
import { useContext, useState } from 'react'
import { Pressable, View } from 'react-native'
import StatusContext from '../Context'
import { Rating } from './Rating'
export const CardNeodb: React.FC = () => {
const { status } = useContext(StatusContext)
const { colors } = useTheme()
const path = Linking.parse(status?.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<number>()
const { data } = useNeodbQuery({ path })
if (!data) return null
const Content = ({ heading, details }: { heading: string[]; details: string[] }) => (
<Pressable
style={{
marginTop: StyleConstants.Spacing.M,
backgroundColor: colors.shimmerDefault,
borderRadius: StyleConstants.BorderRadius,
padding: StyleConstants.Spacing.S,
flexDirection: 'row'
}}
onPress={() => status?.card?.url && openLink(status.card.url)}
>
{data.cover_image_url ? (
<GracefullyImage
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
}}
style={{ marginRight: StyleConstants.Spacing.S }}
imageStyle={{ borderRadius: StyleConstants.BorderRadius / 2 }}
dim
/>
) : null}
<View style={{ flex: 1, gap: StyleConstants.Spacing.S, justifyContent: 'space-between' }}>
<View style={{ gap: StyleConstants.Spacing.S }}>
<CustomText
fontStyle='S'
fontWeight='Bold'
style={{ color: colors.primaryDefault }}
numberOfLines={3}
onTextLayout={({ nativeEvent }) =>
!headingLines && setHeadingLines(nativeEvent.lines.length)
}
children={heading.filter(d => d).join(' ')}
/>
<Rating rating={data.rating / 2} />
</View>
<CustomText
fontStyle='S'
style={{ color: colors.secondary }}
numberOfLines={4 - (headingLines || 3)}
children={details.filter(d => d).join(' / ')}
/>
</View>
</Pressable>
)
switch (segments[0]) {
case 'movie':
return (
<Content
heading={[data.title, data.orig_title, data.year ? `(${data.year})` : null]}
details={[
data.duration
? parseInt(data.duration).toString() === data.duration
? `${data.duration}分钟`
: data.duration
: null,
data.area?.join(' '),
data.genre?.join(' '),
data.director?.join(' ')
]}
/>
)
case 'book':
return (
<Content
heading={[data.title]}
details={[
data.author?.join(' '),
data.pages ? `${data.pages}` : null,
data.language,
data.pub_house
]}
/>
)
case 'tv':
if (segments[1] === 'season') {
return (
<Content
heading={[data.title, data.orig_title, data.year ? `(${data.year})` : null]}
details={[
data.season_number ? `${data.season_number}` : null,
data.episode_count ? `${data.episode_count}` : null,
data.area?.join(' '),
data.genre?.join(' '),
data.director?.join(' ')
]}
/>
)
} else {
return (
<Content
heading={[data.title, data.orig_title, data.year ? `(${data.year})` : null]}
details={[
data.season_count ? `${data.season_count}` : null,
data.area?.join(' '),
data.genre?.join(' '),
data.director?.join(' ')
]}
/>
)
}
case 'game':
return (
<Content
heading={[data.title]}
details={[
data.genre?.join(' '),
data.developer?.join(' '),
data.platform?.join(' '),
data.release_date
]}
/>
)
case 'album':
return (
<Content
heading={[data.title]}
details={[
data.artist.join(' '),
data.release_date,
data.duration,
data.genre.join(' '),
data.company.join(' ')
]}
/>
)
case 'podcast':
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

@ -1,57 +0,0 @@
import { StyleConstants } from '@utils/styles/constants'
import { View } from 'react-native'
import { Star } from './Star'
interface StarRatingProps {
rating?: number
unit?: 'full' | 'half' | 'float'
size?: number
count?: number
roundedCorner?: boolean
}
const starUnitMap = {
full: 100,
half: 50,
float: 10
}
export const Rating: React.FC<StarRatingProps> = ({
rating,
size = StyleConstants.Font.Size.M,
count = 5,
roundedCorner = true,
unit = 'float'
}) => {
if (!rating) return null
const unitValue = starUnitMap[unit]
const getSelectedOffsetPercent = (starIndex: number) => {
const roundedSelectedValue = Math.floor(rating)
if (starIndex < roundedSelectedValue) {
return 100
} else if (starIndex > roundedSelectedValue) {
return 0
} else {
const currentStarOffsetPercentage = (rating % 1) * 100
return Math.ceil(currentStarOffsetPercentage / unitValue) * unitValue
}
}
return (
<View style={{ flexDirection: 'row' }}>
{Array.from({ length: count }, (v, i) => {
return (
<Star
key={i}
size={size}
strokeLinejoin={roundedCorner ? 'round' : 'miter'}
strokeLinecap={roundedCorner ? 'round' : 'butt'}
offset={getSelectedOffsetPercent(i)}
/>
)
})}
</View>
)
}

View File

@ -1,48 +0,0 @@
import { useTheme } from '@utils/styles/ThemeManager'
import { uniqueId } from 'lodash'
import { Defs, LinearGradient, Path, Stop, Svg } from 'react-native-svg'
interface StarProps {
size: number
strokeLinejoin: 'miter' | 'round'
strokeLinecap: 'butt' | 'round'
offset: number
}
const NUM_POINT = 5
export const Star: React.FC<StarProps> = ({ size, strokeLinejoin, strokeLinecap, offset }) => {
const { colors } = useTheme()
const innerRadius = 25
const outerRadius = 50
const id = uniqueId()
const center = Math.max(innerRadius, outerRadius)
const angle = Math.PI / NUM_POINT
const points = []
for (let i = 0; i < NUM_POINT * 2; i++) {
let radius = i % 2 === 0 ? outerRadius : innerRadius
points.push(center + radius * Math.sin(i * angle))
points.push(center - radius * Math.cos(i * angle))
}
return (
<Svg width={size} height={size} viewBox={`0 0 100 100`}>
<Defs>
<LinearGradient id={id} x1='0' x2='100%' y1='0' y2='0'>
<Stop offset={`0%`} stopColor={colors.yellow} />
<Stop offset={`${offset}%`} stopColor={colors.yellow} />
<Stop offset={`${offset}%`} stopColor={colors.secondary} />
</LinearGradient>
</Defs>
<Path
d={`M${points.toString()}Z`}
fill={`url(#${id})`}
strokeLinejoin={strokeLinejoin}
strokeLinecap={strokeLinecap}
/>
</Svg>
)
}

View File

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

View File

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

View File

@ -1,5 +1,4 @@
import menuAccount from '@components/contextMenu/account'
import menuInstance from '@components/contextMenu/instance'
import menuShare from '@components/contextMenu/share'
import menuStatus from '@components/contextMenu/status'
import Icon from '@components/Icon'
@ -18,8 +17,7 @@ import HeaderSharedReplies from './HeaderShared/Replies'
import HeaderSharedVisibility from './HeaderShared/Visibility'
const TimelineHeaderDefault: React.FC = () => {
const { queryKey, status, disableDetails, rawContent, isRemote, highlighted } =
useContext(StatusContext)
const { queryKey, status, disableDetails, rawContent, isRemote } = useContext(StatusContext)
if (!status) return null
const { colors } = useTheme()
@ -39,7 +37,6 @@ const TimelineHeaderDefault: React.FC = () => {
...(status && { status })
})
const mStatus = menuStatus({ status, queryKey })
const mInstance = highlighted ? menuInstance({ status, queryKey }) : []
return (
<View style={{ flex: 1, flexDirection: 'row' }}>
@ -90,7 +87,7 @@ const TimelineHeaderDefault: React.FC = () => {
</DropdownMenu.Trigger>
<DropdownMenu.Content>
{[mShare, mAccount, mStatus, mInstance].map((menu, i) => (
{[mShare, mAccount, mStatus].map((menu, i) => (
<Fragment key={i}>
{menu.map((group, index) => (
<DropdownMenu.Group key={index}>
@ -108,7 +105,7 @@ const TimelineHeaderDefault: React.FC = () => {
case 'sub':
return (
// @ts-ignore
<DropdownMenu.Sub key={item.key}>
<DropdownMenu.Sub key={item}>
<DropdownMenu.SubTrigger
key={item.trigger.key}
{...item.trigger.props}

View File

@ -1,4 +1,3 @@
import Icon from '@components/Icon'
import ComponentSeparator from '@components/Separator'
import CustomText from '@components/Text'
import TimelineDefault from '@components/Timeline/Default'
@ -11,20 +10,12 @@ import {
setAccountStorage,
useGlobalStorageListener
} from '@utils/storage/actions'
import { useTheme } from '@utils/styles/ThemeManager'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import { throttle } from 'lodash'
import React, { RefObject, useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import {
FlatList,
FlatListProps,
Platform,
Pressable,
RefreshControl,
StyleProp,
ViewStyle
} from 'react-native'
import { FlatList, FlatListProps, Platform, RefreshControl } from 'react-native'
import Animated, {
Easing,
runOnJS,
@ -136,27 +127,6 @@ const Timeline: React.FC<Props> = ({
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 fetchingType = useSharedValue<0 | 1 | 2>(0)
@ -199,9 +169,10 @@ const Timeline: React.FC<Props> = ({
throttle(() => {
if (readMarker) {
const currentMarker = getAccountStorage.string(readMarker) || '0'
// setAccountStorage([{ key: readMarker, value: '108425743226508521' }])
if (latestMarker.current > currentMarker) {
setAccountStorage([{ key: readMarker, value: latestMarker.current }])
} else {
// setAccountStorage([{ key: readMarker, value: '105250709762254246' }])
}
}
}, 1000 * 15),
@ -271,18 +242,6 @@ const Timeline: React.FC<Props> = ({
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 (
<>
<TimelineRefresh
@ -306,7 +265,7 @@ const Timeline: React.FC<Props> = ({
initialNumToRender={3}
maxToRenderPerBatch={2}
onEndReached={() => !disableInfinity && !isFetchingNextPage && fetchNextPage()}
onEndReachedThreshold={0.8}
onEndReachedThreshold={0.75}
ListFooterComponent={
<TimelineFooter queryKey={queryKey} disableInfinity={disableInfinity} />
}
@ -327,78 +286,42 @@ const Timeline: React.FC<Props> = ({
{...customProps}
/>
{!disableRefresh ? (
<>
<Animated.View
style={[
{
top: -fetchedNoticeHeight.value - 16,
paddingVertical: StyleConstants.Spacing.S,
paddingHorizontal: StyleConstants.Spacing.M,
...noticeDefaults
},
fetchedNoticeAnimate
]}
onLayout={({
nativeEvent: {
layout: { height }
}
}) => (fetchedNoticeHeight.value = height)}
>
<CustomText
fontStyle='S'
style={{ color: colors.primaryDefault }}
children={
fetchedCount !== null
? fetchedCount > 0
? t('refresh.fetched.found', { count: fetchedCount })
: t('refresh.fetched.none')
: t('refresh.fetching')
}
/>
</Animated.View>
{readMarker ? (
<Animated.View
style={[
{
bottom: 16,
borderColor: colors.primaryDefault,
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}
</>
<Animated.View
style={[
{
position: 'absolute',
alignSelf: 'center',
top: -fetchedNoticeHeight.value - 16,
paddingVertical: StyleConstants.Spacing.S,
paddingHorizontal: StyleConstants.Spacing.M,
backgroundColor: colors.backgroundDefault,
shadowColor: colors.primaryDefault,
shadowOffset: { width: 0, height: 0 },
shadowOpacity: theme === 'light' ? 0.16 : 0.24,
borderRadius: 99,
justifyContent: 'center',
alignItems: 'center'
},
fetchedNoticeAnimate
]}
onLayout={({
nativeEvent: {
layout: { height }
}
}) => (fetchedNoticeHeight.value = height)}
>
<CustomText
fontStyle='S'
style={{ color: colors.primaryDefault }}
children={
fetchedCount !== null
? fetchedCount > 0
? t('refresh.fetched.found', { count: fetchedCount })
: t('refresh.fetched.none')
: t('refresh.fetching')
}
/>
</Animated.View>
) : null}
</>
)

View File

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

View File

@ -33,7 +33,7 @@ type ContextMenuItem = {
hidden: boolean
}
title: string
icon?: any
icon?: string
}
type ContextMenuSub = {
@ -47,7 +47,7 @@ type ContextMenuSub = {
hidden: boolean
}
title: string
icon?: any
icon?: string
}
items: Omit<ContextMenuItem, 'type'>[]
}

View File

@ -2,9 +2,9 @@ import { displayMessage } from '@components/Message'
import { useQueryClient } from '@tanstack/react-query'
import { QueryKeyTimeline, useTimelineMutation } from '@utils/queryHooks/timeline'
import { getAccountStorage } from '@utils/storage/actions'
import * as Linking from 'expo-linking'
import { useTranslation } from 'react-i18next'
import { Alert } from 'react-native'
import parse from 'url-parse'
const menuInstance = ({
status,
@ -32,9 +32,9 @@ const menuInstance = ({
const menus: ContextMenu = []
const instance = Linking.parse(status.uri).hostname
const instance = parse(status.uri).hostname
if (instance && instance !== getAccountStorage.string('auth.domain')) {
if (instance !== getAccountStorage.string('auth.domain')) {
menus.push([
{
type: 'item',

View File

@ -8,7 +8,6 @@ import { QueryKeyStatus } from '@utils/queryHooks/status'
import { getGlobalStorage } from '@utils/storage/actions'
import * as Linking from 'expo-linking'
import * as WebBrowser from 'expo-web-browser'
import { WebBrowserPresentationStyle } from 'expo-web-browser'
const openLink = async (url: string, navigation?: any) => {
const handleNavigation = (page: 'Tab-Shared-Toot' | 'Tab-Shared-Account', options: any) => {
@ -75,7 +74,6 @@ const openLink = async (url: string, navigation?: any) => {
default:
await WebBrowser.openBrowserAsync(url.trim(), {
dismissButtonStyle: 'close',
presentationStyle: WebBrowserPresentationStyle.AUTOMATIC,
enableBarCollapsing: true,
...(await browserPackage())
}).catch(() => Linking.openURL(url.trim()))

View File

@ -1,17 +0,0 @@
export default {
common: require('./common'),
screens: require('./screens'),
screenAnnouncements: require('./screens/announcements'),
screenCompose: require('./screens/compose'),
screenImageViewer: require('./screens/imageViewer'),
screenTabs: require('./screens/tabs'),
componentContextMenu: require('./components/contextMenu'),
componentEmojis: require('./components/emojis'),
componentInstance: require('./components/instance'),
componentMediaSelector: require('./components/mediaSelector'),
componentParse: require('./components/parse'),
componentRelationship: require('./components/relationship'),
componentTimeline: require('./components/timeline')
}

View File

@ -11,11 +11,11 @@
},
"right": {
"button": {
"default": "Апублікаваць",
"default": "Допіс",
"conversation": "Асабістае паведамленне",
"reply": "Адказаць",
"deleteEdit": "Апублікаваць",
"edit": "Апублікаваць",
"deleteEdit": "Допіс",
"edit": "Допіс",
"share": "Допіс"
},
"alert": {

View File

@ -31,13 +31,13 @@
"common": {
"search": {
"accessibilityLabel": "Пошук",
"accessibilityHint": "Шукаць па хэштэгах, карыстальніках ці допісах"
"accessibilityHint": ""
}
},
"notifications": {
"filters": {
"accessibilityLabel": "Фільтр",
"accessibilityHint": "Адфільтраваць тыпы апавяшчэнняў, якія паказваюцца",
"accessibilityHint": "",
"title": "Паказваць апавяшчэнні"
}
},
@ -50,10 +50,10 @@
"name": "Асабістыя паведамленні"
},
"favourites": {
"name": "Абранае"
"name": ""
},
"followedTags": {
"name": "Хэштэгі, на якія вы падпісаліся"
"name": ""
},
"fontSize": {
"name": "Памер шрыфту"
@ -80,13 +80,13 @@
"name": "Push-апавяшчэнні"
},
"preferences": {
"name": "Параметры"
"name": ""
},
"preferencesFilters": {
"name": "Усе фільтры змесціва"
"name": ""
},
"preferencesFilterAdd": {
"name": "Стварыць фільтр"
"name": ""
},
"preferencesFilterEdit": {
"name": "Рэдагаваць фільтр"
@ -104,14 +104,14 @@
"name": "Рэдагаваць метаданыя"
},
"settings": {
"name": "Налады праграмы"
"name": ""
},
"switch": {
"name": "Змяніць уліковы запіс"
"name": ""
}
},
"fontSize": {
"demo": "<p>Гэта дэма допіс😊. Вы можаце выбраць адзін з некалькіх варыянтаў, прыведзеных ніжэй.<br /><br />Гэты параметр уплывае толькі на асноўны змест допісаў, але не на іншыя памеры шрыфтоў.</p>",
"demo": "",
"sizes": {
"S": "S",
"M": "M - Стандартны",
@ -129,11 +129,11 @@
"heading": "Рэдагаваць дэталі спісу",
"title": "Назва",
"repliesPolicy": {
"heading": "Паказваць адказы:",
"heading": "Адказы будуць бачныя для:",
"options": {
"none": "Нікому",
"list": "Удзельнікам спіса",
"followed": "Любому карыстальніку, на якога вы падпісаліся"
"none": "",
"list": "",
"followed": ""
}
}
},
@ -141,61 +141,61 @@
"heading": "Выдаліць спіс",
"confirm": {
"title": "Выдаліць спіс \"{{list}}\"?",
"message": "Гэта дзеянне нельга будзе адмяніць."
"message": ""
}
},
"preferences": {
"visibility": {
"title": "Прадвызначаная бачнасць допісаў",
"title": "",
"options": {
"public": "Публічны",
"unlisted": "Прыватны",
"private": "Толькі для падпісчыкаў"
"public": "",
"unlisted": "",
"private": ""
}
},
"sensitive": {
"title": "Прадвызначана пазначаць медыя як далікатныя"
"title": ""
},
"media": {
"title": "Паказ медыя",
"title": "",
"options": {
"default": "Схаваць медыя, пазначаныя як далікатныя",
"show_all": "Заўсёды паказваць медыя",
"hide_all": "Заўсёды хаваць медыя"
"default": "",
"show_all": "",
"hide_all": ""
}
},
"spoilers": {
"title": "Аўтаматычна разгортваць допісы з папярэджаннем аб змесце"
"title": ""
},
"autoplay_gifs": {
"title": "Аўтапрайграванне GIF у допісах"
"title": ""
},
"filters": {
"title": "Фільтры змесціва",
"content": "{{count}} актыўны"
"title": "",
"content": ""
},
"web_only": {
"title": "Абнавіць налады",
"description": "Наступныя налады можна абнавіць толькі праз вэб-інтэрфейс"
"title": "",
"description": ""
}
},
"preferencesFilters": {
"expired": "Тэрмін дзеяння скончыўся",
"keywords_one": "{{count}} ключавое слова",
"keywords_other": "{{count}} ключавых слоў",
"statuses_one": "{{count}} допіс",
"statuses_other": "{{count}} допісаў",
"context": "Ужываецца ў <0 />",
"expired": "",
"keywords_one": "",
"keywords_other": "",
"statuses_one": "",
"statuses_other": "",
"context": "",
"contexts": {
"home": "падпіскі і спісы",
"notifications": "апавяшчэнне",
"public": "глабальнае",
"thread": "размова",
"account": "профіль"
"home": "",
"notifications": "",
"public": "",
"thread": "",
"account": ""
}
},
"preferencesFilter": {
"name": "Імя",
"name": "",
"expiration": "Заканчэнне тэрміну дзеяння",
"expirationOptions": {
"0": "Ніколі",
@ -206,31 +206,31 @@
"604800": "Праз 1 тыдзень",
"18144000": "Праз 1 месяц"
},
"context": "Ужываецца ў",
"context": "",
"contexts": {
"home": "Падпіскі і спісы",
"home": "",
"notifications": "Апавяшчэнне",
"public": "Глабальная стужка",
"thread": "Выгляд размовы",
"account": "Выгляд профілю"
"public": "",
"thread": "",
"account": ""
},
"action": "Пры супадзенні",
"action": "",
"actions": {
"warn": "Згорнуты, але можа быць раскрыты",
"hide": "Цалкам схаваны"
"warn": "",
"hide": ""
},
"keywords": "",
"keyword": "Ключавое слова",
"keyword": "",
"statuses": ""
},
"profile": {
"feedback": {
"succeed": "{{type}} абноўлена",
"failed": "Збой абнаўлення {{type}}, паспрабуйце яшчэ раз"
"succeed": "",
"failed": ""
},
"root": {
"name": {
"title": "Бачная назва"
"title": ""
},
"avatar": {
"title": "Аватар",
@ -245,84 +245,84 @@
},
"fields": {
"title": "Метаданыя",
"total_one": "{{count}} поле",
"total_other": "{{count}} палей"
"total_one": "",
"total_other": ""
},
"lock": {
"title": "Зрабіце ўліковы запіс прыватным",
"description": "Вам трэба будзе ўручную зацвярджаць новых падпісчыкаў"
"title": "",
"description": ""
},
"bot": {
"title": "Уліковы запіс бота",
"description": "Гэты ўліковы запіс у асноўным выконвае аўтаматызаваныя дзеянні і можа не кантралявацца"
"title": "",
"description": ""
}
},
"fields": {
"group": "Група {{index}}",
"label": "Назва",
"content": "Змесціва"
"group": "",
"label": "",
"content": ""
},
"mediaSelectionFailed": "Збой апрацоўкі відарыса. Паспрабуйце яшчэ раз."
"mediaSelectionFailed": ""
},
"push": {
"notAvailable": "Ваш тэлефон не падтрымлівае push-апавяшчэнні",
"notAvailable": "",
"enable": {
"direct": "Уключыць push-апавяшчэнні",
"settings": "Уключыць у наладах"
"direct": "",
"settings": ""
},
"missingServerKey": {
"message": "Сервер няправільна наладжаны для push",
"description": "Звярніцеся да адміністратара вашага сервера, каб наладзіць падтрымку push"
"message": "",
"description": ""
},
"global": {
"heading": "Уключыць для {{acct}}",
"description": "Паведамленні накіроўваюцца праз сервер tooot"
"heading": "",
"description": ""
},
"decode": {
"heading": "Паказаць дэталі паведамлення",
"description": "Паведамленні, якія перадаюцца праз сервер tooot, зашыфраваныя, але вы можаце ўключыць расшыфроўку паведамленняў на серверы. Зыходны код нашага сервера адкрыты і даступны для ўсіх. Таксама наш сервер не захоўвае вашы даныя."
"heading": "",
"description": ""
},
"default": {
"heading": "Прадвызначана"
"heading": ""
},
"follow": {
"heading": "Новыя падпісчыкі"
"heading": ""
},
"follow_request": {
"heading": "Запыты на падпіску"
"heading": ""
},
"favourite": {
"heading": "Дадаў у абранае"
"heading": ""
},
"reblog": {
"heading": "Пашырыў"
"heading": ""
},
"mention": {
"heading": "Згадаў вас"
"heading": ""
},
"poll": {
"heading": "Абнаўленні апытання"
"heading": ""
},
"status": {
"heading": "Допіс ад падпісаных карыстальнікаў"
"heading": ""
},
"update": {
"heading": "Пашырэнне было адрэдагавана"
"heading": ""
},
"admin.sign_up": {
"heading": "Адміністраванне: рэгістрацыя"
"heading": ""
},
"admin.report": {
"heading": "Адміністраванне: скаргі"
"heading": ""
},
"howitworks": "Даведацца, як працуе маршрутызацыя"
"howitworks": ""
},
"root": {
"announcements": {
"content": {
"unread": "{{amount}} непрачытаных",
"read": "Усё прачытана",
"empty": "Няма"
"unread": "",
"read": "",
"empty": ""
}
},
"push": {
@ -344,7 +344,7 @@
"theme": {
"heading": "Знешні выгляд",
"options": {
"auto": "Як у сістэме",
"auto": "",
"light": "Светлы рэжым",
"dark": "Цёмны рэжым"
}
@ -364,18 +364,18 @@
}
},
"autoplayGifv": {
"heading": "Аўтапрайграванне GIF у стужцы"
"heading": ""
},
"feedback": {
"heading": "Прапанаваць ідэю"
"heading": ""
},
"support": {
"heading": "Падтрымаць tooot"
"heading": ""
},
"contact": {
"heading": "Звязацца з tooot"
"heading": ""
},
"version": "Версія: {{version}}",
"version": "",
"instanceVersion": "Версія Mastodon: v{{version}}"
},
"switch": {
@ -386,13 +386,13 @@
"shared": {
"account": {
"actions": {
"accessibilityLabel": "Дзеянні для карыстальніка {{user}}",
"accessibilityHint": "Вы можаце ігнараваць, блакіраваць або абагуліць гэтага карыстальніка"
"accessibilityLabel": "",
"accessibilityHint": ""
},
"followed_by": " падпісаны на вас",
"privateNote": "Задаць прыватную нататку",
"moved": "Карыстальнік перанесены",
"created_at": "Далучыўся: {{date}}",
"followed_by": "",
"privateNote": "",
"moved": "",
"created_at": "",
"summary": {
"statuses_count": "{{count}} допісаў"
},
@ -400,7 +400,7 @@
"default": "Допісы",
"all": "Допісы і адказы"
},
"suspended": "Уліковы запіс прыпынены мадэратарамі вашага сервера"
"suspended": ""
},
"accountInLists": {
"name": "Спісы @{{username}}",
@ -408,43 +408,29 @@
"notInLists": "Іншыя спісы"
},
"attachments": {
"name": "<0 /><1> медыя</1>"
"name": ""
},
"filter": {
"name": "Дадаць у фільтр",
"existed": "Існаваў у гэтых фільтрах"
"name": "",
"existed": ""
},
"history": {
"name": "Гісторыя рэдагавання"
},
"mute": {
"name": "",
"mute": "",
"description": "",
"notification": "",
"duration": {
"heading": "",
"0": "Бестэрмінова",
"1800": "30 хвілін",
"3600": "1 гадзіна",
"86400": "1 дзень",
"604800": "1 тыдзень"
}
},
"report": {
"name": "Паскардзіцца на {{acct}}",
"report": "Скарга",
"name": "",
"report": "",
"forward": {
"heading": "Ананімна пераслаць на аддалены сервер {{instance}}"
},
"reasons": {
"heading": "Што не так з гэтым уліковым запісам?",
"heading": "",
"spam": "Гэта спам",
"other": "Гэта нешта іншае",
"violation": "Гэта парушае правілы сервера"
},
"comment": {
"heading": "Вы хочаце яшчэ што-небудзь дадаць?"
"heading": ""
},
"violatedRules": {
"heading": "Парушэнне правіл сервера"
@ -456,43 +442,43 @@
"placeholder": "..."
},
"empty": {
"general": "Увядзіце ключавое слова для пошуку <bold>$t(screenTabs:shared.search.sections.accounts)</bold>、<bold>$t(screenTabs:shared.search.sections.hashtags)</bold> або <bold> $t(screenTabs:shared.search.sections.statuses)</bold>",
"general": "",
"advanced": {
"header": "Пашыраны пошук",
"header": "",
"example": {
"account": "$t(shared.search.header.prefix) $t(shared.search.sections.accounts)",
"hashtag": "$t(shared.search.header.prefix) $t(shared.search.sections.hashtags)",
"statusLink": "$t(shared.search.header.prefix) $t(shared.search.sections.statuses)",
"accountLink": "$t(shared.search.header.prefix) $t(shared.search.sections.accounts)"
"account": "",
"hashtag": "",
"statusLink": "",
"accountLink": ""
}
},
"trending": {
"tags": "Папулярныя тэгі"
"tags": ""
}
},
"sections": {
"accounts": "Карыстальнік",
"hashtags": "Хэштэг",
"statuses": "Допіс"
"accounts": "",
"hashtags": "",
"statuses": ""
},
"notFound": "Немагчыма знайсці <bold>{{searchTerm}}</bold>, звязаны з {{type}}",
"noResult": "Нічога не знойдзена, паспрабуйце іншы тэрмін"
"notFound": "",
"noResult": ""
},
"toot": {
"name": "Абмеркаванні",
"name": "",
"remoteFetch": {
"title": "Змяшчае аддаленае змесціва",
"message": "Федэратыўны кантэнт не заўсёды даступны на лакальным серверы. Гэты кантэнт атрымліваецца з аддаленага сервера і мае пазнаку. Вы можаце ўзаемадзейнічаць з гэтым кантэнтам як звычайна."
"title": "",
"message": ""
}
},
"users": {
"accounts": {
"following": "Падпіскі {{count}}",
"followers": "{{count}} падпісчыкаў"
"following": "",
"followers": ""
},
"statuses": {
"reblogged_by": "{{count}} пашырэнняў",
"favourited_by": "{{count}} дадалі ў абранае"
"reblogged_by": "",
"favourited_by": ""
},
"resultIncomplete": "Вынікі з аддаленага інстанса няпоўныя"
}

View File

@ -153,13 +153,13 @@
"refresh": "Actualitza"
},
"count": {
"voters_one": "{{count}} vot",
"voters_other": "{{count}} vots",
"voters_one": "{{count}} usuari ha votat",
"voters_other": "{{count}} usuaris han votat",
"votes_one": "{{count}} vot",
"votes_other": "{{count}} vots"
},
"expiration": {
"expired": "Finalitzada",
"expired": "Votació finalitzada",
"until": "Finalitza <0 />"
}
}

View File

@ -417,20 +417,6 @@
"history": {
"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": {
"name": "Denúncia a {{acct}}",
"report": "Denúncia",

View File

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

View File

@ -417,20 +417,6 @@
"history": {
"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": {
"name": "{{acct}} melden",
"report": "Melden",

View File

@ -1,18 +0,0 @@
export default {
common: require('./common'),
screens: require('./screens'),
screenAccountSelection: require('./screens/accountSelection.json'),
screenAnnouncements: require('./screens/announcements'),
screenCompose: require('./screens/compose'),
screenImageViewer: require('./screens/imageViewer'),
screenTabs: require('./screens/tabs'),
componentContextMenu: require('./components/contextMenu'),
componentEmojis: require('./components/emojis'),
componentInstance: require('./components/instance'),
componentMediaSelector: require('./components/mediaSelector'),
componentParse: require('./components/parse'),
componentRelationship: require('./components/relationship'),
componentTimeline: require('./components/timeline')
}

View File

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

View File

@ -417,20 +417,6 @@
"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": {
"name": "Report {{acct}}",
"report": "Report",

View File

@ -153,13 +153,13 @@
"refresh": "Actualizar"
},
"count": {
"voters_one": "{{count}} voto",
"voters_other": "{{count}} votos",
"voters_one": "{{count}} usuario ha votado",
"voters_other": "{{count}} usuarios han votado",
"votes_one": "{{count}} voto",
"votes_other": "{{count}} votos"
},
"expiration": {
"expired": "Finalizado",
"expired": "Votación expirada",
"until": "Expira <0 />"
}
}

View File

@ -417,20 +417,6 @@
"history": {
"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": {
"name": "Denuncia {{acct}}",
"report": "Denuncia",

View File

@ -17,40 +17,40 @@
},
"followAs": {
"trigger": "Honela jarraitu...",
"succeed_default": "Orain @{{target}} jarraitzen duzu @{{source}} bezala",
"succeed_locked": "@{{target}}-(r)i jarraitzeko eskaera bidali diozu {{source}} bezala, onarpena itxaroten",
"failed": "Jarraitu honela"
"succeed_default": "",
"succeed_locked": "",
"failed": ""
},
"blockReport": "Blokeatu eta salatu",
"block": {
"action_false": "Blokeatu erabiltzailea",
"action_true": "Desblokeatu erabiltzailea",
"action_false": "",
"action_true": "",
"alert": {
"title": "@{{username}} erabiltzailea blokeatzea berresten duzu?"
"title": ""
}
},
"reports": {
"action": "Salatu eta blokeatu erabiltzailea",
"action": "",
"alert": {
"title": "@{{username}} erabiltzailea salatzea eta blokeatzea berresten duzu?"
"title": ""
}
}
},
"at": {
"direct": "Mezu zuzena",
"public": "Mezu publikoa"
"direct": "",
"public": ""
},
"copy": {
"action": "Kopiatu tuta",
"succeed": "Kopiatuta"
"action": "",
"succeed": ""
},
"instance": {
"title": "Instantziarekiko ekintza",
"title": "",
"block": {
"action": "Blokeatu {{instance}} instantzia",
"action": "",
"alert": {
"title": "{{instance}} instantzia blokeatzea berresten duzu?",
"message": "Erabiltzaile konkretu bat mututu edo blokeatu dezakezu.\n\nInstantzia blokeatu ondoren, horren eduki osoa, baita instantzia horretan dituzun jarraitzaileak ere ezabatuak izango dira!"
"title": "",
"message": ""
}
}
},
@ -65,38 +65,38 @@
},
"share": {
"status": {
"action": "Partekatu tuta"
"action": ""
},
"account": {
"action": "Partekatu erabiltzailea"
"action": ""
}
},
"status": {
"title": "Tutarekiko ekintzak",
"title": "",
"edit": {
"action": "Editatu tuta"
"action": ""
},
"delete": {
"action": "Ezabatu tuta",
"action": "",
"alert": {
"title": "Ezabaketa berretsi?",
"message": "Bultzada eta gogoko guztiak ezabatuko dira, erantzun guztiak barne."
"title": "",
"message": ""
}
},
"deleteEdit": {
"action": "Ezabatu tuta eta berrargitaratu",
"action": "",
"alert": {
"title": "Ezabatu eta berrargitaratzea nahi duzu?",
"message": "Bultzada eta gogoko guztiak ezabatuko dira, erantzun guztiak barne."
"title": "",
"message": ""
}
},
"mute": {
"action_false": "Mututu tuta eta erantzunak",
"action_true": "Desmututu tuta eta erantzunak"
"action_false": "",
"action_true": ""
},
"pin": {
"action_false": "Finkatu tuta",
"action_true": "Desfinkatu tuta"
"action_false": "",
"action_true": ""
},
"filter": {
"action_false": "Tuta iragazi...",

View File

@ -1,17 +0,0 @@
export default {
common: require('./common'),
screens: require('./screens'),
screenAnnouncements: require('./screens/announcements'),
screenCompose: require('./screens/compose'),
screenImageViewer: require('./screens/imageViewer'),
screenTabs: require('./screens/tabs'),
componentContextMenu: require('./components/contextMenu'),
componentEmojis: require('./components/emojis'),
componentInstance: require('./components/instance'),
componentMediaSelector: require('./components/mediaSelector'),
componentParse: require('./components/parse'),
componentRelationship: require('./components/relationship'),
componentTimeline: require('./components/timeline')
}

View File

@ -7,11 +7,11 @@
"message": "Saioa iraungita, mesedez, hasi saioa berriro"
},
"pushError": {
"message": "Push zerbitzuaren errorea",
"description": "Mesedez, gaitu berriro push jakinarazpenak ezarpenetan"
"message": "",
"description": ""
},
"shareError": {
"imageNotSupported": "{{type}} irudi-mota ez da bateragarria",
"videoNotSupported": "{{type}} bideo-mota ez da bateragarria"
"imageNotSupported": "",
"videoNotSupported": ""
}
}

View File

@ -1,6 +1,6 @@
{
"heading": "Hona partekatu ...",
"heading": "",
"content": {
"select_account": "Aukeratu kontua"
"select_account": ""
}
}

View File

@ -1,16 +1,16 @@
{
"tabs": {
"local": {
"name": "Jarraitutakoak",
"name": "",
"options": {
"showBoosts": "Erakutsi bultzadak",
"showReplies": "Erakutsi erantzunak"
"showBoosts": "",
"showReplies": ""
}
},
"public": {
"segments": {
"federated": "Federatua",
"local": "Bertakoa",
"federated": "",
"local": "",
"explore": "Arakatu"
},
"exploring": {
@ -25,99 +25,99 @@
}
},
"notifications": {
"name": "Jakinarazpenak"
"name": ""
}
},
"common": {
"search": {
"accessibilityLabel": "Bilatu",
"accessibilityHint": "Bilatu traolak, erabiltzaileak edo tutak"
"accessibilityLabel": "",
"accessibilityHint": ""
}
},
"notifications": {
"filters": {
"accessibilityLabel": "Iragazi",
"accessibilityHint": "Iragazi erakutsitako jakinarazpenen motak",
"title": "Erakutsi jakinarazpenak"
"accessibilityLabel": "",
"accessibilityHint": "",
"title": ""
}
},
"me": {
"stacks": {
"bookmarks": {
"name": "Laster-markak"
"name": ""
},
"conversations": {
"name": "Mezu zuzenak"
"name": ""
},
"favourites": {
"name": "Gogokoak"
"name": ""
},
"followedTags": {
"name": "Jarraitutako traolak"
"name": ""
},
"fontSize": {
"name": "Tuten letra-tamaina"
"name": ""
},
"language": {
"name": "Hizkuntza"
"name": ""
},
"list": {
"name": "Zerrenda: {{list}}"
"name": ""
},
"listAccounts": {
"name": "Zerrendako erabiltzaileak: {{list}}"
"name": ""
},
"listAdd": {
"name": "Sortu zerrenda"
"name": ""
},
"listEdit": {
"name": "Editatu zerrendaren xehetasunak"
"name": ""
},
"lists": {
"name": "Zerrendak"
"name": ""
},
"push": {
"name": "Push jakinarazpenak"
"name": ""
},
"preferences": {
"name": "Ezarpenak"
"name": ""
},
"preferencesFilters": {
"name": "Edukien iragazi guztiak"
"name": ""
},
"preferencesFilterAdd": {
"name": "Sortu iragazkia"
"name": ""
},
"preferencesFilterEdit": {
"name": "Editatu iragazkia"
"name": ""
},
"profile": {
"name": "Editatu profila"
"name": ""
},
"profileName": {
"name": "Editatu bistaratutako izena"
"name": ""
},
"profileNote": {
"name": "Editatu deskribapena"
"name": ""
},
"profileFields": {
"name": "Editatu metadatuak"
"name": ""
},
"settings": {
"name": "Aplikazioaren ezarpenak"
"name": ""
},
"switch": {
"name": "Aldatu kontuz"
"name": ""
}
},
"fontSize": {
"demo": "<p>Tut hau proba bat da 😊. Azpiko aukera ugari erabil ditzakezu.<br /><br />Ezarpen honek soilik tuten eduki nagusian eragiten du, ez bestelakoen testu-tamainan.</p>",
"demo": "",
"sizes": {
"S": "S",
"M": "M - Lehenetsia",
"L": "L",
"XL": "XL",
"XXL": "XXL"
"S": "",
"M": "",
"L": "",
"XL": "",
"XXL": ""
}
},
"listAccounts": {
@ -185,227 +185,227 @@
"keywords_other": "{{count}} gako-hitz",
"statuses_one": "Tut {{count}}",
"statuses_other": "{{count}} tut",
"context": "<0 />-(e)tarako aplikatzen da",
"context": "",
"contexts": {
"home": "jarraitutakoak eta zerrendak",
"notifications": "jakinarazpenak",
"public": "federatua",
"thread": "elkarrizketa",
"account": "profila"
"home": "",
"notifications": "",
"public": "",
"thread": "",
"account": ""
}
},
"preferencesFilter": {
"name": "Izena",
"expiration": "Epemuga",
"name": "",
"expiration": "",
"expirationOptions": {
"0": "Inoiz",
"1800": "30 minuturen ondoren",
"3600": "Ordu baten ondoren",
"43200": "12 orduren ondoren",
"86400": "Egun baten ondoren",
"604800": "Aste baten ondoren",
"18144000": "Hilabete baten ondoren"
"0": "",
"1800": "",
"3600": "",
"43200": "",
"86400": "",
"604800": "",
"18144000": ""
},
"context": "Aplikatzen da",
"context": "",
"contexts": {
"home": "Jarraitutakoak eta zerrendak",
"notifications": "Jakinarazpenak",
"public": "Denbora-lerro federatua",
"thread": "Elkarrizketaren bista",
"account": "Profilaren bista"
"home": "",
"notifications": "",
"public": "",
"thread": "",
"account": ""
},
"action": "Bat etortzean",
"action": "",
"actions": {
"warn": "Ezkutuan baina erakuts daiteke",
"hide": "Guztiz ezkutatua"
"warn": "",
"hide": ""
},
"keywords": "Hitz-gako hauekin bat etortzean",
"keyword": "Hitz-gako",
"statuses": "Tut hauekin bat etortzean"
"keywords": "",
"keyword": "",
"statuses": ""
},
"profile": {
"feedback": {
"succeed": "{{type}} eguneratua",
"failed": "{{type}}(r)en eguneraketak huts egin du, saia zaitez berriro"
"succeed": "",
"failed": ""
},
"root": {
"name": {
"title": "Bistaratutako izena"
"title": ""
},
"avatar": {
"title": "Abatarra",
"description": "400x400px-etara eskalatuko da"
"title": "",
"description": ""
},
"header": {
"title": "Goiburu-irudia",
"description": "1500x1500px-etara eskalatuko da"
"title": "",
"description": ""
},
"note": {
"title": "Deskribapena"
"title": ""
},
"fields": {
"title": "Metadatuak",
"total_one": "Eremu {{count}}",
"total_other": "{{count}} eremu"
"title": "",
"total_one": "",
"total_other": ""
},
"lock": {
"title": "Kontua babestu",
"description": "Jarraitzaileak eskuz onartu beharko dituzu"
"title": "",
"description": ""
},
"bot": {
"title": "Bot kontua",
"description": "Kontu hau, oro har, ekintza automatizatuak egiten ditu eta monitorizatu gabe egon liteke"
"title": "",
"description": ""
}
},
"fields": {
"group": "{{index}} taldea",
"label": "Etiketa",
"content": "Edukia"
"group": "",
"label": "",
"content": ""
},
"mediaSelectionFailed": "Irudi-prozesatzeak huts egin du. Mesedez, saia zaitez berriro."
"mediaSelectionFailed": ""
},
"push": {
"notAvailable": "Zure telefonoa ez da toooten push jakinarazpenekin bateragarria",
"notAvailable": "",
"enable": {
"direct": "Gaitu push jakinarazpenak",
"settings": "Gaitu ezarpenetan"
"direct": "",
"settings": ""
},
"missingServerKey": {
"message": "Zerbitzaria oker konfiguratua push jakinarazpenetarako",
"description": "Mesedez, jar zaitez zerbitzariko administratzailearekin harremanetan push jakinarazpenen bateragarritasuna konfiguratzeko"
"message": "",
"description": ""
},
"global": {
"heading": "Gaitu {{acct}}-(e)rako",
"description": "Mezuak toooten zerbitzariaren bidez bidaltzen dira"
"heading": "",
"description": ""
},
"decode": {
"heading": "Erakutsi mezuaren xehetasunak",
"description": "toooten zerbitzariaren bidez bidalitako mezuak enkriptatuak daude, baina, zerbitzarian desenkripta daitezen aukera dezakezu. Gure zerbitzariko iturburu-kodea irekia da, eta erregistro gabeko politika du."
"heading": "",
"description": ""
},
"default": {
"heading": "Lehenetsia"
"heading": ""
},
"follow": {
"heading": "Jarraitzaile berria"
"heading": ""
},
"follow_request": {
"heading": "Jarraitzeko eskaera"
"heading": ""
},
"favourite": {
"heading": "Gogokoak"
"heading": ""
},
"reblog": {
"heading": "Bultzada"
"heading": ""
},
"mention": {
"heading": "Zuri eginiko aipamena"
"heading": ""
},
"poll": {
"heading": "Bozketen eguneraketak"
"heading": ""
},
"status": {
"heading": "Harpidetutako erabiltzaileen tutak"
"heading": ""
},
"update": {
"heading": "Bultzada editatua izan da"
"heading": ""
},
"admin.sign_up": {
"heading": "Administrazioa: izen-emateak"
"heading": ""
},
"admin.report": {
"heading": "Administrazioa: salaketak"
"heading": ""
},
"howitworks": "Informazio gehiago push jakinarazpenen inguruan"
"howitworks": ""
},
"root": {
"announcements": {
"content": {
"unread": "{{amount}} irakurri gabe",
"read": "Dena irakurria",
"empty": "Bat ere ez"
"unread": "",
"read": "",
"empty": ""
}
},
"push": {
"content_true": "Gaituta",
"content_false": "Desgaituta"
"content_true": "",
"content_false": ""
},
"logout": {
"button": "Saioa amaitu",
"button": "",
"alert": {
"title": "Saioa amaitu?",
"message": "Saioa amaitu ondoren, berriro hasi behar duzu saioa",
"title": "",
"message": "",
"buttons": {
"logout": "Saioa amaitu"
"logout": ""
}
}
}
},
"settings": {
"theme": {
"heading": "Itxura",
"heading": "",
"options": {
"auto": "Sistemakoa",
"light": "Modu argia",
"dark": "Modu iluna"
"auto": "",
"light": "",
"dark": ""
}
},
"darkTheme": {
"heading": "Gai iluna",
"heading": "",
"options": {
"lighter": "Lehenetsia",
"darker": "Beltz-beltza"
"lighter": "",
"darker": ""
}
},
"browser": {
"heading": "Estekak ireki",
"heading": "",
"options": {
"internal": "Aplikazio barruan",
"external": "Sistemako nabigatzailearekin"
"internal": "",
"external": ""
}
},
"autoplayGifv": {
"heading": "Automatikoki erreproduzitu GIFak"
"heading": ""
},
"feedback": {
"heading": "Proposamenak"
"heading": ""
},
"support": {
"heading": "tooot lagundu"
"heading": ""
},
"contact": {
"heading": "tooot-ekin harremanetan jarri"
"heading": ""
},
"version": "v{{version}} bertsioa",
"instanceVersion": "Mastodonen v{{version}} bertsioa"
"version": "",
"instanceVersion": ""
},
"switch": {
"existing": "Aukeratu saioa hasita dutenetatik",
"new": "Saioa hasi instantzian"
"existing": "",
"new": ""
}
},
"shared": {
"account": {
"actions": {
"accessibilityLabel": "{{user}} erabiltzailearekiko ekintzak",
"accessibilityHint": "Erabiltzaile hau mututu, blokeatu, salatu edo partekatu dezakezu"
"accessibilityLabel": "",
"accessibilityHint": ""
},
"followed_by": " jarraitzen zaitu",
"privateNote": "Ezarri ohar pribatua",
"moved": "Erabiltzailea mugitu da",
"created_at": "Bateratze-data: {{date}}",
"followed_by": "",
"privateNote": "",
"moved": "",
"created_at": "",
"summary": {
"statuses_count": "{{count}} tut"
"statuses_count": ""
},
"toots": {
"default": "Tutak",
"all": "Tutak eta erantzunak"
"default": "",
"all": ""
},
"suspended": "Kontu hau bertan behera utzi dute zure zerbitzariko moderatzaileek"
"suspended": ""
},
"accountInLists": {
"name": "@{{username}}-(r)en zerrendak",
"inLists": "Zerrenda hauetan",
"notInLists": "Beste zerrendak"
"name": "",
"inLists": "",
"notInLists": ""
},
"attachments": {
"name": ""
@ -417,20 +417,6 @@
"history": {
"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": {
"name": "",
"report": "",

View File

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

View File

@ -2,20 +2,16 @@ import * as Localization from 'expo-localization'
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import be from './be'
import ca from './ca'
import de from './de'
import el from './el'
import en from './en'
import es from './es'
import eu from './eu'
import fr from './fr'
import it from './it'
import ja from './ja'
import ko from './ko'
import nl from './nl'
import no from './no'
import pl from './pl'
import pt_BR from './pt_BR'
import sv from './sv'
import uk from './uk'
@ -27,20 +23,16 @@ import '@formatjs/intl-getcanonicallocales/polyfill'
import '@formatjs/intl-locale/polyfill'
import '@formatjs/intl-pluralrules/polyfill'
import '@formatjs/intl-pluralrules/locale-data/be'
import '@formatjs/intl-pluralrules/locale-data/ca'
import '@formatjs/intl-pluralrules/locale-data/de'
import '@formatjs/intl-pluralrules/locale-data/el'
import '@formatjs/intl-pluralrules/locale-data/en'
import '@formatjs/intl-pluralrules/locale-data/es'
import '@formatjs/intl-pluralrules/locale-data/eu'
import '@formatjs/intl-pluralrules/locale-data/fr'
import '@formatjs/intl-pluralrules/locale-data/it'
import '@formatjs/intl-pluralrules/locale-data/ja'
import '@formatjs/intl-pluralrules/locale-data/ko'
import '@formatjs/intl-pluralrules/locale-data/nl'
import '@formatjs/intl-pluralrules/locale-data/no'
import '@formatjs/intl-pluralrules/locale-data/pl'
import '@formatjs/intl-pluralrules/locale-data/pt'
import '@formatjs/intl-pluralrules/locale-data/sv'
import '@formatjs/intl-pluralrules/locale-data/uk'
@ -48,20 +40,16 @@ import '@formatjs/intl-pluralrules/locale-data/vi'
import '@formatjs/intl-pluralrules/locale-data/zh'
import '@formatjs/intl-numberformat/polyfill'
import '@formatjs/intl-numberformat/locale-data/be'
import '@formatjs/intl-numberformat/locale-data/ca'
import '@formatjs/intl-numberformat/locale-data/de'
import '@formatjs/intl-numberformat/locale-data/el'
import '@formatjs/intl-numberformat/locale-data/en'
import '@formatjs/intl-numberformat/locale-data/es'
import '@formatjs/intl-numberformat/locale-data/eu'
import '@formatjs/intl-numberformat/locale-data/fr'
import '@formatjs/intl-numberformat/locale-data/it'
import '@formatjs/intl-numberformat/locale-data/ja'
import '@formatjs/intl-numberformat/locale-data/ko'
import '@formatjs/intl-numberformat/locale-data/nl'
import '@formatjs/intl-numberformat/locale-data/no'
import '@formatjs/intl-numberformat/locale-data/pl'
import '@formatjs/intl-numberformat/locale-data/pt'
import '@formatjs/intl-numberformat/locale-data/sv'
import '@formatjs/intl-numberformat/locale-data/uk'
@ -71,20 +59,16 @@ import '@formatjs/intl-numberformat/locale-data/zh-Hant'
import '@formatjs/intl-datetimeformat/polyfill'
import '@formatjs/intl-datetimeformat/add-all-tz'
import '@formatjs/intl-datetimeformat/locale-data/be'
import '@formatjs/intl-datetimeformat/locale-data/ca'
import '@formatjs/intl-datetimeformat/locale-data/de'
import '@formatjs/intl-datetimeformat/locale-data/el'
import '@formatjs/intl-datetimeformat/locale-data/en'
import '@formatjs/intl-datetimeformat/locale-data/es'
import '@formatjs/intl-datetimeformat/locale-data/eu'
import '@formatjs/intl-datetimeformat/locale-data/fr'
import '@formatjs/intl-datetimeformat/locale-data/it'
import '@formatjs/intl-datetimeformat/locale-data/ja'
import '@formatjs/intl-datetimeformat/locale-data/ko'
import '@formatjs/intl-datetimeformat/locale-data/nl'
import '@formatjs/intl-datetimeformat/locale-data/no'
import '@formatjs/intl-datetimeformat/locale-data/pl'
import '@formatjs/intl-datetimeformat/locale-data/pt'
import '@formatjs/intl-datetimeformat/locale-data/sv'
import '@formatjs/intl-datetimeformat/locale-data/uk'
@ -93,20 +77,16 @@ import '@formatjs/intl-datetimeformat/locale-data/zh-Hans'
import '@formatjs/intl-datetimeformat/locale-data/zh-Hant'
import '@formatjs/intl-relativetimeformat/polyfill'
import '@formatjs/intl-relativetimeformat/locale-data/be'
import '@formatjs/intl-relativetimeformat/locale-data/ca'
import '@formatjs/intl-relativetimeformat/locale-data/de'
import '@formatjs/intl-relativetimeformat/locale-data/el'
import '@formatjs/intl-relativetimeformat/locale-data/en'
import '@formatjs/intl-relativetimeformat/locale-data/es'
import '@formatjs/intl-relativetimeformat/locale-data/eu'
import '@formatjs/intl-relativetimeformat/locale-data/fr'
import '@formatjs/intl-relativetimeformat/locale-data/it'
import '@formatjs/intl-relativetimeformat/locale-data/ja'
import '@formatjs/intl-relativetimeformat/locale-data/ko'
import '@formatjs/intl-relativetimeformat/locale-data/nl'
import '@formatjs/intl-relativetimeformat/locale-data/no'
import '@formatjs/intl-relativetimeformat/locale-data/pl'
import '@formatjs/intl-relativetimeformat/locale-data/pt'
import '@formatjs/intl-relativetimeformat/locale-data/sv'
import '@formatjs/intl-relativetimeformat/locale-data/uk'
@ -122,20 +102,16 @@ i18n.use(initReactI18next).init({
defaultNS: 'common',
resources: {
be,
ca,
de,
el,
en,
es,
eu,
fr,
it,
ja,
ko,
nl,
no,
pl,
'pt-BR': pt_BR,
sv,
uk,

View File

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

View File

@ -1,13 +1,13 @@
{
"server": {
"textInput": {
"placeholder": "Dominio dell'istanza"
"placeholder": ""
},
"whitelisted": "Questa potrebbe essere un'istanza nella whitelist nella quale tooot non può accedere ai dati di essa prima di fare il log-in.",
"whitelisted": "",
"button": "Accedi",
"information": {
"name": "Nome",
"description": "Descrizione"
"description": ""
},
"disclaimer": {
"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": {
"fetchPreviousPage": "Più recenti da qui",
"refetch": "Al più recente",
"fetching": "Recupero nuovi toot ...",
"fetching": "",
"fetched": {
"none": "Nessun nuovo toot",
"found": "{{count}} toot recuperati"
"none": "",
"found": ""
}
},
"shared": {

View File

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

View File

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

View File

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

View File

@ -1,18 +1,14 @@
const LOCALES = {
be: 'Беларуская',
ca: 'Català',
de: 'Deutsch',
el: 'Ελληνικά',
en: 'English',
es: 'Español',
eu: 'Euskara',
fr: 'Français',
it: 'Italiano',
ja: '日本語',
ko: '한국어',
nl: 'Nederlands',
no: 'Norsk',
pl: 'Polski',
'pt-br': 'Português (Brasil)',
sv: 'Svenska',
uk: 'українська',

View File

@ -417,20 +417,6 @@
"history": {
"name": "Geschiedenis bewerken"
},
"mute": {
"name": "Demp {{acct}}",
"mute": "Dempen",
"description": "Verberg berichten van deze gebruiker en berichten die hen vermelden, maar het geeft hen nog steeds de mogelijkheid om je posts te zien en je te volgen.",
"notification": "Verberg ook meldingen van deze gebruiker",
"duration": {
"heading": "Voor duur",
"0": "Onbepaalde tijd",
"1800": "30 minuten",
"3600": "1 uur",
"86400": "1 dag",
"604800": "1 week"
}
},
"report": {
"name": "Rapporteer {{acct}}",
"report": "Rapporteer",

View File

@ -417,20 +417,6 @@
"history": {
"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": {
"name": "Rapporter {{acct}}",
"report": "Rapporter",

View File

@ -1,17 +0,0 @@
export default {
common: require('./common'),
screens: require('./screens'),
screenAnnouncements: require('./screens/announcements'),
screenCompose: require('./screens/compose'),
screenImageViewer: require('./screens/imageViewer'),
screenTabs: require('./screens/tabs'),
componentContextMenu: require('./components/contextMenu'),
componentEmojis: require('./components/emojis'),
componentInstance: require('./components/instance'),
componentMediaSelector: require('./components/mediaSelector'),
componentParse: require('./components/parse'),
componentRelationship: require('./components/relationship'),
componentTimeline: require('./components/timeline')
}

View File

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

Some files were not shown because too many files have changed in this diff Show More