Compare commits
No commits in common. "master" and "wallet-balance-extra" have entirely different histories.
master
...
wallet-bal
117 changed files with 12830 additions and 12233 deletions
64
.gitignore
vendored
64
.gitignore
vendored
|
@ -1,66 +1,4 @@
|
||||||
# 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/
|
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
|
*.log
|
||||||
.vagrant
|
.vagrant
|
||||||
android/app/build/*
|
|
||||||
android/bin
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
stages:
|
|
||||||
- build
|
|
||||||
|
|
||||||
build:
|
|
||||||
variables:
|
|
||||||
REACT_NATIVE_BRANCH: $CI_COMMIT_REF_NAME
|
|
||||||
stage: build
|
|
||||||
trigger: lbry/lbry-android
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
||||||
[submodule "android"]
|
|
||||||
path = android
|
|
||||||
url = https://github.com/lbryio/lbry-android
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2017-2020 LBRY Inc
|
Copyright (c) 2017-2019 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:
|
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 React Native
|
# LBRY Android
|
||||||
[![pipeline status](https://ci.lbry.tech/lbry/lbry-android/badges/master/pipeline.svg)](https://ci.lbry.tech/lbry/lbry-android/commits/master)
|
[![pipeline status](https://ci.lbry.tech/lbry/lbry-android/badges/master/pipeline.svg)](https://ci.lbry.tech/lbry/lbry-android/commits/master)
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
<img src="https://spee.ch/8/lbry-android.png" alt="LBRY Android Screenshot" width="384px" />
|
<img src="https://spee.ch/8/lbry-android.png" alt="LBRY Android Screenshot" width="384px" />
|
||||||
|
|
||||||
|
@ -12,41 +12,10 @@ 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.
|
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
|
## Usage
|
||||||
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.
|
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.
|
||||||
|
|
||||||
## Running from Source
|
## Running from Source
|
||||||
### Software Requirements
|
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.
|
||||||
* 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
|
## Contributing
|
||||||
Contributions to this project are welcome, encouraged, and compensated. For more details, see https://lbry.io/faq/contributing
|
Contributions to this project are welcome, encouraged, and compensated. For more details, see https://lbry.io/faq/contributing
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
/**
|
|
||||||
* @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
1
android
|
@ -1 +0,0 @@
|
||||||
Subproject commit ff30e7f6a4358fd997a9e6d9f75bfe6959eafcb6
|
|
|
@ -1,2 +0,0 @@
|
||||||
#!/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/
|
|
|
@ -1,53 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,782 +0,0 @@
|
||||||
// !$*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 */;
|
|
||||||
}
|
|
|
@ -1,129 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,129 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,15 +0,0 @@
|
||||||
/**
|
|
||||||
* 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
|
|
|
@ -1,42 +0,0 @@
|
||||||
/**
|
|
||||||
* 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
|
|
|
@ -1,42 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,38 +0,0 @@
|
||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"info" : {
|
|
||||||
"version" : 1,
|
|
||||||
"author" : "xcode"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,16 +0,0 @@
|
||||||
/**
|
|
||||||
* 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]));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,72 +0,0 @@
|
||||||
/**
|
|
||||||
* 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
53
ios/Podfile
|
@ -1,53 +0,0 @@
|
||||||
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
|
|
|
@ -304,23 +304,5 @@
|
||||||
"This content cannot be viewed at this time. Please try again in a bit.": "This content cannot be viewed at this time. Please try again in a bit.",
|
"This content cannot be viewed at this time. Please try again in a bit.": "This content cannot be viewed at this time. Please try again in a bit.",
|
||||||
"Download file": "Download file",
|
"Download file": "Download file",
|
||||||
"Save %title% (%size%) to your device": "Save %title% (%size%) to your device",
|
"Save %title% (%size%) to your device": "Save %title% (%size%) to your device",
|
||||||
"Save \"%title%\" (%size%) to your device": "Save \"%title%\" (%size%) to your device",
|
"Save \"%title%\" (%size%) to your device": "Save \"%title%\" (%size%) to your device"
|
||||||
"Find Channels to follow": "Find Channels to follow",
|
|
||||||
"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.": "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.",
|
|
||||||
"%remaining% more...": "%remaining% more...",
|
|
||||||
"Did you know that you can earn free credits worth up to %amount%?": "Did you know that you can earn free credits worth up to %amount%?",
|
|
||||||
"SHOW ME": "SHOW ME",
|
|
||||||
"Convert credits to USD on Bittrex": "Convert credits to USD on Bittrex",
|
|
||||||
"You also have": "You also have",
|
|
||||||
"in tips": "in tips",
|
|
||||||
"Earn more tips by uploading cool videos": "Earn more tips by uploading cool videos",
|
|
||||||
"You staked": "You staked",
|
|
||||||
"in your publishes": "in your publishes",
|
|
||||||
"in your supports": "in your supports",
|
|
||||||
"Your wallet is not currently synced with lbry.tv. You are responsible for backing up your wallet.": "Your wallet is not currently synced with lbry.tv. You are responsible for backing up your wallet.",
|
|
||||||
"A backup of your wallet is synced with lbry.tv": "A backup of your wallet is synced with lbry.tv",
|
|
||||||
"What does this mean?": "What does this mean?",
|
|
||||||
"LBRY credits allow you to publish or purchase content.": "LBRY credits allow you to publish or purchase content.",
|
|
||||||
"You can obtain free credits worth %amount% after you provide an email address.": "You can obtain free credits worth %amount% after you provide an email address.",
|
|
||||||
"up to": "up to"
|
|
||||||
}
|
}
|
12178
package-lock.json
generated
Normal file
12178
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
23
package.json
23
package.json
|
@ -1,13 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "LBRYApp",
|
"name": "LBRYApp",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": "true",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"android": "react-native run-android",
|
"start": "node node_modules/react-native/local-cli/cli.js start",
|
||||||
"ios": "react-native run-ios",
|
"devtools": "react-devtools",
|
||||||
"start": "react-native start",
|
|
||||||
"test": "jest",
|
|
||||||
"lint": "eslint .",
|
|
||||||
"format": "prettier 'src/**/*.{js,json}' --write",
|
"format": "prettier 'src/**/*.{js,json}' --write",
|
||||||
"precommit": "lint-staged"
|
"precommit": "lint-staged"
|
||||||
},
|
},
|
||||||
|
@ -15,8 +12,8 @@
|
||||||
"base-64": "^0.1.0",
|
"base-64": "^0.1.0",
|
||||||
"@expo/vector-icons": "^8.1.0",
|
"@expo/vector-icons": "^8.1.0",
|
||||||
"gfycat-style-urls": "^1.0.3",
|
"gfycat-style-urls": "^1.0.3",
|
||||||
"lbry-redux": "lbryio/lbry-redux#69ffd110dbf3633e5847f61f008751edec033017",
|
"lbry-redux": "lbryio/lbry-redux#acbbc66b78566da11faa0fa8c65b44a8d4302c5e",
|
||||||
"lbryinc": "lbryio/lbryinc#667024ebb7cb207609273174ca422cee47469270",
|
"lbryinc": "lbryio/lbryinc#138a053754ec8e3da8e9bf153d32f527c962f25c",
|
||||||
"lodash": ">=4.17.11",
|
"lodash": ">=4.17.11",
|
||||||
"merge": ">=1.2.1",
|
"merge": ">=1.2.1",
|
||||||
"moment": "^2.22.1",
|
"moment": "^2.22.1",
|
||||||
|
@ -28,7 +25,7 @@
|
||||||
"react-native-country-picker-modal": "^1.10.0",
|
"react-native-country-picker-modal": "^1.10.0",
|
||||||
"react-native-exception-handler": "2.10.8",
|
"react-native-exception-handler": "2.10.8",
|
||||||
"react-native-fast-image": "^7.0.2",
|
"react-native-fast-image": "^7.0.2",
|
||||||
"react-native-fs": "^2.16.6",
|
"react-native-fs": "^2.13.3",
|
||||||
"react-native-gesture-handler": "1.5.2",
|
"react-native-gesture-handler": "1.5.2",
|
||||||
"react-native-image-zoom-viewer": "^2.2.5",
|
"react-native-image-zoom-viewer": "^2.2.5",
|
||||||
"react-native-password-strength-meter": "^0.0.2",
|
"react-native-password-strength-meter": "^0.0.2",
|
||||||
|
@ -36,14 +33,13 @@
|
||||||
"react-native-progress-circle": "2.1.0",
|
"react-native-progress-circle": "2.1.0",
|
||||||
"react-native-reanimated": "1.4.0",
|
"react-native-reanimated": "1.4.0",
|
||||||
"react-native-safe-area-context": "^0.6.2",
|
"react-native-safe-area-context": "^0.6.2",
|
||||||
"react-native-screens": "^2.0.0",
|
|
||||||
"react-native-snackbar": "2.0.4",
|
"react-native-snackbar": "2.0.4",
|
||||||
"react-native-super-grid": "^3.0.4",
|
"react-native-super-grid": "^3.0.4",
|
||||||
"react-native-vector-icons": "^6.6.0",
|
"react-native-vector-icons": "^6.6.0",
|
||||||
"react-native-video": "lbryio/react-native-video#7992ff945872f9bd00a3736d9ff1318f343abf47",
|
"react-native-video": "lbryio/react-native-video#7992ff945872f9bd00a3736d9ff1318f343abf47",
|
||||||
"react-native-webview": "^8.0.2",
|
"react-native-webview": "^8.0.2",
|
||||||
"react-navigation": "^4.0.10",
|
"react-navigation": "^4.0.10",
|
||||||
"react-navigation-drawer": "2.3.3",
|
"react-navigation-drawer": "^2.3.3",
|
||||||
"react-navigation-redux-helpers": "^3.0.2",
|
"react-navigation-redux-helpers": "^3.0.2",
|
||||||
"react-navigation-tabs": "^2.7.0",
|
"react-navigation-tabs": "^2.7.0",
|
||||||
"react-navigation-stack": "^1.10.3",
|
"react-navigation-stack": "^1.10.3",
|
||||||
|
@ -77,14 +73,11 @@
|
||||||
"flow-babel-webpack-plugin": "^1.1.1",
|
"flow-babel-webpack-plugin": "^1.1.1",
|
||||||
"husky": "^0.14.3",
|
"husky": "^0.14.3",
|
||||||
"lint-staged": "^7.0.4",
|
"lint-staged": "^7.0.4",
|
||||||
"metro-react-native-babel-preset": "0.56.3",
|
"metro-react-native-babel-preset": "^0.56.0",
|
||||||
"prettier": "^1.11.1",
|
"prettier": "^1.11.1",
|
||||||
"@react-native-community/eslint-config": "^0.0.5",
|
"@react-native-community/eslint-config": "^0.0.5",
|
||||||
"react-devtools": "^3.6.3",
|
"react-devtools": "^3.6.3",
|
||||||
"reactotron-react-native": "4.0.2",
|
"reactotron-react-native": "4.0.2",
|
||||||
"reactotron-redux": "3.1.2"
|
"reactotron-redux": "3.1.2"
|
||||||
},
|
|
||||||
"jest": {
|
|
||||||
"preset": "react-native"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import DiscoverPage from 'page/discover';
|
||||||
import DownloadsPage from 'page/downloads';
|
import DownloadsPage from 'page/downloads';
|
||||||
import DrawerContent from 'component/drawerContent';
|
import DrawerContent from 'component/drawerContent';
|
||||||
import FilePage from 'page/file';
|
import FilePage from 'page/file';
|
||||||
import LiteFilePage from 'page/liteFile';
|
|
||||||
import FirstRunScreen from 'page/firstRun';
|
import FirstRunScreen from 'page/firstRun';
|
||||||
import InvitesPage from 'page/invites';
|
import InvitesPage from 'page/invites';
|
||||||
import PublishPage from 'page/publish';
|
import PublishPage from 'page/publish';
|
||||||
|
@ -20,7 +19,7 @@ import SubscriptionsPage from 'page/subscriptions';
|
||||||
import TransactionHistoryPage from 'page/transactionHistory';
|
import TransactionHistoryPage from 'page/transactionHistory';
|
||||||
import VerificationScreen from 'page/verification';
|
import VerificationScreen from 'page/verification';
|
||||||
import WalletPage from 'page/wallet';
|
import WalletPage from 'page/wallet';
|
||||||
import { NavigationActions, StackActions } from 'react-navigation';
|
import { NavigationActions } from 'react-navigation';
|
||||||
import { createDrawerNavigator } from 'react-navigation-drawer';
|
import { createDrawerNavigator } from 'react-navigation-drawer';
|
||||||
import { createStackNavigator } from 'react-navigation-stack';
|
import { createStackNavigator } from 'react-navigation-stack';
|
||||||
import {
|
import {
|
||||||
|
@ -31,7 +30,6 @@ import {
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
AppState,
|
AppState,
|
||||||
Alert,
|
|
||||||
BackHandler,
|
BackHandler,
|
||||||
DeviceEventEmitter,
|
DeviceEventEmitter,
|
||||||
Linking,
|
Linking,
|
||||||
|
@ -42,10 +40,8 @@ import {
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { selectDrawerStack } from 'redux/selectors/drawer';
|
import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||||
import {
|
import {
|
||||||
Lbry,
|
|
||||||
ACTIONS,
|
ACTIONS,
|
||||||
SETTINGS,
|
SETTINGS,
|
||||||
doBalanceSubscribe,
|
|
||||||
doDismissToast,
|
doDismissToast,
|
||||||
doPopulateSharedUserState,
|
doPopulateSharedUserState,
|
||||||
doPreferenceGet,
|
doPreferenceGet,
|
||||||
|
@ -54,10 +50,6 @@ import {
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import {
|
import {
|
||||||
Lbryio,
|
Lbryio,
|
||||||
rewards as REWARD_TYPES,
|
|
||||||
doBlackListedOutpointsSubscribe,
|
|
||||||
doClaimRewardType,
|
|
||||||
doFilteredOutpointsSubscribe,
|
|
||||||
doGetSync,
|
doGetSync,
|
||||||
doUserCheckEmailVerified,
|
doUserCheckEmailVerified,
|
||||||
doUserEmailVerify,
|
doUserEmailVerify,
|
||||||
|
@ -81,19 +73,27 @@ import discoverStyle from 'styles/discover';
|
||||||
import searchStyle from 'styles/search';
|
import searchStyle from 'styles/search';
|
||||||
import SearchRightHeaderIcon from 'component/searchRightHeaderIcon';
|
import SearchRightHeaderIcon from 'component/searchRightHeaderIcon';
|
||||||
import Snackbar from 'react-native-snackbar';
|
import Snackbar from 'react-native-snackbar';
|
||||||
import { doSetSdkReady } from 'redux/actions/settings';
|
|
||||||
|
|
||||||
const SYNC_GET_INTERVAL = 1000 * 60 * 5; // every 5 minutes
|
const SYNC_GET_INTERVAL = 1000 * 60 * 5; // every 5 minutes
|
||||||
|
|
||||||
|
const menuNavigationButton = navigation => (
|
||||||
|
<NavigationButton
|
||||||
|
name="bars"
|
||||||
|
size={24}
|
||||||
|
style={discoverStyle.drawerMenuButton}
|
||||||
|
iconStyle={discoverStyle.drawerHamburger}
|
||||||
|
onPress={() => navigation.openDrawer()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
const discoverStack = createStackNavigator(
|
const discoverStack = createStackNavigator(
|
||||||
{
|
{
|
||||||
Subscriptions: {
|
Discover: {
|
||||||
screen: SubscriptionsPage,
|
screen: DiscoverPage,
|
||||||
navigationOptions: {
|
navigationOptions: ({ navigation }) => ({
|
||||||
title: 'Following',
|
title: 'Explore',
|
||||||
header: null,
|
header: null,
|
||||||
drawerIcon: ({ tintColor }) => <Icon name="heart" solid size={drawerIconSize} style={{ color: tintColor }} />,
|
}),
|
||||||
},
|
|
||||||
},
|
},
|
||||||
File: {
|
File: {
|
||||||
screen: FilePage,
|
screen: FilePage,
|
||||||
|
@ -160,17 +160,10 @@ const drawer = createDrawerNavigator(
|
||||||
DiscoverStack: {
|
DiscoverStack: {
|
||||||
screen: discoverStack,
|
screen: discoverStack,
|
||||||
navigationOptions: {
|
navigationOptions: {
|
||||||
title: 'Following',
|
title: 'Explore',
|
||||||
drawerIcon: ({ tintColor }) => <Icon name="home" size={drawerIconSize} style={{ color: tintColor }} />,
|
drawerIcon: ({ tintColor }) => <Icon name="home" size={drawerIconSize} style={{ color: tintColor }} />,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Discover: {
|
|
||||||
screen: DiscoverPage,
|
|
||||||
navigationOptions: ({ navigation }) => ({
|
|
||||||
title: 'Your Tags',
|
|
||||||
header: null,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
Trending: {
|
Trending: {
|
||||||
screen: TrendingPage,
|
screen: TrendingPage,
|
||||||
navigationOptions: {
|
navigationOptions: {
|
||||||
|
@ -178,6 +171,13 @@ const drawer = createDrawerNavigator(
|
||||||
drawerIcon: ({ tintColor }) => <Icon name="fire" size={drawerIconSize} style={{ color: tintColor }} />,
|
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: {
|
WalletStack: {
|
||||||
screen: walletStack,
|
screen: walletStack,
|
||||||
navigationOptions: {
|
navigationOptions: {
|
||||||
|
@ -277,12 +277,6 @@ const mainStackNavigator = new createStackNavigator(
|
||||||
drawerLockMode: 'locked-closed',
|
drawerLockMode: 'locked-closed',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
LiteFile: {
|
|
||||||
screen: LiteFilePage,
|
|
||||||
navigationOptions: {
|
|
||||||
drawerLockMode: 'locked-closed',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headerMode: 'none',
|
headerMode: 'none',
|
||||||
|
@ -334,7 +328,6 @@ class AppWithNavigationState extends React.Component {
|
||||||
this.emailVerifyCheckInterval = setInterval(() => this.checkEmailVerification(), 5000);
|
this.emailVerifyCheckInterval = setInterval(() => this.checkEmailVerification(), 5000);
|
||||||
Linking.addEventListener('url', this._handleUrl);
|
Linking.addEventListener('url', this._handleUrl);
|
||||||
|
|
||||||
DeviceEventEmitter.addListener('onSdkReady', this.handleSdkReady);
|
|
||||||
DeviceEventEmitter.addListener('onDownloadAborted', this.handleDownloadAborted);
|
DeviceEventEmitter.addListener('onDownloadAborted', this.handleDownloadAborted);
|
||||||
DeviceEventEmitter.addListener('onDownloadStarted', this.handleDownloadStarted);
|
DeviceEventEmitter.addListener('onDownloadStarted', this.handleDownloadStarted);
|
||||||
DeviceEventEmitter.addListener('onDownloadUpdated', this.handleDownloadUpdated);
|
DeviceEventEmitter.addListener('onDownloadUpdated', this.handleDownloadUpdated);
|
||||||
|
@ -374,70 +367,6 @@ class AppWithNavigationState extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
checkNewAndroidReward = () => {
|
|
||||||
const { dispatch, doToast } = this.props;
|
|
||||||
const claimRewardCallback = err => {
|
|
||||||
if (err) {
|
|
||||||
// an error occurred, do not display anything
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// reward successfully claimed
|
|
||||||
NativeModules.UtilityModule.setNativeBooleanSetting(Constants.SETTING_NEW_ANDROID_REWARD_CLAIMED, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
NativeModules.UtilityModule.getNativeBooleanSetting(Constants.SETTING_NEW_ANDROID_REWARD_CLAIMED, false).then(
|
|
||||||
rewardClaimed => {
|
|
||||||
if (!rewardClaimed) {
|
|
||||||
dispatch(
|
|
||||||
doClaimRewardType(REWARD_TYPES.TYPE_NEW_ANDROID, { notifyError: false, callback: claimRewardCallback }),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSdkReady = () => {
|
|
||||||
const { dispatch } = this.props;
|
|
||||||
dispatch(doSetSdkReady());
|
|
||||||
dispatch(doBalanceSubscribe());
|
|
||||||
dispatch(doBlackListedOutpointsSubscribe());
|
|
||||||
dispatch(doFilteredOutpointsSubscribe());
|
|
||||||
|
|
||||||
Lbry.wallet_status().then(secureWalletStatus => {
|
|
||||||
// For now, automatically unlock the wallet if a password is set so that downloads work
|
|
||||||
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(password => {
|
|
||||||
if ((secureWalletStatus.is_encrypted && !secureWalletStatus.is_locked) || secureWalletStatus.is_locked) {
|
|
||||||
this.setState({
|
|
||||||
message: __('Unlocking account'),
|
|
||||||
details: __('Decrypting wallet'),
|
|
||||||
});
|
|
||||||
|
|
||||||
// unlock the wallet and then finish the splash screen
|
|
||||||
Lbry.wallet_unlock({ password: password || '' }).then(unlocked => {
|
|
||||||
if (unlocked) {
|
|
||||||
} else {
|
|
||||||
// this.handleAccountUnlockFailed();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.checkNewAndroidReward();
|
|
||||||
};
|
|
||||||
|
|
||||||
handleAccountUnlockFailed() {
|
|
||||||
const { dispatch } = this.props;
|
|
||||||
dispatch(
|
|
||||||
doToast({
|
|
||||||
message: __(
|
|
||||||
'Your wallet failed to unlock, which means you may not be able to play any videos or access your funds. Restart the app to fix this.',
|
|
||||||
),
|
|
||||||
isError: true,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleDownloadStarted = evt => {
|
handleDownloadStarted = evt => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
const { uri, outpoint, fileInfo } = evt;
|
const { uri, outpoint, fileInfo } = evt;
|
||||||
|
@ -473,7 +402,6 @@ class AppWithNavigationState extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
DeviceEventEmitter.removeListener('onSdkReady', this.handleSdkReady);
|
|
||||||
DeviceEventEmitter.removeListener('onDownloadAborted', this.handleDownloadAborted);
|
DeviceEventEmitter.removeListener('onDownloadAborted', this.handleDownloadAborted);
|
||||||
DeviceEventEmitter.removeListener('onDownloadStarted', this.handleDownloadStarted);
|
DeviceEventEmitter.removeListener('onDownloadStarted', this.handleDownloadStarted);
|
||||||
DeviceEventEmitter.removeListener('onDownloadUpdated', this.handleDownloadUpdated);
|
DeviceEventEmitter.removeListener('onDownloadUpdated', this.handleDownloadUpdated);
|
||||||
|
|
|
@ -19,4 +19,7 @@ const perform = dispatch => ({
|
||||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(ChannelIconItem);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(ChannelIconItem);
|
||||||
|
|
|
@ -19,11 +19,11 @@ const select = state => ({
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
notify: data => dispatch(doToast(data)),
|
notify: data => dispatch(doToast(data)),
|
||||||
createChannel: (name, amount) => dispatch(doCreateChannel(name, amount)),
|
createChannel: (name, amount) => dispatch(doCreateChannel(name, amount)),
|
||||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||||
getSync: (password, callback) => dispatch(doGetSync(password, callback)),
|
getSync: (password, callback) => dispatch(doGetSync(password, callback)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
select,
|
select,
|
||||||
perform,
|
perform
|
||||||
)(ChannelSelector);
|
)(ChannelSelector);
|
||||||
|
|
|
@ -23,4 +23,7 @@ const perform = dispatch => ({
|
||||||
claimSearch: options => dispatch(doClaimSearch(options)),
|
claimSearch: options => dispatch(doClaimSearch(options)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(ClaimList);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(ClaimList);
|
||||||
|
|
|
@ -36,4 +36,7 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(ClaimResultItem);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(ClaimResultItem);
|
||||||
|
|
|
@ -39,14 +39,10 @@ class ClaimResultItem extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressHandler = () => {
|
onPressHandler = () => {
|
||||||
const { autoplay, navigation, result, urlOpenHandler, setPlayerVisible } = this.props;
|
const { autoplay, navigation, result, setPlayerVisible } = this.props;
|
||||||
const { claimId, name } = result;
|
const { claimId, name } = result;
|
||||||
const url = normalizeURI(`${name}#${claimId}`);
|
const url = normalizeURI(`${name}#${claimId}`);
|
||||||
if (urlOpenHandler) {
|
|
||||||
urlOpenHandler(url);
|
|
||||||
} else {
|
|
||||||
navigateToUri(navigation, url, { autoplay }, false, url, setPlayerVisible);
|
navigateToUri(navigation, url, { autoplay }, false, url, setPlayerVisible);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doToast, selectBalance, selectMyChannelClaims } from 'lbry-redux';
|
import { doFetchChannelListMine, selectMyChannelClaims } from 'lbry-redux';
|
||||||
import { selectUnclaimedRewardValue, selectUser } from 'lbryinc';
|
import { selectUser } from 'lbryinc';
|
||||||
import { selectSdkReady } from 'redux/selectors/settings';
|
|
||||||
import DrawerContent from './view';
|
import DrawerContent from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
balance: selectBalance(state),
|
|
||||||
channels: selectMyChannelClaims(state),
|
channels: selectMyChannelClaims(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
unclaimedRewardAmount: selectUnclaimedRewardValue(state),
|
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
notify: data => dispatch(doToast(data)),
|
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(DrawerContent);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(DrawerContent);
|
||||||
|
|
|
@ -6,13 +6,11 @@ import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import channelIconStyle from 'styles/channelIcon';
|
import channelIconStyle from 'styles/channelIcon';
|
||||||
import discoverStyle from 'styles/discover';
|
import discoverStyle from 'styles/discover';
|
||||||
import { Lbryio } from 'lbryinc';
|
|
||||||
import { formatUsd } from 'utils/helper';
|
|
||||||
|
|
||||||
const groupedMenuItems = {
|
const groupedMenuItems = {
|
||||||
'Find content': [
|
'Find content': [
|
||||||
{ icon: 'heart', solid: true, label: 'Following', route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS },
|
|
||||||
{ icon: 'hashtag', label: 'Your Tags', route: Constants.DRAWER_ROUTE_DISCOVER },
|
{ icon: 'hashtag', label: 'Your Tags', route: Constants.DRAWER_ROUTE_DISCOVER },
|
||||||
|
{ icon: 'heart', solid: true, label: 'Following', route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS },
|
||||||
{ icon: 'globe-americas', label: 'All Content', route: Constants.DRAWER_ROUTE_TRENDING },
|
{ icon: 'globe-americas', label: 'All Content', route: Constants.DRAWER_ROUTE_TRENDING },
|
||||||
],
|
],
|
||||||
'Your content': [
|
'Your content': [
|
||||||
|
@ -33,27 +31,11 @@ const groupedMenuItems = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const groupNames = Object.keys(groupedMenuItems);
|
const groupNames = Object.keys(groupedMenuItems);
|
||||||
const routesRequiringSdkReady = [
|
|
||||||
Constants.DRAWER_ROUTE_CHANNEL_CREATOR,
|
|
||||||
Constants.DRAWER_ROUTE_MY_LBRY,
|
|
||||||
Constants.DRAWER_ROUTE_PUBLISHES,
|
|
||||||
Constants.DRAWER_ROUTE_PUBLISH,
|
|
||||||
Constants.DRAWER_ROUTE_WALLET,
|
|
||||||
Constants.DRAWER_ROUTE_REWARDS,
|
|
||||||
Constants.DRAWER_ROUTE_INVITES,
|
|
||||||
];
|
|
||||||
|
|
||||||
class DrawerContent extends React.PureComponent {
|
class DrawerContent extends React.PureComponent {
|
||||||
state = {
|
|
||||||
usdExchangeRate: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
Lbryio.getExchangeRates().then(rates => {
|
const { fetchChannelListMine } = this.props;
|
||||||
if (!isNaN(rates.LBC_USD)) {
|
fetchChannelListMine();
|
||||||
this.setState({ usdExchangeRate: rates.LBC_USD });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getAvatarImageUrl = () => {
|
getAvatarImageUrl = () => {
|
||||||
|
@ -80,23 +62,8 @@ class DrawerContent extends React.PureComponent {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleItemPress = routeName => {
|
|
||||||
const { navigation, notify, sdkReady } = this.props;
|
|
||||||
if (!sdkReady && routesRequiringSdkReady.includes(routeName)) {
|
|
||||||
if (navigation.closeDrawer) {
|
|
||||||
navigation.closeDrawer();
|
|
||||||
}
|
|
||||||
notify({
|
|
||||||
message: __('The background service is still initializing. Please try again when initialization is complete.'),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
navigation.navigate({ routeName: routeName });
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { activeTintColor, balance, navigation, unclaimedRewardAmount, user, onItemPress } = this.props;
|
const { activeTintColor, navigation, user, onItemPress } = this.props;
|
||||||
const { state } = navigation;
|
const { state } = navigation;
|
||||||
|
|
||||||
const activeItemKey = state.routes[state.index] ? state.routes[state.index].key : null;
|
const activeItemKey = state.routes[state.index] ? state.routes[state.index].key : null;
|
||||||
|
@ -178,7 +145,7 @@ class DrawerContent extends React.PureComponent {
|
||||||
const focused =
|
const focused =
|
||||||
activeItemKey === item.route ||
|
activeItemKey === item.route ||
|
||||||
(activeItemKey === Constants.FULL_ROUTE_NAME_DISCOVER &&
|
(activeItemKey === Constants.FULL_ROUTE_NAME_DISCOVER &&
|
||||||
item.route === Constants.DRAWER_ROUTE_SUBSCRIPTIONS) ||
|
item.route === Constants.DRAWER_ROUTE_DISCOVER) ||
|
||||||
(activeItemKey === Constants.FULL_ROUTE_NAME_WALLET &&
|
(activeItemKey === Constants.FULL_ROUTE_NAME_WALLET &&
|
||||||
item.route === Constants.DRAWER_ROUTE_WALLET);
|
item.route === Constants.DRAWER_ROUTE_WALLET);
|
||||||
return (
|
return (
|
||||||
|
@ -190,7 +157,7 @@ class DrawerContent extends React.PureComponent {
|
||||||
focused ? discoverStyle.menuItemTouchAreaFocused : null,
|
focused ? discoverStyle.menuItemTouchAreaFocused : null,
|
||||||
]}
|
]}
|
||||||
key={item.label}
|
key={item.label}
|
||||||
onPress={() => this.handleItemPress(item.route)}
|
onPress={() => navigation.navigate({ routeName: item.route })}
|
||||||
delayPressIn={0}
|
delayPressIn={0}
|
||||||
>
|
>
|
||||||
<View style={discoverStyle.menuItemIcon}>
|
<View style={discoverStyle.menuItemIcon}>
|
||||||
|
@ -203,15 +170,6 @@ class DrawerContent extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
<Text style={[discoverStyle.menuItem, focused ? discoverStyle.menuItemFocused : null]}>
|
<Text style={[discoverStyle.menuItem, focused ? discoverStyle.menuItemFocused : null]}>
|
||||||
{__(item.label)}
|
{__(item.label)}
|
||||||
{item.label === 'Wallet' && this.state.usdExchangeRate > 0 && (
|
|
||||||
<Text> ({formatUsd(parseFloat(balance) * parseFloat(this.state.usdExchangeRate))})</Text>
|
|
||||||
)}
|
|
||||||
{item.label === 'Rewards' && this.state.usdExchangeRate > 0 && (
|
|
||||||
<Text>
|
|
||||||
{' '}
|
|
||||||
({formatUsd(parseFloat(unclaimedRewardAmount) * parseFloat(this.state.usdExchangeRate))})
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
|
@ -35,4 +35,7 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(FileItem);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(FileItem);
|
||||||
|
|
|
@ -70,9 +70,7 @@ class FileItem extends React.PureComponent {
|
||||||
const outpointsToHide = !blackListedOutpoints
|
const outpointsToHide = !blackListedOutpoints
|
||||||
? filteredOutpoints
|
? filteredOutpoints
|
||||||
: blackListedOutpoints.concat(filteredOutpoints);
|
: blackListedOutpoints.concat(filteredOutpoints);
|
||||||
shouldHide = outpointsToHide.some(
|
shouldHide = outpointsToHide.some(outpoint => outpoint.txid === claim.txid && outpoint.nout === claim.nout);
|
||||||
outpoint => outpoint && outpoint.txid === claim.txid && outpoint.nout === claim.nout,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (shouldHide) {
|
if (shouldHide) {
|
||||||
// don't display blacklisted or filtered outpoints on the Your tags page
|
// don't display blacklisted or filtered outpoints on the Your tags page
|
||||||
|
|
|
@ -36,4 +36,7 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(FileListItem);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(FileListItem);
|
||||||
|
|
|
@ -99,13 +99,9 @@ class FileListItem extends React.PureComponent {
|
||||||
isRewardContent,
|
isRewardContent,
|
||||||
channelClaimId,
|
channelClaimId,
|
||||||
fullChannelUri,
|
fullChannelUri,
|
||||||
repostUrl,
|
|
||||||
repostChannel,
|
|
||||||
repostChannelUrl,
|
|
||||||
shortChannelUri,
|
shortChannelUri,
|
||||||
shouldHide,
|
shouldHide,
|
||||||
signingChannel,
|
signingChannel;
|
||||||
isRepost;
|
|
||||||
if (claim) {
|
if (claim) {
|
||||||
name = claim.name;
|
name = claim.name;
|
||||||
signingChannel = claim.signing_channel;
|
signingChannel = claim.signing_channel;
|
||||||
|
@ -115,21 +111,12 @@ class FileListItem extends React.PureComponent {
|
||||||
channelClaimId = signingChannel ? signingChannel.claim_id : null;
|
channelClaimId = signingChannel ? signingChannel.claim_id : null;
|
||||||
fullChannelUri = channelClaimId ? `${channel}#${channelClaimId}` : channel;
|
fullChannelUri = channelClaimId ? `${channel}#${channelClaimId}` : channel;
|
||||||
shortChannelUri = signingChannel ? signingChannel.short_url : null;
|
shortChannelUri = signingChannel ? signingChannel.short_url : null;
|
||||||
repostUrl = claim.repost_url;
|
|
||||||
repostChannelUrl = claim.repost_channel_url;
|
|
||||||
if (repostUrl) {
|
|
||||||
const { claimName: repostName, channelName } = parseURI(repostUrl);
|
|
||||||
repostChannel = channelName;
|
|
||||||
}
|
|
||||||
isRepost = !!repostUrl;
|
|
||||||
|
|
||||||
if (blackListedOutpoints || filteredOutpoints) {
|
if (blackListedOutpoints || filteredOutpoints) {
|
||||||
const outpointsToHide = !blackListedOutpoints
|
const outpointsToHide = !blackListedOutpoints
|
||||||
? filteredOutpoints
|
? filteredOutpoints
|
||||||
: blackListedOutpoints.concat(filteredOutpoints);
|
: blackListedOutpoints.concat(filteredOutpoints);
|
||||||
shouldHide = outpointsToHide.some(
|
shouldHide = outpointsToHide.some(outpoint => outpoint.txid === claim.txid && outpoint.nout === claim.nout);
|
||||||
outpoint => outpoint && outpoint.txid === claim.txid && outpoint.nout === claim.nout,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: hide channels on tag pages?
|
// TODO: hide channels on tag pages?
|
||||||
|
@ -140,33 +127,11 @@ class FileListItem extends React.PureComponent {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const actualHideChannel = !isRepost && hideChannel;
|
|
||||||
const isChannel = name && name.startsWith('@');
|
const isChannel = name && name.startsWith('@');
|
||||||
const hasThumbnail = !!thumbnail;
|
const hasThumbnail = !!thumbnail;
|
||||||
return (
|
|
||||||
<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 || `@${repostChannel}`),
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>{' '}
|
|
||||||
reposted
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={style}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[style, isChannel ? fileListStyle.channelContainer : null]}
|
style={[style, isChannel ? fileListStyle.channelContainer : null]}
|
||||||
onPress={this.onPressHandler}
|
onPress={this.onPressHandler}
|
||||||
|
@ -247,7 +212,7 @@ class FileListItem extends React.PureComponent {
|
||||||
<View style={fileListStyle.titleContainer}>
|
<View style={fileListStyle.titleContainer}>
|
||||||
<Text
|
<Text
|
||||||
style={featuredResult ? fileListStyle.featuredTitle : fileListStyle.title}
|
style={featuredResult ? fileListStyle.featuredTitle : fileListStyle.title}
|
||||||
numberOfLines={actualHideChannel ? 4 : 3}
|
numberOfLines={hideChannel ? 4 : 3}
|
||||||
>
|
>
|
||||||
{title || name}
|
{title || name}
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -261,7 +226,7 @@ class FileListItem extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(channel || isChannel) && !actualHideChannel && (
|
{(channel || isChannel) && !hideChannel && (
|
||||||
<Link
|
<Link
|
||||||
style={fileListStyle.publisher}
|
style={fileListStyle.publisher}
|
||||||
text={isChannel ? name : channel}
|
text={isChannel ? name : channel}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { connect } from 'react-redux';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import { selectBalance } from 'lbry-redux';
|
import { selectBalance } from 'lbry-redux';
|
||||||
import { selectUnclaimedRewardValue } from 'lbryinc';
|
import { selectUnclaimedRewardValue } from 'lbryinc';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants';
|
||||||
import FloatingWalletBalance from './view';
|
import FloatingWalletBalance from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
@ -11,4 +11,7 @@ const select = state => ({
|
||||||
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, null)(FloatingWalletBalance);
|
export default connect(
|
||||||
|
select,
|
||||||
|
null
|
||||||
|
)(FloatingWalletBalance);
|
||||||
|
|
|
@ -36,7 +36,7 @@ class MediaPlayer extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
buffering: true,
|
buffering: false,
|
||||||
backgroundPlayEnabled: false,
|
backgroundPlayEnabled: false,
|
||||||
autoPaused: false,
|
autoPaused: false,
|
||||||
rate: 1,
|
rate: 1,
|
||||||
|
@ -45,9 +45,9 @@ class MediaPlayer extends React.PureComponent {
|
||||||
resizeMode: 'contain',
|
resizeMode: 'contain',
|
||||||
duration: 0.0,
|
duration: 0.0,
|
||||||
currentTime: 0.0,
|
currentTime: 0.0,
|
||||||
paused: true,
|
paused: !props.autoPlay,
|
||||||
fullscreenMode: false,
|
fullscreenMode: false,
|
||||||
areControlsVisible: false,
|
areControlsVisible: true,
|
||||||
controlsTimeout: -1,
|
controlsTimeout: -1,
|
||||||
seekerOffset: 0,
|
seekerOffset: 0,
|
||||||
seekerPosition: 0,
|
seekerPosition: 0,
|
||||||
|
@ -87,9 +87,7 @@ class MediaPlayer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoad = data => {
|
onLoad = data => {
|
||||||
const { autoPlay } = this.props;
|
|
||||||
this.setState({
|
this.setState({
|
||||||
buffering: false,
|
|
||||||
duration: data.duration,
|
duration: data.duration,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -102,17 +100,13 @@ class MediaPlayer extends React.PureComponent {
|
||||||
if (this.props.onMediaLoaded) {
|
if (this.props.onMediaLoaded) {
|
||||||
this.props.onMediaLoaded();
|
this.props.onMediaLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoPlay) {
|
|
||||||
this.setState({ paused: false });
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onProgress = data => {
|
onProgress = data => {
|
||||||
const { savePosition, claim } = this.props;
|
const { savePosition, claim } = this.props;
|
||||||
|
|
||||||
this.setState({ buffering: false, currentTime: data.currentTime });
|
this.setState({ buffering: false, currentTime: data.currentTime });
|
||||||
if (claim && data.currentTime > 0 && Math.floor(data.currentTime) % positionSaveInterval === 0) {
|
if (data.currentTime > 0 && Math.floor(data.currentTime) % positionSaveInterval === 0) {
|
||||||
const { claim_id: claimId, txid, nout } = claim;
|
const { claim_id: claimId, txid, nout } = claim;
|
||||||
savePosition(claimId, `${txid}:${nout}`, data.currentTime);
|
savePosition(claimId, `${txid}:${nout}`, data.currentTime);
|
||||||
}
|
}
|
||||||
|
@ -173,7 +167,7 @@ class MediaPlayer extends React.PureComponent {
|
||||||
|
|
||||||
togglePlay = () => {
|
togglePlay = () => {
|
||||||
this.showPlayerControls();
|
this.showPlayerControls();
|
||||||
this.setState({ paused: !this.state.paused }, this.updateBackgroundMediaNotification);
|
this.setState({ paused: !this.state.paused }, this.handlePausedState);
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePausedState = () => {
|
handlePausedState = () => {
|
||||||
|
@ -194,7 +188,7 @@ class MediaPlayer extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
onEnd = () => {
|
onEnd = () => {
|
||||||
this.setState({ paused: true }, this.updateBackgroundMediaNotification);
|
this.setState({ paused: true });
|
||||||
if (this.props.onPlaybackFinished) {
|
if (this.props.onPlaybackFinished) {
|
||||||
this.props.onPlaybackFinished();
|
this.props.onPlaybackFinished();
|
||||||
}
|
}
|
||||||
|
@ -333,10 +327,6 @@ class MediaPlayer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onFocusChanged = evt => {
|
|
||||||
this.setState({ paused: !(this.state.paused && evt.hasAudioFocus) }, this.updateBackgroundMediaNotification);
|
|
||||||
};
|
|
||||||
|
|
||||||
onBuffer = () => {
|
onBuffer = () => {
|
||||||
if (!this.state.paused) {
|
if (!this.state.paused) {
|
||||||
this.setState({ buffering: true }, () => this.manualHidePlayerControls());
|
this.setState({ buffering: true }, () => this.manualHidePlayerControls());
|
||||||
|
@ -479,7 +469,6 @@ class MediaPlayer extends React.PureComponent {
|
||||||
onEnd={this.onEnd}
|
onEnd={this.onEnd}
|
||||||
onError={this.onError}
|
onError={this.onError}
|
||||||
minLoadRetryCount={999}
|
minLoadRetryCount={999}
|
||||||
onAudioFocusChanged={this.onFocusChanged}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{this.state.firstPlay && thumbnail && (
|
{this.state.firstPlay && thumbnail && (
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import {
|
|
||||||
doClearRepostError,
|
|
||||||
doFetchChannelListMine,
|
|
||||||
doRepost,
|
|
||||||
doToast,
|
|
||||||
selectBalance,
|
|
||||||
selectMyChannelClaims,
|
|
||||||
selectRepostError,
|
|
||||||
selectRepostLoading,
|
|
||||||
} from 'lbry-redux';
|
|
||||||
import ModalRepostView from './view';
|
|
||||||
|
|
||||||
const select = state => ({
|
|
||||||
balance: selectBalance(state),
|
|
||||||
channels: selectMyChannelClaims(state),
|
|
||||||
reposting: selectRepostLoading(state),
|
|
||||||
error: selectRepostError(state),
|
|
||||||
});
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
|
||||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
|
||||||
notify: data => dispatch(doToast(data)),
|
|
||||||
repost: options => dispatch(doRepost(options)),
|
|
||||||
clearError: () => dispatch(doClearRepostError()),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(select, perform)(ModalRepostView);
|
|
|
@ -1,204 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { ActivityIndicator, Alert, Text, TextInput, TouchableOpacity, View } from 'react-native';
|
|
||||||
import { formatCredits, creditsToString } from 'lbry-redux';
|
|
||||||
import modalStyle from 'styles/modal';
|
|
||||||
import modalRepostStyle from 'styles/modalRepost';
|
|
||||||
import ChannelSelector from 'component/channelSelector';
|
|
||||||
import Button from 'component/button';
|
|
||||||
import Colors from 'styles/colors';
|
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
|
||||||
import Link from 'component/link';
|
|
||||||
import { logPublish } from 'utils/helper';
|
|
||||||
|
|
||||||
export default class ModalRepostView extends React.PureComponent {
|
|
||||||
depositAmountInput;
|
|
||||||
|
|
||||||
state = {
|
|
||||||
channelName: null,
|
|
||||||
creditsInputFocused: false,
|
|
||||||
depositAmount: '0.01',
|
|
||||||
repostName: null,
|
|
||||||
repostStarted: false,
|
|
||||||
showAdvanced: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const { claim, fetchChannelListMine } = this.props;
|
|
||||||
const { name } = claim;
|
|
||||||
fetchChannelListMine();
|
|
||||||
this.setState({ repostName: name });
|
|
||||||
this.checkChannelSelection(this.props);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
this.checkChannelSelection(nextProps);
|
|
||||||
const { notify } = this.props;
|
|
||||||
const { reposting, error } = nextProps;
|
|
||||||
if (this.state.repostStarted && !reposting && error) {
|
|
||||||
this.setState({ repostStarted: false });
|
|
||||||
notify({ message: error, isError: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkChannelSelection = props => {
|
|
||||||
const { channels = [] } = props;
|
|
||||||
if (!this.state.channelName && channels && channels.length > 0) {
|
|
||||||
const firstChannel = channels[0];
|
|
||||||
this.setState({ channelName: firstChannel.name });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChannelChange = channelName => {
|
|
||||||
const { channels = [] } = this.props;
|
|
||||||
if (channels && channels.length > 0) {
|
|
||||||
const filtered = channels.filter(c => c.name === channelName);
|
|
||||||
if (filtered.length > 0) {
|
|
||||||
const channel = filtered[0];
|
|
||||||
this.setState({ channelName });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleRepost = () => {
|
|
||||||
const { claim, balance, notify, repost, onRepostSuccessful, channels = [], clearError } = this.props;
|
|
||||||
const { depositAmount, repostName, channelName } = this.state;
|
|
||||||
|
|
||||||
if (parseInt(depositAmount, 10) > balance) {
|
|
||||||
notify({
|
|
||||||
message: 'Insufficient credits',
|
|
||||||
isError: true,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearError();
|
|
||||||
const channel = channels.filter(ch => ch.name === channelName)[0];
|
|
||||||
this.setState({ repostStarted: true }, () => {
|
|
||||||
repost({
|
|
||||||
name: repostName,
|
|
||||||
bid: creditsToString(depositAmount),
|
|
||||||
channel_id: channel.claim_id,
|
|
||||||
claim_id: claim.claim_id,
|
|
||||||
}).then(repostClaim => {
|
|
||||||
logPublish(repostClaim);
|
|
||||||
this.setState({ repostStarted: false });
|
|
||||||
notify({ message: __('The content was successfully reposted!') });
|
|
||||||
if (onRepostSuccessful) onRepostSuccessful();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { balance, channels, reposting, title, onCancelPress, onOverlayPress } = this.props;
|
|
||||||
const canRepost = !!this.state.channelName && !!this.state.repostName;
|
|
||||||
const channelsLoaded = channels && channels.length > 0;
|
|
||||||
const processing = this.state.repostStarted || reposting || !channelsLoaded;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TouchableOpacity style={modalStyle.overlay} activeOpacity={1} onPress={onOverlayPress}>
|
|
||||||
<TouchableOpacity style={modalStyle.container} activeOpacity={1}>
|
|
||||||
<View
|
|
||||||
style={modalRepostStyle.container}
|
|
||||||
onLayout={() => {
|
|
||||||
if (this.tipAmountInput) {
|
|
||||||
this.tipAmountInput.focus();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text style={modalRepostStyle.title} numberOfLines={1}>
|
|
||||||
{__('Repost %title%', { title })}
|
|
||||||
</Text>
|
|
||||||
<Text style={modalRepostStyle.infoText}>
|
|
||||||
{__('Repost your favorite content to help more people discover them!')}
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Text style={modalRepostStyle.label}>{__('Channel to post on')}</Text>
|
|
||||||
<ChannelSelector
|
|
||||||
showAnonymous={false}
|
|
||||||
channelName={this.state.channelName}
|
|
||||||
onChannelChange={this.handleChannelChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{this.state.showAdvanced && (
|
|
||||||
<View>
|
|
||||||
<Text style={modalRepostStyle.label}>{__('Name')}</Text>
|
|
||||||
<View style={modalRepostStyle.nameRow}>
|
|
||||||
<TextInput
|
|
||||||
editable={false}
|
|
||||||
value={this.state.channelName ? `lbry://${this.state.channelName}/` : ''}
|
|
||||||
style={modalRepostStyle.input}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
editable={canRepost}
|
|
||||||
value={this.state.repostName}
|
|
||||||
underlineColorAndroid={Colors.NextLbryGreen}
|
|
||||||
selectTextOnFocus
|
|
||||||
onChangeText={value => this.setState({ repostName: value })}
|
|
||||||
style={modalRepostStyle.input}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<Text style={modalRepostStyle.label}>{__('Deposit')}</Text>
|
|
||||||
<View style={modalRepostStyle.row}>
|
|
||||||
<View style={modalRepostStyle.amountRow}>
|
|
||||||
<TextInput
|
|
||||||
editable={!this.state.repostStarted}
|
|
||||||
ref={ref => (this.depositAmountInput = ref)}
|
|
||||||
onChangeText={value => this.setState({ tipAmount: value })}
|
|
||||||
underlineColorAndroid={Colors.NextLbryGreen}
|
|
||||||
keyboardType={'numeric'}
|
|
||||||
onFocus={() => this.setState({ creditsInputFocused: true })}
|
|
||||||
onBlur={() => this.setState({ creditsInputFocused: false })}
|
|
||||||
placeholder={'0'}
|
|
||||||
value={this.state.depositAmount}
|
|
||||||
selectTextOnFocus
|
|
||||||
style={modalRepostStyle.depositAmountInput}
|
|
||||||
/>
|
|
||||||
<Text style={modalRepostStyle.currency}>LBC</Text>
|
|
||||||
<View style={modalRepostStyle.balance}>
|
|
||||||
{this.state.creditsInputFocused && <Icon name="coins" size={12} />}
|
|
||||||
{this.state.creditsInputFocused && (
|
|
||||||
<Text style={modalRepostStyle.balanceText}>{formatCredits(parseFloat(balance), 1, true)}</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<View style={modalRepostStyle.buttonRow}>
|
|
||||||
{!processing && (
|
|
||||||
<Link
|
|
||||||
style={modalRepostStyle.cancelLink}
|
|
||||||
text={__('Cancel')}
|
|
||||||
onPress={() => {
|
|
||||||
if (onCancelPress) onCancelPress();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{processing && <ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />}
|
|
||||||
|
|
||||||
<View style={modalRepostStyle.rightButtonRow}>
|
|
||||||
<Link
|
|
||||||
style={modalRepostStyle.advancedLink}
|
|
||||||
text={this.state.showAdvanced ? __('Hide advanced') : __('Show advanced')}
|
|
||||||
onPress={() => {
|
|
||||||
this.setState({ showAdvanced: !this.state.showAdvanced });
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
text={__('Repost')}
|
|
||||||
style={modalRepostStyle.button}
|
|
||||||
disabled={!canRepost || this.state.repostStarted || reposting}
|
|
||||||
onPress={this.handleRepost}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,4 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectFetchingClaimSearch } from 'lbry-redux';
|
|
||||||
import ModalSuggestedSubscriptions from './view';
|
import ModalSuggestedSubscriptions from './view';
|
||||||
|
|
||||||
const select = state => ({
|
export default connect()(ModalSuggestedSubscriptions);
|
||||||
loadingSuggested: selectFetchingClaimSearch(state),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(select)(ModalSuggestedSubscriptions);
|
|
||||||
|
|
|
@ -1,26 +1,23 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ActivityIndicator, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import modalStyle from 'styles/modal';
|
import modalStyle from 'styles/modal';
|
||||||
import subscriptionsStyle from 'styles/subscriptions';
|
import subscriptionsStyle from 'styles/subscriptions';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import SuggestedSubscriptionsGrid from 'component/suggestedSubscriptionsGrid';
|
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
|
|
||||||
export default class ModalSuggestedSubcriptions extends React.PureComponent {
|
export default class ModalSuggestedSubcriptions extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const { loadingSuggested, navigation, onDonePress, onOverlayPress } = this.props;
|
const { navigation, onDonePress, onOverlayPress } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={modalStyle.overlay} activeOpacity={1} onPress={onOverlayPress}>
|
<TouchableOpacity style={modalStyle.overlay} activeOpacity={1} onPress={onOverlayPress}>
|
||||||
<TouchableOpacity style={[modalStyle.container, subscriptionsStyle.modalContainer]} activeOpacity={1}>
|
<TouchableOpacity style={[modalStyle.container, subscriptionsStyle.modalContainer]} activeOpacity={1}>
|
||||||
<SuggestedSubscriptionsGrid inModal navigation={navigation} />
|
<SuggestedSubscriptions inModal navigation={navigation} />
|
||||||
<View style={modalStyle.wideButtons}>
|
<View style={modalStyle.buttons}>
|
||||||
<Button style={modalStyle.wideDoneButton} text={__('Done')} onPress={onDonePress} />
|
<Button style={modalStyle.doneButton} text={__('Done')} onPress={onDonePress} />
|
||||||
{loadingSuggested && (
|
|
||||||
<ActivityIndicator size="small" color={Colors.White} style={subscriptionsStyle.modalLoading} />
|
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doSendTip, doToast, selectBalance } from 'lbry-redux';
|
import { doSendTip, doToast, selectBalance } from 'lbry-redux';
|
||||||
import { selectSdkReady } from 'redux/selectors/settings';
|
|
||||||
import ModalTipView from './view';
|
import ModalTipView from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -14,4 +12,7 @@ const perform = dispatch => ({
|
||||||
dispatch(doSendTip(amount, claimId, isSupport, successCallback, errorCallback)),
|
dispatch(doSendTip(amount, claimId, isSupport, successCallback, errorCallback)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(ModalTipView);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(ModalTipView);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import modalStyle from 'styles/modal';
|
||||||
import modalTipStyle from 'styles/modalTip';
|
import modalTipStyle from 'styles/modalTip';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
|
|
||||||
|
@ -18,22 +19,12 @@ export default class ModalTipView extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleSendTip = () => {
|
handleSendTip = () => {
|
||||||
const { claim, balance, notify, onSendTipFailed, onSendTipSuccessful, sdkReady, sendTip } = this.props;
|
const { claim, balance, notify, onSendTipFailed, onSendTipSuccessful, sendTip } = this.props;
|
||||||
const { tipAmount } = this.state;
|
const { tipAmount } = this.state;
|
||||||
|
|
||||||
if (!sdkReady) {
|
|
||||||
notify({
|
|
||||||
message: __(
|
|
||||||
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
|
||||||
),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tipAmount > balance) {
|
if (tipAmount > balance) {
|
||||||
notify({
|
notify({
|
||||||
message: 'Insufficient credits',
|
message: 'Insufficient credits',
|
||||||
isError: true,
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -65,13 +56,13 @@ export default class ModalTipView extends React.PureComponent {
|
||||||
() => {
|
() => {
|
||||||
// error
|
// error
|
||||||
if (onSendTipFailed) onSendTipFailed();
|
if (onSendTipFailed) onSendTipFailed();
|
||||||
},
|
}
|
||||||
),
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
{ cancelable: true },
|
{ cancelable: true }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -124,7 +115,7 @@ export default class ModalTipView extends React.PureComponent {
|
||||||
<Text style={modalTipStyle.infoText}>
|
<Text style={modalTipStyle.infoText}>
|
||||||
{__(
|
{__(
|
||||||
'This will appear as a tip for %content%, which will boost its ability to be discovered while active.',
|
'This will appear as a tip for %content%, which will boost its ability to be discovered while active.',
|
||||||
{ content: contentName },
|
{ content: contentName }
|
||||||
)}{' '}
|
)}{' '}
|
||||||
<Link
|
<Link
|
||||||
style={modalTipStyle.learnMoreLink}
|
style={modalTipStyle.learnMoreLink}
|
||||||
|
|
|
@ -15,13 +15,7 @@ const RESULT_SIZE = 16;
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
isSearching: selectIsSearching(state),
|
isSearching: selectIsSearching(state),
|
||||||
recommendedContent: makeSelectResolvedRecommendedContentForUri(
|
recommendedContent: makeSelectResolvedRecommendedContentForUri(props.uri, RESULT_SIZE)(state),
|
||||||
props.uri,
|
|
||||||
RESULT_SIZE,
|
|
||||||
props.claimId,
|
|
||||||
props.claimName,
|
|
||||||
props.title,
|
|
||||||
)(state),
|
|
||||||
resolvingUris: selectResolvingUris(state),
|
resolvingUris: selectResolvingUris(state),
|
||||||
showNsfwContent: selectShowNsfw(state),
|
showNsfwContent: selectShowNsfw(state),
|
||||||
});
|
});
|
||||||
|
@ -32,4 +26,7 @@ const perform = dispatch => ({
|
||||||
dispatch(doResolvedSearch(query, RESULT_SIZE, undefined, true, { related_to: claimId }, nsfw)),
|
dispatch(doResolvedSearch(query, RESULT_SIZE, undefined, true, { related_to: claimId }, nsfw)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(RelatedContent);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(RelatedContent);
|
||||||
|
|
|
@ -22,7 +22,7 @@ export default class RelatedContent extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isSearching, recommendedContent, navigation, urlOpenHandler, uri, fullUri } = this.props;
|
const { isSearching, recommendedContent, navigation, uri, fullUri } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={relatedContentStyle.container}>
|
<View style={relatedContentStyle.container}>
|
||||||
|
@ -33,7 +33,6 @@ export default class RelatedContent extends React.PureComponent {
|
||||||
<ClaimResultItem
|
<ClaimResultItem
|
||||||
style={fileListStyle.item}
|
style={fileListStyle.item}
|
||||||
uri={result ? normalizeURI(`${result.name}#${result.claimId}`) : null}
|
uri={result ? normalizeURI(`${result.name}#${result.claimId}`) : null}
|
||||||
urlOpenHandler={urlOpenHandler}
|
|
||||||
key={result.claimId}
|
key={result.claimId}
|
||||||
result={result}
|
result={result}
|
||||||
navigation={navigation}
|
navigation={navigation}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native';
|
import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import { formatUsd } from 'utils/helper';
|
import Colors from '../../styles/colors';
|
||||||
import Colors from 'styles/colors';
|
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from 'component/link';
|
import Link from '../link';
|
||||||
import rewardStyle from 'styles/reward';
|
import rewardStyle from '../../styles/reward';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
canClaim: boolean,
|
canClaim: boolean,
|
||||||
|
@ -62,7 +61,7 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
if (reward) {
|
if (reward) {
|
||||||
const claimed = !!reward.transaction_id;
|
const claimed = !!reward.transaction_id;
|
||||||
if (!claimed && reward.reward_range && reward.reward_range.includes('-')) {
|
if (!claimed && reward.reward_range && reward.reward_range.includes('-')) {
|
||||||
return reward.reward_range.split('-')[1];
|
return reward.reward_range.split('-')[0] + '+'; // ex: 5+
|
||||||
} else if (reward.reward_amount > 0) {
|
} else if (reward.reward_amount > 0) {
|
||||||
return reward.reward_amount;
|
return reward.reward_amount;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +72,7 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { canClaim, isPending, onClaimPress, reward, usdExchangeRate } = this.props;
|
const { canClaim, isPending, onClaimPress, reward } = this.props;
|
||||||
const claimed = !!reward.transaction_id;
|
const claimed = !!reward.transaction_id;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -118,16 +117,8 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
<View style={rewardStyle.rightCol}>
|
<View style={rewardStyle.rightCol}>
|
||||||
{reward.reward_range && reward.reward_range.indexOf('-') > -1 && (
|
|
||||||
<Text style={rewardStyle.rightColHeader}>{__('up to')}</Text>
|
|
||||||
)}
|
|
||||||
<Text style={rewardStyle.rewardAmount}>{this.getDisplayAmount()}</Text>
|
<Text style={rewardStyle.rewardAmount}>{this.getDisplayAmount()}</Text>
|
||||||
<Text style={rewardStyle.rewardCurrency}>LBC</Text>
|
<Text style={rewardStyle.rewardCurrency}>LBC</Text>
|
||||||
{usdExchangeRate > 0 && (
|
|
||||||
<Text style={rewardStyle.rewardUsd}>
|
|
||||||
≈{formatUsd(parseFloat(this.getDisplayAmount()) * parseFloat(usdExchangeRate))}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,7 +7,6 @@ import Link from 'component/link';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import rewardStyle from 'styles/reward';
|
import rewardStyle from 'styles/reward';
|
||||||
import { formatUsd } from '../../utils/helper';
|
|
||||||
|
|
||||||
class RewardEnrolment extends React.Component {
|
class RewardEnrolment extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -30,7 +29,7 @@ class RewardEnrolment extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { unclaimedRewardAmount, usdExchangeRate } = this.props;
|
const { fetching, navigation, unclaimedRewardAmount, user } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={rewardStyle.enrollContainer}>
|
<View style={rewardStyle.enrollContainer}>
|
||||||
|
@ -44,11 +43,9 @@ class RewardEnrolment extends React.Component {
|
||||||
|
|
||||||
<View style={rewardStyle.onboarding}>
|
<View style={rewardStyle.onboarding}>
|
||||||
<Text style={rewardStyle.enrollDescText}>
|
<Text style={rewardStyle.enrollDescText}>
|
||||||
{__('LBRY credits allow you to publish or purchase content.')}
|
{__('LBRY credits allow you to purchase content, publish content, and influence the network.')}
|
||||||
{'\n\n'}
|
{'\n\n'}
|
||||||
{__('You can obtain free credits worth %amount% after you provide an email address.', {
|
{__('You get credits for free for providing an email address and taking other basic actions.')}
|
||||||
amount: formatUsd(parseFloat(unclaimedRewardAmount) * parseFloat(usdExchangeRate)),
|
|
||||||
})}
|
|
||||||
{'\n\n'}
|
{'\n\n'}
|
||||||
<Link style={rewardStyle.learnMoreLink} text={__('Learn more')} onPress={this.onLearnMorePressed} />.
|
<Link style={rewardStyle.learnMoreLink} text={__('Learn more')} onPress={this.onLearnMorePressed} />.
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import SdkLoadingStatus from './view';
|
|
||||||
|
|
||||||
export default connect()(SdkLoadingStatus);
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { ActivityIndicator, Text, View } from 'react-native';
|
|
||||||
import React from 'react';
|
|
||||||
import discoverStyle from 'styles/discover';
|
|
||||||
import Colors from 'styles/colors';
|
|
||||||
|
|
||||||
export default class SdkLoadingStatus extends React.PureComponent {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<View style={discoverStyle.sdkLoading}>
|
|
||||||
<ActivityIndicator color={Colors.White} size={'small'} />
|
|
||||||
<Text style={discoverStyle.sdkLoadingText}>{__('The LBRY background service is initializing...')}</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
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);
|
|
|
@ -1,36 +0,0 @@
|
||||||
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,7 +6,6 @@ import {
|
||||||
makeSelectTitleForUri,
|
makeSelectTitleForUri,
|
||||||
makeSelectIsUriResolving,
|
makeSelectIsUriResolving,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doChannelSubscribe, doChannelUnsubscribe, makeSelectIsSubscribed } from 'lbryinc';
|
|
||||||
import SuggestedSubscriptionItem from './view';
|
import SuggestedSubscriptionItem from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
@ -14,13 +13,13 @@ const select = (state, props) => ({
|
||||||
title: makeSelectTitleForUri(props.uri)(state),
|
title: makeSelectTitleForUri(props.uri)(state),
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
||||||
isSubscribed: makeSelectIsSubscribed(props.uri, true)(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||||
subscribe: subscription => doChannelSubscribe(subscription),
|
|
||||||
unsubscribe: subscription => doChannelUnsubscribe(subscription),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(SuggestedSubscriptionItem);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(SuggestedSubscriptionItem);
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { buildURI, normalizeURI } from 'lbry-redux';
|
import { buildURI, normalizeURI } from 'lbry-redux';
|
||||||
import { ActivityIndicator, FlatList, Image, Text, TouchableOpacity, View } from 'react-native';
|
import { ActivityIndicator, FlatList, Image, Text, View } from 'react-native';
|
||||||
import { navigateToUri } from 'utils/helper';
|
import { navigateToUri } from 'utils/helper';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import ChannelIconItem from 'component/channelIconItem';
|
import ChannelIconItem from 'component/channelIconItem';
|
||||||
import channelIconStyle from 'styles/channelIcon';
|
import channelIconStyle from 'styles/channelIcon';
|
||||||
import discoverStyle from 'styles/discover';
|
import discoverStyle from 'styles/discover';
|
||||||
import FileItem from 'component/fileItem';
|
import FileItem from 'component/fileItem';
|
||||||
import SubscribeButtonOverlay from 'component/subscribeButtonOverlay';
|
import SubscribeButton from 'component/subscribeButton';
|
||||||
import subscriptionsStyle from 'styles/subscriptions';
|
import subscriptionsStyle from 'styles/subscriptions';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import Tag from 'component/tag';
|
import Tag from 'component/tag';
|
||||||
|
@ -31,7 +31,6 @@ class SuggestedSubscriptionItem extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claim, isResolvingUri, navigation, thumbnail, title, uri } = this.props;
|
const { claim, isResolvingUri, navigation, thumbnail, title, uri } = this.props;
|
||||||
|
|
||||||
let shortUrl, tags;
|
let shortUrl, tags;
|
||||||
if (claim) {
|
if (claim) {
|
||||||
shortUrl = claim.short_url;
|
shortUrl = claim.short_url;
|
||||||
|
@ -50,7 +49,7 @@ class SuggestedSubscriptionItem extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={subscriptionsStyle.suggestedItem}>
|
<View style={subscriptionsStyle.suggestedItem}>
|
||||||
<View style={[subscriptionsStyle.suggestedItemThumbnailContainer, this.state.autoStyle]}>
|
<View style={[subscriptionsStyle.suggestedItemThumbnailContainer, this.state.autoStyle]}>
|
||||||
{hasThumbnail && (
|
{hasThumbnail && (
|
||||||
<Image style={subscriptionsStyle.suggestedItemThumbnail} resizeMode={'cover'} source={{ uri: thumbnail }} />
|
<Image style={subscriptionsStyle.suggestedItemThumbnail} resizeMode={'cover'} source={{ uri: thumbnail }} />
|
||||||
|
@ -63,37 +62,35 @@ class SuggestedSubscriptionItem extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={subscriptionsStyle.suggestedItemDetails}>
|
<View style={subscriptionsStyle.suggestedItemDetails}>
|
||||||
<Text style={subscriptionsStyle.suggestedItemTitle} numberOfLines={2}>
|
{title && (
|
||||||
{title || claim.name}
|
<Text style={subscriptionsStyle.suggestedItemTitle} numberOfLines={1}>
|
||||||
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
|
)}
|
||||||
|
{claim && (
|
||||||
|
<Link
|
||||||
|
style={subscriptionsStyle.suggestedItemName}
|
||||||
|
numberOfLines={1}
|
||||||
|
text={claim.name}
|
||||||
|
onPress={() => navigateToUri(navigation, normalizeURI(shortUrl || uri), null, false, claim.permanent_url)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{tags && (
|
{tags && (
|
||||||
<View style={subscriptionsStyle.suggestedItemTagList}>
|
<View style={subscriptionsStyle.suggestedItemTagList}>
|
||||||
{tags &&
|
{tags &&
|
||||||
tags
|
tags
|
||||||
.slice(0, 1)
|
.slice(0, 3)
|
||||||
.map(tag => (
|
.map(tag => (
|
||||||
<Tag
|
<Tag style={subscriptionsStyle.tag} key={tag} name={tag} navigation={navigation} truncate />
|
||||||
numberOfLines={1}
|
|
||||||
onPress={this.handleItemPress}
|
|
||||||
style={subscriptionsStyle.tag}
|
|
||||||
key={tag}
|
|
||||||
name={tag}
|
|
||||||
navigation={navigation}
|
|
||||||
truncate
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{claim && (
|
{claim && (
|
||||||
<SubscribeButtonOverlay
|
<SubscribeButton style={subscriptionsStyle.suggestedItemSubscribe} uri={normalizeURI(claim.permanent_url)} />
|
||||||
claim={claim}
|
|
||||||
style={subscriptionsStyle.suggestedItemSubscribeOverlay}
|
|
||||||
uri={normalizeURI(claim.permanent_url)}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</TouchableOpacity>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,7 @@ const perform = dispatch => ({
|
||||||
claimSearch: options => dispatch(doClaimSearch(options)),
|
claimSearch: options => dispatch(doClaimSearch(options)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(SuggestedSubscriptions);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(SuggestedSubscriptions);
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
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);
|
|
|
@ -1,111 +0,0 @@
|
||||||
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, 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={1}
|
|
||||||
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() {
|
render() {
|
||||||
const { name, numberOfLines, onPress, style, type, truncate } = this.props;
|
const { name, onPress, style, type, truncate } = this.props;
|
||||||
|
|
||||||
let styles = [];
|
let styles = [];
|
||||||
if (style) {
|
if (style) {
|
||||||
|
@ -50,9 +50,7 @@ export default class Tag extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={styles} onPress={onPress || this.onPressDefault}>
|
<TouchableOpacity style={styles} onPress={onPress || this.onPressDefault}>
|
||||||
<View style={tagStyle.content}>
|
<View style={tagStyle.content}>
|
||||||
<Text style={tagStyle.text} numberOfLines={numberOfLines}>
|
<Text style={tagStyle.text}>{truncate ? formatTagName(name) : name}</Text>
|
||||||
{truncate ? formatTagName(name) : name}
|
|
||||||
</Text>
|
|
||||||
{type && <Icon style={tagStyle.icon} name={type === 'add' ? 'plus' : 'times'} size={8} />}
|
{type && <Icon style={tagStyle.icon} name={type === 'add' ? 'plus' : 'times'} size={8} />}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SEARCH_TYPES, isNameValid, isURIValid, normalizeURI } from 'lbry-redux';
|
import { SEARCH_TYPES, isNameValid, isURIValid, normalizeURI } from 'lbry-redux';
|
||||||
import { Alert, Dimensions, FlatList, Keyboard, Text, TextInput, TouchableOpacity, View } from 'react-native';
|
import { Dimensions, FlatList, Keyboard, Text, TextInput, TouchableOpacity, View } from 'react-native';
|
||||||
import { navigateToUri, transformUrl } from 'utils/helper';
|
import { navigateToUri, transformUrl } from 'utils/helper';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import UriBarItem from './internal/uri-bar-item';
|
import UriBarItem from './internal/uri-bar-item';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import NavigationButton from 'component/navigationButton';
|
import NavigationButton from 'component/navigationButton';
|
||||||
import uriBarStyle from 'styles/uriBar';
|
import uriBarStyle from 'styles/uriBar';
|
||||||
import { NavigationActions, StackActions } from 'react-navigation';
|
|
||||||
|
|
||||||
class UriBar extends React.PureComponent {
|
class UriBar extends React.PureComponent {
|
||||||
static INPUT_TIMEOUT = 2500; // 2.5 seconds
|
static INPUT_TIMEOUT = 2500; // 2.5 seconds
|
||||||
|
@ -184,33 +183,6 @@ class UriBar extends React.PureComponent {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleNavigationButtonPress = () => {
|
|
||||||
const { navigation } = this.props;
|
|
||||||
if (!navigation.openDrawer) {
|
|
||||||
Alert.alert(
|
|
||||||
__('Stop watching?'),
|
|
||||||
'The LBRY service is still loading stuff in the background. Would you like to continue?',
|
|
||||||
[
|
|
||||||
{ text: __('No') },
|
|
||||||
{
|
|
||||||
text: __('Yes'),
|
|
||||||
onPress: () => {
|
|
||||||
const resetAction = StackActions.reset({
|
|
||||||
index: 0,
|
|
||||||
actions: [
|
|
||||||
NavigationActions.navigate({ routeName: 'Splash', params: { resetUrl: 'lbry://?subscriptions' } }),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
navigation.dispatch(resetAction);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
navigation.openDrawer();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
allowEdit,
|
allowEdit,
|
||||||
|
@ -290,7 +262,7 @@ class UriBar extends React.PureComponent {
|
||||||
size={24}
|
size={24}
|
||||||
style={uriBarStyle.drawerMenuButton}
|
style={uriBarStyle.drawerMenuButton}
|
||||||
iconStyle={uriBarStyle.drawerHamburger}
|
iconStyle={uriBarStyle.drawerHamburger}
|
||||||
onPress={this.handleNavigationButtonPress}
|
onPress={() => navigation.openDrawer()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!selectionMode && (
|
{!selectionMode && (
|
||||||
|
|
|
@ -6,4 +6,7 @@ const select = state => ({
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, null)(WalletBalance);
|
export default connect(
|
||||||
|
select,
|
||||||
|
null
|
||||||
|
)(WalletBalance);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Image, Text, View } from 'react-native';
|
import { Image, Text, View } from 'react-native';
|
||||||
import { formatCredits } from 'lbry-redux';
|
import { Lbry, formatCredits } from 'lbry-redux';
|
||||||
import { Lbryio } from 'lbryinc';
|
import Address from 'component/address';
|
||||||
import { formatUsd } from 'utils/helper';
|
import Button from 'component/button';
|
||||||
import walletStyle from 'styles/wallet';
|
import walletStyle from 'styles/wallet';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -11,18 +11,6 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class WalletBalance extends React.PureComponent<Props> {
|
class WalletBalance extends React.PureComponent<Props> {
|
||||||
state = {
|
|
||||||
usdExchangeRate: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
Lbryio.getExchangeRates().then(rates => {
|
|
||||||
if (!isNaN(rates.LBC_USD)) {
|
|
||||||
this.setState({ usdExchangeRate: rates.LBC_USD });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { balance } = this.props;
|
const { balance } = this.props;
|
||||||
return (
|
return (
|
||||||
|
@ -33,13 +21,6 @@ class WalletBalance extends React.PureComponent<Props> {
|
||||||
<Text style={walletStyle.balance}>
|
<Text style={walletStyle.balance}>
|
||||||
{(balance || balance === 0) && formatCredits(parseFloat(balance), 2) + ' LBC'}
|
{(balance || balance === 0) && formatCredits(parseFloat(balance), 2) + ' LBC'}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={walletStyle.usdBalance}>
|
|
||||||
{this.state.usdExchangeRate > 0 && (
|
|
||||||
<Text>
|
|
||||||
≈{formatUsd(isNaN(balance) ? 0 : parseFloat(balance) * parseFloat(this.state.usdExchangeRate))}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectClaimsBalance, selectSupportsBalance, selectTipsBalance } from 'lbry-redux';
|
import { selectClaimsBalance, selectSupportsBalance, selectTipsBalance } from 'lbry-redux';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
|
||||||
import WalletBalanceExtra from './view';
|
import WalletBalanceExtra from './view';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
claimsBalance: selectClaimsBalance(state) || 0,
|
claimsBalance: selectClaimsBalance(state) || 0,
|
||||||
deviceWalletSynced: makeSelectClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED)(state),
|
|
||||||
supportsBalance: selectSupportsBalance(state) || 0,
|
supportsBalance: selectSupportsBalance(state) || 0,
|
||||||
tipsBalance: selectTipsBalance(state) || 0,
|
tipsBalance: selectTipsBalance(state) || 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, null)(WalletBalanceExtra);
|
export default connect(
|
||||||
|
select,
|
||||||
|
null,
|
||||||
|
)(WalletBalanceExtra);
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, View } from 'react-native';
|
import { Image, Text, View } from 'react-native';
|
||||||
import { formatCredits } from 'lbry-redux';
|
import { Lbry, formatCredits } from 'lbry-redux';
|
||||||
import { Lbryio } from 'lbryinc';
|
import Address from 'component/address';
|
||||||
import { formatUsd } from 'utils/helper';
|
import Button from 'component/button';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from 'component/link';
|
|
||||||
import walletStyle from 'styles/wallet';
|
import walletStyle from 'styles/wallet';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claimsBalance: number,
|
claimsBalance: number,
|
||||||
|
@ -17,40 +15,10 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class WalletBalanceExtra extends React.PureComponent<Props> {
|
class WalletBalanceExtra extends React.PureComponent<Props> {
|
||||||
state = {
|
|
||||||
usdExchangeRate: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
Lbryio.getExchangeRates().then(rates => {
|
|
||||||
if (!isNaN(rates.LBC_USD)) {
|
|
||||||
this.setState({ usdExchangeRate: rates.LBC_USD });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claimsBalance, deviceWalletSynced, navigation, supportsBalance, tipsBalance } = this.props;
|
const { claimsBalance, supportsBalance, tipsBalance } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={walletStyle.balanceExtra}>
|
|
||||||
<View style={walletStyle.usdInfoCard}>
|
|
||||||
<Text style={walletStyle.usdInfoText}>
|
|
||||||
You can convert your credits to USD and withdraw the converted amount using an exchange.{' '}
|
|
||||||
<Link
|
|
||||||
style={walletStyle.usdConvertFaqLink}
|
|
||||||
href={'https://lbry.com/faq/exchanges'}
|
|
||||||
text={__('Learn more')}
|
|
||||||
/>
|
|
||||||
.
|
|
||||||
</Text>
|
|
||||||
<Link
|
|
||||||
style={walletStyle.usdConvertLink}
|
|
||||||
href={'https://bittrex.com/Account/Register?referralCode=4M1-P30-BON'}
|
|
||||||
text={__('Convert credits to USD on Bittrex')}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={walletStyle.balanceExtraCard}>
|
<View style={walletStyle.balanceExtraCard}>
|
||||||
<View style={walletStyle.walletExtraRow}>
|
<View style={walletStyle.walletExtraRow}>
|
||||||
<View style={walletStyle.walletExtraCol}>
|
<View style={walletStyle.walletExtraCol}>
|
||||||
|
@ -60,18 +28,7 @@ class WalletBalanceExtra extends React.PureComponent<Props> {
|
||||||
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(tipsBalance), 2)}</Text>
|
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(tipsBalance), 2)}</Text>
|
||||||
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={walletStyle.usdWalletExtraBalance}>
|
|
||||||
≈{formatUsd(parseFloat(tipsBalance) * parseFloat(this.state.usdExchangeRate))}
|
|
||||||
</Text>
|
|
||||||
<Text style={walletStyle.text}>{__('in tips')}</Text>
|
<Text style={walletStyle.text}>{__('in tips')}</Text>
|
||||||
|
|
||||||
<Link
|
|
||||||
style={walletStyle.earnTipsLink}
|
|
||||||
onPress={() => {
|
|
||||||
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_PUBLISH });
|
|
||||||
}}
|
|
||||||
text={__('Earn more tips by uploading cool videos')}
|
|
||||||
/>
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={walletStyle.walletExtraCol}>
|
<View style={walletStyle.walletExtraCol}>
|
||||||
|
@ -90,24 +47,6 @@ class WalletBalanceExtra extends React.PureComponent<Props> {
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={walletStyle.syncDriverCustody}>
|
|
||||||
<Text style={walletStyle.syncInfoText}>
|
|
||||||
{deviceWalletSynced
|
|
||||||
? __('A backup of your wallet is synced with lbry.tv')
|
|
||||||
: __('Your wallet is not currently synced with lbry.tv. You are responsible for backing up your wallet.')}
|
|
||||||
</Text>
|
|
||||||
<Link
|
|
||||||
text={__('What does this mean?')}
|
|
||||||
href={
|
|
||||||
deviceWalletSynced
|
|
||||||
? 'https://lbry.com/faq/account-sync'
|
|
||||||
: 'https://lbry.com/faq/how-to-backup-wallet#android'
|
|
||||||
}
|
|
||||||
style={walletStyle.syncInfoLink}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class WalletSyncDriver extends React.PureComponent<Props> {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
{ cancelable: true },
|
{ cancelable: true }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,10 +44,6 @@ const Constants = {
|
||||||
SETTING_BACKUP_DISMISSED: 'backupDismissed',
|
SETTING_BACKUP_DISMISSED: 'backupDismissed',
|
||||||
SETTING_REWARDS_NOT_INTERESTED: 'rewardsNotInterested',
|
SETTING_REWARDS_NOT_INTERESTED: 'rewardsNotInterested',
|
||||||
SETTING_DEVICE_WALLET_SYNCED: 'deviceWalletSynced',
|
SETTING_DEVICE_WALLET_SYNCED: 'deviceWalletSynced',
|
||||||
SETTING_DHT_ENABLED: 'dhtEnabled',
|
|
||||||
SETTING_NEW_ANDROID_REWARD_CLAIMED: 'newAndroidRewardClaimed',
|
|
||||||
|
|
||||||
ACTION_SDK_READY: 'SDK_READY',
|
|
||||||
|
|
||||||
ACTION_DELETE_COMPLETED_BLOBS: 'DELETE_COMPLETED_BLOBS',
|
ACTION_DELETE_COMPLETED_BLOBS: 'DELETE_COMPLETED_BLOBS',
|
||||||
ACTION_FIRST_RUN_PAGE_CHANGED: 'FIRST_RUN_PAGE_CHANGED',
|
ACTION_FIRST_RUN_PAGE_CHANGED: 'FIRST_RUN_PAGE_CHANGED',
|
||||||
|
@ -68,8 +64,6 @@ const Constants = {
|
||||||
ACTION_CLEAR_PUBLISH_FORM_STATE: 'CLEAR_PUBLISH_FORM_STATE',
|
ACTION_CLEAR_PUBLISH_FORM_STATE: 'CLEAR_PUBLISH_FORM_STATE',
|
||||||
ACTION_CLEAR_CHANNEL_FORM_STATE: 'CLEAR_CHANNEL_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',
|
ACTION_FULLSCREEN_MODE_TOGGLED: 'FULLSCREEN_MODE_TOGGLED',
|
||||||
|
|
||||||
ORIENTATION_HORIZONTAL: 'horizontal',
|
ORIENTATION_HORIZONTAL: 'horizontal',
|
||||||
|
@ -97,7 +91,6 @@ const Constants = {
|
||||||
DRAWER_ROUTE_CHANNEL_CREATOR: 'ChannelCreator',
|
DRAWER_ROUTE_CHANNEL_CREATOR: 'ChannelCreator',
|
||||||
DRAWER_ROUTE_CHANNEL_CREATOR_FORM: 'ChannnelCreatorForm',
|
DRAWER_ROUTE_CHANNEL_CREATOR_FORM: 'ChannnelCreatorForm',
|
||||||
DRAWER_ROUTE_INVITES: 'Invites',
|
DRAWER_ROUTE_INVITES: 'Invites',
|
||||||
DRAWER_ROUTE_LITE_FILE: 'LiteFile',
|
|
||||||
|
|
||||||
FULL_ROUTE_NAME_DISCOVER: 'DiscoverStack',
|
FULL_ROUTE_NAME_DISCOVER: 'DiscoverStack',
|
||||||
FULL_ROUTE_NAME_WALLET: 'WalletStack',
|
FULL_ROUTE_NAME_WALLET: 'WalletStack',
|
||||||
|
@ -150,7 +143,7 @@ const Constants = {
|
||||||
|
|
||||||
TRUE_STRING: 'true',
|
TRUE_STRING: 'true',
|
||||||
|
|
||||||
MINIMUM_TRANSACTION_BALANCE: 0.01,
|
MINIMUM_TRANSACTION_BALANCE: 0.1,
|
||||||
|
|
||||||
SHARE_BASE_URL: 'https://open.lbry.com',
|
SHARE_BASE_URL: 'https://open.lbry.com',
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,10 +55,6 @@ import settingsReducer from 'redux/reducers/settings';
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
|
|
||||||
window.__ = __;
|
window.__ = __;
|
||||||
if (!NativeModules.UtilityModule.dhtEnabled) {
|
|
||||||
Lbry.alternateConnectionString = 'https://api.lbry.tv/api/v1/proxy';
|
|
||||||
Lbry.methodsUsingAlternateConnectionString = ['claim_search', 'resolve'];
|
|
||||||
}
|
|
||||||
|
|
||||||
const globalExceptionHandler = (error, isFatal) => {
|
const globalExceptionHandler = (error, isFatal) => {
|
||||||
if (error && NativeModules.Firebase) {
|
if (error && NativeModules.Firebase) {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import aboutStyle from 'styles/about';
|
||||||
class AboutPage extends React.PureComponent {
|
class AboutPage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
appVersion: null,
|
appVersion: null,
|
||||||
firebaseToken: null,
|
|
||||||
lbryId: null,
|
lbryId: null,
|
||||||
versionInfo: null,
|
versionInfo: null,
|
||||||
};
|
};
|
||||||
|
@ -46,12 +45,11 @@ class AboutPage extends React.PureComponent {
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
|
|
||||||
NativeModules.Firebase.setCurrentScreen('About').then(result => {
|
NativeModules.Firebase.setCurrentScreen('About').then(result => {
|
||||||
|
if (NativeModules.VersionInfo) {
|
||||||
NativeModules.VersionInfo.getAppVersion().then(version => {
|
NativeModules.VersionInfo.getAppVersion().then(version => {
|
||||||
this.setState({ appVersion: version });
|
this.setState({ appVersion: version });
|
||||||
});
|
});
|
||||||
NativeModules.Firebase.getMessagingToken().then(firebaseToken => {
|
}
|
||||||
this.setState({ firebaseToken });
|
|
||||||
});
|
|
||||||
Lbry.version().then(info => {
|
Lbry.version().then(info => {
|
||||||
this.setState({
|
this.setState({
|
||||||
versionInfo: info,
|
versionInfo: info,
|
||||||
|
@ -79,7 +77,7 @@ class AboutPage extends React.PureComponent {
|
||||||
<Text style={aboutStyle.title}>{__('Content Freedom')}</Text>
|
<Text style={aboutStyle.title}>{__('Content Freedom')}</Text>
|
||||||
<Text style={aboutStyle.paragraph}>
|
<Text style={aboutStyle.paragraph}>
|
||||||
{__(
|
{__(
|
||||||
'LBRY is a free, open, and community-run digital marketplace. It is a decentralized peer-to-peer content distribution platform for creators to upload and share content, and earn LBRY credits for their effort. Users will be able to find a wide selection of videos, music, ebooks and other digital content they are interested in.',
|
'LBRY is a free, open, and community-run digital marketplace. It is a decentralized peer-to-peer content distribution platform for creators to upload and share content, and earn LBRY credits for their effort. Users will be able to find a wide selection of videos, music, ebooks and other digital content they are interested in.'
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
<View style={aboutStyle.links}>
|
<View style={aboutStyle.links}>
|
||||||
|
@ -90,7 +88,7 @@ class AboutPage extends React.PureComponent {
|
||||||
<Text style={aboutStyle.socialTitle}>{__('Get Social')}</Text>
|
<Text style={aboutStyle.socialTitle}>{__('Get Social')}</Text>
|
||||||
<Text style={aboutStyle.paragraph}>
|
<Text style={aboutStyle.paragraph}>
|
||||||
{__(
|
{__(
|
||||||
'You can interact with the LBRY team and members of the community on Discord, Facebook, Instagram, Twitter or Reddit.',
|
'You can interact with the LBRY team and members of the community on Discord, Facebook, Instagram, Twitter or Reddit.'
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
<View style={aboutStyle.links}>
|
<View style={aboutStyle.links}>
|
||||||
|
@ -166,15 +164,6 @@ class AboutPage extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={aboutStyle.row}>
|
|
||||||
<View style={aboutStyle.col}>
|
|
||||||
<Text style={aboutStyle.text}>{__('Firebase Token')}</Text>
|
|
||||||
<Text selectable style={aboutStyle.lineValueText}>
|
|
||||||
{this.state.firebaseToken ? this.state.firebaseToken : loading}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={aboutStyle.row}>
|
<View style={aboutStyle.row}>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text style={aboutStyle.text}>{__('Logs')}</Text>
|
<Text style={aboutStyle.text}>{__('Logs')}</Text>
|
||||||
|
|
|
@ -18,7 +18,7 @@ const select = (state, props) => ({
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
abandonClaim: (txid, nout) => dispatch(doAbandonClaim(txid, nout)),
|
abandonClaim: (txid, nout) => dispatch(doAbandonClaim(txid, nout)),
|
||||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||||
fetchSubCount: claimId => dispatch(doFetchSubCount(claimId)),
|
fetchSubCount: claimId => dispatch(doFetchSubCount(claimId)),
|
||||||
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
||||||
setSortByItem: item => dispatch(doSetSortByItem(item)),
|
setSortByItem: item => dispatch(doSetSortByItem(item)),
|
||||||
|
@ -27,5 +27,5 @@ const perform = dispatch => ({
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
select,
|
select,
|
||||||
perform,
|
perform
|
||||||
)(ChannelPage);
|
)(ChannelPage);
|
||||||
|
|
|
@ -173,10 +173,9 @@ class ChannelPage extends React.PureComponent {
|
||||||
const { permanent_url: permanentUrl } = claim;
|
const { permanent_url: permanentUrl } = claim;
|
||||||
navigation.navigate({
|
navigation.navigate({
|
||||||
routeName: Constants.DRAWER_ROUTE_CHANNEL_CREATOR,
|
routeName: Constants.DRAWER_ROUTE_CHANNEL_CREATOR,
|
||||||
params: { editChannelUrl: permanentUrl, returnUrl: permanentUrl },
|
params: { editChannelUrl: permanentUrl },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.onEditPressed = null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onTipPressed = () => {
|
onTipPressed = () => {
|
||||||
|
@ -211,7 +210,7 @@ class ChannelPage extends React.PureComponent {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
{ cancelable: true },
|
{ cancelable: true }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,16 +13,10 @@ import {
|
||||||
doToast,
|
doToast,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doGetSync } from 'lbryinc';
|
import { doGetSync } from 'lbryinc';
|
||||||
import {
|
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
doPushDrawerStack,
|
|
||||||
doPopDrawerStack,
|
|
||||||
doSetPlayerVisible,
|
|
||||||
doSetExplicitNavigateBack,
|
|
||||||
} from 'redux/actions/drawer';
|
|
||||||
import { doUpdateChannelFormState, doClearChannelFormState } from 'redux/actions/form';
|
import { doUpdateChannelFormState, doClearChannelFormState } from 'redux/actions/form';
|
||||||
import { selectDrawerStack } from 'redux/selectors/drawer';
|
import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||||
import { selectChannelFormState, selectHasChannelFormState } from 'redux/selectors/form';
|
import { selectChannelFormState, selectHasChannelFormState } from 'redux/selectors/form';
|
||||||
import { selectSdkReady } from 'redux/selectors/settings';
|
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import ChannelCreator from './view';
|
import ChannelCreator from './view';
|
||||||
|
|
||||||
|
@ -34,7 +28,6 @@ const select = state => ({
|
||||||
fetchingChannels: selectFetchingMyChannels(state),
|
fetchingChannels: selectFetchingMyChannels(state),
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
hasFormState: selectHasChannelFormState(state),
|
hasFormState: selectHasChannelFormState(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
updatingChannel: selectUpdatingChannel(state),
|
updatingChannel: selectUpdatingChannel(state),
|
||||||
updateChannelError: selectUpdateChannelError(state),
|
updateChannelError: selectUpdateChannelError(state),
|
||||||
});
|
});
|
||||||
|
@ -44,14 +37,16 @@ const perform = dispatch => ({
|
||||||
notify: data => dispatch(doToast(data)),
|
notify: data => dispatch(doToast(data)),
|
||||||
clearChannelFormState: () => dispatch(doClearChannelFormState()),
|
clearChannelFormState: () => dispatch(doClearChannelFormState()),
|
||||||
createChannel: (name, amount, optionalParams) => dispatch(doCreateChannel(name, amount, optionalParams)),
|
createChannel: (name, amount, optionalParams) => dispatch(doCreateChannel(name, amount, optionalParams)),
|
||||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||||
getSync: (password, callback) => dispatch(doGetSync(password, callback)),
|
getSync: (password, callback) => dispatch(doGetSync(password, callback)),
|
||||||
updateChannel: params => dispatch(doUpdateChannel(params)),
|
updateChannel: params => dispatch(doUpdateChannel(params)),
|
||||||
updateChannelFormState: data => dispatch(doUpdateChannelFormState(data)),
|
updateChannelFormState: data => dispatch(doUpdateChannelFormState(data)),
|
||||||
pushDrawerStack: (routeName, params) => dispatch(doPushDrawerStack(routeName, params)),
|
pushDrawerStack: (routeName, params) => dispatch(doPushDrawerStack(routeName, params)),
|
||||||
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
setExplicitNavigateBack: flag => dispatch(doSetExplicitNavigateBack(flag)),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(ChannelCreator);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(ChannelCreator);
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { navigateBack, navigateToUri, logPublish, uploadImageAsset } from 'utils/helper';
|
import { navigateToUri, logPublish, uploadImageAsset } from 'utils/helper';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import ChannelIconItem from 'component/channelIconItem';
|
import ChannelIconItem from 'component/channelIconItem';
|
||||||
import ChannelRewardsDriver from 'component/channelRewardsDriver';
|
import ChannelRewardsDriver from 'component/channelRewardsDriver';
|
||||||
|
@ -37,7 +37,6 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
autoStyle: null,
|
autoStyle: null,
|
||||||
returnUrl: null,
|
|
||||||
canSave: true,
|
canSave: true,
|
||||||
claimId: null,
|
claimId: null,
|
||||||
creditsInputFocused: false,
|
creditsInputFocused: false,
|
||||||
|
@ -47,7 +46,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
channelNameUserEdited: false,
|
channelNameUserEdited: false,
|
||||||
newChannelTitle: '',
|
newChannelTitle: '',
|
||||||
newChannelName: '',
|
newChannelName: '',
|
||||||
newChannelBid: 0.01,
|
newChannelBid: 0.1,
|
||||||
addingChannel: false,
|
addingChannel: false,
|
||||||
creatingChannel: false,
|
creatingChannel: false,
|
||||||
editChannelUrl: null,
|
editChannelUrl: null,
|
||||||
|
@ -78,7 +77,6 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
descriptionFocused: false,
|
descriptionFocused: false,
|
||||||
websiteFocused: false,
|
websiteFocused: false,
|
||||||
emailFocused: false,
|
emailFocused: false,
|
||||||
hasReturnedBack: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
didFocusListener;
|
didFocusListener;
|
||||||
|
@ -120,14 +118,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const {
|
const { currentRoute: prevRoute, drawerStack: prevDrawerStack, notify } = this.props;
|
||||||
currentRoute: prevRoute,
|
|
||||||
drawerStack: prevDrawerStack,
|
|
||||||
popDrawerStack,
|
|
||||||
setPlayerVisible,
|
|
||||||
navigation,
|
|
||||||
notify,
|
|
||||||
} = this.props;
|
|
||||||
const { currentRoute, drawerStack, updatingChannel, updateChannelError } = nextProps;
|
const { currentRoute, drawerStack, updatingChannel, updateChannelError } = nextProps;
|
||||||
|
|
||||||
if (Constants.DRAWER_ROUTE_CHANNEL_CREATOR === currentRoute && currentRoute !== prevRoute) {
|
if (Constants.DRAWER_ROUTE_CHANNEL_CREATOR === currentRoute && currentRoute !== prevRoute) {
|
||||||
|
@ -151,11 +142,6 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
) {
|
) {
|
||||||
// navigated back from the form
|
// navigated back from the form
|
||||||
this.setState({ currentPhase: Constants.PHASE_LIST });
|
this.setState({ currentPhase: Constants.PHASE_LIST });
|
||||||
if (!this.state.hasReturnedBack && this.state.returnUrl) {
|
|
||||||
this.setState({ hasReturnedBack: true }, () => {
|
|
||||||
navigateBack(navigation, drawerStack, popDrawerStack, setPlayerVisible);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,19 +162,20 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
NativeModules.Firebase.setCurrentScreen('Channels').then(result => {
|
NativeModules.Firebase.setCurrentScreen('Channels').then(result => {
|
||||||
pushDrawerStack(Constants.DRAWER_ROUTE_CHANNEL_CREATOR, navigation.state.params ? navigation.state.params : null);
|
pushDrawerStack(Constants.DRAWER_ROUTE_CHANNEL_CREATOR, navigation.state.params ? navigation.state.params : null);
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
|
if (!fetchingChannels) {
|
||||||
fetchChannelListMine();
|
fetchChannelListMine();
|
||||||
|
}
|
||||||
|
|
||||||
DeviceEventEmitter.addListener('onDocumentPickerFilePicked', this.onFilePicked);
|
DeviceEventEmitter.addListener('onDocumentPickerFilePicked', this.onFilePicked);
|
||||||
DeviceEventEmitter.addListener('onDocumentPickerCanceled', this.onPickerCanceled);
|
DeviceEventEmitter.addListener('onDocumentPickerCanceled', this.onPickerCanceled);
|
||||||
|
|
||||||
let isEditMode = false;
|
let isEditMode = false;
|
||||||
if (navigation.state.params) {
|
if (navigation.state.params) {
|
||||||
const { editChannelUrl, displayForm, returnUrl } = navigation.state.params;
|
const { editChannelUrl, displayForm } = navigation.state.params;
|
||||||
if (editChannelUrl) {
|
if (editChannelUrl) {
|
||||||
isEditMode = true;
|
isEditMode = true;
|
||||||
this.setState({ editChannelUrl, currentPhase: Constants.PHASE_CREATE });
|
this.setState({ editChannelUrl, currentPhase: Constants.PHASE_CREATE });
|
||||||
}
|
}
|
||||||
this.setState({ returnUrl });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEditMode && hasFormState) {
|
if (!isEditMode && hasFormState) {
|
||||||
|
@ -280,7 +267,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
handleCreateCancel = () => {
|
handleCreateCancel = () => {
|
||||||
const { clearChannelFormState } = this.props;
|
const { clearChannelFormState } = this.props;
|
||||||
clearChannelFormState(); // explicitly clear state on cancel?
|
clearChannelFormState(); // explicitly clear state on cancel?
|
||||||
this.setState({ showCreateChannel: false, newChannelName: '', newChannelBid: 0.01 });
|
this.setState({ showCreateChannel: false, newChannelName: '', newChannelBid: 0.1 });
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePickerValueChange = (itemValue, itemIndex) => {
|
handlePickerValueChange = (itemValue, itemIndex) => {
|
||||||
|
@ -589,7 +576,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
channelNameUserEdited: false,
|
channelNameUserEdited: false,
|
||||||
newChannelTitle: '',
|
newChannelTitle: '',
|
||||||
newChannelName: '',
|
newChannelName: '',
|
||||||
newChannelBid: 0.01,
|
newChannelBid: 0.1,
|
||||||
addingChannel: false,
|
addingChannel: false,
|
||||||
creatingChannel: false,
|
creatingChannel: false,
|
||||||
newChannelNameError: '',
|
newChannelNameError: '',
|
||||||
|
@ -800,15 +787,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { abandoningClaimIds, balance, fetchingChannels, updatingChannel, channels = [], navigation } = this.props;
|
||||||
abandoningClaimIds,
|
|
||||||
balance,
|
|
||||||
fetchingChannels,
|
|
||||||
sdkReady,
|
|
||||||
updatingChannel,
|
|
||||||
channels = [],
|
|
||||||
navigation,
|
|
||||||
} = this.props;
|
|
||||||
const {
|
const {
|
||||||
autoStyle,
|
autoStyle,
|
||||||
autoStyles,
|
autoStyles,
|
||||||
|
@ -832,19 +811,6 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
|
|
||||||
const hasChannels = channels && channels.length > 0;
|
const hasChannels = channels && channels.length > 0;
|
||||||
|
|
||||||
if (!sdkReady) {
|
|
||||||
return (
|
|
||||||
<View style={channelCreatorStyle.container}>
|
|
||||||
<UriBar navigation={navigation} />
|
|
||||||
<EmptyStateView
|
|
||||||
message={__(
|
|
||||||
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={channelCreatorStyle.container}>
|
<View style={channelCreatorStyle.container}>
|
||||||
<UriBar
|
<UriBar
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doSetClientSetting, doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
import { doSetClientSetting, doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
||||||
import { makeSelectClientSetting, selectSdkReady, selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import DiscoverPage from './view';
|
import DiscoverPage from './view';
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ const select = state => ({
|
||||||
followedTags: selectFollowedTags(state),
|
followedTags: selectFollowedTags(state),
|
||||||
ratingReminderDisabled: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED)(state),
|
ratingReminderDisabled: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED)(state),
|
||||||
ratingReminderLastShown: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_LAST_SHOWN)(state),
|
ratingReminderLastShown: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_LAST_SHOWN)(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
sortByItem: selectSortByItem(state),
|
sortByItem: selectSortByItem(state),
|
||||||
timeItem: selectTimeItem(state),
|
timeItem: selectTimeItem(state),
|
||||||
unreadSubscriptions: selectUnreadSubscriptions(state),
|
unreadSubscriptions: selectUnreadSubscriptions(state),
|
||||||
|
@ -47,4 +46,7 @@ const perform = dispatch => ({
|
||||||
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(DiscoverPage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(DiscoverPage);
|
||||||
|
|
|
@ -23,7 +23,6 @@ import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import ModalTagSelector from 'component/modalTagSelector';
|
import ModalTagSelector from 'component/modalTagSelector';
|
||||||
import ModalPicker from 'component/modalPicker';
|
import ModalPicker from 'component/modalPicker';
|
||||||
import SdkLoadingStatus from 'component/sdkLoadingStatus';
|
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
@ -38,6 +37,29 @@ class DiscoverPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
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;
|
const { sortByItem, fetchRewardedContent, fileList, followedTags } = this.props;
|
||||||
|
|
||||||
this.buildTagCollection(followedTags);
|
this.buildTagCollection(followedTags);
|
||||||
|
@ -64,8 +86,8 @@ class DiscoverPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
onComponentFocused = () => {
|
onComponentFocused = () => {
|
||||||
const { pushDrawerStack, setPlayerVisible, currentRoute } = this.props;
|
const { pushDrawerStack, setPlayerVisible } = this.props;
|
||||||
pushDrawerStack();
|
// pushDrawerStack();
|
||||||
|
|
||||||
NativeModules.Firebase.setCurrentScreen('Your tags');
|
NativeModules.Firebase.setCurrentScreen('Your tags');
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
|
@ -269,8 +291,8 @@ class DiscoverPage extends React.PureComponent {
|
||||||
);
|
);
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { currentRoute, navigation, sdkReady, sortByItem, timeItem } = this.props;
|
const { currentRoute, navigation, sortByItem, timeItem } = this.props;
|
||||||
const { showModalTagSelector, showSortPicker, showTimePicker } = this.state;
|
const { orderBy, showModalTagSelector, showSortPicker, showTimePicker } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={discoverStyle.container}>
|
<View style={discoverStyle.container}>
|
||||||
|
@ -290,7 +312,7 @@ class DiscoverPage extends React.PureComponent {
|
||||||
keyExtractor={(item, index) => item}
|
keyExtractor={(item, index) => item}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{sdkReady && !showModalTagSelector && !showSortPicker && !showTimePicker && (
|
{!showModalTagSelector && !showSortPicker && !showTimePicker && (
|
||||||
<FloatingWalletBalance navigation={navigation} />
|
<FloatingWalletBalance navigation={navigation} />
|
||||||
)}
|
)}
|
||||||
{showModalTagSelector && (
|
{showModalTagSelector && (
|
||||||
|
@ -317,8 +339,6 @@ class DiscoverPage extends React.PureComponent {
|
||||||
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!sdkReady && <SdkLoadingStatus />}
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,17 +11,15 @@ import {
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doDeleteFile } from 'redux/actions/file';
|
import { doDeleteFile } from 'redux/actions/file';
|
||||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||||
import { selectSdkReady } from 'redux/selectors/settings';
|
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import DownloadsPage from './view';
|
import DownloadsPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
claims: selectMyClaimsWithoutChannels(state),
|
claims: selectMyClaimsWithoutChannels(state),
|
||||||
currentRoute: selectCurrentRoute(state),
|
currentRoute: selectCurrentRoute(state),
|
||||||
downloadedUris: selectDownloadedUris(state),
|
|
||||||
fileInfos: selectFileInfosDownloaded(state),
|
fileInfos: selectFileInfosDownloaded(state),
|
||||||
|
downloadedUris: selectDownloadedUris(state),
|
||||||
fetching: selectIsFetchingFileList(state) || selectIsFetchingClaimListMine(state),
|
fetching: selectIsFetchingFileList(state) || selectIsFetchingClaimListMine(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -34,4 +32,7 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(DownloadsPage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(DownloadsPage);
|
||||||
|
|
|
@ -144,24 +144,11 @@ class DownloadsPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { downloadedUris, fetching, navigation, sdkReady } = this.props;
|
const { fetching, claims, downloadedUris, fileInfos, navigation } = this.props;
|
||||||
const { selectionMode, selectedUris } = this.state;
|
const { selectionMode, selectedUris } = this.state;
|
||||||
const filteredUris = this.getFilteredUris();
|
const filteredUris = this.getFilteredUris();
|
||||||
const hasDownloads = filteredUris && filteredUris.length > 0;
|
const hasDownloads = filteredUris && filteredUris.length > 0;
|
||||||
|
|
||||||
if (!sdkReady) {
|
|
||||||
return (
|
|
||||||
<View style={downloadsStyle.container}>
|
|
||||||
<UriBar navigation={navigation} />
|
|
||||||
<EmptyStateView
|
|
||||||
message={__(
|
|
||||||
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={downloadsStyle.container}>
|
<View style={downloadsStyle.container}>
|
||||||
<UriBar
|
<UriBar
|
||||||
|
|
|
@ -41,7 +41,6 @@ import { doDeleteFile, doStopDownloadingFile } from 'redux/actions/file';
|
||||||
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doToggleFullscreenMode } from 'redux/actions/settings';
|
import { doToggleFullscreenMode } from 'redux/actions/settings';
|
||||||
import { selectDrawerStack, makeSelectPlayerVisible } from 'redux/selectors/drawer';
|
import { selectDrawerStack, makeSelectPlayerVisible } from 'redux/selectors/drawer';
|
||||||
import { selectSdkReady } from 'redux/selectors/settings';
|
|
||||||
import FilePage from './view';
|
import FilePage from './view';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
|
@ -67,7 +66,6 @@ const select = (state, props) => {
|
||||||
failedPurchaseUris: selectFailedPurchaseUris(state),
|
failedPurchaseUris: selectFailedPurchaseUris(state),
|
||||||
myClaimUris: selectMyClaimUrisWithoutChannels(state),
|
myClaimUris: selectMyClaimUrisWithoutChannels(state),
|
||||||
purchaseUriErrorMessage: selectPurchaseUriErrorMessage(state),
|
purchaseUriErrorMessage: selectPurchaseUriErrorMessage(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
streamingUrl: makeSelectStreamingUrlForUri(contentUri)(state),
|
streamingUrl: makeSelectStreamingUrlForUri(contentUri)(state),
|
||||||
thumbnail: makeSelectThumbnailForUri(contentUri)(state),
|
thumbnail: makeSelectThumbnailForUri(contentUri)(state),
|
||||||
title: makeSelectTitleForUri(contentUri)(state),
|
title: makeSelectTitleForUri(contentUri)(state),
|
||||||
|
@ -84,7 +82,7 @@ const perform = dispatch => ({
|
||||||
fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)),
|
fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)),
|
||||||
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
|
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
|
||||||
fetchMyClaims: () => dispatch(doFetchClaimListMine()),
|
fetchMyClaims: () => dispatch(doFetchClaimListMine()),
|
||||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||||
fetchViewCount: claimId => dispatch(doFetchViewCount(claimId)),
|
fetchViewCount: claimId => dispatch(doFetchViewCount(claimId)),
|
||||||
fileGet: (uri, saveFile) => dispatch(doFileGet(uri, saveFile)),
|
fileGet: (uri, saveFile) => dispatch(doFileGet(uri, saveFile)),
|
||||||
notify: data => dispatch(doToast(data)),
|
notify: data => dispatch(doToast(data)),
|
||||||
|
@ -101,4 +99,7 @@ const perform = dispatch => ({
|
||||||
toggleFullscreenMode: mode => dispatch(doToggleFullscreenMode(mode)),
|
toggleFullscreenMode: mode => dispatch(doToggleFullscreenMode(mode)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(FilePage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(FilePage);
|
||||||
|
|
|
@ -37,13 +37,13 @@ import FilePrice from 'component/filePrice';
|
||||||
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import MediaPlayer from 'component/mediaPlayer';
|
import MediaPlayer from 'component/mediaPlayer';
|
||||||
import ModalRepostView from 'component/modalRepostView';
|
|
||||||
import ModalTipView from 'component/modalTipView';
|
import ModalTipView from 'component/modalTipView';
|
||||||
import ProgressCircle from 'react-native-progress-circle';
|
import ProgressCircle from 'react-native-progress-circle';
|
||||||
import RelatedContent from 'component/relatedContent';
|
import RelatedContent from 'component/relatedContent';
|
||||||
import SubscribeButton from 'component/subscribeButton';
|
import SubscribeButton from 'component/subscribeButton';
|
||||||
import SubscribeNotificationButton from 'component/subscribeNotificationButton';
|
import SubscribeNotificationButton from 'component/subscribeNotificationButton';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
|
import Video from 'react-native-video';
|
||||||
import FileRewardsDriver from 'component/fileRewardsDriver';
|
import FileRewardsDriver from 'component/fileRewardsDriver';
|
||||||
import filePageStyle from 'styles/filePage';
|
import filePageStyle from 'styles/filePage';
|
||||||
import uriBarStyle from 'styles/uriBar';
|
import uriBarStyle from 'styles/uriBar';
|
||||||
|
@ -73,7 +73,7 @@ class FilePage extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
autoGetAttempted: false,
|
attemptAutoGet: false,
|
||||||
autoOpened: false,
|
autoOpened: false,
|
||||||
autoDownloadStarted: false,
|
autoDownloadStarted: false,
|
||||||
autoPlayMedia: false,
|
autoPlayMedia: false,
|
||||||
|
@ -95,7 +95,6 @@ class FilePage extends React.PureComponent {
|
||||||
showImageViewer: false,
|
showImageViewer: false,
|
||||||
showWebView: false,
|
showWebView: false,
|
||||||
showTipView: false,
|
showTipView: false,
|
||||||
showRepostView: false,
|
|
||||||
playbackStarted: false,
|
playbackStarted: false,
|
||||||
playerBgHeight: 0,
|
playerBgHeight: 0,
|
||||||
playerHeight: 0,
|
playerHeight: 0,
|
||||||
|
@ -105,8 +104,6 @@ class FilePage extends React.PureComponent {
|
||||||
stopDownloadConfirmed: false,
|
stopDownloadConfirmed: false,
|
||||||
streamingMode: false,
|
streamingMode: false,
|
||||||
viewCountFetched: false,
|
viewCountFetched: false,
|
||||||
isRepost: false,
|
|
||||||
uriPushedToDrawerStack: false,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,22 +114,6 @@ class FilePage extends React.PureComponent {
|
||||||
// this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
|
// 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 = () => {
|
onComponentFocused = () => {
|
||||||
StatusBar.setHidden(false);
|
StatusBar.setHidden(false);
|
||||||
NativeModules.Firebase.setCurrentScreen('File').then(result => {
|
NativeModules.Firebase.setCurrentScreen('File').then(result => {
|
||||||
|
@ -149,8 +130,6 @@ class FilePage extends React.PureComponent {
|
||||||
setPlayerVisible(true, uri);
|
setPlayerVisible(true, uri);
|
||||||
if (!isResolvingUri && !claim) resolveUri(uri);
|
if (!isResolvingUri && !claim) resolveUri(uri);
|
||||||
|
|
||||||
this.checkRepost();
|
|
||||||
|
|
||||||
this.fetchFileInfo(uri, this.props);
|
this.fetchFileInfo(uri, this.props);
|
||||||
this.fetchCostInfo(uri, this.props);
|
this.fetchCostInfo(uri, this.props);
|
||||||
|
|
||||||
|
@ -267,7 +246,6 @@ class FilePage extends React.PureComponent {
|
||||||
'playerBgHeighht',
|
'playerBgHeighht',
|
||||||
'playerHeight',
|
'playerHeight',
|
||||||
'relatedY',
|
'relatedY',
|
||||||
'showRepostView',
|
|
||||||
'showTipView',
|
'showTipView',
|
||||||
'showImageViewer',
|
'showImageViewer',
|
||||||
'showWebView',
|
'showWebView',
|
||||||
|
@ -299,27 +277,12 @@ class FilePage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState) {
|
componentDidUpdate(prevProps, prevState) {
|
||||||
const {
|
const { claim, contentType, costInfo, fileInfo, isResolvingUri, resolveUri, navigation, title } = this.props;
|
||||||
claim,
|
|
||||||
contentType,
|
|
||||||
costInfo,
|
|
||||||
fileInfo,
|
|
||||||
isResolvingUri,
|
|
||||||
resolveUri,
|
|
||||||
sdkReady,
|
|
||||||
navigation,
|
|
||||||
title,
|
|
||||||
} = this.props;
|
|
||||||
const { uri } = this.state;
|
const { uri } = this.state;
|
||||||
if (!isResolvingUri && claim === undefined && uri) {
|
if (!isResolvingUri && claim === undefined && uri) {
|
||||||
resolveUri(uri);
|
resolveUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prevProps.claim && claim) {
|
|
||||||
this.checkRepost();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returned to the page. If mediaLoaded, and currentMediaInfo is different, update
|
// Returned to the page. If mediaLoaded, and currentMediaInfo is different, update
|
||||||
if (this.state.mediaLoaded && window.currentMediaInfo && window.currentMediaInfo.uri !== this.state.uri) {
|
if (this.state.mediaLoaded && window.currentMediaInfo && window.currentMediaInfo.uri !== this.state.uri) {
|
||||||
const { metadata } = this.props;
|
const { metadata } = this.props;
|
||||||
|
@ -335,12 +298,10 @@ class FilePage extends React.PureComponent {
|
||||||
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
||||||
const isViewable = mediaType === 'image' || mediaType === 'text';
|
const isViewable = mediaType === 'image' || mediaType === 'text';
|
||||||
if (claim && costInfo && costInfo.cost === 0 && !this.state.autoGetAttempted && isViewable) {
|
if (claim && costInfo && costInfo.cost === 0 && !this.state.autoGetAttempted && isViewable) {
|
||||||
this.setState({ autoGetAttempted: true }, () => {
|
this.setState({ autoGetAttempted: true }, () => this.checkStoragePermissionForDownload());
|
||||||
this.checkStoragePermissionForDownload();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((costInfo && costInfo.cost > 0) || !isPlayable) && !fileInfo && !isViewable && !this.state.showRecommended) {
|
if (((costInfo && costInfo.cost > 0) || !isPlayable) && (!fileInfo && !isViewable) && !this.state.showRecommended) {
|
||||||
this.setState({ showRecommended: true });
|
this.setState({ showRecommended: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,11 +360,7 @@ class FilePage extends React.PureComponent {
|
||||||
|
|
||||||
onEditPressed = () => {
|
onEditPressed = () => {
|
||||||
const { claim, navigation } = this.props;
|
const { claim, navigation } = this.props;
|
||||||
const uri = this.state.uri || this.getPurchaseUrl();
|
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_PUBLISH, params: { editMode: true, claimToEdit: claim } });
|
||||||
navigation.navigate({
|
|
||||||
routeName: Constants.DRAWER_ROUTE_PUBLISH,
|
|
||||||
params: { editMode: true, claimToEdit: claim, returnUrl: uri },
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onDeletePressed = () => {
|
onDeletePressed = () => {
|
||||||
|
@ -649,7 +606,7 @@ class FilePage extends React.PureComponent {
|
||||||
let timeToStartMillis, timeToStart;
|
let timeToStartMillis, timeToStart;
|
||||||
if (this.startTime) {
|
if (this.startTime) {
|
||||||
timeToStartMillis = Date.now() - this.startTime;
|
timeToStartMillis = Date.now() - this.startTime;
|
||||||
timeToStart = Math.ceil(timeToStartMillis / 1000.0);
|
timeToStart = Math.ceil(timeToStartMillis / 1000);
|
||||||
this.startTime = null;
|
this.startTime = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,8 +616,8 @@ class FilePage extends React.PureComponent {
|
||||||
|
|
||||||
let payload = { uri: uri };
|
let payload = { uri: uri };
|
||||||
if (!isNaN(timeToStart)) {
|
if (!isNaN(timeToStart)) {
|
||||||
payload['time_to_start_seconds'] = parseInt(timeToStart, 10);
|
payload['time_to_start_seconds'] = timeToStart;
|
||||||
payload['time_to_start_ms'] = parseInt(timeToStartMillis, 10);
|
payload['time_to_start_ms'] = timeToStartMillis;
|
||||||
}
|
}
|
||||||
NativeModules.Firebase.track('play', payload);
|
NativeModules.Firebase.track('play', payload);
|
||||||
|
|
||||||
|
@ -720,7 +677,7 @@ class FilePage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
confirmPurchaseUri = (uri, costInfo, download) => {
|
confirmPurchaseUri = (uri, costInfo, download) => {
|
||||||
const { notify, purchaseUri, sdkReady, title } = this.props;
|
const { notify, purchaseUri, title } = this.props;
|
||||||
if (!costInfo) {
|
if (!costInfo) {
|
||||||
notify({ message: __('This content cannot be viewed at this time. Please try again in a bit.'), isError: true });
|
notify({ message: __('This content cannot be viewed at this time. Please try again in a bit.'), isError: true });
|
||||||
this.setState({ downloadPressed: false });
|
this.setState({ downloadPressed: false });
|
||||||
|
@ -729,11 +686,6 @@ class FilePage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { cost } = costInfo;
|
const { cost } = costInfo;
|
||||||
if (!NativeModules.UtilityModule.dhtEnabled && !sdkReady && parseFloat(cost) === 0) {
|
|
||||||
this.attemptLbryTvPlayback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (costInfo.cost > 0) {
|
if (costInfo.cost > 0) {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
__('Confirm Purchase'),
|
__('Confirm Purchase'),
|
||||||
|
@ -746,56 +698,34 @@ class FilePage extends React.PureComponent {
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
text: __('OK'),
|
text: __('OK'),
|
||||||
onPress: () => {
|
onPress: () => purchaseUri(uri, costInfo, download),
|
||||||
this.startTime = Date.now();
|
|
||||||
purchaseUri(uri, costInfo, download);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{ text: __('Cancel') },
|
{ text: __('Cancel') },
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Free content. Just call purchaseUri directly.
|
// Free content. Just call purchaseUri directly.
|
||||||
this.startTime = Date.now();
|
|
||||||
purchaseUri(uri, costInfo, download);
|
purchaseUri(uri, costInfo, download);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getStreamUrlForClaim = claim => {
|
|
||||||
const { name, claim_id: claimId } = claim;
|
|
||||||
return `https://player.lbry.tv/content/claims/${name}/${claimId}/stream`;
|
|
||||||
};
|
|
||||||
|
|
||||||
attemptLbryTvPlayback = () => {
|
|
||||||
const { claim } = this.props;
|
|
||||||
if (claim) {
|
|
||||||
this.setState({ streamingMode: true, currentStreamUrl: this.getStreamUrlForClaim(claim) });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onFileDownloadButtonPressed = () => {
|
onFileDownloadButtonPressed = () => {
|
||||||
this.startTime = Date.now();
|
const { claim, costInfo, contentType, purchaseUri, setPlayerVisible } = this.props;
|
||||||
const { claim, costInfo, contentType, notify, sdkReady, setPlayerVisible } = this.props;
|
|
||||||
const mediaType = Lbry.getMediaType(contentType);
|
const mediaType = Lbry.getMediaType(contentType);
|
||||||
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
||||||
const isViewable = mediaType === 'image' || mediaType === 'text';
|
const isViewable = mediaType === 'image' || mediaType === 'text';
|
||||||
|
|
||||||
const purchaseUrl = this.getPurchaseUrl();
|
const purchaseUrl = this.getPurchaseUrl();
|
||||||
|
NativeModules.Firebase.track('purchase_uri', { uri: purchaseUrl });
|
||||||
|
|
||||||
if (!isPlayable) {
|
if (!isPlayable) {
|
||||||
if (!sdkReady) {
|
|
||||||
notify({
|
|
||||||
message: __('The LBRY background service is still initializing. Please wait a few moments and try again.'),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.onDownloadPressed();
|
this.onDownloadPressed();
|
||||||
} else {
|
} else {
|
||||||
this.confirmPurchaseUri(purchaseUrl, costInfo, !isPlayable);
|
this.confirmPurchaseUri(purchaseUrl, costInfo, !isPlayable);
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeModules.Firebase.track('purchase_uri', { uri: purchaseUrl });
|
|
||||||
|
|
||||||
if (isPlayable) {
|
if (isPlayable) {
|
||||||
|
this.startTime = Date.now();
|
||||||
this.setState({ downloadPressed: true, autoPlayMedia: true, stopDownloadConfirmed: false });
|
this.setState({ downloadPressed: true, autoPlayMedia: true, stopDownloadConfirmed: false });
|
||||||
}
|
}
|
||||||
if (isViewable) {
|
if (isViewable) {
|
||||||
|
@ -820,16 +750,7 @@ class FilePage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
onDownloadPressed = () => {
|
onDownloadPressed = () => {
|
||||||
const { claim, notify, sdkReady, title } = this.props;
|
const { claim, title } = this.props;
|
||||||
if (!sdkReady) {
|
|
||||||
notify({
|
|
||||||
message: __(
|
|
||||||
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
|
||||||
),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fileSize = claim && claim.value && claim.value.source ? claim.value.source.size : 0;
|
const fileSize = claim && claim.value && claim.value.source ? claim.value.source.size : 0;
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
__('Download file'),
|
__('Download file'),
|
||||||
|
@ -1029,6 +950,7 @@ class FilePage extends React.PureComponent {
|
||||||
myClaimUris,
|
myClaimUris,
|
||||||
navigation,
|
navigation,
|
||||||
position,
|
position,
|
||||||
|
purchaseUri,
|
||||||
pushDrawerStack,
|
pushDrawerStack,
|
||||||
setPlayerVisible,
|
setPlayerVisible,
|
||||||
thumbnail,
|
thumbnail,
|
||||||
|
@ -1043,12 +965,6 @@ class FilePage extends React.PureComponent {
|
||||||
|
|
||||||
let innerContent = null;
|
let innerContent = null;
|
||||||
if ((isResolvingUri && !claim) || !claim) {
|
if ((isResolvingUri && !claim) || !claim) {
|
||||||
if (!isResolvingUri && !claim && !this.state.uriPushedToDrawerStack) {
|
|
||||||
this.setState({ uriPushedToDrawerStack: true }, () => {
|
|
||||||
pushDrawerStack(uri);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={filePageStyle.pageContainer}>
|
<View style={filePageStyle.pageContainer}>
|
||||||
<UriBar value={uri} navigation={navigation} />
|
<UriBar value={uri} navigation={navigation} />
|
||||||
|
@ -1117,17 +1033,6 @@ class FilePage extends React.PureComponent {
|
||||||
tags = claim.value.tags;
|
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 completed = fileInfo && fileInfo.completed;
|
||||||
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
const description = metadata.description ? metadata.description : null;
|
const description = metadata.description ? metadata.description : null;
|
||||||
|
@ -1138,8 +1043,7 @@ class FilePage extends React.PureComponent {
|
||||||
const channelName = signingChannel && signingChannel.name;
|
const channelName = signingChannel && signingChannel.name;
|
||||||
const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
|
const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
|
||||||
const fullUri = `${claim.name}#${claim.claim_id}`;
|
const fullUri = `${claim.name}#${claim.claim_id}`;
|
||||||
const canEdit =
|
const canEdit = myClaimUris.includes(normalizeURI(fullUri));
|
||||||
myClaimUris.includes(normalizeURI(fullUri)) || myClaimUris.includes(normalizeURI(claim.canonical_url));
|
|
||||||
const showActions =
|
const showActions =
|
||||||
(canEdit || (fileInfo && fileInfo.download_path)) &&
|
(canEdit || (fileInfo && fileInfo.download_path)) &&
|
||||||
!this.state.fullscreenMode &&
|
!this.state.fullscreenMode &&
|
||||||
|
@ -1223,7 +1127,7 @@ class FilePage extends React.PureComponent {
|
||||||
style={filePageStyle.mediaContainer}
|
style={filePageStyle.mediaContainer}
|
||||||
onPress={this.onFileDownloadButtonPressed}
|
onPress={this.onFileDownloadButtonPressed}
|
||||||
>
|
>
|
||||||
{(canOpen || !fileInfo || (isPlayable && !canLoadMedia) || (!canOpen && fileInfo)) && (
|
{(canOpen || (!fileInfo || (isPlayable && !canLoadMedia)) || (!canOpen && fileInfo)) && (
|
||||||
<FileItemMedia
|
<FileItemMedia
|
||||||
duration={duration}
|
duration={duration}
|
||||||
style={filePageStyle.thumbnail}
|
style={filePageStyle.thumbnail}
|
||||||
|
@ -1360,14 +1264,6 @@ class FilePage extends React.PureComponent {
|
||||||
<Text style={filePageStyle.largeButtonText}>{__('Share')}</Text>
|
<Text style={filePageStyle.largeButtonText}>{__('Share')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<TouchableOpacity
|
|
||||||
style={filePageStyle.largeButton}
|
|
||||||
onPress={() => this.setState({ showRepostView: true })}
|
|
||||||
>
|
|
||||||
<Icon name={'retweet'} size={16} style={filePageStyle.largeButtonIcon} />
|
|
||||||
<Text style={filePageStyle.largeButtonText}>{__('Repost')}</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={filePageStyle.largeButton}
|
style={filePageStyle.largeButton}
|
||||||
onPress={() => this.setState({ showTipView: true })}
|
onPress={() => this.setState({ showTipView: true })}
|
||||||
|
@ -1542,17 +1438,7 @@ class FilePage extends React.PureComponent {
|
||||||
onSendTipSuccessful={() => this.setState({ showTipView: false })}
|
onSendTipSuccessful={() => this.setState({ showTipView: false })}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{this.state.showRepostView && (
|
|
||||||
<ModalRepostView
|
|
||||||
claim={claim}
|
|
||||||
title={title}
|
|
||||||
onCancelPress={() => this.setState({ showRepostView: false })}
|
|
||||||
onOverlayPress={() => this.setState({ showRepostView: false })}
|
|
||||||
onRepostSuccessful={() => this.setState({ showRepostView: false })}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!this.state.fullscreenMode &&
|
{!this.state.fullscreenMode &&
|
||||||
!this.state.showRepostView &&
|
|
||||||
!this.state.showTipView &&
|
!this.state.showTipView &&
|
||||||
!this.state.showImageViewer &&
|
!this.state.showImageViewer &&
|
||||||
!this.state.showWebView && <FloatingWalletBalance navigation={navigation} />}
|
!this.state.showWebView && <FloatingWalletBalance navigation={navigation} />}
|
||||||
|
|
|
@ -12,26 +12,27 @@ import {
|
||||||
doFetchInviteStatus,
|
doFetchInviteStatus,
|
||||||
doUserInviteNew,
|
doUserInviteNew,
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { selectSdkReady } from 'redux/selectors/settings';
|
import { doUpdateChannelFormState, doClearChannelFormState } from 'redux/actions/form';
|
||||||
|
import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||||
|
import { selectChannelFormState, selectHasChannelFormState } from 'redux/selectors/form';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import InvitesPage from './view';
|
import InvitesPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
channels: selectMyChannelClaims(state),
|
channels: selectMyChannelClaims(state),
|
||||||
errorMessage: selectUserInviteNewErrorMessage(state),
|
|
||||||
fetchingChannels: selectFetchingMyChannels(state),
|
fetchingChannels: selectFetchingMyChannels(state),
|
||||||
fetchingInvitees: selectUserInviteStatusIsPending(state),
|
fetchingInvitees: selectUserInviteStatusIsPending(state),
|
||||||
invitees: selectUserInvitees(state),
|
errorMessage: selectUserInviteNewErrorMessage(state),
|
||||||
invitesRemaining: selectUserInvitesRemaining(state),
|
invitesRemaining: selectUserInvitesRemaining(state),
|
||||||
isPending: selectUserInviteNewIsPending(state),
|
|
||||||
referralCode: selectUserInviteReferralCode(state),
|
referralCode: selectUserInviteReferralCode(state),
|
||||||
|
isPending: selectUserInviteNewIsPending(state),
|
||||||
|
invitees: selectUserInvitees(state),
|
||||||
referralReward: selectReferralReward(state),
|
referralReward: selectReferralReward(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||||
fetchInviteStatus: () => dispatch(doFetchInviteStatus()),
|
fetchInviteStatus: () => dispatch(doFetchInviteStatus()),
|
||||||
inviteNew: email => dispatch(doUserInviteNew(email)),
|
inviteNew: email => dispatch(doUserInviteNew(email)),
|
||||||
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_INVITES)),
|
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_INVITES)),
|
||||||
|
@ -39,4 +40,7 @@ const perform = dispatch => ({
|
||||||
notify: data => dispatch(doToast(data)),
|
notify: data => dispatch(doToast(data)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(InvitesPage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(InvitesPage);
|
||||||
|
|
|
@ -11,13 +11,16 @@ import {
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
|
import Link from 'component/link';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import ChannelSelector from 'component/channelSelector';
|
import ChannelSelector from 'component/channelSelector';
|
||||||
import EmptyStateView from 'component/emptyStateView';
|
import PageHeader from 'component/pageHeader';
|
||||||
|
import RewardCard from 'component/rewardCard';
|
||||||
|
import RewardEnrolment from 'component/rewardEnrolment';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import invitesStyle from 'styles/invites';
|
import invitesStyle from 'styles/invites';
|
||||||
import { fetchReferralCode, logPublish } from 'utils/helper';
|
|
||||||
|
|
||||||
class InvitesPage extends React.PureComponent {
|
class InvitesPage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
|
@ -44,19 +47,7 @@ class InvitesPage extends React.PureComponent {
|
||||||
pushDrawerStack();
|
pushDrawerStack();
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
NativeModules.Firebase.setCurrentScreen('Invites').then(result => {
|
NativeModules.Firebase.setCurrentScreen('Invites').then(result => {
|
||||||
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();
|
fetchChannelListMine();
|
||||||
},
|
|
||||||
error => {
|
|
||||||
fetchChannelListMine();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
fetchInviteStatus();
|
fetchInviteStatus();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -71,15 +62,13 @@ class InvitesPage extends React.PureComponent {
|
||||||
const filtered = channels.filter(c => c.name === channelName);
|
const filtered = channels.filter(c => c.name === channelName);
|
||||||
if (filtered.length > 0) {
|
if (filtered.length > 0) {
|
||||||
const channel = filtered[0];
|
const channel = filtered[0];
|
||||||
logPublish(channel);
|
|
||||||
this.setState({ channelName, inviteLink: this.getLinkForChannel(channel) });
|
this.setState({ channelName, inviteLink: this.getLinkForChannel(channel) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getLinkForChannel = channel => {
|
getLinkForChannel = channel => {
|
||||||
const parsedUrl = channel.canonical_url ? parseURI(channel.canonical_url) : parseURI(channel.permanent_url);
|
const { claimId, claimName } = parseURI(channel.permanent_url);
|
||||||
const { claimId, claimName } = parsedUrl;
|
|
||||||
return `https://lbry.tv/$/invite/${claimName}:${claimId}`;
|
return `https://lbry.tv/$/invite/${claimName}:${claimId}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,7 +96,6 @@ class InvitesPage extends React.PureComponent {
|
||||||
|
|
||||||
if (!this.state.channelName && channels && channels.length > 0) {
|
if (!this.state.channelName && channels && channels.length > 0) {
|
||||||
const firstChannel = channels[0];
|
const firstChannel = channels[0];
|
||||||
logPublish(firstChannel);
|
|
||||||
this.setState({ channelName: firstChannel.name, inviteLink: this.getLinkForChannel(firstChannel) });
|
this.setState({ channelName: firstChannel.name, inviteLink: this.getLinkForChannel(firstChannel) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,23 +118,10 @@ class InvitesPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { fetchingInvitees, invitees, isPending, navigation, sdkReady } = this.props;
|
const { fetchingInvitees, user, navigation, notify, isPending, invitees } = this.props;
|
||||||
const { email } = this.state;
|
const { email, inviteLink } = this.state;
|
||||||
const hasInvitees = invitees && invitees.length > 0;
|
const hasInvitees = invitees && invitees.length > 0;
|
||||||
|
|
||||||
if (!sdkReady) {
|
|
||||||
return (
|
|
||||||
<View style={invitesStyle.container}>
|
|
||||||
<UriBar navigation={navigation} />
|
|
||||||
<EmptyStateView
|
|
||||||
message={__(
|
|
||||||
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={invitesStyle.container}>
|
<View style={invitesStyle.container}>
|
||||||
<UriBar navigation={navigation} />
|
<UriBar navigation={navigation} />
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { makeSelectContentPositionForUri, selectBalance } from 'lbry-redux';
|
|
||||||
import { doClaimEligiblePurchaseRewards, makeSelectViewCountForUri, selectRewardContentClaimIds } from 'lbryinc';
|
|
||||||
import { doSetPlayerVisible } from 'redux/actions/drawer';
|
|
||||||
import { makeSelectPlayerVisible } from 'redux/selectors/drawer';
|
|
||||||
import { doToggleFullscreenMode } from 'redux/actions/settings';
|
|
||||||
import LiteFilePage from './view';
|
|
||||||
|
|
||||||
const select = (state, props) => {
|
|
||||||
const { uri, fullUri } = props.navigation.state.params;
|
|
||||||
const contentUri = fullUri || uri;
|
|
||||||
const selectProps = { uri: contentUri };
|
|
||||||
return {
|
|
||||||
balance: selectBalance(state),
|
|
||||||
isPlayerVisible: makeSelectPlayerVisible(uri)(state), // use navigation uri for this selector
|
|
||||||
position: makeSelectContentPositionForUri(contentUri)(state),
|
|
||||||
viewCount: makeSelectViewCountForUri(contentUri)(state),
|
|
||||||
rewardedContentClaimIds: selectRewardContentClaimIds(state),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
|
||||||
claimEligibleRewards: () => dispatch(doClaimEligiblePurchaseRewards()),
|
|
||||||
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
|
||||||
toggleFullscreenMode: mode => dispatch(doToggleFullscreenMode(mode)),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(select, perform)(LiteFilePage);
|
|
|
@ -1,297 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Lbry, formatCredits, normalizeURI, parseURI, parseQueryParams } from 'lbry-redux';
|
|
||||||
import { Lbryio } from 'lbryinc';
|
|
||||||
import {
|
|
||||||
ActivityIndicator,
|
|
||||||
Alert,
|
|
||||||
DeviceEventEmitter,
|
|
||||||
Dimensions,
|
|
||||||
Image,
|
|
||||||
Linking,
|
|
||||||
NativeModules,
|
|
||||||
Platform,
|
|
||||||
ScrollView,
|
|
||||||
StatusBar,
|
|
||||||
StyleSheet,
|
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
TouchableOpacity,
|
|
||||||
TouchableWithoutFeedback,
|
|
||||||
View,
|
|
||||||
} from 'react-native';
|
|
||||||
import UriBar from 'component/uriBar';
|
|
||||||
import Link from 'component/link';
|
|
||||||
import MediaPlayer from 'component/mediaPlayer';
|
|
||||||
import RelatedContent from 'component/relatedContent';
|
|
||||||
import filePageStyle from 'styles/filePage';
|
|
||||||
import { decode, formatLbryUrlForWeb, navigateToUri } from 'utils/helper';
|
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
|
||||||
import uriBarStyle from 'styles/uriBar';
|
|
||||||
import { NavigationActions, StackActions } from 'react-navigation';
|
|
||||||
|
|
||||||
// This page will only be used for playing audio / video content from a remote stream URL
|
|
||||||
class LiteFilePage extends React.PureComponent {
|
|
||||||
playerBackground = null;
|
|
||||||
|
|
||||||
scrollView = null;
|
|
||||||
|
|
||||||
player = null;
|
|
||||||
|
|
||||||
startTime = null;
|
|
||||||
|
|
||||||
state = {
|
|
||||||
channelName: null,
|
|
||||||
channelUrl: null,
|
|
||||||
fileViewLogged: false,
|
|
||||||
fullscreenMode: false,
|
|
||||||
playbackStarted: false,
|
|
||||||
playerHeight: null,
|
|
||||||
isLandscape: false,
|
|
||||||
sdkReady: false, // TODO: progressively enable features (e.g. tip) when sdk is ready
|
|
||||||
showRecommended: false,
|
|
||||||
title: null,
|
|
||||||
viewCount: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
checkOrientation = () => {
|
|
||||||
if (this.state.fullscreenMode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const screenDimension = Dimensions.get('window');
|
|
||||||
const screenWidth = screenDimension.width;
|
|
||||||
const screenHeight = screenDimension.height;
|
|
||||||
const isLandscape = screenWidth > screenHeight;
|
|
||||||
this.setState({ isLandscape });
|
|
||||||
|
|
||||||
if (!this.playerBackground) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLandscape) {
|
|
||||||
this.playerBackground.setNativeProps({
|
|
||||||
height: screenHeight - StyleSheet.flatten(uriBarStyle.uriContainer).height,
|
|
||||||
});
|
|
||||||
} else if (this.state.playerBgHeight > 0) {
|
|
||||||
this.playerBackground.setNativeProps({ height: this.state.playerBgHeight });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleFullscreenToggle = isFullscreen => {
|
|
||||||
const { toggleFullscreenMode } = this.props;
|
|
||||||
toggleFullscreenMode(isFullscreen);
|
|
||||||
|
|
||||||
if (isFullscreen) {
|
|
||||||
// fullscreen, so change orientation to landscape mode
|
|
||||||
NativeModules.ScreenOrientation.lockOrientationLandscape();
|
|
||||||
|
|
||||||
// hide the navigation bar (on devices that have the soft navigation bar)
|
|
||||||
NativeModules.UtilityModule.hideNavigationBar();
|
|
||||||
} else {
|
|
||||||
// Switch back to portrait mode when the media is not fullscreen
|
|
||||||
NativeModules.ScreenOrientation.lockOrientationPortrait();
|
|
||||||
|
|
||||||
// show the navigation bar (on devices that have the soft navigation bar)
|
|
||||||
NativeModules.UtilityModule.showNavigationBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ fullscreenMode: isFullscreen });
|
|
||||||
StatusBar.setHidden(isFullscreen);
|
|
||||||
};
|
|
||||||
|
|
||||||
getStreamUrl = url => {
|
|
||||||
const { claimName, claimId } = parseURI(url);
|
|
||||||
return `https://player.lbry.tv/content/claims/${claimName}/${claimId}/stream`;
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSharePress = url => {
|
|
||||||
const shareUrl = Constants.SHARE_BASE_URL + formatLbryUrlForWeb(url);
|
|
||||||
NativeModules.UtilityModule.shareUrl(shareUrl);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleOpenUrl = url => {
|
|
||||||
const { navigation } = this.props;
|
|
||||||
Alert.alert(
|
|
||||||
__('Stop watching?'),
|
|
||||||
'The LBRY service is still loading stuff in the background. Would you like to continue?',
|
|
||||||
[
|
|
||||||
{ text: __('No') },
|
|
||||||
{
|
|
||||||
text: __('Yes'),
|
|
||||||
onPress: () => {
|
|
||||||
const resetAction = StackActions.reset({
|
|
||||||
index: 0,
|
|
||||||
actions: [NavigationActions.navigate({ routeName: 'Splash', params: { resetUrl: url } })],
|
|
||||||
});
|
|
||||||
navigation.dispatch(resetAction);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.startTime = Date.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
const { navigation } = this.props;
|
|
||||||
const { uri } = navigation.state.params;
|
|
||||||
|
|
||||||
if (!this.state.title) {
|
|
||||||
const params = parseQueryParams(uri);
|
|
||||||
const { channelUrl, contentTitle } = params;
|
|
||||||
const channelName = channelUrl ? parseURI(decode(channelUrl)).claimName : null;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
title: decode(contentTitle),
|
|
||||||
channelUrl,
|
|
||||||
channelName,
|
|
||||||
showRecommended: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { navigation, rewardedContentClaimIds } = this.props;
|
|
||||||
const { channelName, channelUrl, title, sdkReady, viewCount } = this.state;
|
|
||||||
const { uri } = navigation.state.params;
|
|
||||||
const { claimName, claimId } = parseURI(uri);
|
|
||||||
const isRewardContent = rewardedContentClaimIds.includes(claimId);
|
|
||||||
|
|
||||||
const playerBgStyle = [filePageStyle.playerBackground, filePageStyle.containedPlayerBackground];
|
|
||||||
const fsPlayerBgStyle = [filePageStyle.playerBackground, filePageStyle.fullscreenPlayerBackground];
|
|
||||||
|
|
||||||
const playerStyle = [
|
|
||||||
filePageStyle.player,
|
|
||||||
this.state.isLandscape
|
|
||||||
? filePageStyle.containedPlayerLandscape
|
|
||||||
: this.state.fullscreenMode
|
|
||||||
? filePageStyle.fullscreenPlayer
|
|
||||||
: filePageStyle.containedPlayer,
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={filePageStyle.pageContainer}>
|
|
||||||
{!this.state.fullscreenMode && <UriBar value={uri.split('?')[0]} navigation={navigation} />}
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={this.state.fullscreenMode ? filePageStyle.innerPageContainerFsMode : filePageStyle.innerPageContainer}
|
|
||||||
onLayout={this.checkOrientation}
|
|
||||||
>
|
|
||||||
<TouchableOpacity activeOpacity={0.5} style={filePageStyle.mediaContainer} />
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={playerBgStyle}
|
|
||||||
ref={ref => {
|
|
||||||
this.playerBackground = ref;
|
|
||||||
}}
|
|
||||||
onLayout={evt => {
|
|
||||||
if (!this.state.playerBgHeight) {
|
|
||||||
this.setState({ playerBgHeight: evt.nativeEvent.layout.height });
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{this.state.fullscreenMode && <View style={fsPlayerBgStyle} />}
|
|
||||||
<MediaPlayer
|
|
||||||
assignPlayer={ref => {
|
|
||||||
this.player = ref;
|
|
||||||
}}
|
|
||||||
uri={uri}
|
|
||||||
source={this.getStreamUrl(uri)}
|
|
||||||
style={playerStyle}
|
|
||||||
autoPlay
|
|
||||||
onFullscreenToggled={this.handleFullscreenToggle}
|
|
||||||
onLayout={evt => {
|
|
||||||
if (!this.state.playerHeight) {
|
|
||||||
this.setState({ playerHeight: evt.nativeEvent.layout.height });
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ScrollView
|
|
||||||
style={filePageStyle.scrollContainer}
|
|
||||||
contentContainerStyle={filePageStyle.scrollContent}
|
|
||||||
keyboardShouldPersistTaps={'handled'}
|
|
||||||
ref={ref => {
|
|
||||||
this.scrollView = ref;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<TouchableWithoutFeedback
|
|
||||||
style={filePageStyle.titleTouch}
|
|
||||||
onPress={() => this.setState({ showDescription: !this.state.showDescription })}
|
|
||||||
>
|
|
||||||
<View style={filePageStyle.titleArea}>
|
|
||||||
<View style={filePageStyle.titleRow}>
|
|
||||||
<Text style={filePageStyle.title} selectable>
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
{isRewardContent && <Icon name="award" style={filePageStyle.rewardIcon} size={16} />}
|
|
||||||
</View>
|
|
||||||
<Text style={filePageStyle.viewCount}>
|
|
||||||
{viewCount === 1 && __('%view% view', { view: viewCount })}
|
|
||||||
{viewCount > 1 && __('%view% views', { view: viewCount })}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</TouchableWithoutFeedback>
|
|
||||||
|
|
||||||
<View style={filePageStyle.largeButtonsRow}>
|
|
||||||
<TouchableOpacity style={filePageStyle.largeButton} onPress={() => this.handleSharePress(uri)}>
|
|
||||||
<Icon name={'share-alt'} size={16} style={filePageStyle.largeButtonIcon} />
|
|
||||||
<Text style={filePageStyle.largeButtonText}>{__('Share')}</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
{sdkReady && (
|
|
||||||
<TouchableOpacity
|
|
||||||
style={filePageStyle.largeButton}
|
|
||||||
onPress={() => this.setState({ showTipView: true })}
|
|
||||||
>
|
|
||||||
<Icon name={'gift'} size={16} style={filePageStyle.largeButtonIcon} />
|
|
||||||
<Text style={filePageStyle.largeButtonText}>{__('Tip')}</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={filePageStyle.channelRow}>
|
|
||||||
<View style={filePageStyle.publishInfo}>
|
|
||||||
{channelName && (
|
|
||||||
<Link
|
|
||||||
style={filePageStyle.channelName}
|
|
||||||
selectable
|
|
||||||
text={channelName}
|
|
||||||
numberOfLines={1}
|
|
||||||
ellipsizeMode={'tail'}
|
|
||||||
onPress={() => this.handleOpenUrl(channelUrl)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!channelName && (
|
|
||||||
<Text style={filePageStyle.anonChannelName} selectable ellipsizeMode={'tail'}>
|
|
||||||
{__('Anonymous')}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View onLayout={this.setRelatedContentPosition} />
|
|
||||||
|
|
||||||
{this.state.showRecommended && (
|
|
||||||
<RelatedContent
|
|
||||||
navigation={navigation}
|
|
||||||
claimId={claimId}
|
|
||||||
claimName={claimName}
|
|
||||||
title={title}
|
|
||||||
urlOpenHandler={this.handleOpenUrl}
|
|
||||||
uri={uri}
|
|
||||||
fullUri={uri}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ScrollView>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LiteFilePage;
|
|
|
@ -13,7 +13,6 @@ import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||||
import { doUpdatePublishFormState, doClearPublishFormState, doPendingPublishSuccess } from 'redux/actions/form';
|
import { doUpdatePublishFormState, doClearPublishFormState, doPendingPublishSuccess } from 'redux/actions/form';
|
||||||
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { selectPublishFormState, selectHasPublishFormState } from 'redux/selectors/form';
|
import { selectPublishFormState, selectHasPublishFormState } from 'redux/selectors/form';
|
||||||
import { selectSdkReady } from 'redux/selectors/settings';
|
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import PublishPage from './view';
|
import PublishPage from './view';
|
||||||
|
|
||||||
|
@ -24,7 +23,6 @@ const select = state => ({
|
||||||
myClaims: selectMyClaims(state),
|
myClaims: selectMyClaims(state),
|
||||||
publishFormState: selectPublishFormState(state),
|
publishFormState: selectPublishFormState(state),
|
||||||
publishFormValues: selectPublishFormValues(state),
|
publishFormValues: selectPublishFormValues(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -41,4 +39,7 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(PublishPage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(PublishPage);
|
||||||
|
|
|
@ -37,7 +37,6 @@ import Button from 'component/button';
|
||||||
import ChannelSelector from 'component/channelSelector';
|
import ChannelSelector from 'component/channelSelector';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import EmptyStateView from 'component/emptyStateView';
|
|
||||||
import FastImage from 'react-native-fast-image';
|
import FastImage from 'react-native-fast-image';
|
||||||
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
|
@ -48,7 +47,7 @@ import Tag from 'component/tag';
|
||||||
import TagSearch from 'component/tagSearch';
|
import TagSearch from 'component/tagSearch';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import publishStyle from 'styles/publish';
|
import publishStyle from 'styles/publish';
|
||||||
import { navigateToUri, navigateBack, logPublish, uploadImageAsset } from 'utils/helper';
|
import { navigateToUri, logPublish, uploadImageAsset } from 'utils/helper';
|
||||||
|
|
||||||
const languages = {
|
const languages = {
|
||||||
en: 'English',
|
en: 'English',
|
||||||
|
@ -121,7 +120,7 @@ class PublishPage extends React.PureComponent {
|
||||||
|
|
||||||
// input data
|
// input data
|
||||||
hasEditedContentAddress: false,
|
hasEditedContentAddress: false,
|
||||||
bid: 0.01,
|
bid: 0.1,
|
||||||
description: null,
|
description: null,
|
||||||
title: null,
|
title: null,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
|
@ -142,8 +141,6 @@ class PublishPage extends React.PureComponent {
|
||||||
// other
|
// other
|
||||||
publishStarted: false,
|
publishStarted: false,
|
||||||
storagePermissionRequired: false,
|
storagePermissionRequired: false,
|
||||||
hasReturnedBack: false,
|
|
||||||
returnUrl: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
didFocusListener;
|
didFocusListener;
|
||||||
|
@ -239,7 +236,7 @@ class PublishPage extends React.PureComponent {
|
||||||
let isEditMode = false,
|
let isEditMode = false,
|
||||||
vanityUrlSet = false;
|
vanityUrlSet = false;
|
||||||
if (navigation.state.params) {
|
if (navigation.state.params) {
|
||||||
const { displayForm, editMode, claimToEdit, vanityUrl, returnUrl } = navigation.state.params;
|
const { displayForm, editMode, claimToEdit, vanityUrl } = navigation.state.params;
|
||||||
if (editMode) {
|
if (editMode) {
|
||||||
this.prepareEdit(claimToEdit);
|
this.prepareEdit(claimToEdit);
|
||||||
isEditMode = true;
|
isEditMode = true;
|
||||||
|
@ -253,7 +250,6 @@ class PublishPage extends React.PureComponent {
|
||||||
vanityUrl: claimName,
|
vanityUrl: claimName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.setState({ returnUrl });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEditMode && hasFormState) {
|
if (!isEditMode && hasFormState) {
|
||||||
|
@ -476,15 +472,7 @@ class PublishPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const {
|
const { currentRoute: prevRoute, drawerStack: prevDrawerStack, notify, updatePublishFormState } = this.props;
|
||||||
currentRoute: prevRoute,
|
|
||||||
drawerStack: prevDrawerStack,
|
|
||||||
popDrawerStack,
|
|
||||||
setPlayerVisible,
|
|
||||||
navigation,
|
|
||||||
notify,
|
|
||||||
updatePublishFormState,
|
|
||||||
} = this.props;
|
|
||||||
const { currentRoute, drawerStack, publishFormValues } = nextProps;
|
const { currentRoute, drawerStack, publishFormValues } = nextProps;
|
||||||
|
|
||||||
if (Constants.DRAWER_ROUTE_PUBLISH === currentRoute && currentRoute !== prevRoute) {
|
if (Constants.DRAWER_ROUTE_PUBLISH === currentRoute && currentRoute !== prevRoute) {
|
||||||
|
@ -498,11 +486,6 @@ class PublishPage extends React.PureComponent {
|
||||||
) {
|
) {
|
||||||
// navigated back from the form
|
// navigated back from the form
|
||||||
this.showSelector();
|
this.showSelector();
|
||||||
if (!this.state.hasReturnedBack && this.state.returnUrl) {
|
|
||||||
this.setState({ hasReturnedBack: true }, () => {
|
|
||||||
navigateBack(navigation, drawerStack, popDrawerStack, setPlayerVisible);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -975,7 +958,7 @@ class PublishPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { balance, navigation, notify, sdkReady } = this.props;
|
const { balance, navigation, notify, publishFormValues } = this.props;
|
||||||
const {
|
const {
|
||||||
allThumbnailsChecked,
|
allThumbnailsChecked,
|
||||||
canUseCamera,
|
canUseCamera,
|
||||||
|
@ -988,19 +971,6 @@ class PublishPage extends React.PureComponent {
|
||||||
videos,
|
videos,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
if (!sdkReady) {
|
|
||||||
return (
|
|
||||||
<View style={publishStyle.container}>
|
|
||||||
<UriBar navigation={navigation} />
|
|
||||||
<EmptyStateView
|
|
||||||
message={__(
|
|
||||||
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let content;
|
let content;
|
||||||
if (Constants.PHASE_SELECTOR === currentPhase) {
|
if (Constants.PHASE_SELECTOR === currentPhase) {
|
||||||
content = (
|
content = (
|
||||||
|
|
|
@ -9,7 +9,6 @@ import {
|
||||||
selectIsFetchingClaimListMine,
|
selectIsFetchingClaimListMine,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { selectSdkReady } from 'redux/selectors/settings';
|
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import PublishesPage from './view';
|
import PublishesPage from './view';
|
||||||
|
|
||||||
|
@ -17,7 +16,6 @@ const select = state => ({
|
||||||
uris: selectMyClaimUrisWithoutChannels(state),
|
uris: selectMyClaimUrisWithoutChannels(state),
|
||||||
fetching: selectIsFetchingClaimListMine(state),
|
fetching: selectIsFetchingClaimListMine(state),
|
||||||
pendingClaims: selectPendingClaims(state),
|
pendingClaims: selectPendingClaims(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -29,4 +27,7 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(PublishesPage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(PublishesPage);
|
||||||
|
|
|
@ -114,27 +114,14 @@ class PublishesPage extends React.PureComponent {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
{ cancelable: true },
|
{ cancelable: true }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { fetching, navigation, sdkReady, uris } = this.props;
|
const { fetching, navigation, uris } = this.props;
|
||||||
const { selectionMode, selectedUris } = this.state;
|
const { selectionMode, selectedUris } = this.state;
|
||||||
|
|
||||||
if (!sdkReady) {
|
|
||||||
return (
|
|
||||||
<View style={publishStyle.container}>
|
|
||||||
<UriBar navigation={navigation} />
|
|
||||||
<EmptyStateView
|
|
||||||
message={__(
|
|
||||||
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={publishStyle.container}>
|
<View style={publishStyle.container}>
|
||||||
<UriBar
|
<UriBar
|
||||||
|
@ -194,7 +181,7 @@ class PublishesPage extends React.PureComponent {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// TODO: when shortUrl is available for my claims, navigate to that URL instead
|
// TODO: when shortUrl is available for my claims, navigate to that URL instead
|
||||||
navigateToUri(navigation, claim.permanent_url);
|
navigateToUri(navigation, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -12,8 +12,7 @@ import {
|
||||||
import { doToast } from 'lbry-redux';
|
import { doToast } from 'lbry-redux';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||||
import { selectSdkReady } from 'redux/selectors/settings';
|
import Constants from 'constants';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
|
||||||
import RewardsPage from './view';
|
import RewardsPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
@ -23,7 +22,6 @@ const select = state => ({
|
||||||
emailVerifyPending: selectEmailVerifyIsPending(state),
|
emailVerifyPending: selectEmailVerifyIsPending(state),
|
||||||
fetching: selectFetchingRewards(state),
|
fetching: selectFetchingRewards(state),
|
||||||
rewards: selectUnclaimedRewards(state),
|
rewards: selectUnclaimedRewards(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,4 +33,7 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(RewardsPage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(RewardsPage);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Lbryio } from 'lbryinc';
|
import { Lbry } from 'lbry-redux';
|
||||||
import { ActivityIndicator, NativeModules, ScrollView, Text, View } from 'react-native';
|
import { ActivityIndicator, NativeModules, ScrollView, Text, View } from 'react-native';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import CustomRewardCard from 'component/customRewardCard';
|
import CustomRewardCard from 'component/customRewardCard';
|
||||||
import EmptyStateView from 'component/emptyStateView';
|
import PageHeader from 'component/pageHeader';
|
||||||
import RewardCard from 'component/rewardCard';
|
import RewardCard from 'component/rewardCard';
|
||||||
import RewardEnrolment from 'component/rewardEnrolment';
|
import RewardEnrolment from 'component/rewardEnrolment';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
|
@ -17,14 +17,13 @@ const FILTER_CLAIMED = 'claimed';
|
||||||
|
|
||||||
class RewardsPage extends React.PureComponent {
|
class RewardsPage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
currentFilter: FILTER_AVAILABLE,
|
|
||||||
firstRewardClaimed: false,
|
|
||||||
isEmailVerified: false,
|
isEmailVerified: false,
|
||||||
isIdentityVerified: false,
|
isIdentityVerified: false,
|
||||||
isRewardApproved: false,
|
isRewardApproved: false,
|
||||||
revealVerification: true,
|
|
||||||
usdExchangeRate: 0,
|
|
||||||
verifyRequestStarted: false,
|
verifyRequestStarted: false,
|
||||||
|
revealVerification: true,
|
||||||
|
firstRewardClaimed: false,
|
||||||
|
currentFilter: FILTER_AVAILABLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
scrollView = null;
|
scrollView = null;
|
||||||
|
@ -49,12 +48,6 @@ class RewardsPage extends React.PureComponent {
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
NativeModules.Firebase.setCurrentScreen('Rewards');
|
NativeModules.Firebase.setCurrentScreen('Rewards');
|
||||||
|
|
||||||
Lbryio.getExchangeRates().then(rates => {
|
|
||||||
if (!isNaN(rates.LBC_USD)) {
|
|
||||||
this.setState({ usdExchangeRate: rates.LBC_USD });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
fetchRewards();
|
fetchRewards();
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -165,7 +158,6 @@ class RewardsPage extends React.PureComponent {
|
||||||
canClaim={!isNotEligible}
|
canClaim={!isNotEligible}
|
||||||
reward={reward}
|
reward={reward}
|
||||||
reward_type={reward.reward_type}
|
reward_type={reward.reward_type}
|
||||||
usdExchangeRate={this.state.usdExchangeRate}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<CustomRewardCard canClaim={!isNotEligible} showVerification={this.showVerification} />
|
<CustomRewardCard canClaim={!isNotEligible} showVerification={this.showVerification} />
|
||||||
|
@ -200,28 +192,13 @@ class RewardsPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { navigation, sdkReady } = this.props;
|
const { user, navigation } = this.props;
|
||||||
const { currentFilter } = this.state;
|
const { currentFilter } = this.state;
|
||||||
|
|
||||||
if (!sdkReady) {
|
|
||||||
return (
|
return (
|
||||||
<View style={rewardStyle.container}>
|
<View style={rewardStyle.container}>
|
||||||
<UriBar navigation={navigation} />
|
<UriBar navigation={navigation} />
|
||||||
<EmptyStateView
|
{(!this.state.isEmailVerified || !this.state.isRewardApproved) && <RewardEnrolment navigation={navigation} />}
|
||||||
message={__(
|
|
||||||
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={rewardStyle.container}>
|
|
||||||
<UriBar navigation={navigation} />
|
|
||||||
{(!this.state.isEmailVerified || !this.state.isRewardApproved) && (
|
|
||||||
<RewardEnrolment usdExchangeRate={this.state.usdExchangeRate} navigation={navigation} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{this.state.isEmailVerified && this.state.isRewardApproved && (
|
{this.state.isEmailVerified && this.state.isRewardApproved && (
|
||||||
<ScrollView
|
<ScrollView
|
||||||
|
|
|
@ -26,14 +26,10 @@ const select = state => ({
|
||||||
query: selectSearchValue(state),
|
query: selectSearchValue(state),
|
||||||
resolvingUris: selectResolvingUris(state),
|
resolvingUris: selectResolvingUris(state),
|
||||||
showNsfwContent: selectShowNsfw(state),
|
showNsfwContent: selectShowNsfw(state),
|
||||||
uris: makeSelectSearchUris(
|
uris: makeSelectSearchUris(makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state))(state),
|
||||||
makeSelectQueryWithOptions(null, { size: Constants.DEFAULT_PAGE_SIZE, isBackgroundSearch: false })(state),
|
results: makeSelectResolvedSearchResults(makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state))(state),
|
||||||
)(state),
|
|
||||||
results: makeSelectResolvedSearchResults(
|
|
||||||
makeSelectQueryWithOptions(null, { size: Constants.DEFAULT_PAGE_SIZE, isBackgroundSearch: false })(state),
|
|
||||||
)(state),
|
|
||||||
lastPageReached: makeSelectResolvedSearchResultsLastPageReached(
|
lastPageReached: makeSelectResolvedSearchResultsLastPageReached(
|
||||||
makeSelectQueryWithOptions(null, { size: Constants.DEFAULT_PAGE_SIZE, isBackgroundSearch: false })(state),
|
makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state),
|
||||||
)(state),
|
)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ const select = state => ({
|
||||||
backgroundPlayEnabled: makeSelectClientSetting(SETTINGS.BACKGROUND_PLAY_ENABLED)(state),
|
backgroundPlayEnabled: makeSelectClientSetting(SETTINGS.BACKGROUND_PLAY_ENABLED)(state),
|
||||||
currentRoute: selectCurrentRoute(state),
|
currentRoute: selectCurrentRoute(state),
|
||||||
drawerStack: selectDrawerStack(state),
|
drawerStack: selectDrawerStack(state),
|
||||||
enableDht: makeSelectClientSetting(Constants.SETTING_DHT_ENABLED)(state),
|
|
||||||
keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state),
|
keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state),
|
||||||
language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state),
|
language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state),
|
||||||
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state),
|
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state),
|
||||||
|
@ -30,4 +29,7 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(SettingsPage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(SettingsPage);
|
||||||
|
|
|
@ -1,16 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SETTINGS } from 'lbry-redux';
|
import { SETTINGS } from 'lbry-redux';
|
||||||
import {
|
import { ActivityIndicator, Picker, Platform, Text, View, ScrollView, Switch, NativeModules } from 'react-native';
|
||||||
ActivityIndicator,
|
|
||||||
Picker,
|
|
||||||
Platform,
|
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
View,
|
|
||||||
ScrollView,
|
|
||||||
Switch,
|
|
||||||
NativeModules,
|
|
||||||
} from 'react-native';
|
|
||||||
import { navigateBack } from 'utils/helper';
|
import { navigateBack } from 'utils/helper';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
|
@ -21,27 +11,16 @@ import settingsStyle from 'styles/settings';
|
||||||
|
|
||||||
const languageOptions = [
|
const languageOptions = [
|
||||||
{ code: 'default', name: 'Use device language' },
|
{ code: 'default', name: 'Use device language' },
|
||||||
{ code: 'jv', name: 'Basa Jawa' },
|
|
||||||
{ code: 'da', name: 'Danish' },
|
|
||||||
{ code: 'nl', name: 'Dutch' },
|
|
||||||
{ code: 'en', name: 'English' },
|
{ code: 'en', name: 'English' },
|
||||||
{ code: 'et', name: 'Estonian' },
|
|
||||||
{ code: 'fr', name: 'French' },
|
|
||||||
{ code: 'gu', name: 'Gujarati' },
|
{ code: 'gu', name: 'Gujarati' },
|
||||||
{ code: 'hi', name: 'Hindi' },
|
{ code: 'hi', name: 'Hindi' },
|
||||||
{ code: 'id', name: 'Indonesian' },
|
{ code: 'id', name: 'Indonesian' },
|
||||||
{ code: 'it', name: 'Italian' },
|
{ code: 'it', name: 'Italian' },
|
||||||
{ code: 'kn', name: 'Kannada' },
|
|
||||||
{ code: 'ms', name: 'Malay' },
|
{ code: 'ms', name: 'Malay' },
|
||||||
{ code: 'mr', name: 'Marathi' },
|
{ code: 'tr', name: 'Turkish' },
|
||||||
{ code: 'pl', name: 'Polish' },
|
{ code: 'pl', name: 'Polish' },
|
||||||
{ code: 'pt', name: 'Portuguese' },
|
{ code: 'pt', name: 'Portuguese' },
|
||||||
{ code: 'ro', name: 'Romanian' },
|
|
||||||
{ code: 'ru', name: 'Russian' },
|
|
||||||
{ code: 'sk', name: 'Slovak' },
|
|
||||||
{ code: 'es', name: 'Spanish' },
|
{ code: 'es', name: 'Spanish' },
|
||||||
{ code: 'tr', name: 'Turkish' },
|
|
||||||
{ code: 'uk', name: 'Ukrainian' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
class SettingsPage extends React.PureComponent {
|
class SettingsPage extends React.PureComponent {
|
||||||
|
@ -161,7 +140,6 @@ class SettingsPage extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
backgroundPlayEnabled,
|
backgroundPlayEnabled,
|
||||||
enableDht,
|
|
||||||
keepDaemonRunning,
|
keepDaemonRunning,
|
||||||
receiveSubscriptionNotifications,
|
receiveSubscriptionNotifications,
|
||||||
receiveRewardNotifications,
|
receiveRewardNotifications,
|
||||||
|
@ -179,7 +157,6 @@ class SettingsPage extends React.PureComponent {
|
||||||
const actualReceiveRewardNotifications = this.getBooleanSetting(receiveRewardNotifications, true);
|
const actualReceiveRewardNotifications = this.getBooleanSetting(receiveRewardNotifications, true);
|
||||||
const actualReceiveInterestsNotifications = this.getBooleanSetting(receiveInterestsNotifications, true);
|
const actualReceiveInterestsNotifications = this.getBooleanSetting(receiveInterestsNotifications, true);
|
||||||
const actualReceiveCreatorNotifications = this.getBooleanSetting(receiveCreatorNotifications, true);
|
const actualReceiveCreatorNotifications = this.getBooleanSetting(receiveCreatorNotifications, true);
|
||||||
const actualEnableDht = this.getBooleanSetting(enableDht, false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={settingsStyle.container}>
|
<View style={settingsStyle.container}>
|
||||||
|
@ -317,7 +294,7 @@ class SettingsPage extends React.PureComponent {
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={settingsStyle.description}>
|
<Text style={settingsStyle.description}>
|
||||||
{__(
|
{__(
|
||||||
'Enable this option for quicker app launch and to keep the synchronisation with the blockchain up to date.',
|
'Enable this option for quicker app launch and to keep the synchronisation with the blockchain up to date.'
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
@ -333,25 +310,6 @@ class SettingsPage extends React.PureComponent {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={settingsStyle.row}>
|
|
||||||
<View style={settingsStyle.switchText}>
|
|
||||||
<Text style={settingsStyle.label}>{__('Participate in the data network')}</Text>
|
|
||||||
<Text style={settingsStyle.description}>
|
|
||||||
{__(
|
|
||||||
'Enable peer-to-peer functionality (this will take effect upon app and background service restart)',
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View style={settingsStyle.switchContainer}>
|
|
||||||
<Switch
|
|
||||||
value={actualEnableDht}
|
|
||||||
onValueChange={value => {
|
|
||||||
this.setNativeBooleanSetting(Constants.SETTING_DHT_ENABLED, value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { SETTINGS, doUpdateBlockHeight, doPopulateSharedUserState, doToast } from 'lbry-redux';
|
import { SETTINGS, doBalanceSubscribe, doUpdateBlockHeight, doPopulateSharedUserState, doToast } from 'lbry-redux';
|
||||||
import {
|
import {
|
||||||
doAuthenticate,
|
doAuthenticate,
|
||||||
doClaimRewardType,
|
doBlackListedOutpointsSubscribe,
|
||||||
doInstallNewWithParams,
|
doFilteredOutpointsSubscribe,
|
||||||
doFetchMySubscriptions,
|
doFetchMySubscriptions,
|
||||||
doFetchRewardedContent,
|
doFetchRewardedContent,
|
||||||
doGetSync,
|
doGetSync,
|
||||||
|
@ -26,10 +26,10 @@ const select = state => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
authenticate: (appVersion, os, firebaseToken, callInstall) =>
|
authenticate: (appVersion, os, firebaseToken) => dispatch(doAuthenticate(appVersion, os, firebaseToken)),
|
||||||
dispatch(doAuthenticate(appVersion, os, firebaseToken, true, null, callInstall)),
|
balanceSubscribe: () => dispatch(doBalanceSubscribe()),
|
||||||
installNewWithParams: (appVersion, installationId, nodeId, lbrynetVersion, os, platform, firebaseToken) =>
|
blacklistedOutpointsSubscribe: () => dispatch(doBlackListedOutpointsSubscribe()),
|
||||||
dispatch(doInstallNewWithParams(appVersion, installationId, nodeId, lbrynetVersion, os, platform, firebaseToken)),
|
filteredOutpointsSubscribe: () => dispatch(doFilteredOutpointsSubscribe()),
|
||||||
fetchRewardedContent: () => dispatch(doFetchRewardedContent()),
|
fetchRewardedContent: () => dispatch(doFetchRewardedContent()),
|
||||||
fetchSubscriptions: callback => dispatch(doFetchMySubscriptions(callback)),
|
fetchSubscriptions: callback => dispatch(doFetchMySubscriptions(callback)),
|
||||||
getSync: (password, callback) => dispatch(doGetSync(password, callback)),
|
getSync: (password, callback) => dispatch(doGetSync(password, callback)),
|
||||||
|
@ -42,4 +42,7 @@ const perform = dispatch => ({
|
||||||
verifyUserEmailFailure: error => dispatch(doUserEmailVerifyFailure(error)),
|
verifyUserEmailFailure: error => dispatch(doUserEmailVerifyFailure(error)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(SplashScreen);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(SplashScreen);
|
||||||
|
|
|
@ -23,12 +23,9 @@ class SplashScreen extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
authWithoutSdk: false,
|
|
||||||
accountUnlockFailed: false,
|
accountUnlockFailed: false,
|
||||||
appVersion: null,
|
|
||||||
daemonReady: false,
|
daemonReady: false,
|
||||||
details: __('Starting up'),
|
details: __('Starting up'),
|
||||||
firebaseToken: null,
|
|
||||||
message: __('Connecting'),
|
message: __('Connecting'),
|
||||||
isRunning: false,
|
isRunning: false,
|
||||||
isLagging: false,
|
isLagging: false,
|
||||||
|
@ -37,57 +34,12 @@ class SplashScreen extends React.PureComponent {
|
||||||
headersDownloadProgress: 0,
|
headersDownloadProgress: 0,
|
||||||
shouldAuthenticate: false,
|
shouldAuthenticate: false,
|
||||||
subscriptionsFetched: false,
|
subscriptionsFetched: false,
|
||||||
liteMode: false,
|
|
||||||
liteModeParams: {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
initLiteMode = () => {
|
|
||||||
NativeModules.UtilityModule.getLbrynetDirectory().then(path => {
|
|
||||||
NativeModules.UtilityModule.getPlatform().then(platform => {
|
|
||||||
RNFS.readFile(`${path}/install_id`, 'utf8')
|
|
||||||
.then(installIdContent => {
|
|
||||||
// node_id is actually optional (won't be present if dht is disabled)
|
|
||||||
// RNFS.readFile(`${path}/node_id`, 'utf8').then(nodeIdContent => {
|
|
||||||
// TODO: Load proper lbrynetVersion value
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
liteModeParams: {
|
|
||||||
installationId: installIdContent,
|
|
||||||
nodeId: null,
|
|
||||||
lbrynetVersion: '0.64.0',
|
|
||||||
platform,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
() => this.updateStatus(),
|
|
||||||
);
|
|
||||||
// }).catch((err) => { console.log(err); console.log('node_id not found.'); this.lbryConnect() });
|
|
||||||
})
|
|
||||||
.catch(() => this.lbryConnect());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
authenticateWithoutSdk() {
|
|
||||||
const { authenticate } = this.props;
|
|
||||||
NativeModules.VersionInfo.getAppVersion().then(appVersion => {
|
|
||||||
this.setState({ appVersion, shouldAuthenticate: true, authWithoutSdk: true });
|
|
||||||
NativeModules.Firebase.getMessagingToken()
|
|
||||||
.then(firebaseToken => {
|
|
||||||
this.setState({ firebaseToken }, () => authenticate(appVersion, Platform.OS, firebaseToken, false));
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
authenticate(appVersion, Platform.OS, null, false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updateStatus() {
|
updateStatus() {
|
||||||
const { liteMode } = this.state;
|
Lbry.status().then(status => {
|
||||||
|
this._updateStatusCallback(status);
|
||||||
// authenticate immediately
|
});
|
||||||
if (!NativeModules.UtilityModule.dhtEnabled) {
|
|
||||||
this.authenticateWithoutSdk();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateToMain = () => {
|
navigateToMain = () => {
|
||||||
|
@ -115,43 +67,15 @@ 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) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { getSync, installNewWithParams } = this.props;
|
const { emailToVerify, getSync, setEmailToVerify, verifyUserEmail, verifyUserEmailFailure } = this.props;
|
||||||
const {
|
const { daemonReady, shouldAuthenticate } = this.state;
|
||||||
daemonReady,
|
|
||||||
authWithoutSdk,
|
|
||||||
shouldAuthenticate,
|
|
||||||
liteMode,
|
|
||||||
liteModeParams,
|
|
||||||
appVersion,
|
|
||||||
firebaseToken,
|
|
||||||
} = this.state;
|
|
||||||
const { user } = nextProps;
|
const { user } = nextProps;
|
||||||
|
|
||||||
if (liteMode && user && user.id) {
|
if (daemonReady && shouldAuthenticate && user && user.id) {
|
||||||
this.navigateToLiteMode();
|
|
||||||
} else if (shouldAuthenticate && user && user.id) {
|
|
||||||
if (daemonReady || authWithoutSdk) {
|
|
||||||
this.setState({ shouldAuthenticate: false }, () => {
|
this.setState({ shouldAuthenticate: false }, () => {
|
||||||
// call install new after successful authentication
|
|
||||||
if (authWithoutSdk) {
|
|
||||||
const { installationId, nodeId, lbrynetVersion, platform } = liteModeParams;
|
|
||||||
installNewWithParams(
|
|
||||||
appVersion,
|
|
||||||
installationId,
|
|
||||||
nodeId,
|
|
||||||
lbrynetVersion,
|
|
||||||
Platform.OS,
|
|
||||||
platform,
|
|
||||||
firebaseToken,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// user is authenticated, navigate to the main view
|
// user is authenticated, navigate to the main view
|
||||||
if (user.has_verified_email) {
|
if (user.has_verified_email) {
|
||||||
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(walletPassword => {
|
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(walletPassword => {
|
||||||
|
@ -159,7 +83,6 @@ class SplashScreen extends React.PureComponent {
|
||||||
this.getUserSettings();
|
this.getUserSettings();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.navigateToMain();
|
this.navigateToMain();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -168,22 +91,6 @@ class SplashScreen extends React.PureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
navigateToLiteMode = () => {
|
|
||||||
const { navigation } = this.props;
|
|
||||||
const { launchUrl } = this.state;
|
|
||||||
const resetAction = StackActions.reset({
|
|
||||||
index: 0,
|
|
||||||
actions: [
|
|
||||||
NavigationActions.navigate({
|
|
||||||
routeName: Constants.DRAWER_ROUTE_LITE_FILE,
|
|
||||||
params: { uri: launchUrl },
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
navigation.dispatch(resetAction);
|
|
||||||
};
|
|
||||||
|
|
||||||
getUserSettings = () => {
|
getUserSettings = () => {
|
||||||
const { populateSharedUserState } = this.props;
|
const { populateSharedUserState } = this.props;
|
||||||
|
@ -206,9 +113,22 @@ class SplashScreen extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
finishSplashScreen = () => {
|
finishSplashScreen = () => {
|
||||||
const { authenticate, getSync, user } = this.props;
|
const {
|
||||||
|
authenticate,
|
||||||
|
balanceSubscribe,
|
||||||
|
blacklistedOutpointsSubscribe,
|
||||||
|
filteredOutpointsSubscribe,
|
||||||
|
getSync,
|
||||||
|
updateBlockHeight,
|
||||||
|
user,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
// Lbry.resolve({ urls: 'lbry://one' }).then(() => {
|
||||||
// Leave the splash screen
|
// Leave the splash screen
|
||||||
|
balanceSubscribe();
|
||||||
|
blacklistedOutpointsSubscribe();
|
||||||
|
filteredOutpointsSubscribe();
|
||||||
|
|
||||||
if (user && user.id && user.has_verified_email) {
|
if (user && user.id && user.has_verified_email) {
|
||||||
// user already authenticated
|
// user already authenticated
|
||||||
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(walletPassword => {
|
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(walletPassword => {
|
||||||
|
@ -222,20 +142,37 @@ class SplashScreen extends React.PureComponent {
|
||||||
this.setState({ shouldAuthenticate: true }, () => {
|
this.setState({ shouldAuthenticate: true }, () => {
|
||||||
NativeModules.Firebase.getMessagingToken()
|
NativeModules.Firebase.getMessagingToken()
|
||||||
.then(firebaseToken => {
|
.then(firebaseToken => {
|
||||||
authenticate(appVersion, Platform.OS, firebaseToken, true);
|
authenticate(appVersion, Platform.OS, firebaseToken);
|
||||||
})
|
})
|
||||||
.catch(() => authenticate(appVersion, Platform.OS, null, true));
|
.catch(() => authenticate(appVersion, Platform.OS));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// });
|
||||||
};
|
};
|
||||||
|
|
||||||
handleAccountUnlockFailed() {
|
handleAccountUnlockFailed() {
|
||||||
this.setState({ accountUnlockFailed: true });
|
this.setState({ accountUnlockFailed: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSdkReady = () => {
|
_updateStatusCallback(status) {
|
||||||
this.setState({ daemonReady: true }, () => {
|
const { fetchSubscriptions, getSync, setClientSetting } = this.props;
|
||||||
|
const startupStatus = status.startup_status;
|
||||||
|
const walletStatus = status.wallet;
|
||||||
|
|
||||||
|
// At the minimum, wallet should be started and blocks_behind equal to 0 before calling resolve
|
||||||
|
const hasStarted = startupStatus.stream_manager && startupStatus.wallet && status.wallet.blocks_behind <= 0;
|
||||||
|
if (hasStarted) {
|
||||||
|
// Wait until we are able to resolve a name before declaring
|
||||||
|
// that we are done.
|
||||||
|
// TODO: This is a hack, and the logic should live in the daemon
|
||||||
|
// to give us a better sense of when we are actually started
|
||||||
|
this.setState({
|
||||||
|
daemonReady: true,
|
||||||
|
isLagging: false,
|
||||||
|
isRunning: true,
|
||||||
|
});
|
||||||
|
|
||||||
Lbry.wallet_status().then(secureWalletStatus => {
|
Lbry.wallet_status().then(secureWalletStatus => {
|
||||||
// For now, automatically unlock the wallet if a password is set so that downloads work
|
// For now, automatically unlock the wallet if a password is set so that downloads work
|
||||||
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(password => {
|
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(password => {
|
||||||
|
@ -266,12 +203,9 @@ class SplashScreen extends React.PureComponent {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSdkStatusResponse = evt => {
|
return;
|
||||||
const { status } = evt;
|
}
|
||||||
const walletStatus = status.wallet;
|
|
||||||
|
|
||||||
const headerSyncProgress = walletStatus ? walletStatus.headers_synchronization_progress : null;
|
const headerSyncProgress = walletStatus ? walletStatus.headers_synchronization_progress : null;
|
||||||
if (headerSyncProgress && headerSyncProgress < 100) {
|
if (headerSyncProgress && headerSyncProgress < 100) {
|
||||||
|
@ -306,61 +240,36 @@ class SplashScreen extends React.PureComponent {
|
||||||
details: __('Initializing LBRY service'),
|
details: __('Initializing LBRY service'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.updateStatus();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
DeviceEventEmitter.addListener('onNotificationTargetLaunch', this.onNotificationTargetLaunch);
|
DeviceEventEmitter.addListener('onNotificationTargetLaunch', this.onNotificationTargetLaunch);
|
||||||
DeviceEventEmitter.addListener('onSdkReady', this.handleSdkReady);
|
|
||||||
DeviceEventEmitter.addListener('onSdkStatusResponse', this.handleSdkStatusResponse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
DeviceEventEmitter.removeListener('onNotificationTargetLaunch', this.onNotificationTargetLaunch);
|
DeviceEventEmitter.removeListener('onNotificationTargetLaunch', this.onNotificationTargetLaunch);
|
||||||
DeviceEventEmitter.removeListener('onSdkReady', this.handleSdkReady);
|
|
||||||
DeviceEventEmitter.removeListener('onSdkStatusResponse', this.handleSdkStatusResponse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
NativeModules.Firebase.track('app_launch', null);
|
NativeModules.Firebase.track('app_launch', null);
|
||||||
NativeModules.Firebase.setCurrentScreen('Splash');
|
NativeModules.Firebase.setCurrentScreen('Splash');
|
||||||
NativeModules.UtilityModule.checkSdkReady();
|
|
||||||
|
|
||||||
const { navigation } = this.props;
|
|
||||||
const { resetUrl } = navigation.state.params;
|
|
||||||
const isResetUrlSet = !!resetUrl;
|
|
||||||
|
|
||||||
this.props.fetchRewardedContent();
|
this.props.fetchRewardedContent();
|
||||||
Linking.getInitialURL().then(url => {
|
Linking.getInitialURL().then(url => {
|
||||||
let liteMode;
|
|
||||||
if (url) {
|
if (url) {
|
||||||
liteMode = !isResetUrlSet && url.indexOf('liteMode=1') > -1;
|
this.setState({ launchUrl: url });
|
||||||
this.setState({ launchUrl: resetUrl || url, liteMode });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeModules.UtilityModule.getNotificationLaunchTarget().then(target => {
|
NativeModules.UtilityModule.getNotificationLaunchTarget().then(target => {
|
||||||
if (target) {
|
if (target) {
|
||||||
liteMode = !isResetUrlSet && target.indexOf('liteMode=1') > -1;
|
this.setState({ launchUrl: target });
|
||||||
this.setState({ launchUrl: resetUrl || target, liteMode });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only connect after checking initial launch url / notification launch target
|
// Only connect after checking initial launch url / notification launch target
|
||||||
this.initLiteMode();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Start measuring the first launch time from the splash screen
|
|
||||||
// (time to first user interaction - after first run completed)
|
|
||||||
AsyncStorage.getItem('hasLaunched').then(value => {
|
|
||||||
if (value !== 'true') {
|
|
||||||
AsyncStorage.setItem('hasLaunched', 'true');
|
|
||||||
// only set firstLaunchTime since we've determined that this is the first app launch ever
|
|
||||||
AsyncStorage.setItem('firstLaunchTime', String(moment().unix()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
lbryConnect = () => {
|
|
||||||
if (NativeModules.UtilityModule.dhtEnabled) {
|
|
||||||
Lbry.connect()
|
Lbry.connect()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.updateStatus();
|
this.updateStatus();
|
||||||
|
@ -374,10 +283,19 @@ class SplashScreen extends React.PureComponent {
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
});
|
||||||
this.updateStatus(); // skip lbry.connect for now (unless dht flag is enabled)
|
});
|
||||||
|
|
||||||
|
// Start measuring the first launch time from the splash screen
|
||||||
|
// (time to first user interaction - after first run completed)
|
||||||
|
AsyncStorage.getItem('hasLaunched').then(value => {
|
||||||
|
if (value !== 'true') {
|
||||||
|
AsyncStorage.setItem('hasLaunched', 'true');
|
||||||
|
// only set firstLaunchTime since we've determined that this is the first app launch ever
|
||||||
|
AsyncStorage.setItem('firstLaunchTime', String(moment().unix()));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
handleContinueAnywayPressed = () => {
|
handleContinueAnywayPressed = () => {
|
||||||
this.setState(
|
this.setState(
|
||||||
|
|
|
@ -7,18 +7,16 @@ import {
|
||||||
selectSubscriptionClaims,
|
selectSubscriptionClaims,
|
||||||
selectSubscriptions,
|
selectSubscriptions,
|
||||||
selectIsFetchingSubscriptions,
|
selectIsFetchingSubscriptions,
|
||||||
|
selectIsFetchingSuggested,
|
||||||
selectSuggestedChannels,
|
selectSuggestedChannels,
|
||||||
selectUnreadSubscriptions,
|
selectUnreadSubscriptions,
|
||||||
selectViewMode,
|
selectViewMode,
|
||||||
selectFirstRunCompleted,
|
selectFirstRunCompleted,
|
||||||
selectShowSuggestedSubs,
|
selectShowSuggestedSubs,
|
||||||
selectUnclaimedRewardValue,
|
|
||||||
selectUser,
|
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { doToast, selectFetchingClaimSearch } from 'lbry-redux';
|
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doSetClientSetting, doSetTimeItem } from 'redux/actions/settings';
|
import { doSetClientSetting, doSetTimeItem } from 'redux/actions/settings';
|
||||||
import { makeSelectClientSetting, selectSdkReady, selectTimeItem } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectTimeItem } from 'redux/selectors/settings';
|
||||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import SubscriptionsPage from './view';
|
import SubscriptionsPage from './view';
|
||||||
|
@ -26,7 +24,7 @@ import SubscriptionsPage from './view';
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
currentRoute: selectCurrentRoute(state),
|
currentRoute: selectCurrentRoute(state),
|
||||||
loading: selectIsFetchingSubscriptions(state),
|
loading: selectIsFetchingSubscriptions(state),
|
||||||
loadingSuggested: selectFetchingClaimSearch(state),
|
loadingSuggested: selectIsFetchingSuggested(state),
|
||||||
subscribedChannels: selectSubscriptions(state),
|
subscribedChannels: selectSubscriptions(state),
|
||||||
suggestedChannels: selectSuggestedChannels(state),
|
suggestedChannels: selectSuggestedChannels(state),
|
||||||
subscriptionsViewMode: makeSelectClientSetting(Constants.SETTING_SUBSCRIPTIONS_VIEW_MODE)(state),
|
subscriptionsViewMode: makeSelectClientSetting(Constants.SETTING_SUBSCRIPTIONS_VIEW_MODE)(state),
|
||||||
|
@ -34,12 +32,8 @@ const select = state => ({
|
||||||
unreadSubscriptions: selectUnreadSubscriptions(state),
|
unreadSubscriptions: selectUnreadSubscriptions(state),
|
||||||
viewMode: selectViewMode(state),
|
viewMode: selectViewMode(state),
|
||||||
firstRunCompleted: selectFirstRunCompleted(state),
|
firstRunCompleted: selectFirstRunCompleted(state),
|
||||||
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
|
||||||
showSuggestedSubs: selectShowSuggestedSubs(state),
|
showSuggestedSubs: selectShowSuggestedSubs(state),
|
||||||
timeItem: selectTimeItem(state),
|
timeItem: selectTimeItem(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
unclaimedRewardAmount: selectUnclaimedRewardValue(state),
|
|
||||||
user: selectUser(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -47,11 +41,13 @@ const perform = dispatch => ({
|
||||||
doFetchMySubscriptions: () => dispatch(doFetchMySubscriptions()),
|
doFetchMySubscriptions: () => dispatch(doFetchMySubscriptions()),
|
||||||
doFetchRecommendedSubscriptions: () => dispatch(doFetchRecommendedSubscriptions()),
|
doFetchRecommendedSubscriptions: () => dispatch(doFetchRecommendedSubscriptions()),
|
||||||
doSetViewMode: viewMode => dispatch(doSetViewMode(viewMode)),
|
doSetViewMode: viewMode => dispatch(doSetViewMode(viewMode)),
|
||||||
notify: data => dispatch(doToast(data)),
|
|
||||||
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SUBSCRIPTIONS)),
|
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SUBSCRIPTIONS)),
|
||||||
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
|
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(SubscriptionsPage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(SubscriptionsPage);
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { buildURI, parseURI } from 'lbry-redux';
|
import { buildURI, parseURI } from 'lbry-redux';
|
||||||
import { formatUsd, getOrderBy } from 'utils/helper';
|
import { getOrderBy } from 'utils/helper';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -28,24 +28,17 @@ import ModalPicker from 'component/modalPicker';
|
||||||
import ModalSuggestedSubscriptions from 'component/modalSuggestedSubscriptions';
|
import ModalSuggestedSubscriptions from 'component/modalSuggestedSubscriptions';
|
||||||
import SubscribedChannelList from 'component/subscribedChannelList';
|
import SubscribedChannelList from 'component/subscribedChannelList';
|
||||||
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
|
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
|
||||||
import SuggestedSubscriptionsGrid from 'component/suggestedSubscriptionsGrid';
|
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import SdkLoadingStatus from 'component/sdkLoadingStatus';
|
|
||||||
import Snackbar from 'react-native-snackbar';
|
|
||||||
import { Lbryio } from 'lbryinc';
|
|
||||||
|
|
||||||
class SubscriptionsPage extends React.PureComponent {
|
class SubscriptionsPage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1], // should always default to sorting subscriptions by new
|
|
||||||
filteredChannels: [],
|
|
||||||
orderBy: ['release_time'],
|
|
||||||
showRewardsNag: true,
|
|
||||||
showingSuggestedSubs: false,
|
showingSuggestedSubs: false,
|
||||||
showSortPicker: false,
|
showSortPicker: false,
|
||||||
showTimePicker: false,
|
showTimePicker: false,
|
||||||
showModalSuggestedSubs: false,
|
showModalSuggestedSubs: false,
|
||||||
usdExchangeRate: 0,
|
orderBy: ['release_time'],
|
||||||
userEmailVerified: false,
|
filteredChannels: [],
|
||||||
|
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1], // should always default to sorting subscriptions by new
|
||||||
};
|
};
|
||||||
|
|
||||||
didFocusListener;
|
didFocusListener;
|
||||||
|
@ -62,26 +55,21 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
onComponentFocused = () => {
|
onComponentFocused = () => {
|
||||||
const { currentRoute, doFetchMySubscriptions, pushDrawerStack, sdkReady, setPlayerVisible, user } = this.props;
|
const {
|
||||||
|
doFetchMySubscriptions,
|
||||||
|
doFetchRecommendedSubscriptions,
|
||||||
|
doSetViewMode,
|
||||||
|
pushDrawerStack,
|
||||||
|
setPlayerVisible,
|
||||||
|
subscriptionsViewMode,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
if (currentRoute === Constants.DRAWER_ROUTE_SUBSCRIPTIONS) {
|
|
||||||
pushDrawerStack();
|
pushDrawerStack();
|
||||||
}
|
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
NativeModules.Firebase.setCurrentScreen('Subscriptions');
|
NativeModules.Firebase.setCurrentScreen('Subscriptions');
|
||||||
|
|
||||||
Lbryio.getExchangeRates().then(rates => {
|
|
||||||
if (!isNaN(rates.LBC_USD)) {
|
|
||||||
this.setState({ usdExchangeRate: rates.LBC_USD }, () => {
|
|
||||||
if (sdkReady && parseFloat(this.state.usdExchangeRate) > 0 && user && !user.is_reward_approved) {
|
|
||||||
this.showRewardsAvailable();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setState({ userEmailVerified: user && user.has_verified_email });
|
|
||||||
doFetchMySubscriptions();
|
doFetchMySubscriptions();
|
||||||
|
doFetchRecommendedSubscriptions();
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -89,69 +77,19 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { currentRoute, user, sdkReady } = nextProps;
|
const { currentRoute } = nextProps;
|
||||||
const { currentRoute: prevRoute, doFetchMySubscriptions } = this.props;
|
const { currentRoute: prevRoute } = this.props;
|
||||||
if (Constants.DRAWER_ROUTE_SUBSCRIPTIONS === currentRoute && currentRoute !== prevRoute) {
|
if (Constants.DRAWER_ROUTE_SUBSCRIPTIONS === currentRoute && currentRoute !== prevRoute) {
|
||||||
this.onComponentFocused();
|
this.onComponentFocused();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user && user.has_verified_email && !this.state.userEmailVerified) {
|
|
||||||
// user just signed in
|
|
||||||
this.setState({ showingSuggestedSubs: false, userEmailVerified: true }, () => {
|
|
||||||
doFetchMySubscriptions();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
sdkReady &&
|
|
||||||
parseFloat(this.state.usdExchangeRate) > 0 &&
|
|
||||||
this.state.showRewardsNag &&
|
|
||||||
user &&
|
|
||||||
!user.is_reward_approved
|
|
||||||
) {
|
|
||||||
this.showRewardsAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.unsubscribeShortChannelUrls();
|
this.unsubscribeShortChannelUrls();
|
||||||
}
|
}
|
||||||
|
|
||||||
showRewardsAvailable = () => {
|
|
||||||
const { navigation, unclaimedRewardAmount, rewardsNotInterested } = this.props;
|
|
||||||
if (rewardsNotInterested) {
|
|
||||||
this.setState({ showRewardsNag: false });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ showRewardsNag: false }, () => {
|
|
||||||
Snackbar.show({
|
|
||||||
title: __('Did you know that you can earn free credits worth up to %amount%?', {
|
|
||||||
amount: formatUsd(parseFloat(this.state.usdExchangeRate) * parseFloat(unclaimedRewardAmount)),
|
|
||||||
}),
|
|
||||||
duration: Snackbar.LENGTH_LONG,
|
|
||||||
action: {
|
|
||||||
title: __('SHOW ME'),
|
|
||||||
color: Colors.LbryGreen,
|
|
||||||
onPress: () => {
|
|
||||||
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_REWARDS });
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSortByItemSelected = item => {
|
handleSortByItemSelected = item => {
|
||||||
this.setState({ currentSortByItem: item, orderBy: getOrderBy(item), showSortPicker: false });
|
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 => {
|
handleTimeItemSelected = item => {
|
||||||
const { setTimeItem } = this.props;
|
const { setTimeItem } = this.props;
|
||||||
setTimeItem(item);
|
setTimeItem(item);
|
||||||
|
@ -187,7 +125,20 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { subscribedChannels, loading, loadingSuggested, sdkReady, timeItem, navigation, notify } = this.props;
|
const {
|
||||||
|
suggestedChannels,
|
||||||
|
subscribedChannels,
|
||||||
|
allSubscriptions,
|
||||||
|
doCompleteFirstRun,
|
||||||
|
doShowSuggestedSubs,
|
||||||
|
loading,
|
||||||
|
loadingSuggested,
|
||||||
|
firstRunCompleted,
|
||||||
|
showSuggestedSubs,
|
||||||
|
timeItem,
|
||||||
|
unreadSubscriptions,
|
||||||
|
navigation,
|
||||||
|
} = this.props;
|
||||||
const { currentSortByItem, filteredChannels, showModalSuggestedSubs, showSortPicker, showTimePicker } = this.state;
|
const { currentSortByItem, filteredChannels, showModalSuggestedSubs, showSortPicker, showTimePicker } = this.state;
|
||||||
|
|
||||||
const numberOfSubscriptions = subscribedChannels ? subscribedChannels.length : 0;
|
const numberOfSubscriptions = subscribedChannels ? subscribedChannels.length : 0;
|
||||||
|
@ -213,11 +164,7 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
<View style={subscriptionsStyle.container}>
|
<View style={subscriptionsStyle.container}>
|
||||||
<UriBar navigation={navigation} belowOverlay={this.state.showSortPicker} />
|
<UriBar navigation={navigation} belowOverlay={this.state.showSortPicker} />
|
||||||
<View style={subscriptionsStyle.titleRow}>
|
<View style={subscriptionsStyle.titleRow}>
|
||||||
<Text style={subscriptionsStyle.pageTitle}>
|
<Text style={subscriptionsStyle.pageTitle}>{__('Channels you follow')}</Text>
|
||||||
{hasSubscriptions && !this.state.showingSuggestedSubs
|
|
||||||
? __('Channels you follow')
|
|
||||||
: __('Find Channels to follow')}
|
|
||||||
</Text>
|
|
||||||
</View>
|
</View>
|
||||||
{!this.state.showingSuggestedSubs && hasSubscriptions && (
|
{!this.state.showingSuggestedSubs && hasSubscriptions && (
|
||||||
<View style={subscriptionsStyle.pickerRow}>
|
<View style={subscriptionsStyle.pickerRow}>
|
||||||
|
@ -243,7 +190,7 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
style={subscriptionsStyle.suggestedLink}
|
style={subscriptionsStyle.suggestedLink}
|
||||||
text={__('Discover')}
|
text={__('Suggested')}
|
||||||
onPress={() => this.setState({ showModalSuggestedSubs: true })}
|
onPress={() => this.setState({ showModalSuggestedSubs: true })}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
@ -273,40 +220,39 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
|
|
||||||
{this.state.showingSuggestedSubs && (
|
{this.state.showingSuggestedSubs && (
|
||||||
<View style={subscriptionsStyle.suggestedSubsContainer}>
|
<View style={subscriptionsStyle.suggestedSubsContainer}>
|
||||||
|
{!hasSubscriptions && (
|
||||||
<View style={subscriptionsStyle.infoArea}>
|
<View style={subscriptionsStyle.infoArea}>
|
||||||
<Text style={subscriptionsStyle.infoText}>
|
<Text style={subscriptionsStyle.infoText}>
|
||||||
{__(
|
{__('You are not subscribed to any channels at the moment.')}
|
||||||
'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>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
<View style={subscriptionsStyle.mainSuggested}>
|
{hasSubscriptions && (
|
||||||
<SuggestedSubscriptionsGrid navigation={navigation} />
|
<View style={subscriptionsStyle.infoArea}>
|
||||||
</View>
|
<Text style={subscriptionsStyle.infoText}>
|
||||||
|
You are currently subscribed to {numberOfSubscriptions} channel{numberOfSubscriptions > 1 ? 's' : ''}.
|
||||||
|
</Text>
|
||||||
<Button
|
<Button
|
||||||
style={subscriptionsStyle.suggestedDoneButton}
|
style={subscriptionsStyle.button}
|
||||||
text={
|
text={__('View my subscriptions')}
|
||||||
numberOfSubscriptions < 5
|
onPress={() => this.setState({ showingSuggestedSubs: false })}
|
||||||
? __('%remaining% more...', { remaining: 5 - numberOfSubscriptions })
|
|
||||||
: __('Done')
|
|
||||||
}
|
|
||||||
onPress={() => {
|
|
||||||
if (!hasSubscriptions) {
|
|
||||||
notify({ message: __('Tap on any channel to follow') });
|
|
||||||
} else {
|
|
||||||
this.setState({ showingSuggestedSubs: false });
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
{loadingSuggested && (
|
{loadingSuggested && (
|
||||||
<ActivityIndicator size="small" color={Colors.White} style={subscriptionsStyle.suggestedLoading} />
|
<View style={subscriptionsStyle.centered}>
|
||||||
|
<ActivityIndicator size="large" colors={Colors.NextLbryGreen} style={subscriptionsStyle.loading} />
|
||||||
|
</View>
|
||||||
)}
|
)}
|
||||||
|
{!loadingSuggested && <SuggestedSubscriptions navigation={navigation} />}
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{!showSortPicker && !showTimePicker && !showModalSuggestedSubs && (
|
||||||
|
<FloatingWalletBalance navigation={navigation} />
|
||||||
|
)}
|
||||||
{showSortPicker && (
|
{showSortPicker && (
|
||||||
<ModalPicker
|
<ModalPicker
|
||||||
title={__('Sort content by')}
|
title={__('Sort content by')}
|
||||||
|
@ -332,8 +278,6 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
onDonePress={() => this.setState({ showModalSuggestedSubs: false })}
|
onDonePress={() => this.setState({ showModalSuggestedSubs: false })}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!sdkReady && <SdkLoadingStatus />}
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,11 @@ import { selectFollowedTags, doToggleTagFollow } from 'lbry-redux';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
import { doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
||||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||||
import { selectSdkReady, selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
import { selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
||||||
import TagPage from './view';
|
import TagPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
currentRoute: selectCurrentRoute(state),
|
currentRoute: selectCurrentRoute(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
sortByItem: selectSortByItem(state),
|
sortByItem: selectSortByItem(state),
|
||||||
timeItem: selectTimeItem(state),
|
timeItem: selectTimeItem(state),
|
||||||
followedTags: selectFollowedTags(state),
|
followedTags: selectFollowedTags(state),
|
||||||
|
@ -22,4 +21,7 @@ const perform = dispatch => ({
|
||||||
toggleTagFollow: tag => dispatch(doToggleTagFollow(tag)),
|
toggleTagFollow: tag => dispatch(doToggleTagFollow(tag)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(TagPage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(TagPage);
|
||||||
|
|
|
@ -14,7 +14,6 @@ import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import ModalPicker from 'component/modalPicker';
|
import ModalPicker from 'component/modalPicker';
|
||||||
import SdkLoadingStatus from 'component/sdkLoadingStatus';
|
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
|
|
||||||
class TagPage extends React.PureComponent {
|
class TagPage extends React.PureComponent {
|
||||||
|
@ -128,7 +127,7 @@ class TagPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { navigation, sdkReady, sortByItem, timeItem } = this.props;
|
const { navigation, sortByItem, timeItem } = this.props;
|
||||||
const { tag, showSortPicker, showTimePicker } = this.state;
|
const { tag, showSortPicker, showTimePicker } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -145,7 +144,7 @@ class TagPage extends React.PureComponent {
|
||||||
orientation={Constants.ORIENTATION_VERTICAL}
|
orientation={Constants.ORIENTATION_VERTICAL}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{sdkReady && !showSortPicker && !showTimePicker && <FloatingWalletBalance navigation={navigation} />}
|
{!showSortPicker && !showTimePicker && <FloatingWalletBalance navigation={navigation} />}
|
||||||
{showSortPicker && (
|
{showSortPicker && (
|
||||||
<ModalPicker
|
<ModalPicker
|
||||||
title={__('Sort content by')}
|
title={__('Sort content by')}
|
||||||
|
@ -164,7 +163,6 @@ class TagPage extends React.PureComponent {
|
||||||
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!sdkReady && <SdkLoadingStatus />}
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
import { makeSelectClientSetting, selectSdkReady } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||||
import { selectBalance } from 'lbry-redux';
|
import { selectBalance } from 'lbry-redux';
|
||||||
|
@ -15,7 +15,6 @@ const select = state => ({
|
||||||
deviceWalletSynced: makeSelectClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED)(state),
|
deviceWalletSynced: makeSelectClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED)(state),
|
||||||
hasSyncedWallet: selectHasSyncedWallet(state),
|
hasSyncedWallet: selectHasSyncedWallet(state),
|
||||||
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
||||||
sdkReady: selectSdkReady(state),
|
|
||||||
understandsRisks: makeSelectClientSetting(Constants.SETTING_ALPHA_UNDERSTANDS_RISKS)(state),
|
understandsRisks: makeSelectClientSetting(Constants.SETTING_ALPHA_UNDERSTANDS_RISKS)(state),
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
});
|
});
|
||||||
|
@ -28,4 +27,7 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(WalletPage);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(WalletPage);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NativeModules, ScrollView, Text, View } from 'react-native';
|
import { NativeModules, ScrollView, Text, View } from 'react-native';
|
||||||
import EmptyStateView from 'component/emptyStateView';
|
|
||||||
import TransactionListRecent from 'component/transactionListRecent';
|
import TransactionListRecent from 'component/transactionListRecent';
|
||||||
import WalletAddress from 'component/walletAddress';
|
import WalletAddress from 'component/walletAddress';
|
||||||
import WalletBalance from 'component/walletBalance';
|
import WalletBalance from 'component/walletBalance';
|
||||||
|
@ -9,6 +8,8 @@ import WalletSend from 'component/walletSend';
|
||||||
import WalletRewardsDriver from 'component/walletRewardsDriver';
|
import WalletRewardsDriver from 'component/walletRewardsDriver';
|
||||||
import WalletSignIn from 'component/walletSignIn';
|
import WalletSignIn from 'component/walletSignIn';
|
||||||
import WalletSyncDriver from 'component/walletSyncDriver';
|
import WalletSyncDriver from 'component/walletSyncDriver';
|
||||||
|
import Button from 'component/button';
|
||||||
|
import Link from 'component/link';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import walletStyle from 'styles/wallet';
|
import walletStyle from 'styles/wallet';
|
||||||
|
@ -59,20 +60,16 @@ class WalletPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { balance, rewardsNotInterested, understandsRisks, navigation, sdkReady, user } = this.props;
|
const {
|
||||||
|
balance,
|
||||||
if (!sdkReady) {
|
backupDismissed,
|
||||||
return (
|
hasSyncedWallet,
|
||||||
<View style={walletStyle.container}>
|
rewardsNotInterested,
|
||||||
<UriBar navigation={navigation} />
|
understandsRisks,
|
||||||
<EmptyStateView
|
setClientSetting,
|
||||||
message={__(
|
navigation,
|
||||||
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
user,
|
||||||
)}
|
} = this.props;
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const signedIn = user && user.has_verified_email;
|
const signedIn = user && user.has_verified_email;
|
||||||
if (!signedIn && !understandsRisks) {
|
if (!signedIn && !understandsRisks) {
|
||||||
|
@ -94,7 +91,7 @@ class WalletPage extends React.PureComponent {
|
||||||
>
|
>
|
||||||
{!rewardsNotInterested && (!balance || balance === 0) && <WalletRewardsDriver navigation={navigation} />}
|
{!rewardsNotInterested && (!balance || balance === 0) && <WalletRewardsDriver navigation={navigation} />}
|
||||||
<WalletBalance />
|
<WalletBalance />
|
||||||
<WalletBalanceExtra navigation={navigation} />
|
<WalletBalanceExtra />
|
||||||
<WalletAddress />
|
<WalletAddress />
|
||||||
<WalletSend />
|
<WalletSend />
|
||||||
<TransactionListRecent navigation={navigation} />
|
<TransactionListRecent navigation={navigation} />
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue