Merge remote-tracking branch 'origin/master' into fast-lite-mode
This commit is contained in:
commit
0202054edb
71 changed files with 10599 additions and 273 deletions
64
.gitignore
vendored
64
.gitignore
vendored
|
@ -1,4 +1,66 @@
|
|||
# OSX
|
||||
#
|
||||
.DS_Store
|
||||
|
||||
# Xcode
|
||||
#
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
|
||||
# Android/IntelliJ
|
||||
#
|
||||
build/
|
||||
.idea
|
||||
.gradle
|
||||
local.properties
|
||||
*.iml
|
||||
|
||||
# node.js
|
||||
#
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# BUCK
|
||||
buck-out/
|
||||
\.buckd/
|
||||
*.keystore
|
||||
!debug.keystore
|
||||
|
||||
# fastlane
|
||||
#
|
||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||
# screenshots whenever they are needed.
|
||||
# For more information about the recommended setup visit:
|
||||
# https://docs.fastlane.tools/best-practices/source-control/
|
||||
|
||||
*/fastlane/report.xml
|
||||
*/fastlane/Preview.html
|
||||
*/fastlane/screenshots
|
||||
|
||||
# Bundle artifact
|
||||
*.jsbundle
|
||||
|
||||
# CocoaPods
|
||||
/ios/Pods/
|
||||
|
||||
# Other Files
|
||||
android/app/google-services.json
|
||||
*.log
|
||||
.vagrant
|
||||
|
||||
android/app/build/*
|
||||
android/bin
|
||||
|
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "android"]
|
||||
path = android
|
||||
url = https://github.com/lbryio/lbry-android
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2019 LBRY Inc
|
||||
Copyright (c) 2017-2020 LBRY Inc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish,distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
|
39
README.md
39
README.md
|
@ -1,7 +1,7 @@
|
|||
# LBRY Android
|
||||
# LBRY React Native
|
||||
[![pipeline status](https://ci.lbry.tech/lbry/lbry-android/badges/master/pipeline.svg)](https://ci.lbry.tech/lbry/lbry-android/commits/master)
|
||||
|
||||
An Android browser and wallet for the [LBRY](https://lbry.com) network. This app bundles [lbrynet-daemon](https://github.com/lbryio/lbry) as a background service with a UI layer built with React Native. The APK is built using buildozer and the Gradle build tool.
|
||||
A mobile browser and wallet for the [LBRY](https://lbry.com) network. This app bundles [LBRY SDK](https://github.com/lbryio/lbry) as a background service with a UI layer built with React Native.
|
||||
|
||||
<img src="https://spee.ch/8/lbry-android.png" alt="LBRY Android Screenshot" width="384px" />
|
||||
|
||||
|
@ -12,10 +12,41 @@ The minimum supported Android version is 5.0 Lollipop. There are two ways to ins
|
|||
1. Direct APK install available at [http://build.lbry.io/android/latest.apk](http://build.lbry.io/android/latest.apk). You will need to enable installation from third-party sources on your device in order to install from this source.
|
||||
|
||||
## Usage
|
||||
The app can be launched by opening **LBRY Browser** from the device's app drawer or via the shortcut on the home screen if that was created upon installation.
|
||||
The app can be launched by opening **LBRY** from the device's app drawer or via the shortcut on the home screen if that was created upon installation.
|
||||
|
||||
## Running from Source
|
||||
The app is built from source via [Buildozer](https://github.com/kivy/buildozer). After cloning the repository, copy `buildozer.spec.sample` to `buildozer.spec` and modify this file as necessary for your environment. Please see [BUILD.md](BUILD.md) for detailed build instructions.
|
||||
### Software Requirements
|
||||
* Android Studio
|
||||
* WebStorm (or other IDE for editing React Native / JavaScript code)
|
||||
* npm
|
||||
* yarn
|
||||
|
||||
### Android Steps
|
||||
* Clone the repository using `git clone https://github.com/lbryio/lbry-react-native`
|
||||
* Initialise the submodules.
|
||||
```
|
||||
cd lbry-react-native
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
* Install `react-native-cli` globally using `npm install -g react-native-cli`.
|
||||
* Install the required package modules by running `yarn` in the cloned repository folder.
|
||||
* Download a `google-services.json` from the Firebase console (https://console.firebase.google.com/) and place it in the `android/app` folder. Alternatively, use the included sample JSON file.
|
||||
```
|
||||
cp android/app/google-services.sample.json android/app/google-services.json
|
||||
```
|
||||
* Open Android Studio and click File > Open...
|
||||
* Navigate to the cloned repository on your local filesystem and select the `android` subfolder.
|
||||
* Connect your Android device in USB debugging mode, or create an ARM emulator (slower) to run the app.
|
||||
* Click Run > Run... and select the corresponding app configuration. Note that it may take a while for the project files to sync before you can run the app
|
||||
* In order to edit the React Native / JavaScript files, open the cloned repository folder using WebStorm (or your favourite IDE).
|
||||
|
||||
### React Native Fast Refresh
|
||||
In order to enable fast refresh when updating React Native code
|
||||
* Connect your Android device in USB debugging mode, or create an ARM emulator
|
||||
* Run `adb reverse tcp:8081 tcp:8081` (`adb` can be found in the `platform-tools` folder of your Android SDK installation)
|
||||
* Run `yarn start`
|
||||
* Press `r` to reload the app.
|
||||
* Anytime you make an update to the React Native code, the app should automatically refresh.
|
||||
|
||||
## Contributing
|
||||
Contributions to this project are welcome, encouraged, and compensated. For more details, see https://lbry.io/faq/contributing
|
||||
|
|
14
__tests__/App-test.js
Normal file
14
__tests__/App-test.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* @format
|
||||
*/
|
||||
|
||||
import 'react-native';
|
||||
import React from 'react';
|
||||
import App from '../App';
|
||||
|
||||
// Note: test renderer must be required after react-native.
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
it('renders correctly', () => {
|
||||
renderer.create(<App />);
|
||||
});
|
1
android
Submodule
1
android
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 37b893103da874282f2bdef4a8a1bb543d2c9859
|
3
bundle-android.sh
Normal file
3
bundle-android.sh
Normal file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
react-native bundle --platform android --dev false --entry-file src/index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
|
||||
|
2
index.js
2
index.js
|
@ -1,5 +1,5 @@
|
|||
if (__DEV__) {
|
||||
import('./reactotron').then(() => console.log('Reactotron Configured'));
|
||||
import('./reactotron').then(() => console.log('Reactotron Configured'));
|
||||
}
|
||||
|
||||
import LBRYApp from './src/index';
|
||||
|
|
53
ios/LbryApp-tvOS/Info.plist
Normal file
53
ios/LbryApp-tvOS/Info.plist
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>localhost</key>
|
||||
<dict>
|
||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
24
ios/LbryApp-tvOSTests/Info.plist
Normal file
24
ios/LbryApp-tvOSTests/Info.plist
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
782
ios/LbryApp.xcodeproj/project.pbxproj
Normal file
782
ios/LbryApp.xcodeproj/project.pbxproj
Normal file
|
@ -0,0 +1,782 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
00E356F31AD99517003FC87E /* LbryAppTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* LbryAppTests.m */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
2DCD954D1E0B4F2C00145EB5 /* LbryAppTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* LbryAppTests.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||
remoteInfo = LbryApp;
|
||||
};
|
||||
2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7;
|
||||
remoteInfo = "LbryApp-tvOS";
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
|
||||
00E356EE1AD99517003FC87E /* LbryAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LbryAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
00E356F21AD99517003FC87E /* LbryAppTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LbryAppTests.m; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* LbryApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LbryApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = LbryApp/AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = LbryApp/AppDelegate.m; sourceTree = "<group>"; };
|
||||
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = LbryApp/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = LbryApp/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = LbryApp/main.m; sourceTree = "<group>"; };
|
||||
2D02E47B1E0B4A5D006451C7 /* LbryApp-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "LbryApp-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2D02E4901E0B4A5D006451C7 /* LbryApp-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "LbryApp-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
00E356EB1AD99517003FC87E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2D02E4781E0B4A5D006451C7 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2D02E48D1E0B4A5D006451C7 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
00E356EF1AD99517003FC87E /* LbryAppTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00E356F21AD99517003FC87E /* LbryAppTests.m */,
|
||||
00E356F01AD99517003FC87E /* Supporting Files */,
|
||||
);
|
||||
path = LbryAppTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
00E356F01AD99517003FC87E /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00E356F11AD99517003FC87E /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* LbryApp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
);
|
||||
name = LbryApp;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
ED2971642150620600B7C4FE /* JavaScriptCore.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* LbryApp */,
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
00E356EF1AD99517003FC87E /* LbryAppTests */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
usesTabs = 0;
|
||||
};
|
||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* LbryApp.app */,
|
||||
00E356EE1AD99517003FC87E /* LbryAppTests.xctest */,
|
||||
2D02E47B1E0B4A5D006451C7 /* LbryApp-tvOS.app */,
|
||||
2D02E4901E0B4A5D006451C7 /* LbryApp-tvOSTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
00E356ED1AD99517003FC87E /* LbryAppTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "LbryAppTests" */;
|
||||
buildPhases = (
|
||||
00E356EA1AD99517003FC87E /* Sources */,
|
||||
00E356EB1AD99517003FC87E /* Frameworks */,
|
||||
00E356EC1AD99517003FC87E /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
00E356F51AD99517003FC87E /* PBXTargetDependency */,
|
||||
);
|
||||
name = LbryAppTests;
|
||||
productName = LbryAppTests;
|
||||
productReference = 00E356EE1AD99517003FC87E /* LbryAppTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
13B07F861A680F5B00A75B9A /* LbryApp */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "LbryApp" */;
|
||||
buildPhases = (
|
||||
FD10A7F022414F080027D42C /* Start Packager */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = LbryApp;
|
||||
productName = "LbryApp";
|
||||
productReference = 13B07F961A680F5B00A75B9A /* LbryApp.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
2D02E47A1E0B4A5D006451C7 /* LbryApp-tvOS */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "LbryApp-tvOS" */;
|
||||
buildPhases = (
|
||||
FD10A7F122414F3F0027D42C /* Start Packager */,
|
||||
2D02E4771E0B4A5D006451C7 /* Sources */,
|
||||
2D02E4781E0B4A5D006451C7 /* Frameworks */,
|
||||
2D02E4791E0B4A5D006451C7 /* Resources */,
|
||||
2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "LbryApp-tvOS";
|
||||
productName = "LbryApp-tvOS";
|
||||
productReference = 2D02E47B1E0B4A5D006451C7 /* LbryApp-tvOS.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
2D02E48F1E0B4A5D006451C7 /* LbryApp-tvOSTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "LbryApp-tvOSTests" */;
|
||||
buildPhases = (
|
||||
2D02E48C1E0B4A5D006451C7 /* Sources */,
|
||||
2D02E48D1E0B4A5D006451C7 /* Frameworks */,
|
||||
2D02E48E1E0B4A5D006451C7 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "LbryApp-tvOSTests";
|
||||
productName = "LbryApp-tvOSTests";
|
||||
productReference = 2D02E4901E0B4A5D006451C7 /* LbryApp-tvOSTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0940;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
00E356ED1AD99517003FC87E = {
|
||||
CreatedOnToolsVersion = 6.2;
|
||||
TestTargetID = 13B07F861A680F5B00A75B9A;
|
||||
};
|
||||
2D02E47A1E0B4A5D006451C7 = {
|
||||
CreatedOnToolsVersion = 8.2.1;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
2D02E48F1E0B4A5D006451C7 = {
|
||||
CreatedOnToolsVersion = 8.2.1;
|
||||
ProvisioningStyle = Automatic;
|
||||
TestTargetID = 2D02E47A1E0B4A5D006451C7;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "LbryApp" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* LbryApp */,
|
||||
00E356ED1AD99517003FC87E /* LbryAppTests */,
|
||||
2D02E47A1E0B4A5D006451C7 /* LbryApp-tvOS */,
|
||||
2D02E48F1E0B4A5D006451C7 /* LbryApp-tvOSTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
00E356EC1AD99517003FC87E /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2D02E4791E0B4A5D006451C7 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2D02E48E1E0B4A5D006451C7 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Bundle React Native code and images";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
|
||||
};
|
||||
2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Bundle React Native Code And Images";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
|
||||
};
|
||||
FD10A7F022414F080027D42C /* Start Packager */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Start Packager";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FD10A7F122414F3F0027D42C /* Start Packager */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Start Packager";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
00E356EA1AD99517003FC87E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
00E356F31AD99517003FC87E /* LbryAppTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2D02E4771E0B4A5D006451C7 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */,
|
||||
2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2D02E48C1E0B4A5D006451C7 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2DCD954D1E0B4F2C00145EB5 /* LbryAppTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 13B07F861A680F5B00A75B9A /* LbryApp */;
|
||||
targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
|
||||
};
|
||||
2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 2D02E47A1E0B4A5D006451C7 /* LbryApp-tvOS */;
|
||||
targetProxy = 2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
13B07FB21A68108700A75B9A /* Base */,
|
||||
);
|
||||
name = LaunchScreen.xib;
|
||||
path = LbryApp;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
00E356F61AD99517003FC87E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = LbryAppTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
"$(inherited)",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LbryApp.app/LbryApp";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
00E356F71AD99517003FC87E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
INFOPLIST_FILE = LbryAppTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
"$(inherited)",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LbryApp.app/LbryApp";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEAD_CODE_STRIPPING = NO;
|
||||
INFOPLIST_FILE = LbryApp/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = LbryApp;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
INFOPLIST_FILE = LbryApp/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = LbryApp;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
2D02E4971E0B4A5E006451C7 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = "LbryApp-tvOS/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.LbryApp-tvOS";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = appletvos;
|
||||
TARGETED_DEVICE_FAMILY = 3;
|
||||
TVOS_DEPLOYMENT_TARGET = 9.2;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
2D02E4981E0B4A5E006451C7 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = "LbryApp-tvOS/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.LbryApp-tvOS";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = appletvos;
|
||||
TARGETED_DEVICE_FAMILY = 3;
|
||||
TVOS_DEPLOYMENT_TARGET = 9.2;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
2D02E4991E0B4A5E006451C7 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = "LbryApp-tvOSTests/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.LbryApp-tvOSTests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = appletvos;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LbryApp-tvOS.app/LbryApp-tvOS";
|
||||
TVOS_DEPLOYMENT_TARGET = 10.1;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
2D02E49A1E0B4A5E006451C7 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = "LbryApp-tvOSTests/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.LbryApp-tvOSTests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = appletvos;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LbryApp-tvOS.app/LbryApp-tvOS";
|
||||
TVOS_DEPLOYMENT_TARGET = 10.1;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
83CBBA211A601CBA00E9B192 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "LbryAppTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
00E356F61AD99517003FC87E /* Debug */,
|
||||
00E356F71AD99517003FC87E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "LbryApp" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
13B07F951A680F5B00A75B9A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "LbryApp-tvOS" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
2D02E4971E0B4A5E006451C7 /* Debug */,
|
||||
2D02E4981E0B4A5E006451C7 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "LbryApp-tvOSTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
2D02E4991E0B4A5E006451C7 /* Debug */,
|
||||
2D02E49A1E0B4A5E006451C7 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "LbryApp" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
83CBBA211A601CBA00E9B192 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0940"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "NO"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2D2A28121D9B038B00D4039D"
|
||||
BuildableName = "libReact.a"
|
||||
BlueprintName = "React-tvOS"
|
||||
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
|
||||
BuildableName = "LbryApp-tvOS.app"
|
||||
BlueprintName = "LbryApp-tvOS"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2D02E48F1E0B4A5D006451C7"
|
||||
BuildableName = "LbryApp-tvOSTests.xctest"
|
||||
BlueprintName = "LbryApp-tvOSTests"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2D02E48F1E0B4A5D006451C7"
|
||||
BuildableName = "LbryApp-tvOSTests.xctest"
|
||||
BlueprintName = "LbryApp-tvOSTests"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
|
||||
BuildableName = "LbryApp-tvOS.app"
|
||||
BlueprintName = "LbryApp-tvOS"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
|
||||
BuildableName = "LbryApp-tvOS.app"
|
||||
BlueprintName = "LbryApp-tvOS"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
|
||||
BuildableName = "LbryApp-tvOS.app"
|
||||
BlueprintName = "LbryApp-tvOS"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
129
ios/LbryApp.xcodeproj/xcshareddata/xcschemes/LbryApp.xcscheme
Normal file
129
ios/LbryApp.xcodeproj/xcshareddata/xcschemes/LbryApp.xcscheme
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0940"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "NO"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
|
||||
BuildableName = "libReact.a"
|
||||
BlueprintName = "React"
|
||||
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "LbryApp.app"
|
||||
BlueprintName = "LbryApp"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "LbryAppTests.xctest"
|
||||
BlueprintName = "LbryAppTests"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "LbryAppTests.xctest"
|
||||
BlueprintName = "LbryAppTests"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "LbryApp.app"
|
||||
BlueprintName = "LbryApp"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "LbryApp.app"
|
||||
BlueprintName = "LbryApp"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "LbryApp.app"
|
||||
BlueprintName = "LbryApp"
|
||||
ReferencedContainer = "container:LbryApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
15
ios/LbryApp/AppDelegate.h
Normal file
15
ios/LbryApp/AppDelegate.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridgeDelegate.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
|
||||
|
||||
@property (nonatomic, strong) UIWindow *window;
|
||||
|
||||
@end
|
42
ios/LbryApp/AppDelegate.m
Normal file
42
ios/LbryApp/AppDelegate.m
Normal file
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBundleURLProvider.h>
|
||||
#import <React/RCTRootView.h>
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
|
||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
|
||||
moduleName:@"LbryApp"
|
||||
initialProperties:nil];
|
||||
|
||||
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
UIViewController *rootViewController = [UIViewController new];
|
||||
rootViewController.view = rootView;
|
||||
self.window.rootViewController = rootViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
||||
{
|
||||
#if DEBUG
|
||||
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
|
||||
#else
|
||||
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
42
ios/LbryApp/Base.lproj/LaunchScreen.xib
Normal file
42
ios/LbryApp/Base.lproj/LaunchScreen.xib
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
|
||||
<rect key="frame" x="20" y="439" width="441" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="LbryApp" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
|
||||
<rect key="frame" x="20" y="140" width="441" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
|
||||
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
|
||||
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
|
||||
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
|
||||
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="548" y="455"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
38
ios/LbryApp/Images.xcassets/AppIcon.appiconset/Contents.json
Normal file
38
ios/LbryApp/Images.xcassets/AppIcon.appiconset/Contents.json
Normal file
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
6
ios/LbryApp/Images.xcassets/Contents.json
Normal file
6
ios/LbryApp/Images.xcassets/Contents.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
57
ios/LbryApp/Info.plist
Normal file
57
ios/LbryApp/Info.plist
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>LbryApp</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>localhost</key>
|
||||
<dict>
|
||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
16
ios/LbryApp/main.m
Normal file
16
ios/LbryApp/main.m
Normal file
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
24
ios/LbryAppTests/Info.plist
Normal file
24
ios/LbryAppTests/Info.plist
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
72
ios/LbryAppTests/LbryAppTests.m
Normal file
72
ios/LbryAppTests/LbryAppTests.m
Normal file
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTRootView.h>
|
||||
|
||||
#define TIMEOUT_SECONDS 600
|
||||
#define TEXT_TO_LOOK_FOR @"Welcome to React"
|
||||
|
||||
@interface LbryAppTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation LbryAppTests
|
||||
|
||||
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
|
||||
{
|
||||
if (test(view)) {
|
||||
return YES;
|
||||
}
|
||||
for (UIView *subview in [view subviews]) {
|
||||
if ([self findSubviewInView:subview matching:test]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)testRendersWelcomeScreen
|
||||
{
|
||||
UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
|
||||
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
|
||||
BOOL foundElement = NO;
|
||||
|
||||
__block NSString *redboxError = nil;
|
||||
#ifdef DEBUG
|
||||
RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
|
||||
if (level >= RCTLogLevelError) {
|
||||
redboxError = message;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
|
||||
foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
|
||||
if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}];
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
RCTSetLogFunction(RCTDefaultLogFunction);
|
||||
#endif
|
||||
|
||||
XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
|
||||
XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
|
||||
}
|
||||
|
||||
|
||||
@end
|
53
ios/Podfile
Normal file
53
ios/Podfile
Normal file
|
@ -0,0 +1,53 @@
|
|||
platform :ios, '9.0'
|
||||
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
||||
|
||||
target 'LbryApp' do
|
||||
# Pods for LbryAndroid
|
||||
pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
|
||||
pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
|
||||
pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
|
||||
pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
|
||||
pod 'React', :path => '../node_modules/react-native/'
|
||||
pod 'React-Core', :path => '../node_modules/react-native/'
|
||||
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
|
||||
pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
|
||||
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
|
||||
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
|
||||
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
|
||||
pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
|
||||
pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
|
||||
pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
|
||||
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
|
||||
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
|
||||
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
|
||||
pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
|
||||
|
||||
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
|
||||
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
|
||||
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
|
||||
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
|
||||
pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
|
||||
pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
|
||||
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
|
||||
|
||||
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
|
||||
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
|
||||
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
|
||||
|
||||
target 'LbryAndroidTests' do
|
||||
inherit! :search_paths
|
||||
# Pods for testing
|
||||
end
|
||||
|
||||
use_native_modules!
|
||||
end
|
||||
|
||||
target 'LbryAndroid-tvOS' do
|
||||
# Pods for LbryAndroid-tvOS
|
||||
|
||||
target 'LbryAndroid-tvOSTests' do
|
||||
inherit! :search_paths
|
||||
# Pods for testing
|
||||
end
|
||||
|
||||
end
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -7067,8 +7067,8 @@
|
|||
}
|
||||
},
|
||||
"lbry-redux": {
|
||||
"version": "github:lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
|
||||
"from": "github:lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
|
||||
"version": "github:lbryio/lbry-redux#5c874e921769093428966fa7ecdf723719cb9067",
|
||||
"from": "github:lbryio/lbry-redux#5c874e921769093428966fa7ecdf723719cb9067",
|
||||
"requires": {
|
||||
"proxy-polyfill": "0.1.6",
|
||||
"reselect": "^3.0.0",
|
||||
|
@ -7076,8 +7076,8 @@
|
|||
}
|
||||
},
|
||||
"lbryinc": {
|
||||
"version": "github:lbryio/lbryinc#138a053754ec8e3da8e9bf153d32f527c962f25c",
|
||||
"from": "github:lbryio/lbryinc#138a053754ec8e3da8e9bf153d32f527c962f25c",
|
||||
"version": "github:lbryio/lbryinc#0dc8829a319a708f45a855765f70a193ccb72676",
|
||||
"from": "github:lbryio/lbryinc#0dc8829a319a708f45a855765f70a193ccb72676",
|
||||
"requires": {
|
||||
"reselect": "^3.0.0"
|
||||
}
|
||||
|
|
169
package.json
169
package.json
|
@ -1,83 +1,90 @@
|
|||
{
|
||||
"name": "LBRYApp",
|
||||
"version": "0.0.1",
|
||||
"private": "true",
|
||||
"scripts": {
|
||||
"start": "node node_modules/react-native/local-cli/cli.js start",
|
||||
"devtools": "react-devtools",
|
||||
"format": "prettier 'src/**/*.{js,json}' --write",
|
||||
"precommit": "lint-staged"
|
||||
},
|
||||
"dependencies": {
|
||||
"base-64": "^0.1.0",
|
||||
"@expo/vector-icons": "^8.1.0",
|
||||
"gfycat-style-urls": "^1.0.3",
|
||||
"lbry-redux": "lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
|
||||
"lbryinc": "lbryio/lbryinc#138a053754ec8e3da8e9bf153d32f527c962f25c",
|
||||
"lodash": ">=4.17.11",
|
||||
"merge": ">=1.2.1",
|
||||
"moment": "^2.22.1",
|
||||
"react": "16.9.0",
|
||||
"react-native": "0.61.5",
|
||||
"@react-native-community/async-storage": "^1.5.1",
|
||||
"@react-native-community/masked-view": "^0.1.5",
|
||||
"react-native-camera": "^3.15.0",
|
||||
"react-native-country-picker-modal": "^1.10.0",
|
||||
"react-native-exception-handler": "2.10.8",
|
||||
"react-native-fast-image": "^7.0.2",
|
||||
"react-native-fs": "^2.13.3",
|
||||
"react-native-gesture-handler": "1.5.2",
|
||||
"react-native-image-zoom-viewer": "^2.2.5",
|
||||
"react-native-password-strength-meter": "^0.0.2",
|
||||
"react-native-phone-input": "lbryio/react-native-phone-input",
|
||||
"react-native-progress-circle": "2.1.0",
|
||||
"react-native-reanimated": "1.4.0",
|
||||
"react-native-safe-area-context": "^0.6.2",
|
||||
"react-native-snackbar": "2.0.4",
|
||||
"react-native-super-grid": "^3.0.4",
|
||||
"react-native-vector-icons": "^6.6.0",
|
||||
"react-native-video": "lbryio/react-native-video#7992ff945872f9bd00a3736d9ff1318f343abf47",
|
||||
"react-native-webview": "^8.0.2",
|
||||
"react-navigation": "^4.0.10",
|
||||
"react-navigation-drawer": "^2.3.3",
|
||||
"react-navigation-redux-helpers": "^3.0.2",
|
||||
"react-navigation-tabs": "^2.7.0",
|
||||
"react-navigation-stack": "^1.10.3",
|
||||
"react-redux": "^5.0.3",
|
||||
"redux": "^4.0.4",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-persist-filesystem-storage": "^2.1.0",
|
||||
"redux-persist-transform-compress": "^4.2.0",
|
||||
"redux-persist-transform-filter": "0.0.18",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"rn-fetch-blob": "0.12.0",
|
||||
"seedrandom": "3.0.3",
|
||||
"showdown": "1.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.6.2",
|
||||
"babel-eslint": "10.0.2",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.5.4",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-preset-stage-2": "^6.18.0",
|
||||
"babel-plugin-module-resolver": "^3.1.1",
|
||||
"eslint": "^6.5.1",
|
||||
"eslint-config-standard": "^12.0.0",
|
||||
"eslint-config-standard-jsx": "^6.0.2",
|
||||
"eslint-plugin-flowtype": "^2.46.1",
|
||||
"eslint-plugin-import": "^2.17.2",
|
||||
"eslint-plugin-node": "^8.0.1",
|
||||
"eslint-plugin-promise": "^4.1.1",
|
||||
"eslint-plugin-react": "^7.12.4",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
"flow-babel-webpack-plugin": "^1.1.1",
|
||||
"husky": "^0.14.3",
|
||||
"lint-staged": "^7.0.4",
|
||||
"metro-react-native-babel-preset": "^0.56.0",
|
||||
"prettier": "^1.11.1",
|
||||
"@react-native-community/eslint-config": "^0.0.5",
|
||||
"react-devtools": "^3.6.3",
|
||||
"reactotron-react-native": "4.0.2",
|
||||
"reactotron-redux": "3.1.2"
|
||||
}
|
||||
"name": "LBRYApp",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"android": "react-native run-android",
|
||||
"ios": "react-native run-ios",
|
||||
"start": "react-native start",
|
||||
"test": "jest",
|
||||
"lint": "eslint .",
|
||||
"format": "prettier 'src/**/*.{js,json}' --write",
|
||||
"precommit": "lint-staged"
|
||||
},
|
||||
"dependencies": {
|
||||
"base-64": "^0.1.0",
|
||||
"@expo/vector-icons": "^8.1.0",
|
||||
"gfycat-style-urls": "^1.0.3",
|
||||
"lbry-redux": "lbryio/lbry-redux#9c48cce570ee8e057068c86cb6507e1b441841ee",
|
||||
"lbryinc": "lbryio/lbryinc#0dc8829a319a708f45a855765f70a193ccb72676",
|
||||
"lodash": ">=4.17.11",
|
||||
"merge": ">=1.2.1",
|
||||
"moment": "^2.22.1",
|
||||
"react": "16.9.0",
|
||||
"react-native": "0.61.5",
|
||||
"@react-native-community/async-storage": "^1.5.1",
|
||||
"@react-native-community/masked-view": "^0.1.5",
|
||||
"react-native-camera": "^3.15.0",
|
||||
"react-native-country-picker-modal": "^1.10.0",
|
||||
"react-native-exception-handler": "2.10.8",
|
||||
"react-native-fast-image": "^7.0.2",
|
||||
"react-native-fs": "^2.16.6",
|
||||
"react-native-gesture-handler": "1.5.2",
|
||||
"react-native-image-zoom-viewer": "^2.2.5",
|
||||
"react-native-password-strength-meter": "^0.0.2",
|
||||
"react-native-phone-input": "lbryio/react-native-phone-input",
|
||||
"react-native-progress-circle": "2.1.0",
|
||||
"react-native-reanimated": "1.4.0",
|
||||
"react-native-safe-area-context": "^0.6.2",
|
||||
"react-native-screens": "^2.0.0",
|
||||
"react-native-snackbar": "2.0.4",
|
||||
"react-native-super-grid": "^3.0.4",
|
||||
"react-native-vector-icons": "^6.6.0",
|
||||
"react-native-video": "lbryio/react-native-video#7992ff945872f9bd00a3736d9ff1318f343abf47",
|
||||
"react-native-webview": "^8.0.2",
|
||||
"react-navigation": "^4.0.10",
|
||||
"react-navigation-drawer": "2.3.3",
|
||||
"react-navigation-redux-helpers": "^3.0.2",
|
||||
"react-navigation-tabs": "^2.7.0",
|
||||
"react-navigation-stack": "^1.10.3",
|
||||
"react-redux": "^5.0.3",
|
||||
"redux": "^4.0.4",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-persist-filesystem-storage": "^2.1.0",
|
||||
"redux-persist-transform-compress": "^4.2.0",
|
||||
"redux-persist-transform-filter": "0.0.18",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"rn-fetch-blob": "0.12.0",
|
||||
"seedrandom": "3.0.3",
|
||||
"showdown": "1.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.6.2",
|
||||
"babel-eslint": "10.0.2",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.5.4",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-preset-stage-2": "^6.18.0",
|
||||
"babel-plugin-module-resolver": "^3.1.1",
|
||||
"eslint": "^6.5.1",
|
||||
"eslint-config-standard": "^12.0.0",
|
||||
"eslint-config-standard-jsx": "^6.0.2",
|
||||
"eslint-plugin-flowtype": "^2.46.1",
|
||||
"eslint-plugin-import": "^2.17.2",
|
||||
"eslint-plugin-node": "^8.0.1",
|
||||
"eslint-plugin-promise": "^4.1.1",
|
||||
"eslint-plugin-react": "^7.12.4",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
"flow-babel-webpack-plugin": "^1.1.1",
|
||||
"husky": "^0.14.3",
|
||||
"lint-staged": "^7.0.4",
|
||||
"metro-react-native-babel-preset": "^0.58.0",
|
||||
"prettier": "^1.11.1",
|
||||
"@react-native-community/eslint-config": "^0.0.5",
|
||||
"react-devtools": "^3.6.3",
|
||||
"reactotron-react-native": "4.0.2",
|
||||
"reactotron-redux": "3.1.2"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "react-native"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,12 +89,13 @@ const menuNavigationButton = navigation => (
|
|||
|
||||
const discoverStack = createStackNavigator(
|
||||
{
|
||||
Discover: {
|
||||
screen: DiscoverPage,
|
||||
navigationOptions: ({ navigation }) => ({
|
||||
title: 'Explore',
|
||||
Subscriptions: {
|
||||
screen: SubscriptionsPage,
|
||||
navigationOptions: {
|
||||
title: 'Following',
|
||||
header: null,
|
||||
}),
|
||||
drawerIcon: ({ tintColor }) => <Icon name="heart" solid size={drawerIconSize} style={{ color: tintColor }} />,
|
||||
},
|
||||
},
|
||||
File: {
|
||||
screen: FilePage,
|
||||
|
@ -161,10 +162,17 @@ const drawer = createDrawerNavigator(
|
|||
DiscoverStack: {
|
||||
screen: discoverStack,
|
||||
navigationOptions: {
|
||||
title: 'Explore',
|
||||
title: 'Following',
|
||||
drawerIcon: ({ tintColor }) => <Icon name="home" size={drawerIconSize} style={{ color: tintColor }} />,
|
||||
},
|
||||
},
|
||||
Discover: {
|
||||
screen: DiscoverPage,
|
||||
navigationOptions: ({ navigation }) => ({
|
||||
title: 'Your Tags',
|
||||
header: null,
|
||||
}),
|
||||
},
|
||||
Trending: {
|
||||
screen: TrendingPage,
|
||||
navigationOptions: {
|
||||
|
@ -172,13 +180,6 @@ const drawer = createDrawerNavigator(
|
|||
drawerIcon: ({ tintColor }) => <Icon name="fire" size={drawerIconSize} style={{ color: tintColor }} />,
|
||||
},
|
||||
},
|
||||
Subscriptions: {
|
||||
screen: SubscriptionsPage,
|
||||
navigationOptions: {
|
||||
title: 'Subscriptions',
|
||||
drawerIcon: ({ tintColor }) => <Icon name="heart" solid size={drawerIconSize} style={{ color: tintColor }} />,
|
||||
},
|
||||
},
|
||||
WalletStack: {
|
||||
screen: walletStack,
|
||||
navigationOptions: {
|
||||
|
|
|
@ -19,11 +19,11 @@ const select = state => ({
|
|||
const perform = dispatch => ({
|
||||
notify: data => dispatch(doToast(data)),
|
||||
createChannel: (name, amount) => dispatch(doCreateChannel(name, amount)),
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
||||
getSync: (password, callback) => dispatch(doGetSync(password, callback)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
perform,
|
||||
)(ChannelSelector);
|
||||
|
|
|
@ -12,11 +12,11 @@ import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
|||
import ClaimList from './view';
|
||||
|
||||
const select = state => ({
|
||||
showNsfwContent: selectShowNsfw(state),
|
||||
claimSearchByQuery: selectClaimSearchByQuery(state),
|
||||
lastPageReached: selectClaimSearchByQueryLastPageReached(state),
|
||||
loadingByQuery: selectFetchingClaimSearchByQuery(state),
|
||||
loading: selectFetchingClaimSearch(state),
|
||||
showNsfwContent: selectShowNsfw(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
@ -25,5 +25,5 @@ const perform = dispatch => ({
|
|||
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
perform,
|
||||
)(ClaimList);
|
||||
|
|
|
@ -9,10 +9,10 @@ const select = state => ({
|
|||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
perform,
|
||||
)(DrawerContent);
|
||||
|
|
|
@ -9,8 +9,8 @@ import discoverStyle from 'styles/discover';
|
|||
|
||||
const groupedMenuItems = {
|
||||
'Find content': [
|
||||
{ icon: 'hashtag', label: 'Your Tags', route: Constants.DRAWER_ROUTE_DISCOVER },
|
||||
{ icon: 'heart', solid: true, label: 'Following', route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS },
|
||||
{ icon: 'hashtag', label: 'Your Tags', route: Constants.DRAWER_ROUTE_DISCOVER },
|
||||
{ icon: 'globe-americas', label: 'All Content', route: Constants.DRAWER_ROUTE_TRENDING },
|
||||
],
|
||||
'Your content': [
|
||||
|
@ -145,7 +145,7 @@ class DrawerContent extends React.PureComponent {
|
|||
const focused =
|
||||
activeItemKey === item.route ||
|
||||
(activeItemKey === Constants.FULL_ROUTE_NAME_DISCOVER &&
|
||||
item.route === Constants.DRAWER_ROUTE_DISCOVER) ||
|
||||
item.route === Constants.DRAWER_ROUTE_SUBSCRIPTIONS) ||
|
||||
(activeItemKey === Constants.FULL_ROUTE_NAME_WALLET &&
|
||||
item.route === Constants.DRAWER_ROUTE_WALLET);
|
||||
return (
|
||||
|
|
|
@ -99,9 +99,12 @@ class FileListItem extends React.PureComponent {
|
|||
isRewardContent,
|
||||
channelClaimId,
|
||||
fullChannelUri,
|
||||
repostChannel,
|
||||
repostChannelUrl,
|
||||
shortChannelUri,
|
||||
shouldHide,
|
||||
signingChannel;
|
||||
signingChannel,
|
||||
isRepost;
|
||||
if (claim) {
|
||||
name = claim.name;
|
||||
signingChannel = claim.signing_channel;
|
||||
|
@ -111,6 +114,12 @@ class FileListItem extends React.PureComponent {
|
|||
channelClaimId = signingChannel ? signingChannel.claim_id : null;
|
||||
fullChannelUri = channelClaimId ? `${channel}#${channelClaimId}` : channel;
|
||||
shortChannelUri = signingChannel ? signingChannel.short_url : null;
|
||||
repostChannelUrl = claim.repost_channel_url;
|
||||
if (repostChannelUrl) {
|
||||
const { claimName: repostChannelName } = parseURI(repostChannelUrl);
|
||||
repostChannel = repostChannelName;
|
||||
}
|
||||
isRepost = !!repostChannelUrl;
|
||||
|
||||
if (blackListedOutpoints || filteredOutpoints) {
|
||||
const outpointsToHide = !blackListedOutpoints
|
||||
|
@ -127,11 +136,20 @@ class FileListItem extends React.PureComponent {
|
|||
return null;
|
||||
}
|
||||
|
||||
const actualHideChannel = !isRepost && hideChannel;
|
||||
const isChannel = name && name.startsWith('@');
|
||||
const hasThumbnail = !!thumbnail;
|
||||
|
||||
return (
|
||||
<View style={style}>
|
||||
<View>
|
||||
{isRepost && (
|
||||
<View style={fileListStyle.repostInfo}>
|
||||
<Icon name={"retweet"} size={14} style={fileListStyle.repostIcon} />
|
||||
<Text style={fileListStyle.repostChannelName}>
|
||||
<Link text={repostChannel}
|
||||
onPress={() => navigateToUri(navigation, normalizeURI(repostChannelUrl), null, false, null, false)} /> reposted</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<TouchableOpacity
|
||||
style={[style, isChannel ? fileListStyle.channelContainer : null]}
|
||||
onPress={this.onPressHandler}
|
||||
|
@ -212,7 +230,7 @@ class FileListItem extends React.PureComponent {
|
|||
<View style={fileListStyle.titleContainer}>
|
||||
<Text
|
||||
style={featuredResult ? fileListStyle.featuredTitle : fileListStyle.title}
|
||||
numberOfLines={hideChannel ? 4 : 3}
|
||||
numberOfLines={actualHideChannel ? 4 : 3}
|
||||
>
|
||||
{title || name}
|
||||
</Text>
|
||||
|
@ -226,7 +244,7 @@ class FileListItem extends React.PureComponent {
|
|||
</View>
|
||||
)}
|
||||
|
||||
{(channel || isChannel) && !hideChannel && (
|
||||
{(channel || isChannel) && !actualHideChannel && (
|
||||
<Link
|
||||
style={fileListStyle.publisher}
|
||||
text={isChannel ? name : channel}
|
||||
|
|
|
@ -167,7 +167,7 @@ class MediaPlayer extends React.PureComponent {
|
|||
|
||||
togglePlay = () => {
|
||||
this.showPlayerControls();
|
||||
this.setState({ paused: !this.state.paused }, this.handlePausedState);
|
||||
this.setState({ paused: !this.state.paused }, this.updateBackgroundMediaNotification);
|
||||
};
|
||||
|
||||
handlePausedState = () => {
|
||||
|
@ -188,7 +188,7 @@ class MediaPlayer extends React.PureComponent {
|
|||
};
|
||||
|
||||
onEnd = () => {
|
||||
this.setState({ paused: true });
|
||||
this.setState({ paused: true }, this.updateBackgroundMediaNotification);
|
||||
if (this.props.onPlaybackFinished) {
|
||||
this.props.onPlaybackFinished();
|
||||
}
|
||||
|
@ -327,6 +327,10 @@ class MediaPlayer extends React.PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
onFocusChanged = evt => {
|
||||
this.setState({ paused: !(this.state.paused && evt.hasAudioFocus) }, this.updateBackgroundMediaNotification);
|
||||
};
|
||||
|
||||
onBuffer = () => {
|
||||
if (!this.state.paused) {
|
||||
this.setState({ buffering: true }, () => this.manualHidePlayerControls());
|
||||
|
@ -469,6 +473,7 @@ class MediaPlayer extends React.PureComponent {
|
|||
onEnd={this.onEnd}
|
||||
onError={this.onError}
|
||||
minLoadRetryCount={999}
|
||||
onAudioFocusChanged={this.onFocusChanged}
|
||||
/>
|
||||
|
||||
{this.state.firstPlay && thumbnail && (
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectFetchingClaimSearch } from 'lbry-redux';
|
||||
import ModalSuggestedSubscriptions from './view';
|
||||
|
||||
export default connect()(ModalSuggestedSubscriptions);
|
||||
const select = state => ({
|
||||
loadingSuggested: selectFetchingClaimSearch(state),
|
||||
});
|
||||
|
||||
export default connect(select)(ModalSuggestedSubscriptions);
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
import React from 'react';
|
||||
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
||||
import { ActivityIndicator, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
||||
import modalStyle from 'styles/modal';
|
||||
import subscriptionsStyle from 'styles/subscriptions';
|
||||
import Button from 'component/button';
|
||||
import Colors from 'styles/colors';
|
||||
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
|
||||
import SuggestedSubscriptionsGrid from 'component/suggestedSubscriptionsGrid';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
|
||||
export default class ModalSuggestedSubcriptions extends React.PureComponent {
|
||||
render() {
|
||||
const { navigation, onDonePress, onOverlayPress } = this.props;
|
||||
const { loadingSuggested, navigation, onDonePress, onOverlayPress } = this.props;
|
||||
|
||||
return (
|
||||
<TouchableOpacity style={modalStyle.overlay} activeOpacity={1} onPress={onOverlayPress}>
|
||||
<TouchableOpacity style={[modalStyle.container, subscriptionsStyle.modalContainer]} activeOpacity={1}>
|
||||
<SuggestedSubscriptions inModal navigation={navigation} />
|
||||
<View style={modalStyle.buttons}>
|
||||
<Button style={modalStyle.doneButton} text={__('Done')} onPress={onDonePress} />
|
||||
<SuggestedSubscriptionsGrid inModal navigation={navigation} />
|
||||
<View style={modalStyle.wideButtons}>
|
||||
<Button style={modalStyle.wideDoneButton} text={__('Done')} onPress={onDonePress} />
|
||||
{loadingSuggested && (
|
||||
<ActivityIndicator size="small" color={Colors.White} style={subscriptionsStyle.modalLoading} />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</TouchableOpacity>
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
selectResolvingUris,
|
||||
selectIsSearching,
|
||||
} from 'lbry-redux';
|
||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||
import RelatedContent from './view';
|
||||
|
||||
const RESULT_SIZE = 16;
|
||||
|
@ -16,12 +17,13 @@ const select = (state, props) => ({
|
|||
isSearching: selectIsSearching(state),
|
||||
recommendedContent: makeSelectResolvedRecommendedContentForUri(props.uri, RESULT_SIZE)(state),
|
||||
resolvingUris: selectResolvingUris(state),
|
||||
showNsfwContent: selectShowNsfw(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
resolveUris: uris => dispatch(doResolveUris(uris)),
|
||||
searchRecommended: (query, claimId) =>
|
||||
dispatch(doResolvedSearch(query, RESULT_SIZE, undefined, true, { related_to: claimId }, false)),
|
||||
searchRecommended: (query, claimId, nsfw) =>
|
||||
dispatch(doResolvedSearch(query, RESULT_SIZE, undefined, true, { related_to: claimId }, nsfw)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -10,9 +10,9 @@ import relatedContentStyle from 'styles/relatedContent';
|
|||
|
||||
export default class RelatedContent extends React.PureComponent {
|
||||
componentDidMount() {
|
||||
const { title, claimId, searchRecommended } = this.props;
|
||||
const { title, claimId, searchRecommended, showNsfwContent } = this.props;
|
||||
if (title && claimId) {
|
||||
searchRecommended(title, claimId);
|
||||
searchRecommended(title, claimId, showNsfwContent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
18
src/component/subscribeButtonOverlay/index.js
Normal file
18
src/component/subscribeButtonOverlay/index.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doChannelSubscribe, doChannelUnsubscribe, selectSubscriptions, makeSelectIsSubscribed } from 'lbryinc';
|
||||
import { doToast } from 'lbry-redux';
|
||||
import SubscribeButtonOverlay from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
subscriptions: selectSubscriptions(state),
|
||||
isSubscribed: makeSelectIsSubscribed(props.uri, true)(state),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
{
|
||||
doChannelSubscribe,
|
||||
doChannelUnsubscribe,
|
||||
doToast,
|
||||
},
|
||||
)(SubscribeButtonOverlay);
|
36
src/component/subscribeButtonOverlay/view.js
Normal file
36
src/component/subscribeButtonOverlay/view.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
import React from 'react';
|
||||
import { normalizeURI, parseURI } from 'lbry-redux';
|
||||
import { NativeModules, Text, View, TouchableOpacity } from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import Button from 'component/button';
|
||||
import Colors from 'styles/colors';
|
||||
|
||||
class SubscribeButtonOverlay extends React.PureComponent {
|
||||
handlePress = () => {
|
||||
const { claim, isSubscribed, doChannelSubscribe, doChannelUnsubscribe, uri } = this.props;
|
||||
if (!claim) {
|
||||
return;
|
||||
}
|
||||
|
||||
const subscriptionHandler = isSubscribed ? doChannelUnsubscribe : doChannelSubscribe;
|
||||
const { name: claimName } = claim;
|
||||
subscriptionHandler({
|
||||
channelName: claimName,
|
||||
uri: normalizeURI(uri),
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { uri, isSubscribed, style } = this.props;
|
||||
let styles = style.length ? style : [style];
|
||||
|
||||
return (
|
||||
<TouchableOpacity style={styles} opacity={0.7} onPress={this.handlePress}>
|
||||
{isSubscribed && <Icon name={'heart'} size={20} solid color={Colors.Red} />}
|
||||
{!isSubscribed && <Icon name={'heart'} size={20} color={Colors.Red} />}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SubscribeButtonOverlay;
|
|
@ -6,6 +6,7 @@ import {
|
|||
makeSelectTitleForUri,
|
||||
makeSelectIsUriResolving,
|
||||
} from 'lbry-redux';
|
||||
import { doChannelSubscribe, doChannelUnsubscribe, makeSelectIsSubscribed } from 'lbryinc';
|
||||
import SuggestedSubscriptionItem from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
|
@ -13,13 +14,16 @@ const select = (state, props) => ({
|
|||
title: makeSelectTitleForUri(props.uri)(state),
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
||||
isSubscribed: makeSelectIsSubscribed(props.uri, true)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||
subscribe: subscription => doChannelSubscribe(subscription),
|
||||
unsubscribe: subscription => doChannelUnsubscribe(subscription),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
perform,
|
||||
)(SuggestedSubscriptionItem);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React from 'react';
|
||||
import { buildURI, normalizeURI } from 'lbry-redux';
|
||||
import { ActivityIndicator, FlatList, Image, Text, View } from 'react-native';
|
||||
import { ActivityIndicator, FlatList, Image, Text, TouchableOpacity, View } from 'react-native';
|
||||
import { navigateToUri } from 'utils/helper';
|
||||
import Colors from 'styles/colors';
|
||||
import ChannelIconItem from 'component/channelIconItem';
|
||||
import channelIconStyle from 'styles/channelIcon';
|
||||
import discoverStyle from 'styles/discover';
|
||||
import FileItem from 'component/fileItem';
|
||||
import SubscribeButton from 'component/subscribeButton';
|
||||
import SubscribeButtonOverlay from 'component/subscribeButtonOverlay';
|
||||
import subscriptionsStyle from 'styles/subscriptions';
|
||||
import Link from 'component/link';
|
||||
import Tag from 'component/tag';
|
||||
|
@ -31,6 +31,7 @@ class SuggestedSubscriptionItem extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
const { claim, isResolvingUri, navigation, thumbnail, title, uri } = this.props;
|
||||
|
||||
let shortUrl, tags;
|
||||
if (claim) {
|
||||
shortUrl = claim.short_url;
|
||||
|
@ -49,7 +50,7 @@ class SuggestedSubscriptionItem extends React.PureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<View style={subscriptionsStyle.suggestedItem}>
|
||||
<TouchableOpacity style={subscriptionsStyle.suggestedItem}>
|
||||
<View style={[subscriptionsStyle.suggestedItemThumbnailContainer, this.state.autoStyle]}>
|
||||
{hasThumbnail && (
|
||||
<Image style={subscriptionsStyle.suggestedItemThumbnail} resizeMode={'cover'} source={{ uri: thumbnail }} />
|
||||
|
@ -62,35 +63,37 @@ class SuggestedSubscriptionItem extends React.PureComponent {
|
|||
</View>
|
||||
|
||||
<View style={subscriptionsStyle.suggestedItemDetails}>
|
||||
{title && (
|
||||
<Text style={subscriptionsStyle.suggestedItemTitle} numberOfLines={1}>
|
||||
{title}
|
||||
</Text>
|
||||
)}
|
||||
{claim && (
|
||||
<Link
|
||||
style={subscriptionsStyle.suggestedItemName}
|
||||
numberOfLines={1}
|
||||
text={claim.name}
|
||||
onPress={() => navigateToUri(navigation, normalizeURI(shortUrl || uri), null, false, claim.permanent_url)}
|
||||
/>
|
||||
)}
|
||||
<Text style={subscriptionsStyle.suggestedItemTitle} numberOfLines={2}>
|
||||
{title || claim.name}
|
||||
</Text>
|
||||
{tags && (
|
||||
<View style={subscriptionsStyle.suggestedItemTagList}>
|
||||
{tags &&
|
||||
tags
|
||||
.slice(0, 3)
|
||||
.slice(0, 1)
|
||||
.map(tag => (
|
||||
<Tag style={subscriptionsStyle.tag} key={tag} name={tag} navigation={navigation} truncate />
|
||||
<Tag
|
||||
numberOfLines={1}
|
||||
onPress={this.handleItemPress}
|
||||
style={subscriptionsStyle.tag}
|
||||
key={tag}
|
||||
name={tag}
|
||||
navigation={navigation}
|
||||
truncate
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{claim && (
|
||||
<SubscribeButton style={subscriptionsStyle.suggestedItemSubscribe} uri={normalizeURI(claim.permanent_url)} />
|
||||
<SubscribeButtonOverlay
|
||||
claim={claim}
|
||||
style={subscriptionsStyle.suggestedItemSubscribeOverlay}
|
||||
uri={normalizeURI(claim.permanent_url)}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
30
src/component/suggestedSubscriptionsGrid/index.js
Normal file
30
src/component/suggestedSubscriptionsGrid/index.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { connect } from 'react-redux';
|
||||
import {
|
||||
doClaimSearch,
|
||||
selectFetchingClaimSearch,
|
||||
selectClaimSearchByQuery,
|
||||
selectClaimSearchByQueryLastPageReached,
|
||||
selectFollowedTags,
|
||||
} from 'lbry-redux';
|
||||
import { selectSubscriptions, selectSuggestedChannels, selectIsFetchingSuggested } from 'lbryinc';
|
||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||
import SuggestedSubscriptionsGrid from './view';
|
||||
|
||||
const select = state => ({
|
||||
followedTags: selectFollowedTags(state),
|
||||
subscriptions: selectSubscriptions(state),
|
||||
suggested: selectSuggestedChannels(state),
|
||||
loading: selectIsFetchingSuggested(state) || selectFetchingClaimSearch(state),
|
||||
claimSearchByQuery: selectClaimSearchByQuery(state),
|
||||
lastPageReached: selectClaimSearchByQueryLastPageReached(state),
|
||||
showNsfwContent: selectShowNsfw(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
claimSearch: options => dispatch(doClaimSearch(options)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
perform,
|
||||
)(SuggestedSubscriptionsGrid);
|
111
src/component/suggestedSubscriptionsGrid/view.js
Normal file
111
src/component/suggestedSubscriptionsGrid/view.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
import React from 'react';
|
||||
import { ActivityIndicator, SectionList, Text, View } from 'react-native';
|
||||
import { MATURE_TAGS, createNormalizedClaimSearchKey, normalizeURI } from 'lbry-redux';
|
||||
import { navigateToUri } from 'utils/helper';
|
||||
import { FlatGrid } from 'react-native-super-grid';
|
||||
import SubscribeButton from 'component/subscribeButton';
|
||||
import SuggestedSubscriptionItem from 'component/suggestedSubscriptionItem';
|
||||
import Colors from 'styles/colors';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import discoverStyle from 'styles/discover';
|
||||
import subscriptionsStyle from 'styles/subscriptions';
|
||||
import Link from 'component/link';
|
||||
import _ from 'lodash';
|
||||
|
||||
const suggestedPageSize = 24;
|
||||
const softLimit = 2400;
|
||||
class SuggestedSubscriptionsGrid extends React.PureComponent {
|
||||
state = {
|
||||
currentPage: 1,
|
||||
options: {},
|
||||
// maintain a local state of subscriptions so that changes don't affect the search
|
||||
subscriptionIds: [],
|
||||
};
|
||||
|
||||
buildClaimSearchOptions() {
|
||||
const { showNsfwContent } = this.props;
|
||||
const { currentPage } = this.state;
|
||||
|
||||
const options = {
|
||||
no_totals: true,
|
||||
page: currentPage,
|
||||
page_size: suggestedPageSize,
|
||||
claim_type: 'channel',
|
||||
order_by: [Constants.ORDER_BY_EFFECTIVE_AMOUNT],
|
||||
};
|
||||
if (!showNsfwContent) {
|
||||
options.not_tags = MATURE_TAGS;
|
||||
}
|
||||
if (this.state.subscriptionIds.length > 0) {
|
||||
options.not_channel_ids = this.state.subscriptionIds;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
doClaimSearch() {
|
||||
const { claimSearch } = this.props;
|
||||
const options = this.buildClaimSearchOptions();
|
||||
claimSearch(options);
|
||||
}
|
||||
|
||||
handleVerticalEndReached = () => {
|
||||
// fetch more content
|
||||
const { claimSearchByQuery, lastPageReached } = this.props;
|
||||
|
||||
const options = this.buildClaimSearchOptions();
|
||||
const claimSearchKey = createNormalizedClaimSearchKey(options);
|
||||
const uris = claimSearchByQuery[claimSearchKey];
|
||||
if (
|
||||
lastPageReached[claimSearchKey] ||
|
||||
((uris.length > 0 && uris.length < suggestedPageSize) || uris.length >= softLimit)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ currentPage: this.state.currentPage + 1 }, () => this.doClaimSearch());
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { claimSearch, followedTags, showNsfwContent, subscriptions } = this.props;
|
||||
if (subscriptions && subscriptions.length > 0) {
|
||||
this.setState(
|
||||
{
|
||||
subscriptionIds: subscriptions.map(subscription => subscription.uri.split('#')[1]),
|
||||
},
|
||||
() => this.doClaimSearch(),
|
||||
);
|
||||
} else {
|
||||
this.doClaimSearch();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { claimSearchByQuery, suggested, inModal, navigation } = this.props;
|
||||
const options = this.buildClaimSearchOptions();
|
||||
const claimSearchKey = createNormalizedClaimSearchKey(options);
|
||||
const claimSearchUris = claimSearchByQuery[claimSearchKey];
|
||||
|
||||
return (
|
||||
<FlatGrid
|
||||
initialNumToRender={24}
|
||||
maxToRenderPerBatch={48}
|
||||
removeClippedSubviews
|
||||
itemDimension={120}
|
||||
spacing={2}
|
||||
items={claimSearchUris}
|
||||
style={inModal ? subscriptionsStyle.modalScrollContainer : subscriptionsStyle.scrollContainer}
|
||||
contentContainerStyle={
|
||||
inModal ? subscriptionsStyle.modalSuggestedScrollContent : subscriptionsStyle.suggestedScrollContent
|
||||
}
|
||||
renderItem={({ item, index }) => (
|
||||
<SuggestedSubscriptionItem key={item} uri={normalizeURI(item)} navigation={navigation} />
|
||||
)}
|
||||
onEndReached={this.handleVerticalEndReached}
|
||||
onEndReachedThreshold={0.2}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SuggestedSubscriptionsGrid;
|
|
@ -30,7 +30,7 @@ export default class Tag extends React.PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { name, onPress, style, type, truncate } = this.props;
|
||||
const { name, numberOfLines, onPress, style, type, truncate } = this.props;
|
||||
|
||||
let styles = [];
|
||||
if (style) {
|
||||
|
@ -50,7 +50,9 @@ export default class Tag extends React.PureComponent {
|
|||
return (
|
||||
<TouchableOpacity style={styles} onPress={onPress || this.onPressDefault}>
|
||||
<View style={tagStyle.content}>
|
||||
<Text style={tagStyle.text}>{truncate ? formatTagName(name) : name}</Text>
|
||||
<Text style={tagStyle.text} numberOfLines={numberOfLines}>
|
||||
{truncate ? formatTagName(name) : name}
|
||||
</Text>
|
||||
{type && <Icon style={tagStyle.icon} name={type === 'add' ? 'plus' : 'times'} size={8} />}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
|
14
src/component/walletBalanceExtra/index.js
Normal file
14
src/component/walletBalanceExtra/index.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectClaimsBalance, selectSupportsBalance, selectTipsBalance } from 'lbry-redux';
|
||||
import WalletBalanceExtra from './view';
|
||||
|
||||
const select = state => ({
|
||||
claimsBalance: selectClaimsBalance(state) || 0,
|
||||
supportsBalance: selectSupportsBalance(state) || 0,
|
||||
tipsBalance: selectTipsBalance(state) || 0,
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
null,
|
||||
)(WalletBalanceExtra);
|
54
src/component/walletBalanceExtra/view.js
Normal file
54
src/component/walletBalanceExtra/view.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { Image, Text, View } from 'react-native';
|
||||
import { Lbry, formatCredits } from 'lbry-redux';
|
||||
import Address from 'component/address';
|
||||
import Button from 'component/button';
|
||||
import Colors from 'styles/colors';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import walletStyle from 'styles/wallet';
|
||||
|
||||
type Props = {
|
||||
claimsBalance: number,
|
||||
supportsBalance: number,
|
||||
tipsBalance: number,
|
||||
};
|
||||
|
||||
class WalletBalanceExtra extends React.PureComponent<Props> {
|
||||
render() {
|
||||
const { claimsBalance, supportsBalance, tipsBalance } = this.props;
|
||||
|
||||
return (
|
||||
<View style={walletStyle.balanceExtraCard}>
|
||||
<View style={walletStyle.walletExtraRow}>
|
||||
<View style={walletStyle.walletExtraCol}>
|
||||
<Icon style={walletStyle.walletExtraIcon} color={Colors.LbryGreen} name={'gift'} size={16} />
|
||||
<Text style={walletStyle.walletExtraCaption}>{__('You also have')}</Text>
|
||||
<View style={walletStyle.balanceRow}>
|
||||
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(tipsBalance), 2)}</Text>
|
||||
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
||||
</View>
|
||||
<Text style={walletStyle.text}>{__('in tips')}</Text>
|
||||
</View>
|
||||
|
||||
<View style={walletStyle.walletExtraCol}>
|
||||
<Icon style={walletStyle.walletExtraIcon} color={Colors.LbryGreen} name={'lock'} size={16} />
|
||||
<Text style={walletStyle.walletExtraCaption}>{__('You staked')}</Text>
|
||||
<View style={walletStyle.balanceRow}>
|
||||
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(claimsBalance), 2)}</Text>
|
||||
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
||||
</View>
|
||||
<Text style={walletStyle.text}>{__('in your publishes')}</Text>
|
||||
<View style={[walletStyle.balanceRow, walletStyle.walletExtraTopMargin]}>
|
||||
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(supportsBalance), 2)}</Text>
|
||||
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
||||
</View>
|
||||
<Text style={walletStyle.text}>{__('in your supports')}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default WalletBalanceExtra;
|
|
@ -64,6 +64,8 @@ const Constants = {
|
|||
ACTION_CLEAR_PUBLISH_FORM_STATE: 'CLEAR_PUBLISH_FORM_STATE',
|
||||
ACTION_CLEAR_CHANNEL_FORM_STATE: 'CLEAR_CHANNEL_FORM_STATE',
|
||||
|
||||
ACTION_SET_EXPLICIT_NAVIGATE_BACK: 'SET_EXPLICIT_NAVIGATE_BACK',
|
||||
|
||||
ACTION_FULLSCREEN_MODE_TOGGLED: 'FULLSCREEN_MODE_TOGGLED',
|
||||
|
||||
ORIENTATION_HORIZONTAL: 'horizontal',
|
||||
|
|
|
@ -18,7 +18,7 @@ const select = (state, props) => ({
|
|||
|
||||
const perform = dispatch => ({
|
||||
abandonClaim: (txid, nout) => dispatch(doAbandonClaim(txid, nout)),
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
||||
fetchSubCount: claimId => dispatch(doFetchSubCount(claimId)),
|
||||
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
||||
setSortByItem: item => dispatch(doSetSortByItem(item)),
|
||||
|
@ -27,5 +27,5 @@ const perform = dispatch => ({
|
|||
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
perform,
|
||||
)(ChannelPage);
|
||||
|
|
|
@ -173,9 +173,10 @@ class ChannelPage extends React.PureComponent {
|
|||
const { permanent_url: permanentUrl } = claim;
|
||||
navigation.navigate({
|
||||
routeName: Constants.DRAWER_ROUTE_CHANNEL_CREATOR,
|
||||
params: { editChannelUrl: permanentUrl },
|
||||
params: { editChannelUrl: permanentUrl, returnUrl: permanentUrl },
|
||||
});
|
||||
}
|
||||
this.onEditPressed = null;
|
||||
};
|
||||
|
||||
onTipPressed = () => {
|
||||
|
@ -210,7 +211,7 @@ class ChannelPage extends React.PureComponent {
|
|||
},
|
||||
},
|
||||
],
|
||||
{ cancelable: true }
|
||||
{ cancelable: true },
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -13,7 +13,12 @@ import {
|
|||
doToast,
|
||||
} from 'lbry-redux';
|
||||
import { doGetSync } from 'lbryinc';
|
||||
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||
import {
|
||||
doPushDrawerStack,
|
||||
doPopDrawerStack,
|
||||
doSetPlayerVisible,
|
||||
doSetExplicitNavigateBack,
|
||||
} from 'redux/actions/drawer';
|
||||
import { doUpdateChannelFormState, doClearChannelFormState } from 'redux/actions/form';
|
||||
import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||
import { selectChannelFormState, selectHasChannelFormState } from 'redux/selectors/form';
|
||||
|
@ -37,16 +42,17 @@ const perform = dispatch => ({
|
|||
notify: data => dispatch(doToast(data)),
|
||||
clearChannelFormState: () => dispatch(doClearChannelFormState()),
|
||||
createChannel: (name, amount, optionalParams) => dispatch(doCreateChannel(name, amount, optionalParams)),
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
||||
getSync: (password, callback) => dispatch(doGetSync(password, callback)),
|
||||
updateChannel: params => dispatch(doUpdateChannel(params)),
|
||||
updateChannelFormState: data => dispatch(doUpdateChannelFormState(data)),
|
||||
pushDrawerStack: (routeName, params) => dispatch(doPushDrawerStack(routeName, params)),
|
||||
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||
setExplicitNavigateBack: flag => dispatch(doSetExplicitNavigateBack(flag)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
perform,
|
||||
)(ChannelCreator);
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { navigateToUri, logPublish, uploadImageAsset } from 'utils/helper';
|
||||
import { navigateBack, navigateToUri, logPublish, uploadImageAsset } from 'utils/helper';
|
||||
import Button from 'component/button';
|
||||
import ChannelIconItem from 'component/channelIconItem';
|
||||
import ChannelRewardsDriver from 'component/channelRewardsDriver';
|
||||
|
@ -37,6 +37,7 @@ export default class ChannelCreator extends React.PureComponent {
|
|||
|
||||
state = {
|
||||
autoStyle: null,
|
||||
returnUrl: null,
|
||||
canSave: true,
|
||||
claimId: null,
|
||||
creditsInputFocused: false,
|
||||
|
@ -77,6 +78,7 @@ export default class ChannelCreator extends React.PureComponent {
|
|||
descriptionFocused: false,
|
||||
websiteFocused: false,
|
||||
emailFocused: false,
|
||||
hasReturnedBack: false,
|
||||
};
|
||||
|
||||
didFocusListener;
|
||||
|
@ -118,7 +120,14 @@ export default class ChannelCreator extends React.PureComponent {
|
|||
};
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { currentRoute: prevRoute, drawerStack: prevDrawerStack, notify } = this.props;
|
||||
const {
|
||||
currentRoute: prevRoute,
|
||||
drawerStack: prevDrawerStack,
|
||||
popDrawerStack,
|
||||
setPlayerVisible,
|
||||
navigation,
|
||||
notify,
|
||||
} = this.props;
|
||||
const { currentRoute, drawerStack, updatingChannel, updateChannelError } = nextProps;
|
||||
|
||||
if (Constants.DRAWER_ROUTE_CHANNEL_CREATOR === currentRoute && currentRoute !== prevRoute) {
|
||||
|
@ -142,6 +151,11 @@ export default class ChannelCreator extends React.PureComponent {
|
|||
) {
|
||||
// navigated back from the form
|
||||
this.setState({ currentPhase: Constants.PHASE_LIST });
|
||||
if (!this.state.hasReturnedBack && this.state.returnUrl) {
|
||||
this.setState({ hasReturnedBack: true }, () => {
|
||||
navigateBack(navigation, drawerStack, popDrawerStack, setPlayerVisible);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,11 +185,12 @@ export default class ChannelCreator extends React.PureComponent {
|
|||
|
||||
let isEditMode = false;
|
||||
if (navigation.state.params) {
|
||||
const { editChannelUrl, displayForm } = navigation.state.params;
|
||||
const { editChannelUrl, displayForm, returnUrl } = navigation.state.params;
|
||||
if (editChannelUrl) {
|
||||
isEditMode = true;
|
||||
this.setState({ editChannelUrl, currentPhase: Constants.PHASE_CREATE });
|
||||
}
|
||||
this.setState({ returnUrl });
|
||||
}
|
||||
|
||||
if (!isEditMode && hasFormState) {
|
||||
|
|
|
@ -37,29 +37,6 @@ class DiscoverPage extends React.PureComponent {
|
|||
};
|
||||
|
||||
componentDidMount() {
|
||||
// Track the total time taken if this is the first launch
|
||||
AsyncStorage.getItem('firstLaunchTime').then(startTime => {
|
||||
if (startTime !== null && !isNaN(parseInt(startTime, 10))) {
|
||||
// We don't need this value anymore once we've retrieved it
|
||||
AsyncStorage.removeItem('firstLaunchTime');
|
||||
|
||||
// We know this is the first app launch because firstLaunchTime is set and it"s a valid number
|
||||
const start = parseInt(startTime, 10);
|
||||
const now = moment().unix();
|
||||
const delta = now - start;
|
||||
AsyncStorage.getItem('firstLaunchSuspended').then(suspended => {
|
||||
AsyncStorage.removeItem('firstLaunchSuspended');
|
||||
const appSuspended = suspended === 'true';
|
||||
if (NativeModules.Firebase) {
|
||||
NativeModules.Firebase.track('first_run_time', {
|
||||
total_seconds: delta,
|
||||
app_suspended: appSuspended,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const { sortByItem, fetchRewardedContent, fileList, followedTags } = this.props;
|
||||
|
||||
this.buildTagCollection(followedTags);
|
||||
|
@ -86,8 +63,8 @@ class DiscoverPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
onComponentFocused = () => {
|
||||
const { pushDrawerStack, setPlayerVisible } = this.props;
|
||||
// pushDrawerStack();
|
||||
const { pushDrawerStack, setPlayerVisible, currentRoute } = this.props;
|
||||
pushDrawerStack();
|
||||
|
||||
NativeModules.Firebase.setCurrentScreen('Your tags');
|
||||
setPlayerVisible();
|
||||
|
|
|
@ -82,7 +82,7 @@ const perform = dispatch => ({
|
|||
fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)),
|
||||
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
|
||||
fetchMyClaims: () => dispatch(doFetchClaimListMine()),
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
||||
fetchViewCount: claimId => dispatch(doFetchViewCount(claimId)),
|
||||
fileGet: (uri, saveFile) => dispatch(doFileGet(uri, saveFile)),
|
||||
notify: data => dispatch(doToast(data)),
|
||||
|
|
|
@ -104,6 +104,8 @@ class FilePage extends React.PureComponent {
|
|||
stopDownloadConfirmed: false,
|
||||
streamingMode: false,
|
||||
viewCountFetched: false,
|
||||
isRepost: false,
|
||||
uriPushedToDrawerStack: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -114,6 +116,22 @@ class FilePage extends React.PureComponent {
|
|||
// this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
|
||||
}
|
||||
|
||||
checkRepost = () => {
|
||||
const { claim, isResolvingUri, navigation, pushDrawerStack } = this.props;
|
||||
const { uri } = this.state;
|
||||
if (!isResolvingUri) {
|
||||
if (claim && claim.repost_url) {
|
||||
// redirect to canonical url
|
||||
this.setState({ isRepost: true });
|
||||
navigateToUri(navigation, claim.canonical_url, null, false, claim.permanent_url, false, true);
|
||||
} else {
|
||||
this.setState({ uriPushedToDrawerStack: true }, () => {
|
||||
pushDrawerStack(uri);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onComponentFocused = () => {
|
||||
StatusBar.setHidden(false);
|
||||
NativeModules.Firebase.setCurrentScreen('File').then(result => {
|
||||
|
@ -130,6 +148,8 @@ class FilePage extends React.PureComponent {
|
|||
setPlayerVisible(true, uri);
|
||||
if (!isResolvingUri && !claim) resolveUri(uri);
|
||||
|
||||
this.checkRepost();
|
||||
|
||||
this.fetchFileInfo(uri, this.props);
|
||||
this.fetchCostInfo(uri, this.props);
|
||||
|
||||
|
@ -283,6 +303,11 @@ class FilePage extends React.PureComponent {
|
|||
resolveUri(uri);
|
||||
}
|
||||
|
||||
if (!prevProps.claim && claim) {
|
||||
this.checkRepost();
|
||||
return;
|
||||
}
|
||||
|
||||
// Returned to the page. If mediaLoaded, and currentMediaInfo is different, update
|
||||
if (this.state.mediaLoaded && window.currentMediaInfo && window.currentMediaInfo.uri !== this.state.uri) {
|
||||
const { metadata } = this.props;
|
||||
|
@ -360,7 +385,11 @@ class FilePage extends React.PureComponent {
|
|||
|
||||
onEditPressed = () => {
|
||||
const { claim, navigation } = this.props;
|
||||
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_PUBLISH, params: { editMode: true, claimToEdit: claim } });
|
||||
const uri = this.state.uri || this.getPurchaseUrl();
|
||||
navigation.navigate({
|
||||
routeName: Constants.DRAWER_ROUTE_PUBLISH,
|
||||
params: { editMode: true, claimToEdit: claim, returnUrl: uri },
|
||||
});
|
||||
};
|
||||
|
||||
onDeletePressed = () => {
|
||||
|
@ -606,7 +635,7 @@ class FilePage extends React.PureComponent {
|
|||
let timeToStartMillis, timeToStart;
|
||||
if (this.startTime) {
|
||||
timeToStartMillis = Date.now() - this.startTime;
|
||||
timeToStart = Math.ceil(timeToStartMillis / 1000);
|
||||
timeToStart = Math.ceil(timeToStartMillis / 1000.0);
|
||||
this.startTime = null;
|
||||
}
|
||||
|
||||
|
@ -616,8 +645,8 @@ class FilePage extends React.PureComponent {
|
|||
|
||||
let payload = { uri: uri };
|
||||
if (!isNaN(timeToStart)) {
|
||||
payload['time_to_start_seconds'] = timeToStart;
|
||||
payload['time_to_start_ms'] = timeToStartMillis;
|
||||
payload['time_to_start_seconds'] = parseInt(timeToStart, 10);
|
||||
payload['time_to_start_ms'] = parseInt(timeToStartMillis, 10);
|
||||
}
|
||||
NativeModules.Firebase.track('play', payload);
|
||||
|
||||
|
@ -698,19 +727,24 @@ class FilePage extends React.PureComponent {
|
|||
[
|
||||
{
|
||||
text: __('OK'),
|
||||
onPress: () => purchaseUri(uri, costInfo, download),
|
||||
onPress: () => {
|
||||
this.startTime = Date.now();
|
||||
purchaseUri(uri, costInfo, download);
|
||||
},
|
||||
},
|
||||
{ text: __('Cancel') },
|
||||
],
|
||||
);
|
||||
} else {
|
||||
// Free content. Just call purchaseUri directly.
|
||||
this.startTime = Date.now();
|
||||
purchaseUri(uri, costInfo, download);
|
||||
}
|
||||
};
|
||||
|
||||
onFileDownloadButtonPressed = () => {
|
||||
const { claim, costInfo, contentType, purchaseUri, setPlayerVisible } = this.props;
|
||||
this.startTime = Date.now();
|
||||
const { claim, costInfo, contentType, setPlayerVisible } = this.props;
|
||||
const mediaType = Lbry.getMediaType(contentType);
|
||||
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
||||
const isViewable = mediaType === 'image' || mediaType === 'text';
|
||||
|
@ -725,7 +759,6 @@ class FilePage extends React.PureComponent {
|
|||
}
|
||||
|
||||
if (isPlayable) {
|
||||
this.startTime = Date.now();
|
||||
this.setState({ downloadPressed: true, autoPlayMedia: true, stopDownloadConfirmed: false });
|
||||
}
|
||||
if (isViewable) {
|
||||
|
@ -965,6 +998,12 @@ class FilePage extends React.PureComponent {
|
|||
|
||||
let innerContent = null;
|
||||
if ((isResolvingUri && !claim) || !claim) {
|
||||
if (!isResolvingUri && !claim && !this.state.uriPushedToDrawerStack) {
|
||||
this.setState({ uriPushedToDrawerStack: true }, () => {
|
||||
pushDrawerStack(uri);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={filePageStyle.pageContainer}>
|
||||
<UriBar value={uri} navigation={navigation} />
|
||||
|
@ -1033,6 +1072,17 @@ class FilePage extends React.PureComponent {
|
|||
tags = claim.value.tags;
|
||||
}
|
||||
|
||||
if (!isResolvingUri && this.state.isRepost) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// in case we somehow get here without the uri pushed to the drawer stack
|
||||
if (!isResolvingUri && !this.state.isRepost && !this.state.uriPushedToDrawerStack) {
|
||||
this.setState({ uriPushedToDrawerStack: true }, () => {
|
||||
pushDrawerStack(uri);
|
||||
});
|
||||
}
|
||||
|
||||
const completed = fileInfo && fileInfo.completed;
|
||||
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
||||
const description = metadata.description ? metadata.description : null;
|
||||
|
|
|
@ -32,7 +32,7 @@ const select = state => ({
|
|||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
||||
fetchInviteStatus: () => dispatch(doFetchInviteStatus()),
|
||||
inviteNew: email => dispatch(doUserInviteNew(email)),
|
||||
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_INVITES)),
|
||||
|
|
|
@ -21,6 +21,7 @@ import RewardCard from 'component/rewardCard';
|
|||
import RewardEnrolment from 'component/rewardEnrolment';
|
||||
import UriBar from 'component/uriBar';
|
||||
import invitesStyle from 'styles/invites';
|
||||
import { fetchReferralCode, logPublish } from 'utils/helper';
|
||||
|
||||
class InvitesPage extends React.PureComponent {
|
||||
state = {
|
||||
|
@ -47,7 +48,19 @@ class InvitesPage extends React.PureComponent {
|
|||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Invites').then(result => {
|
||||
fetchChannelListMine();
|
||||
fetchReferralCode(
|
||||
response => {
|
||||
if (response && response.length > 0) {
|
||||
// only need to use the first referral code.
|
||||
// inviteLink will be updated after channels are loaded (if the user has created at least one channel)
|
||||
this.setState({ inviteLink: `https://lbry.tv/$/invite/${response[0]}` });
|
||||
}
|
||||
fetchChannelListMine();
|
||||
},
|
||||
error => {
|
||||
fetchChannelListMine();
|
||||
},
|
||||
);
|
||||
fetchInviteStatus();
|
||||
});
|
||||
};
|
||||
|
@ -62,13 +75,15 @@ class InvitesPage extends React.PureComponent {
|
|||
const filtered = channels.filter(c => c.name === channelName);
|
||||
if (filtered.length > 0) {
|
||||
const channel = filtered[0];
|
||||
logPublish(channel);
|
||||
this.setState({ channelName, inviteLink: this.getLinkForChannel(channel) });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getLinkForChannel = channel => {
|
||||
const { claimId, claimName } = parseURI(channel.permanent_url);
|
||||
const parsedUrl = channel.canonical_url ? parseURI(channel.canonical_url) : parseURI(channel.permanent_url);
|
||||
const { claimId, claimName } = parsedUrl;
|
||||
return `https://lbry.tv/$/invite/${claimName}:${claimId}`;
|
||||
};
|
||||
|
||||
|
@ -96,6 +111,7 @@ class InvitesPage extends React.PureComponent {
|
|||
|
||||
if (!this.state.channelName && channels && channels.length > 0) {
|
||||
const firstChannel = channels[0];
|
||||
logPublish(firstChannel);
|
||||
this.setState({ channelName: firstChannel.name, inviteLink: this.getLinkForChannel(firstChannel) });
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ import Tag from 'component/tag';
|
|||
import TagSearch from 'component/tagSearch';
|
||||
import UriBar from 'component/uriBar';
|
||||
import publishStyle from 'styles/publish';
|
||||
import { navigateToUri, logPublish, uploadImageAsset } from 'utils/helper';
|
||||
import { navigateToUri, navigateBack, logPublish, uploadImageAsset } from 'utils/helper';
|
||||
|
||||
const languages = {
|
||||
en: 'English',
|
||||
|
@ -141,6 +141,8 @@ class PublishPage extends React.PureComponent {
|
|||
// other
|
||||
publishStarted: false,
|
||||
storagePermissionRequired: false,
|
||||
hasReturnedBack: false,
|
||||
returnUrl: null,
|
||||
};
|
||||
|
||||
didFocusListener;
|
||||
|
@ -236,7 +238,7 @@ class PublishPage extends React.PureComponent {
|
|||
let isEditMode = false,
|
||||
vanityUrlSet = false;
|
||||
if (navigation.state.params) {
|
||||
const { displayForm, editMode, claimToEdit, vanityUrl } = navigation.state.params;
|
||||
const { displayForm, editMode, claimToEdit, vanityUrl, returnUrl } = navigation.state.params;
|
||||
if (editMode) {
|
||||
this.prepareEdit(claimToEdit);
|
||||
isEditMode = true;
|
||||
|
@ -250,6 +252,7 @@ class PublishPage extends React.PureComponent {
|
|||
vanityUrl: claimName,
|
||||
});
|
||||
}
|
||||
this.setState({ returnUrl });
|
||||
}
|
||||
|
||||
if (!isEditMode && hasFormState) {
|
||||
|
@ -472,7 +475,15 @@ class PublishPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { currentRoute: prevRoute, drawerStack: prevDrawerStack, notify, updatePublishFormState } = this.props;
|
||||
const {
|
||||
currentRoute: prevRoute,
|
||||
drawerStack: prevDrawerStack,
|
||||
popDrawerStack,
|
||||
setPlayerVisible,
|
||||
navigation,
|
||||
notify,
|
||||
updatePublishFormState,
|
||||
} = this.props;
|
||||
const { currentRoute, drawerStack, publishFormValues } = nextProps;
|
||||
|
||||
if (Constants.DRAWER_ROUTE_PUBLISH === currentRoute && currentRoute !== prevRoute) {
|
||||
|
@ -486,6 +497,11 @@ class PublishPage extends React.PureComponent {
|
|||
) {
|
||||
// navigated back from the form
|
||||
this.showSelector();
|
||||
if (!this.state.hasReturnedBack && this.state.returnUrl) {
|
||||
this.setState({ hasReturnedBack: true }, () => {
|
||||
navigateBack(navigation, drawerStack, popDrawerStack, setPlayerVisible);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from 'lbry-redux';
|
||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import SearchPage from './view';
|
||||
|
||||
|
@ -24,15 +25,20 @@ const select = state => ({
|
|||
isSearching: selectIsSearching(state),
|
||||
query: selectSearchValue(state),
|
||||
resolvingUris: selectResolvingUris(state),
|
||||
uris: makeSelectSearchUris(makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state))(state),
|
||||
results: makeSelectResolvedSearchResults(makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state))(state),
|
||||
showNsfwContent: selectShowNsfw(state),
|
||||
uris: makeSelectSearchUris(
|
||||
makeSelectQueryWithOptions(null, { size: Constants.DEFAULT_PAGE_SIZE, isBackgroundSearch: false })(state),
|
||||
)(state),
|
||||
results: makeSelectResolvedSearchResults(
|
||||
makeSelectQueryWithOptions(null, { size: Constants.DEFAULT_PAGE_SIZE, isBackgroundSearch: false })(state),
|
||||
)(state),
|
||||
lastPageReached: makeSelectResolvedSearchResultsLastPageReached(
|
||||
makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state),
|
||||
makeSelectQueryWithOptions(null, { size: Constants.DEFAULT_PAGE_SIZE, isBackgroundSearch: false })(state),
|
||||
)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
search: (query, from) => dispatch(doResolvedSearch(query, Constants.DEFAULT_PAGE_SIZE, from, false, {})),
|
||||
search: (query, from, nsfw) => dispatch(doResolvedSearch(query, Constants.DEFAULT_PAGE_SIZE, from, false, {}, nsfw)),
|
||||
claimSearch: options => dispatch(doClaimSearch(options)),
|
||||
updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)),
|
||||
pushDrawerStack: (routeName, params) => dispatch(doPushDrawerStack(routeName, params)),
|
||||
|
|
|
@ -52,7 +52,7 @@ class SearchPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
onComponentFocused = () => {
|
||||
const { pushDrawerStack, setPlayerVisible, navigation, query, search } = this.props;
|
||||
const { pushDrawerStack, setPlayerVisible, navigation, query, search, showNsfwContent } = this.props;
|
||||
setPlayerVisible();
|
||||
pushDrawerStack(Constants.DRAWER_ROUTE_SEARCH, navigation.state.params ? navigation.state.params : null);
|
||||
NativeModules.Firebase.setCurrentScreen('Search').then(result => {
|
||||
|
@ -68,7 +68,7 @@ class SearchPage extends React.PureComponent {
|
|||
resultsResolved: false,
|
||||
tagResultDisplayed: false,
|
||||
});
|
||||
search(searchQuery, 0);
|
||||
search(searchQuery, 0, showNsfwContent);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -79,7 +79,7 @@ class SearchPage extends React.PureComponent {
|
|||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { currentRoute, query, isSearching } = nextProps;
|
||||
const { currentRoute: prevRoute, search, isSearching: prevIsSearching } = this.props;
|
||||
const { currentRoute: prevRoute, search, isSearching: prevIsSearching, showNsfwContent } = this.props;
|
||||
|
||||
if (Constants.DRAWER_ROUTE_SEARCH === currentRoute && currentRoute !== prevRoute) {
|
||||
this.onComponentFocused();
|
||||
|
@ -93,7 +93,7 @@ class SearchPage extends React.PureComponent {
|
|||
resultsResolved: false,
|
||||
tagResultDisplayed: false,
|
||||
});
|
||||
search(query, 0);
|
||||
search(query, 0, showNsfwContent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ class SearchPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
handleSearchSubmitted = keywords => {
|
||||
const { search } = this.props;
|
||||
const { search, showNsfwContent } = this.props;
|
||||
this.setState({
|
||||
currentUri: isURIValid(keywords) ? normalizeURI(keywords) : null,
|
||||
currentFrom: 0,
|
||||
|
@ -147,7 +147,7 @@ class SearchPage extends React.PureComponent {
|
|||
resultsResolved: false,
|
||||
tagResultDisplayed: false,
|
||||
});
|
||||
search(keywords, 0);
|
||||
search(keywords, 0, showNsfwContent);
|
||||
};
|
||||
|
||||
listEmptyComponent = () => {
|
||||
|
@ -195,7 +195,7 @@ class SearchPage extends React.PureComponent {
|
|||
|
||||
handleVerticalEndReached = () => {
|
||||
// fetch more results
|
||||
const { lastPageReached, results, search, isSearching } = this.props;
|
||||
const { lastPageReached, results, search, showNsfwContent, isSearching } = this.props;
|
||||
if (lastPageReached || (results && results.length > softLimit)) {
|
||||
return;
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ class SearchPage extends React.PureComponent {
|
|||
if (!isSearching) {
|
||||
const from = results ? results.length : 0;
|
||||
this.setState({ currentFrom: from }, () => {
|
||||
search(this.state.currentQuery, from);
|
||||
search(this.state.currentQuery, from, showNsfwContent);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
doUserEmailToVerify,
|
||||
doUserEmailVerify,
|
||||
doUserEmailVerifyFailure,
|
||||
selectAuthenticationIsPending,
|
||||
selectUser,
|
||||
selectEmailToVerify,
|
||||
} from 'lbryinc';
|
||||
|
@ -18,6 +19,7 @@ import { selectLastRouteInStack } from 'redux/selectors/drawer';
|
|||
import SplashScreen from './view';
|
||||
|
||||
const select = state => ({
|
||||
authIsPending: selectAuthenticationIsPending(state),
|
||||
user: selectUser(state),
|
||||
emailToVerify: selectEmailToVerify(state),
|
||||
lastRouteInStack: selectLastRouteInStack(state),
|
||||
|
|
|
@ -82,6 +82,9 @@ class SplashScreen extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// splash screen is done at this point, next page to be displayed will be user-interactable
|
||||
NativeModules.Firebase.logLaunchTiming();
|
||||
};
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
|
@ -165,12 +168,13 @@ class SplashScreen extends React.PureComponent {
|
|||
this.navigateToMain();
|
||||
} else {
|
||||
NativeModules.VersionInfo.getAppVersion().then(appVersion => {
|
||||
this.setState({ shouldAuthenticate: true });
|
||||
NativeModules.Firebase.getMessagingToken()
|
||||
.then(firebaseToken => {
|
||||
authenticate(appVersion, Platform.OS, firebaseToken);
|
||||
})
|
||||
.catch(() => authenticate(appVersion, Platform.OS));
|
||||
this.setState({ shouldAuthenticate: true }, () => {
|
||||
NativeModules.Firebase.getMessagingToken()
|
||||
.then(firebaseToken => {
|
||||
authenticate(appVersion, Platform.OS, firebaseToken);
|
||||
})
|
||||
.catch(() => authenticate(appVersion, Platform.OS));
|
||||
});
|
||||
});
|
||||
}
|
||||
// });
|
||||
|
|
|
@ -7,13 +7,13 @@ import {
|
|||
selectSubscriptionClaims,
|
||||
selectSubscriptions,
|
||||
selectIsFetchingSubscriptions,
|
||||
selectIsFetchingSuggested,
|
||||
selectSuggestedChannels,
|
||||
selectUnreadSubscriptions,
|
||||
selectViewMode,
|
||||
selectFirstRunCompleted,
|
||||
selectShowSuggestedSubs,
|
||||
} from 'lbryinc';
|
||||
import { doToast, selectFetchingClaimSearch } from 'lbry-redux';
|
||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||
import { doSetClientSetting, doSetTimeItem } from 'redux/actions/settings';
|
||||
import { makeSelectClientSetting, selectTimeItem } from 'redux/selectors/settings';
|
||||
|
@ -24,7 +24,7 @@ import SubscriptionsPage from './view';
|
|||
const select = state => ({
|
||||
currentRoute: selectCurrentRoute(state),
|
||||
loading: selectIsFetchingSubscriptions(state),
|
||||
loadingSuggested: selectIsFetchingSuggested(state),
|
||||
loadingSuggested: selectFetchingClaimSearch(state),
|
||||
subscribedChannels: selectSubscriptions(state),
|
||||
suggestedChannels: selectSuggestedChannels(state),
|
||||
subscriptionsViewMode: makeSelectClientSetting(Constants.SETTING_SUBSCRIPTIONS_VIEW_MODE)(state),
|
||||
|
@ -41,6 +41,7 @@ const perform = dispatch => ({
|
|||
doFetchMySubscriptions: () => dispatch(doFetchMySubscriptions()),
|
||||
doFetchRecommendedSubscriptions: () => dispatch(doFetchRecommendedSubscriptions()),
|
||||
doSetViewMode: viewMode => dispatch(doSetViewMode(viewMode)),
|
||||
notify: data => dispatch(doToast(data)),
|
||||
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SUBSCRIPTIONS)),
|
||||
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
|
||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||
|
@ -49,5 +50,5 @@ const perform = dispatch => ({
|
|||
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
perform,
|
||||
)(SubscriptionsPage);
|
||||
|
|
|
@ -28,6 +28,7 @@ import ModalPicker from 'component/modalPicker';
|
|||
import ModalSuggestedSubscriptions from 'component/modalSuggestedSubscriptions';
|
||||
import SubscribedChannelList from 'component/subscribedChannelList';
|
||||
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
|
||||
import SuggestedSubscriptionsGrid from 'component/suggestedSubscriptionsGrid';
|
||||
import UriBar from 'component/uriBar';
|
||||
|
||||
class SubscriptionsPage extends React.PureComponent {
|
||||
|
@ -56,6 +57,7 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
|
||||
onComponentFocused = () => {
|
||||
const {
|
||||
currentRoute,
|
||||
doFetchMySubscriptions,
|
||||
doFetchRecommendedSubscriptions,
|
||||
doSetViewMode,
|
||||
|
@ -64,12 +66,13 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
subscriptionsViewMode,
|
||||
} = this.props;
|
||||
|
||||
pushDrawerStack();
|
||||
if (currentRoute === Constants.DRAWER_ROUTE_SUBSCRIPTIONS) {
|
||||
pushDrawerStack();
|
||||
}
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Subscriptions');
|
||||
|
||||
doFetchMySubscriptions();
|
||||
doFetchRecommendedSubscriptions();
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -90,6 +93,15 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
this.setState({ currentSortByItem: item, orderBy: getOrderBy(item), showSortPicker: false });
|
||||
};
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
const { showModalSuggestedSubs: prevShowModalSuggestedSubs } = this.state;
|
||||
const { showModalSuggestedSubs } = this.state;
|
||||
if (prevShowModalSuggestedSubs && showModalSuggestedSubs) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
handleTimeItemSelected = item => {
|
||||
const { setTimeItem } = this.props;
|
||||
setTimeItem(item);
|
||||
|
@ -138,6 +150,7 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
timeItem,
|
||||
unreadSubscriptions,
|
||||
navigation,
|
||||
notify,
|
||||
} = this.props;
|
||||
const { currentSortByItem, filteredChannels, showModalSuggestedSubs, showSortPicker, showTimePicker } = this.state;
|
||||
|
||||
|
@ -164,7 +177,11 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
<View style={subscriptionsStyle.container}>
|
||||
<UriBar navigation={navigation} belowOverlay={this.state.showSortPicker} />
|
||||
<View style={subscriptionsStyle.titleRow}>
|
||||
<Text style={subscriptionsStyle.pageTitle}>{__('Channels you follow')}</Text>
|
||||
<Text style={subscriptionsStyle.pageTitle}>
|
||||
{hasSubscriptions && !this.state.showingSuggestedSubs
|
||||
? __('Channels you follow')
|
||||
: __('Find Channels to follow')}
|
||||
</Text>
|
||||
</View>
|
||||
{!this.state.showingSuggestedSubs && hasSubscriptions && (
|
||||
<View style={subscriptionsStyle.pickerRow}>
|
||||
|
@ -190,7 +207,7 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
|
||||
<Link
|
||||
style={subscriptionsStyle.suggestedLink}
|
||||
text={__('Suggested')}
|
||||
text={__('Discover')}
|
||||
onPress={() => this.setState({ showModalSuggestedSubs: true })}
|
||||
/>
|
||||
</View>
|
||||
|
@ -220,39 +237,40 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
|
||||
{this.state.showingSuggestedSubs && (
|
||||
<View style={subscriptionsStyle.suggestedSubsContainer}>
|
||||
{!hasSubscriptions && (
|
||||
<View style={subscriptionsStyle.infoArea}>
|
||||
<Text style={subscriptionsStyle.infoText}>
|
||||
{__('You are not subscribed to any channels at the moment.')}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
<View style={subscriptionsStyle.infoArea}>
|
||||
<Text style={subscriptionsStyle.infoText}>
|
||||
{__(
|
||||
'LBRY works better if you follow at least 5 creators you like. Sign in to show creators you follow if you already have an account.',
|
||||
)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{hasSubscriptions && (
|
||||
<View style={subscriptionsStyle.infoArea}>
|
||||
<Text style={subscriptionsStyle.infoText}>
|
||||
You are currently subscribed to {numberOfSubscriptions} channel{numberOfSubscriptions > 1 ? 's' : ''}.
|
||||
</Text>
|
||||
<Button
|
||||
style={subscriptionsStyle.button}
|
||||
text={__('View my subscriptions')}
|
||||
onPress={() => this.setState({ showingSuggestedSubs: false })}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
<View style={subscriptionsStyle.mainSuggested}>
|
||||
<SuggestedSubscriptionsGrid navigation={navigation} />
|
||||
</View>
|
||||
|
||||
<Button
|
||||
style={subscriptionsStyle.suggestedDoneButton}
|
||||
text={
|
||||
numberOfSubscriptions < 5
|
||||
? __('%remaining% more...', { remaining: 5 - numberOfSubscriptions })
|
||||
: __('Done')
|
||||
}
|
||||
onPress={() => {
|
||||
if (!hasSubscriptions) {
|
||||
notify({ message: __('Tap on any channel to follow') });
|
||||
} else {
|
||||
this.setState({ showingSuggestedSubs: false });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{loadingSuggested && (
|
||||
<View style={subscriptionsStyle.centered}>
|
||||
<ActivityIndicator size="large" colors={Colors.NextLbryGreen} style={subscriptionsStyle.loading} />
|
||||
</View>
|
||||
<ActivityIndicator size="small" color={Colors.White} style={subscriptionsStyle.suggestedLoading} />
|
||||
)}
|
||||
{!loadingSuggested && <SuggestedSubscriptions navigation={navigation} />}
|
||||
</View>
|
||||
)}
|
||||
|
||||
{!showSortPicker && !showTimePicker && !showModalSuggestedSubs && (
|
||||
<FloatingWalletBalance navigation={navigation} />
|
||||
)}
|
||||
{showSortPicker && (
|
||||
<ModalPicker
|
||||
title={__('Sort content by')}
|
||||
|
|
|
@ -3,6 +3,7 @@ import { NativeModules, ScrollView, Text, View } from 'react-native';
|
|||
import TransactionListRecent from 'component/transactionListRecent';
|
||||
import WalletAddress from 'component/walletAddress';
|
||||
import WalletBalance from 'component/walletBalance';
|
||||
import WalletBalanceExtra from 'component/walletBalanceExtra';
|
||||
import WalletSend from 'component/walletSend';
|
||||
import WalletRewardsDriver from 'component/walletRewardsDriver';
|
||||
import WalletSignIn from 'component/walletSignIn';
|
||||
|
@ -90,6 +91,7 @@ class WalletPage extends React.PureComponent {
|
|||
>
|
||||
{!rewardsNotInterested && (!balance || balance === 0) && <WalletRewardsDriver navigation={navigation} />}
|
||||
<WalletBalance />
|
||||
<WalletBalanceExtra />
|
||||
<WalletAddress />
|
||||
<WalletSend />
|
||||
<TransactionListRecent navigation={navigation} />
|
||||
|
|
|
@ -2,7 +2,7 @@ import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
|||
|
||||
const reducers = {};
|
||||
const defaultState = {
|
||||
stack: [{ route: Constants.DRAWER_ROUTE_DISCOVER, params: {} }], // Discover is always the first drawer route
|
||||
stack: [{ route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS, params: {} }], // Following is always the first drawer route
|
||||
lastRouteInStack: {},
|
||||
playerVisible: false,
|
||||
playerVisibleByUri: {},
|
||||
|
@ -42,6 +42,9 @@ reducers[Constants.ACTION_PUSH_DRAWER_STACK] = (state, action) => {
|
|||
if (lastRoute === Constants.DRAWER_ROUTE_PUBLISH_FORM && routeName === Constants.DRAWER_ROUTE_PUBLISH) {
|
||||
canPushStack = false;
|
||||
}
|
||||
if (routeName === Constants.DRAWER_ROUTE_SUBSCRIPTIONS && newStack.length === 1) {
|
||||
canPushStack = false;
|
||||
}
|
||||
|
||||
let lastRouteInStack;
|
||||
if (canPushStack) {
|
||||
|
|
|
@ -25,10 +25,10 @@ const claimListStyle = StyleSheet.create({
|
|||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
marginLeft: 8,
|
||||
marginRight: 8,
|
||||
marginTop: 4,
|
||||
marginBottom: 4,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
marginTop: 8,
|
||||
marginBottom: 12,
|
||||
},
|
||||
verticalLoading: {
|
||||
width: '100%',
|
||||
|
|
|
@ -165,6 +165,21 @@ const fileListStyle = StyleSheet.create({
|
|||
marginRight: 2,
|
||||
color: '#0c604b',
|
||||
},
|
||||
repostChannelName: {
|
||||
color: Colors.DescriptionGrey,
|
||||
fontFamily: 'Inter-Regular',
|
||||
fontSize: 14,
|
||||
},
|
||||
repostIcon: {
|
||||
color: Colors.DescriptionGrey,
|
||||
marginRight: 4,
|
||||
},
|
||||
repostInfo: {
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
});
|
||||
|
||||
export default fileListStyle;
|
||||
|
|
|
@ -37,12 +37,24 @@ const modalPickerStyle = StyleSheet.create({
|
|||
bottom: 8,
|
||||
position: 'absolute',
|
||||
},
|
||||
wideButtons: {
|
||||
marginTop: 16,
|
||||
left: 8,
|
||||
bottom: 8,
|
||||
right: 8,
|
||||
position: 'absolute',
|
||||
},
|
||||
doneButton: {
|
||||
alignSelf: 'flex-start',
|
||||
backgroundColor: Colors.LbryGreen,
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
},
|
||||
wideDoneButton: {
|
||||
backgroundColor: Colors.LbryGreen,
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
},
|
||||
});
|
||||
|
||||
export default modalPickerStyle;
|
||||
|
|
|
@ -38,11 +38,13 @@ const subscriptionsStyle = StyleSheet.create({
|
|||
},
|
||||
infoText: {
|
||||
fontFamily: 'Inter-Regular',
|
||||
fontSize: 16,
|
||||
fontSize: 14,
|
||||
marginTop: 8,
|
||||
marginBottom: 8,
|
||||
},
|
||||
infoArea: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
paddingBottom: 4,
|
||||
|
@ -188,11 +190,11 @@ const subscriptionsStyle = StyleSheet.create({
|
|||
justifyContent: 'center',
|
||||
},
|
||||
suggestedItem: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 16,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
height: 140,
|
||||
},
|
||||
suggestedItemThumbnailContainer: {
|
||||
width: 70,
|
||||
|
@ -209,30 +211,37 @@ const subscriptionsStyle = StyleSheet.create({
|
|||
suggestedItemDetails: {
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
flex: 0.8,
|
||||
alignItems: 'center',
|
||||
},
|
||||
suggestedItemSubscribe: {
|
||||
backgroundColor: Colors.White,
|
||||
},
|
||||
suggestedItemSubscribeOverlay: {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
paddingBottom: 4,
|
||||
height: 70,
|
||||
},
|
||||
suggestedItemTitle: {
|
||||
fontFamily: 'Inter-Regular',
|
||||
fontSize: 16,
|
||||
marginBottom: 4,
|
||||
width: '85%',
|
||||
textAlign: 'center',
|
||||
fontSize: 14,
|
||||
marginTop: 4,
|
||||
marginBottom: 2,
|
||||
},
|
||||
suggestedItemName: {
|
||||
fontFamily: 'Inter-SemiBold',
|
||||
fontSize: 14,
|
||||
marginBottom: 4,
|
||||
color: Colors.LbryGreen,
|
||||
width: '95%',
|
||||
},
|
||||
suggestedItemTagList: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
suggestedSubTitle: {
|
||||
fontFamily: 'Inter-Regular',
|
||||
|
@ -266,6 +275,23 @@ const subscriptionsStyle = StyleSheet.create({
|
|||
modalSuggestedScrollContent: {
|
||||
paddingTop: 16,
|
||||
},
|
||||
suggestedDoneButton: {
|
||||
backgroundColor: Colors.LbryGreen,
|
||||
margin: 16,
|
||||
},
|
||||
mainSuggested: {
|
||||
flex: 1,
|
||||
},
|
||||
suggestedLoading: {
|
||||
position: 'absolute',
|
||||
right: 24,
|
||||
bottom: 22,
|
||||
},
|
||||
modalLoading: {
|
||||
position: 'absolute',
|
||||
right: 7,
|
||||
bottom: 7,
|
||||
},
|
||||
});
|
||||
|
||||
export default subscriptionsStyle;
|
||||
|
|
|
@ -103,6 +103,12 @@ const walletStyle = StyleSheet.create({
|
|||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
},
|
||||
balanceExtraCard: {
|
||||
backgroundColor: Colors.White,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
padding: 16,
|
||||
},
|
||||
balanceBackground: {
|
||||
position: 'absolute',
|
||||
alignSelf: 'stretch',
|
||||
|
@ -191,6 +197,7 @@ const walletStyle = StyleSheet.create({
|
|||
paddingRight: 18,
|
||||
},
|
||||
currency: {
|
||||
fontFamily: 'Inter-Regular',
|
||||
alignSelf: 'flex-start',
|
||||
fontSize: 12,
|
||||
marginTop: 16,
|
||||
|
@ -366,6 +373,39 @@ const walletStyle = StyleSheet.create({
|
|||
fontFamily: 'Inter-Regular',
|
||||
fontSize: 28,
|
||||
},
|
||||
walletExtraRow: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
walletExtraCol: {
|
||||
flex: 0.5,
|
||||
paddingLeft: 24,
|
||||
},
|
||||
walletExtraBalance: {
|
||||
fontFamily: 'Inter-SemiBold',
|
||||
fontSize: 28,
|
||||
},
|
||||
balanceRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
walletExtraCaption: {
|
||||
fontFamily: 'Inter-Medium',
|
||||
fontSize: 14,
|
||||
},
|
||||
walletExtraCurrency: {
|
||||
fontFamily: 'Inter-Regular',
|
||||
fontSize: 12,
|
||||
marginTop: 8,
|
||||
marginLeft: 4,
|
||||
},
|
||||
walletExtraTopMargin: {
|
||||
marginTop: 16,
|
||||
},
|
||||
walletExtraIcon: {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
},
|
||||
});
|
||||
|
||||
export default walletStyle;
|
||||
|
|
|
@ -10,6 +10,7 @@ const specialRouteMap = {
|
|||
about: Constants.DRAWER_ROUTE_ABOUT,
|
||||
allContent: Constants.DRAWER_ROUTE_TRENDING,
|
||||
channels: Constants.DRAWER_ROUTE_CHANNEL_CREATOR,
|
||||
invite: Constants.DRAWER_ROUTE_INVITES,
|
||||
invites: Constants.DRAWER_ROUTE_INVITES,
|
||||
library: Constants.DRAWER_ROUTE_MY_LBRY,
|
||||
publish: Constants.DRAWER_ROUTE_PUBLISH,
|
||||
|
@ -115,7 +116,15 @@ function parseUriVars(vars) {
|
|||
return uriVars;
|
||||
}
|
||||
|
||||
export function navigateToUri(navigation, uri, additionalParams, isNavigatingBack, fullUri, setPlayerVisible) {
|
||||
export function navigateToUri(
|
||||
navigation,
|
||||
uri,
|
||||
additionalParams,
|
||||
isNavigatingBack,
|
||||
fullUri,
|
||||
setPlayerVisible,
|
||||
pushStack = false,
|
||||
) {
|
||||
if (!navigation) {
|
||||
return;
|
||||
}
|
||||
|
@ -153,7 +162,7 @@ export function navigateToUri(navigation, uri, additionalParams, isNavigatingBac
|
|||
}
|
||||
|
||||
navigation.navigate({ routeName: 'File', key: uri, params });
|
||||
if (store && store.dispatch && !isNavigatingBack) {
|
||||
if (pushStack && store && store.dispatch && !isNavigatingBack) {
|
||||
store.dispatch(doPushDrawerStack(uri));
|
||||
}
|
||||
}
|
||||
|
@ -170,6 +179,7 @@ export function navigateBack(navigation, drawerStack, popDrawerStack, setPlayerV
|
|||
if (popDrawerStack) {
|
||||
popDrawerStack();
|
||||
}
|
||||
|
||||
if (setPlayerVisible) {
|
||||
setPlayerVisible(false);
|
||||
}
|
||||
|
@ -177,6 +187,7 @@ export function navigateBack(navigation, drawerStack, popDrawerStack, setPlayerV
|
|||
const target = drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0];
|
||||
const { route, params } = target;
|
||||
navigation.goBack(navigation.state.key);
|
||||
|
||||
if (!DrawerRoutes.includes(route) && !InnerDrawerRoutes.includes(route) && isURIValid(route)) {
|
||||
navigateToUri(navigation, route, null, true, null, setPlayerVisible);
|
||||
} else {
|
||||
|
@ -186,7 +197,7 @@ export function navigateBack(navigation, drawerStack, popDrawerStack, setPlayerV
|
|||
if (Constants.DRAWER_ROUTE_CHANNEL_CREATOR_FORM === route) {
|
||||
targetRoute = Constants.DRAWER_ROUTE_CHANNEL_CREATOR;
|
||||
} else if (Constants.DRAWER_ROUTE_PUBLISH_FORM === route) {
|
||||
targetRoute = Constants.DRAWER_ROUTE_PUBLISH_FORM;
|
||||
targetRoute = Constants.DRAWER_ROUTE_PUBLISH;
|
||||
}
|
||||
|
||||
if (targetParams) {
|
||||
|
@ -201,8 +212,15 @@ export function navigateBack(navigation, drawerStack, popDrawerStack, setPlayerV
|
|||
}
|
||||
|
||||
export function dispatchNavigateBack(dispatch, nav, drawerStack) {
|
||||
if (drawerStack[drawerStack.length - 1].route === Constants.DRAWER_ROUTE_FILE_VIEW) {
|
||||
// inner file_view (web / image view) is handled differently
|
||||
const currentRoute = drawerStack[drawerStack.length - 1].route;
|
||||
if (
|
||||
[
|
||||
Constants.DRAWER_ROUTE_FILE_VIEW,
|
||||
Constants.DRAWER_ROUTE_CHANNEL_CREATOR_FORM,
|
||||
Constants.DRAWER_ROUTE_PUBLISH_FORM,
|
||||
].includes(currentRoute)
|
||||
) {
|
||||
// inner routes are handled a little differently
|
||||
dispatch(doPopDrawerStack());
|
||||
return;
|
||||
}
|
||||
|
@ -223,7 +241,7 @@ export function dispatchNavigateBack(dispatch, nav, drawerStack) {
|
|||
if (Constants.DRAWER_ROUTE_CHANNEL_CREATOR_FORM === route) {
|
||||
targetRoute = Constants.DRAWER_ROUTE_CHANNEL_CREATOR;
|
||||
} else if (Constants.DRAWER_ROUTE_PUBLISH_FORM === route) {
|
||||
targetRoute = Constants.DRAWER_ROUTE_PUBLISH_FORM;
|
||||
targetRoute = Constants.DRAWER_ROUTE_PUBLISH;
|
||||
}
|
||||
|
||||
if (targetParams) {
|
||||
|
@ -400,3 +418,17 @@ export function formatTitle(title) {
|
|||
|
||||
return title.length > 80 ? title.substring(0, 77).trim() + '...' : title;
|
||||
}
|
||||
|
||||
export function fetchReferralCode(successCallback, errorCallback) {
|
||||
Lbryio.call('user_referral_code', 'list')
|
||||
.then(response => {
|
||||
if (successCallback) {
|
||||
successCallback(response);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
if (errorCallback) {
|
||||
errorCallback(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue