Compare commits
94 commits
master
...
anthony-fi
Author | SHA1 | Date | |
---|---|---|---|
|
11a6c78928 | ||
|
d5e582050a | ||
|
a77e59cb53 | ||
|
4b0a06cef7 | ||
|
00d28fe26e | ||
|
5dd5826b33 | ||
|
cbedc4b933 | ||
|
6b39fc1bbb | ||
|
f8f9b86cb4 | ||
|
1a5fb5fa51 | ||
|
c24153c6ca | ||
|
762bddb158 | ||
|
2922f0f2dc | ||
|
3849683a59 | ||
|
247ee757d1 | ||
|
03f69eff86 | ||
|
08adb805e9 | ||
|
3788ef58ec | ||
|
310fc81bd9 | ||
|
9569b6c7a5 | ||
|
0febd32c71 | ||
|
a90c516c71 | ||
|
dad7264636 | ||
|
27f346d8f1 | ||
|
e2176d0566 | ||
|
17121b2066 | ||
|
1b43c54725 | ||
|
398388de10 | ||
|
b8c763f749 | ||
|
b4f62e78de | ||
|
8c4224f1ce | ||
|
b7685a151d | ||
|
e14ec9b83e | ||
|
23525b0baa | ||
|
d62f63aff8 | ||
|
dcd00c2308 | ||
|
c782f73f30 | ||
|
6ff9a51058 | ||
|
9041e5e38d | ||
|
ce1621f7ed | ||
|
da63991972 | ||
|
b6ad4ae974 | ||
|
5d8fc40051 | ||
|
4b0318cd38 | ||
|
0c2c21b67e | ||
|
9bbd72d179 | ||
|
249b73f8c6 | ||
|
aabfc41ce9 | ||
|
5bcf89394e | ||
|
35072c0400 | ||
|
296febcffa | ||
|
cfdfdce2fe | ||
|
2a7f89d6b5 | ||
|
30023422b8 | ||
|
702297e722 | ||
|
07102c4988 | ||
|
3b442531ef | ||
|
f6e60abbf5 | ||
|
dab1ca1cb7 | ||
|
bba3a17977 | ||
|
4a22814c75 | ||
|
91be939c19 | ||
|
0b0f2848da | ||
|
055d437865 | ||
|
d1493d5fb3 | ||
|
b86a56f75b | ||
|
8498554f23 | ||
|
2505d67a7d | ||
|
03ea298236 | ||
|
a3302b1be8 | ||
|
58db9576b9 | ||
|
a9b9c3ccf0 | ||
|
ea516f88dc | ||
|
5f55a3f128 | ||
|
53063931ab | ||
|
6727e2766b | ||
|
c10fc675db | ||
|
fa889112c5 | ||
|
0e96f8d468 | ||
|
d5ad63c6e9 | ||
|
cd8f90c82d | ||
|
24eb2ef8ec | ||
|
37ddc395ea | ||
|
02a8099514 | ||
|
9dbee19961 | ||
|
b49fed4cf5 | ||
|
2b5d32c313 | ||
|
7c518aa712 | ||
|
6f3c43c95f | ||
|
a168dbcc01 | ||
|
3087f7c367 | ||
|
3f969ae20d | ||
|
19797c747e | ||
|
caadd889ce |
809 changed files with 53963 additions and 42270 deletions
|
@ -15,15 +15,17 @@ COMMENT_SERVER_API=https://comments.odysee.com/api/v2
|
||||||
COMMENT_SERVER_NAME=Odysee
|
COMMENT_SERVER_NAME=Odysee
|
||||||
SEARCH_SERVER_API=https://lighthouse.odysee.com/search
|
SEARCH_SERVER_API=https://lighthouse.odysee.com/search
|
||||||
SOCKETY_SERVER_API=wss://sockety.odysee.com/ws
|
SOCKETY_SERVER_API=wss://sockety.odysee.com/ws
|
||||||
THUMBNAIL_CDN_URL=https://image-processor.vanwanet.com/optimize/
|
THUMBNAIL_CDN_URL=https://thumbnails.odysee.com/optimize/
|
||||||
WELCOME_VERSION=1.2
|
THUMBNAIL_CARDS_CDN_URL=https://cards.odysee.com/
|
||||||
|
THUMBNAIL_HEIGHT=220
|
||||||
|
THUMBNAIL_WIDTH=390
|
||||||
|
THUMBNAIL_QUALITY=85
|
||||||
|
WELCOME_VERSION=1.0
|
||||||
|
|
||||||
# STRIPE
|
# STRIPE
|
||||||
# STRIPE_PUBLIC_KEY='pk_test_NoL1JWL7i1ipfhVId5KfDZgo'
|
# STRIPE_PUBLIC_KEY='pk_test_NoL1JWL7i1ipfhVId5KfDZgo'
|
||||||
|
|
||||||
# Analytics
|
# Analytics
|
||||||
MATOMO_URL=https://analytics.lbry.com/
|
|
||||||
MATOMO_ID=4
|
|
||||||
|
|
||||||
# OG
|
# OG
|
||||||
OG_TITLE_SUFFIX=| lbry.tv
|
OG_TITLE_SUFFIX=| lbry.tv
|
||||||
|
@ -35,19 +37,25 @@ SITE_CANONICAL_URL=https://lbry.tv
|
||||||
## Custom Site info
|
## Custom Site info
|
||||||
DOMAIN=lbry.tv
|
DOMAIN=lbry.tv
|
||||||
URL=https://lbry.tv
|
URL=https://lbry.tv
|
||||||
SITE_TITLE=LBRY
|
SITE_TITLE=lbry.tv
|
||||||
SITE_NAME=LBRY
|
SITE_NAME=lbry.tv
|
||||||
SITE_DESCRIPTION=Meet LBRY, an open, free, and community-controlled content wonderland.
|
SITE_DESCRIPTION=Meet LBRY, an open, free, and community-controlled content wonderland.
|
||||||
SITE_HELP_EMAIL=help@lbry.com
|
SITE_HELP_EMAIL=help@lbry.com
|
||||||
LOGO_TITLE=LBRY
|
LOGO_TITLE=lbry.tv
|
||||||
CLOUD_CONNECT_SITE_NAME=Odysee
|
|
||||||
## Social media
|
## Social media
|
||||||
TWITTER_ACCOUNT=LBRYcom
|
TWITTER_ACCOUNT=LBRYcom
|
||||||
BRANDED_SITE=odysee
|
BRANDED_SITE=odysee
|
||||||
|
|
||||||
## OLD IMAGE ASSETS
|
## IMAGE ASSETS
|
||||||
#YRBL_HAPPY_IMG_URL=https://player.odysee.com/api/v3/streams/free/yrbl-happy/7aa50a7e5adaf48691935d55e45d697547392929/839d9a
|
YRBL_HAPPY_IMG_URL=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-happy/7aa50a7e5adaf48691935d55e45d697547392929/839d9a
|
||||||
#YRBL_SAD_IMG_URL=https://player.odysee.com/api/v3/streams/free/yrbl-sad/c2d9649633d974e5ffb503925e1f17d951f1bd0f/f262dd
|
YRBL_SAD_IMG_URL=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649633d974e5ffb503925e1f17d951f1bd0f/f262dd
|
||||||
|
#LOGIN_IMG_URL=https://cdn.lbryplayer.xyz/api/v3/streams/free/login/b671946e911c66c5fa7233afb35de2badd9eceb8/0e1d81
|
||||||
|
#LOGO=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649633d974e5ffb503925e1f17d951f1bd0f/f262dd
|
||||||
|
#LOGO_TEXT_LIGHT=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649633d974e5ffb503925e1f17d951f1bd0f/f262dd
|
||||||
|
#LOGO_TEXT_DARK=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649633d974e5ffb503925e1f17d951f1bd0f/f262dd
|
||||||
|
#AVATAR_DEFAULT=
|
||||||
|
#MISSING_THUMB_DEFAULT=
|
||||||
|
#FAVICON=
|
||||||
|
|
||||||
# LOCALE
|
# LOCALE
|
||||||
DEFAULT_LANGUAGE=en
|
DEFAULT_LANGUAGE=en
|
||||||
|
@ -72,8 +80,8 @@ SIMPLE_SITE=false
|
||||||
#BRANDED_SITE
|
#BRANDED_SITE
|
||||||
|
|
||||||
ENABLE_COMMENT_REACTIONS=true
|
ENABLE_COMMENT_REACTIONS=true
|
||||||
ENABLE_FILE_REACTIONS=true
|
ENABLE_FILE_REACTIONS=false
|
||||||
ENABLE_CREATOR_REACTIONS=true
|
ENABLE_CREATOR_REACTIONS=false
|
||||||
ENABLE_NO_SOURCE_CLAIMS=false
|
ENABLE_NO_SOURCE_CLAIMS=false
|
||||||
ENABLE_PREROLL_ADS=false
|
ENABLE_PREROLL_ADS=false
|
||||||
CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS=4
|
CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS=4
|
||||||
|
@ -82,7 +90,7 @@ WEB_PUBLISH_SIZE_LIMIT_GB=4
|
||||||
LOADING_BAR_COLOR=#2bbb90
|
LOADING_BAR_COLOR=#2bbb90
|
||||||
LIGHTHOUSE_DEFAULT_TYPES=audio,video,text,image,application
|
LIGHTHOUSE_DEFAULT_TYPES=audio,video,text,image,application
|
||||||
|
|
||||||
SHOW_ADS=false
|
SHOW_ADS=true
|
||||||
|
|
||||||
## SIMPLE_SITE REPLACEMENTS
|
## SIMPLE_SITE REPLACEMENTS
|
||||||
ENABLE_MATURE=true
|
ENABLE_MATURE=true
|
||||||
|
@ -107,3 +115,13 @@ ENABLE_UI_NOTIFICATIONS=false
|
||||||
#MODELS_ENABLED=true
|
#MODELS_ENABLED=true
|
||||||
|
|
||||||
BRANDED_SITE=odysee
|
BRANDED_SITE=odysee
|
||||||
|
|
||||||
|
#FIREBASE
|
||||||
|
FIREBASE_API_KEY=AIzaSyAgc-4QORyglpYZ3qH9E5pDauEDOJXgM3A
|
||||||
|
FIREBASE_AUTH_DOMAIN=lbry-mobile.firebaseapp.com
|
||||||
|
FIREBASE_PROJECT_ID=lbry-mobile
|
||||||
|
FIREBASE_STORAGE_BUCKET=lbry-mobile.appspot.com
|
||||||
|
FIREBASE_MESSAGING_SENDER_ID=638894153788
|
||||||
|
FIREBASE_APP_ID=1:638894153788:web:35b295b15297201bd2e339
|
||||||
|
FIREBASE_MEASUREMENT_ID=G-2MPJGFEEXC
|
||||||
|
FIREBASE_VAPID_KEY=BFayEBpwMTU9GQQpXgitIJkfx-SD8-ltrFb3wLTZWgA27MfBhG4948pe0eERl432NzPrMKsbkXnA7ap_vLPgLYk
|
|
@ -2,9 +2,7 @@
|
||||||
.*\.typeface\.json
|
.*\.typeface\.json
|
||||||
.*/node_modules/findup/.*
|
.*/node_modules/findup/.*
|
||||||
.*/node_modules/react-plastic/.*
|
.*/node_modules/react-plastic/.*
|
||||||
.*/node_modules/raf-schd/.*
|
|
||||||
.*/node_modules/react-beautiful-dnd/.*
|
|
||||||
.*/node_modules/resolve/test/.*
|
|
||||||
|
|
||||||
[include]
|
[include]
|
||||||
|
|
||||||
|
@ -37,6 +35,8 @@ module.name_mapper='^web\/effects\(.*\)$' -> '<PROJECT_ROOT>/web/effects\1'
|
||||||
module.name_mapper='^web\/page\(.*\)$' -> '<PROJECT_ROOT>/web/page\1'
|
module.name_mapper='^web\/page\(.*\)$' -> '<PROJECT_ROOT>/web/page\1'
|
||||||
module.name_mapper='^homepage\(.*\)$' -> '<PROJECT_ROOT>/ui/util/homepage\1'
|
module.name_mapper='^homepage\(.*\)$' -> '<PROJECT_ROOT>/ui/util/homepage\1'
|
||||||
module.name_mapper='^scss\/component\(.*\)$' -> '<PROJECT_ROOT>/ui/scss/component/\1'
|
module.name_mapper='^scss\/component\(.*\)$' -> '<PROJECT_ROOT>/ui/scss/component/\1'
|
||||||
|
module.name_mapper='^\$web\(.*\)$' -> '<PROJECT_ROOT>/web\1'
|
||||||
|
module.name_mapper='^\$ui\(.*\)$' -> '<PROJECT_ROOT>/ui\1'
|
||||||
|
|
||||||
esproposal.optional_chaining=enable
|
esproposal.optional_chaining=enable
|
||||||
|
|
||||||
|
|
127
.github/workflows/deploy.yml
vendored
127
.github/workflows/deploy.yml
vendored
|
@ -1,127 +0,0 @@
|
||||||
name: Node.js CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master]
|
|
||||||
pull_request:
|
|
||||||
branches: [master]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
name: lint
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- run: corepack enable
|
|
||||||
- run: yarn
|
|
||||||
- run: yarn lint
|
|
||||||
|
|
||||||
build:
|
|
||||||
needs: ['lint']
|
|
||||||
name: 'build'
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
node-version: [16.x]
|
|
||||||
os:
|
|
||||||
- ubuntu-latest
|
|
||||||
- macos-latest
|
|
||||||
- windows-latest
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
continue-on-error: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
- run: corepack enable
|
|
||||||
|
|
||||||
- uses: maxim-lobanov/setup-xcode@v1
|
|
||||||
if: startsWith(runner.os, 'mac')
|
|
||||||
with:
|
|
||||||
xcode-version: '13.1.0'
|
|
||||||
# This is gonna be hacky.
|
|
||||||
# Github made us upgrade xcode, which would force an upgrade of electron-builder to fix mac.
|
|
||||||
# But there were bugs with copyfiles / extraFiles that kept seeing duplicates erroring on ln.
|
|
||||||
# A flag USE_HARD_LINKS=false in electron-builder.json was suggested in comments, but that broke windows builds.
|
|
||||||
# So for now we'll install python2 on mac and make sure it can find it.
|
|
||||||
# Remove this after successfully upgrading electron-builder.
|
|
||||||
# HACK part 1
|
|
||||||
- uses: Homebrew/actions/setup-homebrew@master
|
|
||||||
if: startsWith(runner.os, 'mac')
|
|
||||||
# HACK part 2
|
|
||||||
- name: Install Python2
|
|
||||||
if: startsWith(runner.os, 'mac')
|
|
||||||
run: |
|
|
||||||
/bin/bash -c "$(curl -fsSL https://github.com/alfredapp/dependency-scripts/raw/main/scripts/install-python2.sh)"
|
|
||||||
echo "PYTHON_PATH=/usr/local/bin/python" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Download blockchain headers
|
|
||||||
run: |
|
|
||||||
mkdir -p ./static/daemon
|
|
||||||
curl -o ./static/daemon/headers https://headers.lbry.io/blockchain_headers_latest
|
|
||||||
ls ./static/daemon
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
yarn dlx cross-env
|
|
||||||
yarn --network-timeout 600000
|
|
||||||
yarn build
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN_NEW }}
|
|
||||||
NOTARIZATION_USERNAME: ${{ secrets.NOTARIZATION_USERNAME }}
|
|
||||||
NOTARIZATION_PASSWORD: ${{ secrets.NOTARIZATION_PASSWORD }}
|
|
||||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }}
|
|
||||||
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
|
|
||||||
|
|
||||||
WIN_CSC_LINK: https://raw.githubusercontent.com/lbryio/lbry-desktop/master/build/cert2023.pfx
|
|
||||||
CSC_LINK: https://s3.amazonaws.com/files.lbry.io/cert/osx-csc-2021-2022.p12
|
|
||||||
|
|
||||||
# UI
|
|
||||||
MATOMO_URL: https://analytics.lbry.com/
|
|
||||||
MATOMO_ID: 4
|
|
||||||
WELCOME_VERSION: 1.0
|
|
||||||
DOMAIN: lbry.tv
|
|
||||||
URL: https://lbry.tv
|
|
||||||
SHARE_DOMAIN_URL: https://open.lbry.com
|
|
||||||
SITE_TITLE: lbry.tv
|
|
||||||
SITE_NAME: lbry.tv
|
|
||||||
SHOW_ADS: false
|
|
||||||
ENABLE_COMMENT_REACTIONS: true
|
|
||||||
ENABLE_NO_SOURCE_CLAIMS: false
|
|
||||||
|
|
||||||
DEFAULT_LANGUAGE: en
|
|
||||||
KNOWN_APP_DOMAINS: lbry.tv,lbry.lat,odysee.com
|
|
||||||
CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS: 0
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2.2.4
|
|
||||||
if: |
|
|
||||||
startsWith(runner.os, 'linux')
|
|
||||||
with:
|
|
||||||
name: Linux
|
|
||||||
path: ./dist/electron/*.*
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2.2.4
|
|
||||||
if: |
|
|
||||||
startsWith(runner.os, 'mac')
|
|
||||||
with:
|
|
||||||
name: macOS
|
|
||||||
path: ./dist/electron/*.*
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2.2.4
|
|
||||||
if: |
|
|
||||||
startsWith(runner.os, 'windows')
|
|
||||||
with:
|
|
||||||
name: Windows
|
|
||||||
path: ./dist/electron/*.*
|
|
||||||
- uses: jakejarvis/s3-sync-action@master
|
|
||||||
if: |
|
|
||||||
startsWith(runner.os, 'linux')
|
|
||||||
with:
|
|
||||||
args: --acl public-read --follow-symlinks --exclude '*' --include '*.deb' --include '*.AppImage' --include '*.dmg'
|
|
||||||
env:
|
|
||||||
AWS_S3_BUCKET: ${{ secrets.ARTIFACTS_BUCKET }}
|
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.ARTIFACTS_KEY }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.ARTIFACTS_SECRET }}
|
|
||||||
AWS_REGION: 'us-east-1'
|
|
||||||
SOURCE_DIR: 'dist/electron'
|
|
||||||
DEST_DIR: 'app/release'
|
|
57
.github/workflows/node.js.yml
vendored
Normal file
57
.github/workflows/node.js.yml
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||||
|
|
||||||
|
name: Node.js CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
name: lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: Borales/actions-yarn@v2.3.0
|
||||||
|
- run: yarn lint
|
||||||
|
|
||||||
|
build:
|
||||||
|
needs: ['lint']
|
||||||
|
name: 'build'
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [14.x]
|
||||||
|
os:
|
||||||
|
- ubuntu-latest
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v2-beta
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
yarn global add cross-env
|
||||||
|
yarn
|
||||||
|
yarn compile:web
|
||||||
|
env:
|
||||||
|
# UI
|
||||||
|
WELCOME_VERSION: 1.0
|
||||||
|
DOMAIN: odysee.com
|
||||||
|
URL: https://odysee.com
|
||||||
|
SHARE_DOMAIN_URL: https://odysee.com
|
||||||
|
SITE_TITLE: Odysee
|
||||||
|
SITE_NAME: Odysee
|
||||||
|
SHOW_ADS: false
|
||||||
|
YRBL_HAPPY_IMG_URL: https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-happy/7aa50a7e5adaf48691935d55e45d697547392929/839d9a
|
||||||
|
YRBL_SAD_IMG_URL: https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649633d974e5ffb503925e1f17d951f1bd0f/f262dd
|
||||||
|
ENABLE_COMMENT_REACTIONS: true
|
||||||
|
ENABLE_NO_SOURCE_CLAIMS: true
|
||||||
|
DEFAULT_LANGUAGE: en
|
||||||
|
KNOWN_APP_DOMAINS: lbry.tv,lbry.lat,odysee.com
|
||||||
|
CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS: 4
|
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -33,12 +33,7 @@ package-lock.json
|
||||||
!/custom/robots.disallowall
|
!/custom/robots.disallowall
|
||||||
!/custom/robots.allowall
|
!/custom/robots.allowall
|
||||||
.env
|
.env
|
||||||
!.env.ody
|
.env.ody
|
||||||
.env.desktop
|
.env.desktop
|
||||||
.env.lbrytv
|
.env.lbrytv
|
||||||
.yarn/*
|
analyzeResults*.html
|
||||||
!.yarn/patches
|
|
||||||
!.yarn/plugins
|
|
||||||
!.yarn/sdks
|
|
||||||
!.yarn/versions
|
|
||||||
!.yarn/releases
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
{
|
{
|
||||||
"linters": {
|
"linters": {
|
||||||
"ui/**/*.{js,jsx,scss,json}": ["prettier --write", "git add"],
|
"ui/**/*.{js,jsx,scss,json}": ["prettier --write", "git add"],
|
||||||
"ui/**/*.{js,jsx}": ["eslint", "flow focus-check --color always", "git add"]
|
"extras/**/*.{js,jsx,scss,json}": ["prettier --write", "git add"],
|
||||||
|
"web/**/*.{js,jsx,scss,json}": ["prettier --write", "git add"],
|
||||||
|
"ui/**/*.{js,jsx}": ["eslint", "flow focus-check --color always", "git add"],
|
||||||
|
"extras/**/*.{js,jsx}": ["eslint", "flow focus-check --color always", "git add"],
|
||||||
|
"web/**/*.{js,jsx}": ["eslint", "git add"]
|
||||||
},
|
},
|
||||||
"ignore": ["node_modules", "dist/**/*", "package-lock.json"]
|
"ignore": ["node_modules", "web/dist/**/*", "dist/**/*", "package-lock.json"]
|
||||||
}
|
}
|
||||||
|
|
550
.yarn/plugins/@yarnpkg/plugin-version.cjs
vendored
550
.yarn/plugins/@yarnpkg/plugin-version.cjs
vendored
File diff suppressed because one or more lines are too long
785
.yarn/releases/yarn-3.2.0.cjs
vendored
785
.yarn/releases/yarn-3.2.0.cjs
vendored
File diff suppressed because one or more lines are too long
0
.yarn/versions/17d7e90d.yml
vendored
0
.yarn/versions/17d7e90d.yml
vendored
0
.yarn/versions/33178102.yml
vendored
0
.yarn/versions/33178102.yml
vendored
0
.yarn/versions/35f2125e.yml
vendored
0
.yarn/versions/35f2125e.yml
vendored
0
.yarn/versions/4f9fb046.yml
vendored
0
.yarn/versions/4f9fb046.yml
vendored
0
.yarn/versions/5bc94294.yml
vendored
0
.yarn/versions/5bc94294.yml
vendored
0
.yarn/versions/5f1212ad.yml
vendored
0
.yarn/versions/5f1212ad.yml
vendored
0
.yarn/versions/5f4cac99.yml
vendored
0
.yarn/versions/5f4cac99.yml
vendored
0
.yarn/versions/6b35c994.yml
vendored
0
.yarn/versions/6b35c994.yml
vendored
0
.yarn/versions/6be5ab70.yml
vendored
0
.yarn/versions/6be5ab70.yml
vendored
0
.yarn/versions/86ac1afd.yml
vendored
0
.yarn/versions/86ac1afd.yml
vendored
0
.yarn/versions/8e384637.yml
vendored
0
.yarn/versions/8e384637.yml
vendored
0
.yarn/versions/909c3734.yml
vendored
0
.yarn/versions/909c3734.yml
vendored
0
.yarn/versions/951a8d12.yml
vendored
0
.yarn/versions/951a8d12.yml
vendored
0
.yarn/versions/97e7141a.yml
vendored
0
.yarn/versions/97e7141a.yml
vendored
0
.yarn/versions/ac69bc5f.yml
vendored
0
.yarn/versions/ac69bc5f.yml
vendored
0
.yarn/versions/c6e2b914.yml
vendored
0
.yarn/versions/c6e2b914.yml
vendored
0
.yarn/versions/d1a18cef.yml
vendored
0
.yarn/versions/d1a18cef.yml
vendored
0
.yarn/versions/ec3a9ddf.yml
vendored
0
.yarn/versions/ec3a9ddf.yml
vendored
0
.yarn/versions/fc1fde84.yml
vendored
0
.yarn/versions/fc1fde84.yml
vendored
0
.yarn/versions/fc597c00.yml
vendored
0
.yarn/versions/fc597c00.yml
vendored
|
@ -1,7 +0,0 @@
|
||||||
nodeLinker: node-modules
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
|
|
||||||
spec: "@yarnpkg/plugin-version"
|
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-3.2.0.cjs
|
|
236
CHANGELOG.md
236
CHANGELOG.md
|
@ -1,239 +1,25 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## [0.53.9] - [2023-2-8]
|
## [Unreleased for Desktop]
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Updated lbrynet to [0.113.0](https://github.com/lbryio/lbry-sdk/releases/tag/v0.113.0)
|
|
||||||
|
|
||||||
## [0.53.8] - [2022-11-17]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Selecting a large file in publish no longer crashes ([#7736](https://github.com/lbryio/lbry-desktop/pull/7736))
|
|
||||||
- Unfollowing unpublished channels ([#7737](https://github.com/lbryio/lbry-desktop/pull/7737))
|
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Updated xcode to 13.1 and hacked a fix for release ([#7736](https://github.com/lbryio/lbry-desktop/pull/7736))
|
|
||||||
|
|
||||||
## [0.53.7] - [2022-11-10]
|
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- 'Collections' to txo filter _community pr!_ ([#7711](https://github.com/lbryio/lbry-desktop/pull/7711))
|
- Added direct replying to notifications _community pr!_ ([#6935](https://github.com/lbryio/lbry-desktop/pull/6935))
|
||||||
- Swap comment servers _community pr!_ ([#7670](https://github.com/lbryio/lbry-desktop/pull/7670))
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Thumbnails no longer disable publish ([#7714](https://github.com/lbryio/lbry-desktop/pull/7714))
|
|
||||||
- Publishing posts were empty ([#7715](https://github.com/lbryio/lbry-desktop/pull/7715))
|
|
||||||
- Minor layout fixes _community pr!_ ([#7709](https://github.com/lbryio/lbry-desktop/pull/7709))
|
|
||||||
- Comment section buttons layout ([#7716](https://github.com/lbryio/lbry-desktop/pull/7716))
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Removed watchman and its errors ([#7710](https://github.com/lbryio/lbry-desktop/pull/7710))
|
|
||||||
- Updated lbrynet to [0.112.0](https://github.com/lbryio/lbry-sdk/releases/tag/v0.112.0)
|
|
||||||
|
|
||||||
## [0.53.6] - [2022-10-21]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Make thumbnails optional ([#7690](https://github.com/lbryio/lbry-desktop/pull/7690))
|
|
||||||
- Show downloads newest first ([#7684](https://github.com/lbryio/lbry-desktop/pull/7684))
|
|
||||||
- Only allow images in image uploader ([#7672](https://github.com/lbryio/lbry-desktop/pull/7672))
|
|
||||||
- Fixed bug with csv exports ([#7697](https://github.com/lbryio/lbry-desktop/pull/7697))
|
|
||||||
- Fixed various upload bugs including transcoding ([#7688](https://github.com/lbryio/lbry-desktop/pull/7688))
|
|
||||||
- Fallback for files with no extension ([#7704](https://github.com/lbryio/lbry-desktop/pull/7704))
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Upgraded Electron to v17.2.0 ([#7703](https://github.com/lbryio/lbry-desktop/pull/7703))
|
|
||||||
- Upgraded Electron to v17.0.0 ([#7691](https://github.com/lbryio/lbry-desktop/pull/7691))
|
|
||||||
- Updated lbrynet to [0.111.0](https://github.com/lbryio/lbry-sdk/releases/tag/v0.111.0)
|
|
||||||
|
|
||||||
## [0.53.5] - [2022-08-26]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Checkbox to disable background wallpaper ([#7630](https://github.com/lbryio/lbry-desktop/pull/7630))
|
|
||||||
- Handle content blocking from hub ([#7665](https://github.com/lbryio/lbry-desktop/pull/7665))
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Better handle decimals liquidating supports ([#7648](https://github.com/lbryio/lbry-desktop/pull/7648))
|
|
||||||
- Better handle cover uploads ([#7647](https://github.com/lbryio/lbry-desktop/pull/7647))
|
|
||||||
- Use default path when first choosing file on windows ([#7625](https://github.com/lbryio/lbry-desktop/pull/7625))
|
|
||||||
- Emoji button hover ([#7620](https://github.com/lbryio/lbry-desktop/pull/7620))
|
|
||||||
- Prevent infinite retries on thumbs ([#7618](https://github.com/lbryio/lbry-desktop/pull/7618))
|
|
||||||
- Double splash/error on app startup ([#7615](https://github.com/lbryio/lbry-desktop/pull/7615))
|
|
||||||
- App updates are now more coherent, also debs work. ([#7502](https://github.com/lbryio/lbry-desktop/pull/7502))
|
|
||||||
- Better handle many channels moderation calls at startup ([#7674](https://github.com/lbryio/lbry-desktop/pull/7674))
|
|
||||||
- Fix mobile floating viewer position ([#7677](https://github.com/lbryio/lbry-desktop/pull/7677))
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Upgraded Electron to v15.5.5 ([#7614](https://github.com/lbryio/lbry-desktop/pull/7614))
|
|
||||||
- Upgraded to lbrynet v0.110.0 ([#7680](https://github.com/lbryio/lbry-desktop/pull/7680))
|
|
||||||
|
|
||||||
|
|
||||||
## [0.53.4] - [2022-06-10]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Add top in language category for non-english on homepage ([#7585](https://github.com/lbryio/lbry-desktop/pull/7585))
|
|
||||||
- Auto hosting in settings and hosting first run page ([#7598](https://github.com/lbryio/lbry-desktop/pull/7598))
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Updated lbry-sdk to [0.107.2](https://github.com/lbryio/lbry-sdk/releases/tag/v0.107.2)
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Better handle empty collections ([#7571](https://github.com/lbryio/lbry-desktop/pull/7571))
|
|
||||||
- Better handle thumbnails in uploads/collections ([#7574](https://github.com/lbryio/lbry-desktop/pull/7574))
|
|
||||||
- Work towards supporting collections of any claim type ([#7578](https://github.com/lbryio/lbry-desktop/pull/7578))
|
|
||||||
- Improve handling of downed custom servers on startup ([#7593](https://github.com/lbryio/lbry-desktop/pull/7593))
|
|
||||||
- Hide watch progress in related if being played ([#7606](https://github.com/lbryio/lbry-desktop/pull/7606))
|
|
||||||
- IPC disk space calls wait for daemon ready; refresh on vis. component load ([#7610](https://github.com/lbryio/lbry-desktop/pull/7610))
|
|
||||||
|
|
||||||
## [0.53.3] - [2022-04-27]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Reverted lbry.tv changes that broke production login ([#7569](https://github.com/lbryio/lbry-desktop/pull/7569))
|
|
||||||
- Reverted lbry.tv changes that broke login ([#7570](https://github.com/lbryio/lbry-desktop/pull/7570))
|
|
||||||
|
|
||||||
## [0.53.2] - [2022-04-26]
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Upgraded Yarn to Berry branch ([#7530](https://github.com/lbryio/lbry-desktop/pull/7530))
|
|
||||||
- Removed some lbrytv references ([#7560](https://github.com/lbryio/lbry-desktop/pull/7560))
|
|
||||||
- Removed some lbrytv player references ([#7552](https://github.com/lbryio/lbry-desktop/pull/7552))
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Repost style issues ([#7559](https://github.com/lbryio/lbry-desktop/pull/7559))
|
|
||||||
- Disappearing sidebar thumbs ([#7556](https://github.com/lbryio/lbry-desktop/pull/7556))
|
|
||||||
- Restore tags sidebar link ([#7555](https://github.com/lbryio/lbry-desktop/pull/7555))
|
|
||||||
- Playlist view link no longer crashes ([#7552](https://github.com/lbryio/lbry-desktop/pull/7552))
|
|
||||||
|
|
||||||
## [0.53.1] - [2022-04-22]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Uploads: show placeholder when loading page _community pr!_ ([#7531](https://github.com/lbryio/lbry-desktop/pull/7531))
|
|
||||||
- Sidebar channel search _styles pr_ ([#7542](https://github.com/lbryio/lbry-desktop/pull/7542))
|
|
||||||
- Viewed content progress indicator on thumbnail part 1 ([#7541](https://github.com/lbryio/lbry-desktop/pull/7541))
|
|
||||||
- Viewed content progress indicator on thumbnail part 2 ([#7547](https://github.com/lbryio/lbry-desktop/pull/7547))
|
|
||||||
- Ability to search through publishes ([#7535](https://github.com/lbryio/lbry-desktop/pull/7535))
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Large styles revamp following odysee _styles pr_ ([#7542](https://github.com/lbryio/lbry-desktop/pull/7542))
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Fix bad rerender on homepage _styles pr_ ([#7542](https://github.com/lbryio/lbry-desktop/pull/7542))
|
|
||||||
- Fix post-editor preview mode _community pr!_ ([#7532](https://github.com/lbryio/lbry-desktop/pull/7532))
|
|
||||||
- Fix send-tip default tab ([#7533](https://github.com/lbryio/lbry-desktop/pull/7533))
|
|
||||||
|
|
||||||
## [0.52.6] - [2022-04-04]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Discover page medium duration filter ([#7506](https://github.com/lbryio/lbry-desktop/pull/7506))
|
|
||||||
- Keep last used collection for Add To ([#7491](https://github.com/lbryio/lbry-desktop/pull/7491))
|
|
||||||
- Disk space functionality on mac / windows ([#7500](https://github.com/lbryio/lbry-desktop/pull/7500))
|
|
||||||
- Enable renaming private collections ([#7519](https://github.com/lbryio/lbry-desktop/pull/7519))
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Some upgrade modal improvements ([#7488](https://github.com/lbryio/lbry-desktop/pull/7488))
|
|
||||||
- Updated lbry-sdk to [0.107.1](https://github.com/lbryio/lbry-sdk/releases/tag/v0.107.1)
|
|
||||||
- New YRBL!; facelift for first run ([#7527](https://github.com/lbryio/lbry-desktop/pull/7527))
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Failed comment count increment ([#7510](https://github.com/lbryio/lbry-desktop/pull/7510))
|
|
||||||
- App crash playing media on older windows versions by updating electron ([#7509](https://github.com/lbryio/lbry-desktop/pull/7509))
|
|
||||||
- Local build failures on mac ([#7497](https://github.com/lbryio/lbry-desktop/pull/7497))
|
|
||||||
- Language change now rerenders whole app ([#7504](https://github.com/lbryio/lbry-desktop/pull/7504))
|
|
||||||
- Mac notarization ([#7518](https://github.com/lbryio/lbry-desktop/pull/7518))
|
|
||||||
- Prevent crash when deleting last comment reply ([#7526](https://github.com/lbryio/lbry-desktop/pull/7526))
|
|
||||||
|
|
||||||
## [0.52.5] - [2022-02-25]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- New data hosting ux ([#7493](https://github.com/lbryio/lbry-desktop/pull/7493))
|
|
||||||
- Fix markdown guide button ([#7485](https://github.com/lbryio/lbry-desktop/pull/7485))
|
|
||||||
|
|
||||||
## [0.52.4] - [2022-02-15]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fixed active channel ([#7481](https://github.com/lbryio/lbry-desktop/pull/7481))
|
|
||||||
- Remove extra search button in header ([#7482](https://github.com/lbryio/lbry-desktop/pull/7482))
|
|
||||||
|
|
||||||
## [0.52.3] - [2022-02-15]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Fixed comment editing and pinning ([#7476](https://github.com/lbryio/lbry-desktop/pull/7476))
|
|
||||||
- Fixed mac header ([#7479](https://github.com/lbryio/lbry-desktop/pull/7479))
|
|
||||||
- Fixed markdown display and lbry url embedding ([#7474](https://github.com/lbryio/lbry-desktop/pull/7474))
|
|
||||||
|
|
||||||
## [0.52.2] - [2022-02-11]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Reenabled generating thumbs from video ([#7384](https://github.com/lbryio/lbry-desktop/pull/7409))
|
|
||||||
- Brought in playlist drag and drop playlist reordering _odysee team!_ ([#7442](https://github.com/lbryio/lbry-desktop/pull/7442))
|
|
||||||
- Added duration overlays to ClaimPreview component ([#7420](https://github.com/lbryio/lbry-desktop/pull/7420))
|
|
||||||
- Some Horizontal Scroll groundwork from _odysee team!_
|
|
||||||
- Comment Emotes and Stickers and Mentions refactors from _odysee team!_ ([#7435](https://github.com/lbryio/lbry-desktop/pull/7435))
|
|
||||||
- Seek forward and back from _odysee team!_ () ([#7460](https://github.com/lbryio/lbry-desktop/pull/7460))
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Upgraded Electron to v15 ([#7384](https://github.com/lbryio/lbry-desktop/pull/7384))
|
|
||||||
- Performance improvements in some selectors ([#7370](https://github.com/lbryio/lbry-desktop/pull/7370))
|
|
||||||
- More Header refactoring from _odysee team!_ ([#7441](https://github.com/lbryio/lbry-desktop/pull/7441))
|
|
||||||
- Header refactoring from _odysee team!_ ([#7440](https://github.com/lbryio/lbry-desktop/pull/7440))
|
|
||||||
- Data hosting ui _incomplete_ ([#7438](https://github.com/lbryio/lbry-desktop/pull/7438))
|
|
||||||
- Updated c: control tags from _odysee team!_ ([#7433](https://github.com/lbryio/lbry-desktop/pull/7433))
|
|
||||||
- Nav keycodes (alt+left) no longer navigate while textarea is focused ([#7458](https://github.com/lbryio/lbry-desktop/pull/7458))
|
|
||||||
- Improved comment-server selection ui/ux ([#7455](https://github.com/lbryio/lbry-desktop/pull/7455))
|
|
||||||
- Improved Data Hosting settings ([#7563](https://github.com/lbryio/lbry-desktop/pull/7563))
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Several fallout bugs from recent changes
|
|
||||||
|
|
||||||
## [0.52.1]
|
|
||||||
|
|
||||||
### Skipped patch version
|
|
||||||
|
|
||||||
## [0.52.0] - [2021-12-31]
|
|
||||||
|
|
||||||
### Compatibility
|
|
||||||
|
|
||||||
- Mac <= 10.13 (High Sierra) and Ubuntu <= 16 (Xenial) are no longer supported. If you upgrade, you will need to manually build and install your own lbrynet SDK
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Direct replying to notifications _community pr!_ ([#6935](https://github.com/lbryio/lbry-desktop/pull/6935))
|
|
||||||
- Added "Replay" option on autoplay countdown ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
- Added "Replay" option on autoplay countdown ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
||||||
- Added "Loop" option on Lists ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
- Added "Loop" option on Lists ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
||||||
- Added "Shuffle" option on Lists ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
- Added "Shuffle" option on Lists ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
||||||
- Added Play Next/Previous buttons (with shortcuts SHIFT+N/SHIFT+P) ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
- Added Play Next/Previous buttons (with shortcuts SHIFT+N/SHIFT+P) ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
||||||
- Separate control for autoplay next on video player ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
- Added separate control for autoplay next on video player ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
||||||
- Channel Mention selection ability while creating a comment ([#7151](https://github.com/lbryio/lbry-desktop/pull/7151))
|
- Added Channel Mention selection ability while creating a comment ([#7151](https://github.com/lbryio/lbry-desktop/pull/7151))
|
||||||
- Disk space setting under Data Hosting ([#7266](https://github.com/lbryio/lbry-desktop/pull/7266))
|
|
||||||
- Paginated 'All Playlists' page ([#7268](https://github.com/lbryio/lbry-desktop/pull/7268))
|
|
||||||
- Expanded playlist ordering tools ([#7305](https://github.com/lbryio/lbry-desktop/pull/7305))
|
|
||||||
- Setting to upgrade to alpha prerelease builds ([#7353](https://github.com/lbryio/lbry-desktop/pull/7353))
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Changing the supported language from Filipino to Tagalog _community pr!_ ([#6951](https://github.com/lbryio/lbry-desktop/pull/6951))
|
- Changing the supported language from Filipino to Tagalog _community pr!_ ([#6951](https://github.com/lbryio/lbry-desktop/pull/6951))
|
||||||
- Don't show countdown to next item in list ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
- Don't show countdown to next item in list ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
||||||
- Changed "View List" popup option to link, so can be opened on a new tab ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
- Changed "View List" popup option to link, so can be opened on a new tab ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
||||||
- App reorganized to remove lbry-redux and lbryinc repository dependencies ([#7240](https://github.com/lbryio/lbry-desktop/pull/7240))
|
|
||||||
- Styling cleanup for file reactions ([#7251](https://github.com/lbryio/lbry-desktop/pull/7251))
|
|
||||||
- Change share url to odysee and allow custom share url in settings ([#7258](https://github.com/lbryio/lbry-desktop/pull/7258))
|
|
||||||
- Change Sign in/up to Cloud Connect for Odysee ([#7260](https://github.com/lbryio/lbry-desktop/pull/7260))
|
|
||||||
- Upgraded to lbrynet v0.106.0 ([#7315](https://github.com/lbryio/lbry-desktop/pull/7315))
|
|
||||||
- Upgraded Electron to v11.5.0 ([#7276](https://github.com/lbryio/lbry-desktop/pull/7276))
|
|
||||||
- Cleaner Discover page filters ([#7306](https://github.com/lbryio/lbry-desktop/pull/7306))
|
|
||||||
- Scroll bar styling ([#7314](https://github.com/lbryio/lbry-desktop/pull/7314))
|
|
||||||
- Remove pages for obsolete features like invites, rewards, swap ([#7330](https://github.com/lbryio/lbry-desktop/pull/7330))
|
|
||||||
- Change file repost to modal _community pr!_ ([#7341](https://github.com/lbryio/lbry-desktop/pull/7341))
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Clicking on the title of a floating player will take you back to the list ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
- Clicking on the title of a floating player will take you back to the list ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
|
||||||
- Fix floating player stopping on markdown or image files ([#7073](https://github.com/lbryio/lbry-desktop/pull/7073))
|
- Fix floating player stopping on markdown or image files ([#7073](https://github.com/lbryio/lbry-desktop/pull/7073))
|
||||||
- Fix list thumbnail upload ([#7074](https://github.com/lbryio/lbry-desktop/pull/7074))
|
- Fix list thumbnail upload ([#7074](https://github.com/lbryio/lbry-desktop/pull/7074))
|
||||||
|
@ -241,14 +27,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Fix playlist preview thumbnail ([#7178](https://github.com/lbryio/lbry-desktop/pull/7178)
|
- Fix playlist preview thumbnail ([#7178](https://github.com/lbryio/lbry-desktop/pull/7178)
|
||||||
- Fixed “Your Account” popup on mobile ([#7172](https://github.com/lbryio/lbry-desktop/pull/7172))
|
- Fixed “Your Account” popup on mobile ([#7172](https://github.com/lbryio/lbry-desktop/pull/7172))
|
||||||
- Fix disable-support for comments ([#7245](https://github.com/lbryio/lbry-desktop/pull/7245))
|
- Fix disable-support for comments ([#7245](https://github.com/lbryio/lbry-desktop/pull/7245))
|
||||||
- Fix Electron taking over .html files on linux ([#7291](https://github.com/lbryio/lbry-desktop/pull/7291))
|
|
||||||
- Fix floating player play/pause on drag _community pr!_ ([#7339](https://github.com/lbryio/lbry-desktop/pull/7339))
|
|
||||||
- Fix card dropdown menus triggering menu actions _community pr!_ ([#7335](https://github.com/lbryio/lbry-desktop/pull/7335))
|
|
||||||
|
|
||||||
## [0.51.2] - [2021-08-20]
|
## [0.51.2] - [2021-08-20]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Show currently active playing item on playlist _community pr!_ ([#6453](https://github.com/lbryio/lbry-desktop/pull/6453))
|
- Show currently active playing item on playlist _community pr!_ ([#6453](https://github.com/lbryio/lbry-desktop/pull/6453))
|
||||||
- Add watch later to hover action for last used playlist on popup _community pr!_ ([#6274](https://github.com/lbryio/lbry-desktop/pull/6274))
|
- Add watch later to hover action for last used playlist on popup _community pr!_ ([#6274](https://github.com/lbryio/lbry-desktop/pull/6274))
|
||||||
- Add confirmation on comment removal _community pr!_ ([#6563](https://github.com/lbryio/lbry-desktop/pull/6563))
|
- Add confirmation on comment removal _community pr!_ ([#6563](https://github.com/lbryio/lbry-desktop/pull/6563))
|
||||||
|
@ -256,7 +38,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Add filtering to playlists ([#6905](https://github.com/lbryio/lbry-desktop/pull/6905))
|
- Add filtering to playlists ([#6905](https://github.com/lbryio/lbry-desktop/pull/6905))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Use Canonical Url for copy link ([#6500](https://github.com/lbryio/lbry-desktop/pull/6500))
|
- Use Canonical Url for copy link ([#6500](https://github.com/lbryio/lbry-desktop/pull/6500))
|
||||||
- Use better icon for copy link ([#6485](https://github.com/lbryio/lbry-desktop/pull/6485))
|
- Use better icon for copy link ([#6485](https://github.com/lbryio/lbry-desktop/pull/6485))
|
||||||
- Comments load paginated ([#6390](https://github.com/lbryio/lbry-desktop/pull/6390))
|
- Comments load paginated ([#6390](https://github.com/lbryio/lbry-desktop/pull/6390))
|
||||||
|
@ -267,7 +48,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Improved clickability of notification links _community pr!_ ([#6711](https://github.com/lbryio/lbry-desktop/pull/6711))
|
- Improved clickability of notification links _community pr!_ ([#6711](https://github.com/lbryio/lbry-desktop/pull/6711))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- App now supports '#' and ':' for claimId separator ([#6496](https://github.com/lbryio/lbry-desktop/pull/6496))
|
- App now supports '#' and ':' for claimId separator ([#6496](https://github.com/lbryio/lbry-desktop/pull/6496))
|
||||||
- Fix "exact match" being applied to Recommended ([#6460](https://github.com/lbryio/lbry-desktop/pull/6460))
|
- Fix "exact match" being applied to Recommended ([#6460](https://github.com/lbryio/lbry-desktop/pull/6460))
|
||||||
- Fix upload button on creator analytics _community pr!_ ([#6458](https://github.com/lbryio/lbry-desktop/pull/6458))
|
- Fix upload button on creator analytics _community pr!_ ([#6458](https://github.com/lbryio/lbry-desktop/pull/6458))
|
||||||
|
@ -293,13 +73,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Enable sign up on desktop ([#6071](https://github.com/lbryio/lbry-desktop/issues/6071))
|
- Enable sign up on desktop ([#6071](https://github.com/lbryio/lbry-desktop/issues/6071))
|
||||||
|
|
||||||
## [0.51.0] - [2021-06-26]
|
## [0.51.0] - [2021-06-26]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Private and Publishable Playlists ([#6157](https://github.com/lbryio/lbry-desktop/pull/6157))
|
- Private and Publishable Playlists ([#6157](https://github.com/lbryio/lbry-desktop/pull/6157))
|
||||||
- Channel thumbnails in following side menu ([#6193](https://github.com/lbryio/lbry-desktop/pull/6193))
|
- Channel thumbnails in following side menu ([#6193](https://github.com/lbryio/lbry-desktop/pull/6193))
|
||||||
- Web is now PWA app ([#6120](https://github.com/lbryio/lbry-desktop/pull/6120))
|
- Web is now PWA app ([#6120](https://github.com/lbryio/lbry-desktop/pull/6120))
|
||||||
|
@ -957,7 +735,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Channels page above Publishes which lists all your channels ([#2925](https://github.com/lbryio/lbry-desktop/pull/2925))
|
- Channels page above Publishes which lists all your channels ([#2925](https://github.com/lbryio/lbry-desktop/pull/2925))
|
||||||
- YouTube channel claiming and transfer ([#2925](https://github.com/lbryio/lbry-desktop/pull/2925)). See our [YouTube FAQ](https://lbry.com/faq/youtube) for more information.
|
- YouTube channel claiming and transfer ([#2925](https://github.com/lbryio/lbry-desktop/pull/2925)). See our [YouTube FAQ](https://odysee.com/@OdyseeHelp:b/youtube-sync:b) for more information.
|
||||||
- New user sign in flow now includes automatic redeeming of 1 LBC and channel creation ([#2925](https://github.com/lbryio/lbry-desktop/pull/2925))
|
- New user sign in flow now includes automatic redeeming of 1 LBC and channel creation ([#2925](https://github.com/lbryio/lbry-desktop/pull/2925))
|
||||||
- Ability to save wallet encryption password ([#2925](https://github.com/lbryio/lbry-desktop/pull/2925))
|
- Ability to save wallet encryption password ([#2925](https://github.com/lbryio/lbry-desktop/pull/2925))
|
||||||
- Sync your balance (only for users with new wallets) and preferences (subscriptions and tags) between devices ([#2925](https://github.com/lbryio/lbry-desktop/pull/2925)). See our [FAQ for more information](https://lbry.com/faq/account-sync)
|
- Sync your balance (only for users with new wallets) and preferences (subscriptions and tags) between devices ([#2925](https://github.com/lbryio/lbry-desktop/pull/2925)). See our [FAQ for more information](https://lbry.com/faq/account-sync)
|
||||||
|
@ -1112,7 +890,7 @@ This release includes a breaking change that will reset many of your settings. T
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- New app design for better [content discovery](https://lbry.com/faq/trending) with infinite scroll ([#2477](https://github.com/lbryio/lbry-desktop/pull/2477))
|
- New app design for better [content discovery](https://odysee.com/@OdyseeHelp:b/OdyseeBasics:c) with infinite scroll ([#2477](https://github.com/lbryio/lbry-desktop/pull/2477))
|
||||||
- First implementation of comments ([#2510](https://github.com/lbryio/lbry-desktop/pull/2510))
|
- First implementation of comments ([#2510](https://github.com/lbryio/lbry-desktop/pull/2510))
|
||||||
- Ability to edit channels with new metadata and tags ([#2584](https://github.com/lbryio/lbry-desktop/pull/2584))
|
- Ability to edit channels with new metadata and tags ([#2584](https://github.com/lbryio/lbry-desktop/pull/2584))
|
||||||
- Tagging content on publish page ([#2593](https://github.com/lbryio/lbry-desktop/pull/2593))
|
- Tagging content on publish page ([#2593](https://github.com/lbryio/lbry-desktop/pull/2593))
|
||||||
|
|
88
README.md
88
README.md
|
@ -1,11 +1,7 @@
|
||||||
<img width="40%" src="https://miro.medium.com/max/5198/1*bTVuL2THG_0mpwmE-n7Ezg.png" />
|
|
||||||
|
|
||||||
# LBRY App
|
# Odysee Frontend - Odysee.com
|
||||||
|
|
||||||
This repo contains the UI code that powers the official LBRY desktop app. The LBRY app is a graphical browser for the decentralized content marketplace provided by the
|
This repo contains the UI and front end code that powers Odysee.com.
|
||||||
[LBRY](https://lbry.com) protocol. It is essentially the
|
|
||||||
[lbry daemon](https://github.com/lbryio/lbry) bundled with a UI using
|
|
||||||
[Electron](https://electron.atom.io/).
|
|
||||||
|
|
||||||
<a href="https://github.com/lbryio/lbry-desktop/blob/master/LICENSE" title="MIT licensed">
|
<a href="https://github.com/lbryio/lbry-desktop/blob/master/LICENSE" title="MIT licensed">
|
||||||
<img alt="npm" src="https://img.shields.io/dub/l/vibe-d.svg?style=flat">
|
<img alt="npm" src="https://img.shields.io/dub/l/vibe-d.svg?style=flat">
|
||||||
|
@ -29,7 +25,6 @@ This repo contains the UI code that powers the official LBRY desktop app. The LB
|
||||||
</a>
|
</a>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
![App GIF](https://spee.ch/ba/lbry-joule.gif)
|
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
|
@ -65,26 +60,26 @@ _Note: If coming from a deb install, the directory structure is different and yo
|
||||||
|
|
||||||
| | Flatpak | Arch | Nixpkgs | ARM/ARM64 |
|
| | Flatpak | Arch | Nixpkgs | ARM/ARM64 |
|
||||||
| -------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------- |
|
| -------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------- |
|
||||||
| Latest Release | [FlatHub Page](https://flathub.org/apps/details/io.lbry.lbry-app) | [AUR Package](https://aur.archlinux.org/packages/lbry-desktop-bin/) | [Nixpkgs](https://search.nixos.org/packages?channel=unstable&show=lbry&query=lbry) | [Build Guide](https://lbry.tv/@LBRYarm:5) |
|
| Latest Release | [FlatHub Page](https://flathub.org/apps/details/io.lbry.lbry-app) | [AUR Package](https://aur.archlinux.org/packages/lbry-app-bin/) | [Nixpkgs](https://search.nixos.org/packages?channel=unstable&show=lbry&query=lbry) | [Build Guide](https://lbry.tv/@LBRYarm:5) |
|
||||||
| Maintainers | N/A | [@RubenKelevra](https://github.com/RubenKelevra) | [@Enderger](https://github.com/enderger) | [@Madiator2011](https://github.com/kodxana) |
|
| Maintainers | [@kcSeb](https://keybase.io/kcseb) | [@kcSeb](https://keybase.io/kcseb) | [@Enderger](https://github.com/enderger) | [@Madiator2011](https://github.com/kodxana) |
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Start the installed application to interact with the LBRY network.
|
Double click the installed application to interact with the LBRY network.
|
||||||
|
|
||||||
## Running from Source
|
## Running from Source
|
||||||
|
|
||||||
|
You can run the web version (lbry.tv), the electron app, or both at the same time.
|
||||||
|
|
||||||
#### Prerequisites
|
#### Prerequisites
|
||||||
|
|
||||||
- [Git](https://git-scm.com/downloads)
|
- [Git](https://git-scm.com/downloads)
|
||||||
- [Node.js](https://nodejs.org/en/download/) (v16 required)
|
- [Node.js](https://nodejs.org/en/download/) (v14 required)
|
||||||
- [Corepack](https://nodejs.org/dist/latest-v17.x/docs/api/corepack.html) `npm i -g corepack` (Included in nodejs 14 LTS, 16 LTS and 17)
|
|
||||||
- [Yarn](https://yarnpkg.com/en/docs/install)
|
- [Yarn](https://yarnpkg.com/en/docs/install)
|
||||||
|
|
||||||
1. Clone (or [fork](https://help.github.com/articles/fork-a-repo/)) this repository: `git clone https://github.com/lbryio/lbry-desktop`
|
1. Clone (or [fork](https://help.github.com/articles/fork-a-repo/)) this repository: `git clone https://github.com/lbryio/lbry-desktop`
|
||||||
2. Change directory into the cloned repository: `cd lbry-desktop`
|
2. Change directory into the cloned repository: `cd lbry-desktop`
|
||||||
3. If corepack is not enabled, run `sudo corepack enable` (the sudo is necessary for system-wide installation, if you use container, nvm etc... you might not be forced to use it)
|
3. Install the dependencies: `yarn`
|
||||||
4. Install the dependencies: `yarn`
|
|
||||||
|
|
||||||
#### Run the electron app
|
#### Run the electron app
|
||||||
|
|
||||||
|
@ -92,6 +87,66 @@ Start the installed application to interact with the LBRY network.
|
||||||
|
|
||||||
- If you want to build and launch the production app you can run `yarn build`. This will give you an executable inside the `/dist` folder. We use [electron-builder](https://github.com/electron-userland/electron-builder) to create distributable packages.
|
- If you want to build and launch the production app you can run `yarn build`. This will give you an executable inside the `/dist` folder. We use [electron-builder](https://github.com/electron-userland/electron-builder) to create distributable packages.
|
||||||
|
|
||||||
|
#### Run the web app for development
|
||||||
|
|
||||||
|
`yarn dev:web`
|
||||||
|
|
||||||
|
- This uses webpack-dev-server and includes hot-reloading. If you want to debug the [web server we use in production](https://github.com/lbryio/lbry-desktop/blob/master/web/index.js) you can run `yarn dev:web-server`. This starts a server at `localhost:1337` and does not include hot reloading.
|
||||||
|
|
||||||
|
#### Customize the web app
|
||||||
|
|
||||||
|
- In root directory, duplicate the .env.default file and rename it to .env then copy the code below and paste it anywhere in the .env file.
|
||||||
|
|
||||||
|
```
|
||||||
|
cp .env.defaults .env
|
||||||
|
nano .env
|
||||||
|
```
|
||||||
|
|
||||||
|
- To specify your own OG-IMAGE
|
||||||
|
You can either place a png named v2-og.png in the /custom folder or specify the OG_IMAGE_URL in .env
|
||||||
|
|
||||||
|
- To specify your own channels to be followed on first run
|
||||||
|
`AUTO_FOLLOW_URLS=lbry://@chan#123...a lbry://@chan2#456...a`
|
||||||
|
|
||||||
|
- If you want to customize the homepage content
|
||||||
|
|
||||||
|
1. add `CUSTOM_HOMEPAGE=true` to the '.env' file
|
||||||
|
2. copy `/custom/homepage.example.js` to `/custom/homepage.js` and make desired changes to `homepage.js`
|
||||||
|
|
||||||
|
- If you want up to two custom sidebar links
|
||||||
|
|
||||||
|
```
|
||||||
|
PINNED_URI_1=@someurl#2/someclaim#4
|
||||||
|
PINNED_LABEL_1=Linktext
|
||||||
|
|
||||||
|
PINNED_URI_2=$/discover?t=tag&[queryparams]
|
||||||
|
PINNED_LABEL_2=OtherLinkText
|
||||||
|
```
|
||||||
|
|
||||||
|
- Finally `NODE_ENV=production yarn compile:web` to rebuild
|
||||||
|
_Note: You don't need to edit the .env file in the /web folder - that is copied during compile._
|
||||||
|
|
||||||
|
#### Deploy the web app (_experimental_)
|
||||||
|
|
||||||
|
1. Create a server with a domain name and a reverse proxy https to port 1337.
|
||||||
|
2. Install pm2, node v10, yarn
|
||||||
|
3. Clone this repo
|
||||||
|
4. Make any customizations as above
|
||||||
|
5. Run `yarn` to install
|
||||||
|
6. Run `NODE_ENV=production yarn compile:web` to build
|
||||||
|
7. Set up pm2 to start ./web/index.js
|
||||||
|
|
||||||
|
#### Run both at the same time
|
||||||
|
|
||||||
|
Run the two commands above in separate terminal windows
|
||||||
|
|
||||||
|
```
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
// in another terminal window
|
||||||
|
yarn dev:web
|
||||||
|
```
|
||||||
|
|
||||||
#### Resetting your Packages
|
#### Resetting your Packages
|
||||||
|
|
||||||
If the app isn't building, or `yarn xxx` commands aren't working you may need to just reset your `node_modules`. To do so you can run: `rm -r node_modules && yarn` or `del /s /q node_modules && yarn` on Windows.
|
If the app isn't building, or `yarn xxx` commands aren't working you may need to just reset your `node_modules`. To do so you can run: `rm -r node_modules && yarn` or `del /s /q node_modules && yarn` on Windows.
|
||||||
|
@ -110,9 +165,6 @@ This project is MIT licensed. For the full license, see [LICENSE](LICENSE).
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
We take security seriously. Please contact security@lbry.com regarding any security issues. Our PGP key is [here](https://lbry.com/faq/pgp-key) if you need it. Previous versions up to v0.50.2 were signed by [Sean Yesmunt](https://keybase.io/seanyesmunt/key.asc).
|
We take security seriously. Please contact security@odysee.com regarding any security issues. Our PGP key is [here](https://lbry.com/faq/pgp-key) if you need it. Previous versions up to v0.50.2 were signed by [Sean Yesmunt](https://keybase.io/seanyesmunt/key.asc).
|
||||||
New Releases are signed by [Jessop Breth](https://keybase.io/jessopb/key.asc).
|
New Releases are signed by [Jessop Breth](https://keybase.io/jessopb/key.asc).
|
||||||
|
|
||||||
## Contact
|
|
||||||
|
|
||||||
The primary contact for this project is [@jessopb](https://github.com/jessopb).
|
|
||||||
|
|
|
@ -7,8 +7,6 @@ module.exports = api => {
|
||||||
'import-glob',
|
'import-glob',
|
||||||
'@babel/plugin-transform-runtime',
|
'@babel/plugin-transform-runtime',
|
||||||
['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }],
|
['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }],
|
||||||
['@babel/plugin-proposal-private-methods', { 'loose': false }],
|
|
||||||
['@babel/plugin-proposal-private-property-in-object', { 'loose': false }],
|
|
||||||
'@babel/plugin-transform-flow-strip-types',
|
'@babel/plugin-transform-flow-strip-types',
|
||||||
'@babel/plugin-proposal-class-properties',
|
'@babel/plugin-proposal-class-properties',
|
||||||
'react-hot-loader/babel',
|
'react-hot-loader/babel',
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,14 +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>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.network.client</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.network.server</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.cs.disable-library-validation</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
20
config.js
20
config.js
|
@ -3,18 +3,15 @@
|
||||||
require('dotenv-defaults').config({ silent: false });
|
require('dotenv-defaults').config({ silent: false });
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
MATOMO_URL: process.env.MATOMO_URL,
|
|
||||||
MATOMO_ID: process.env.MATOMO_ID,
|
|
||||||
WEBPACK_WEB_PORT: process.env.WEBPACK_WEB_PORT,
|
WEBPACK_WEB_PORT: process.env.WEBPACK_WEB_PORT,
|
||||||
WEBPACK_ELECTRON_PORT: process.env.WEBPACK_ELECTRON_PORT,
|
WEBPACK_ELECTRON_PORT: process.env.WEBPACK_ELECTRON_PORT,
|
||||||
WEB_SERVER_PORT: process.env.WEB_SERVER_PORT,
|
WEB_SERVER_PORT: process.env.WEB_SERVER_PORT,
|
||||||
LBRY_WEB_API: process.env.LBRY_WEB_API, //api.na-backend.odysee.com',
|
LBRY_WEB_API: process.env.LBRY_WEB_API, //api.na-backend.odysee.com',
|
||||||
LBRY_WEB_PUBLISH_API: process.env.LBRY_WEB_PUBLISH_API,
|
LBRY_WEB_PUBLISH_API: process.env.LBRY_WEB_PUBLISH_API,
|
||||||
LBRY_API_URL: process.env.LBRY_API_URL, //api.lbry.com',
|
LBRY_API_URL: process.env.LBRY_API_URL, //api.lbry.com',
|
||||||
LBRY_WEB_STREAMING_API: process.env.LBRY_WEB_STREAMING_API, //player.odysee.com
|
LBRY_WEB_STREAMING_API: process.env.LBRY_WEB_STREAMING_API, //cdn.lbryplayer.xyz',
|
||||||
LBRY_WEB_BUFFER_API: process.env.LBRY_WEB_BUFFER_API,
|
LBRY_WEB_BUFFER_API: process.env.LBRY_WEB_BUFFER_API,
|
||||||
SEARCH_SERVER_API: process.env.SEARCH_SERVER_API,
|
SEARCH_SERVER_API: process.env.SEARCH_SERVER_API,
|
||||||
CLOUD_CONNECT_SITE_NAME: process.env.CLOUD_CONNECT_SITE_NAME,
|
|
||||||
COMMENT_SERVER_API: process.env.COMMENT_SERVER_API,
|
COMMENT_SERVER_API: process.env.COMMENT_SERVER_API,
|
||||||
COMMENT_SERVER_NAME: process.env.COMMENT_SERVER_NAME,
|
COMMENT_SERVER_NAME: process.env.COMMENT_SERVER_NAME,
|
||||||
SOCKETY_SERVER_API: process.env.SOCKETY_SERVER_API,
|
SOCKETY_SERVER_API: process.env.SOCKETY_SERVER_API,
|
||||||
|
@ -23,6 +20,10 @@ const config = {
|
||||||
SHARE_DOMAIN_URL: process.env.SHARE_DOMAIN_URL,
|
SHARE_DOMAIN_URL: process.env.SHARE_DOMAIN_URL,
|
||||||
URL: process.env.URL,
|
URL: process.env.URL,
|
||||||
THUMBNAIL_CDN_URL: process.env.THUMBNAIL_CDN_URL,
|
THUMBNAIL_CDN_URL: process.env.THUMBNAIL_CDN_URL,
|
||||||
|
THUMBNAIL_CARDS_CDN_URL: process.env.THUMBNAIL_CARDS_CDN_URL,
|
||||||
|
THUMBNAIL_HEIGHT: process.env.THUMBNAIL_HEIGHT,
|
||||||
|
THUMBNAIL_WIDTH: process.env.THUMBNAIL_WIDTH,
|
||||||
|
THUMBNAIL_QUALITY: process.env.THUMBNAIL_QUALITY,
|
||||||
SITE_TITLE: process.env.SITE_TITLE,
|
SITE_TITLE: process.env.SITE_TITLE,
|
||||||
SITE_NAME: process.env.SITE_NAME,
|
SITE_NAME: process.env.SITE_NAME,
|
||||||
SITE_DESCRIPTION: process.env.SITE_DESCRIPTION,
|
SITE_DESCRIPTION: process.env.SITE_DESCRIPTION,
|
||||||
|
@ -74,6 +75,17 @@ const config = {
|
||||||
SHOW_TAGS_INTRO: process.env.SHOW_TAGS_INTRO === 'true',
|
SHOW_TAGS_INTRO: process.env.SHOW_TAGS_INTRO === 'true',
|
||||||
LIGHTHOUSE_DEFAULT_TYPES: process.env.LIGHTHOUSE_DEFAULT_TYPES,
|
LIGHTHOUSE_DEFAULT_TYPES: process.env.LIGHTHOUSE_DEFAULT_TYPES,
|
||||||
BRANDED_SITE: process.env.BRANDED_SITE,
|
BRANDED_SITE: process.env.BRANDED_SITE,
|
||||||
|
|
||||||
|
// FIREBASE SDK
|
||||||
|
FIREBASE_API_KEY: process.env.FIREBASE_API_KEY,
|
||||||
|
FIREBASE_AUTH_DOMAIN: process.env.FIREBASE_AUTH_DOMAIN,
|
||||||
|
FIREBASE_PROJECT_ID: process.env.FIREBASE_PROJECT_ID,
|
||||||
|
FIREBASE_STORAGE_BUCKET: process.env.FIREBASE_STORAGE_BUCKET,
|
||||||
|
FIREBASE_MESSAGING_SENDER_ID: process.env.FIREBASE_MESSAGING_SENDER_ID,
|
||||||
|
FIREBASE_APP_ID: process.env.FIREBASE_APP_ID,
|
||||||
|
FIREBASE_MEASUREMENT_ID: process.env.FIREBASE_MEASUREMENT_ID,
|
||||||
|
FIREBASE_VAPID_KEY: process.env.FIREBASE_VAPID_KEY,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config.URL_DEV = `http://localhost:${config.WEBPACK_WEB_PORT}`;
|
config.URL_DEV = `http://localhost:${config.WEBPACK_WEB_PORT}`;
|
||||||
|
|
|
@ -20,6 +20,11 @@
|
||||||
"to": "static/daemon/",
|
"to": "static/daemon/",
|
||||||
"filter": ["**/*"]
|
"filter": ["**/*"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"from": "./static/lbry-first/",
|
||||||
|
"to": "static/lbry-first/",
|
||||||
|
"filter": ["**/*"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"from": "./static/img",
|
"from": "./static/img",
|
||||||
"to": "static/img",
|
"to": "static/img",
|
||||||
|
@ -29,10 +34,6 @@
|
||||||
"from": "./static/font",
|
"from": "./static/font",
|
||||||
"to": "static/font",
|
"to": "static/font",
|
||||||
"filter": ["**/*"]
|
"filter": ["**/*"]
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "./static/app-update.yml",
|
|
||||||
"to": "app-update.yml"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"publish": [
|
"publish": [
|
||||||
|
@ -41,11 +42,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"mac": {
|
"mac": {
|
||||||
"category": "public.app-category.entertainment",
|
"category": "public.app-category.entertainment"
|
||||||
"entitlements": "build/entitlements.mac.plist",
|
|
||||||
"entitlementsInherit": "build/entitlements.mac.plist",
|
|
||||||
"hardenedRuntime" : true,
|
|
||||||
"gatekeeperAssess": false
|
|
||||||
},
|
},
|
||||||
"dmg": {
|
"dmg": {
|
||||||
"iconSize": 128,
|
"iconSize": 128,
|
||||||
|
@ -85,7 +82,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deb": {
|
"deb": {
|
||||||
"depends": ["gconf2", "gconf-service", "libnotify4", "libxtst6", "libnss3"]
|
"depends": ["gconf2", "gconf-service", "libnotify4", "libappindicator1", "libxtst6", "libnss3"]
|
||||||
},
|
},
|
||||||
"nsis": {
|
"nsis": {
|
||||||
"perMachine": true,
|
"perMachine": true,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { WEBPACK_ELECTRON_PORT } from 'config';
|
import { WEBPACK_ELECTRON_PORT } from 'config';
|
||||||
import { app, BrowserWindow, dialog, screen, nativeImage } from 'electron';
|
import { app, BrowserWindow, dialog, shell, screen, nativeImage } from 'electron';
|
||||||
import isDev from 'electron-is-dev';
|
import isDev from 'electron-is-dev';
|
||||||
import windowStateKeeper from 'electron-window-state';
|
import windowStateKeeper from 'electron-window-state';
|
||||||
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
||||||
|
@ -9,8 +9,7 @@ import { TO_TRAY_WHEN_CLOSED } from 'constants/settings';
|
||||||
|
|
||||||
import setupBarMenu from './menu/setupBarMenu';
|
import setupBarMenu from './menu/setupBarMenu';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
const remote = require('@electron/remote/main');
|
|
||||||
const shell = require('electron').shell;
|
|
||||||
function GetAppLangCode() {
|
function GetAppLangCode() {
|
||||||
// https://www.electronjs.org/docs/api/locales
|
// https://www.electronjs.org/docs/api/locales
|
||||||
// 1. Gets the user locale.
|
// 1. Gets the user locale.
|
||||||
|
@ -55,8 +54,6 @@ export default appState => {
|
||||||
webSecurity: !isDev,
|
webSecurity: !isDev,
|
||||||
plugins: true,
|
plugins: true,
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
contextIsolation: false,
|
|
||||||
enableRemoteModule: true, // see about removing this
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const lbryProto = 'lbry://';
|
const lbryProto = 'lbry://';
|
||||||
|
@ -64,7 +61,6 @@ export default appState => {
|
||||||
const rendererURL = isDev ? `http://localhost:${WEBPACK_ELECTRON_PORT}` : `file://${__dirname}/index.html`;
|
const rendererURL = isDev ? `http://localhost:${WEBPACK_ELECTRON_PORT}` : `file://${__dirname}/index.html`;
|
||||||
|
|
||||||
let window = new BrowserWindow(windowConfiguration);
|
let window = new BrowserWindow(windowConfiguration);
|
||||||
remote.enable(window.webContents);
|
|
||||||
|
|
||||||
// Let us register listeners on the window, so we can update the state
|
// Let us register listeners on the window, so we can update the state
|
||||||
// automatically (the listeners will be removed when the window is closed)
|
// automatically (the listeners will be removed when the window is closed)
|
||||||
|
@ -95,7 +91,7 @@ export default appState => {
|
||||||
|
|
||||||
// is it a lbry://? pointing to an app page
|
// is it a lbry://? pointing to an app page
|
||||||
if (deepLinkingURI.includes(lbryProtoQ)) {
|
if (deepLinkingURI.includes(lbryProtoQ)) {
|
||||||
let path = deepLinkingURI.slice(lbryProtoQ.length);
|
let path = deepLinkingURI.substr(lbryProtoQ.length);
|
||||||
let page = path.indexOf('?') >= 0 ? path.substring(0, path.indexOf('?')) : path;
|
let page = path.indexOf('?') >= 0 ? path.substring(0, path.indexOf('?')) : path;
|
||||||
if (Object.values(PAGES).includes(page)) {
|
if (Object.values(PAGES).includes(page)) {
|
||||||
deepLinkingURI = deepLinkingURI.replace(lbryProtoQ, '#/$/');
|
deepLinkingURI = deepLinkingURI.replace(lbryProtoQ, '#/$/');
|
||||||
|
@ -190,13 +186,9 @@ export default appState => {
|
||||||
window = null;
|
window = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
window.webContents.setWindowOpenHandler((details) => {
|
window.webContents.on('new-window', (event, url) => {
|
||||||
// Only open http and https links to prevent
|
event.preventDefault();
|
||||||
// security issues.
|
shell.openExternal(url);
|
||||||
if (['https:', 'http:'].includes(new URL(details.url).protocol)) {
|
|
||||||
shell.openExternal(details.url);
|
|
||||||
}
|
|
||||||
return { action: 'deny' };
|
|
||||||
});
|
});
|
||||||
|
|
||||||
window.webContents.on('update-target-url', (event, url) => {
|
window.webContents.on('update-target-url', (event, url) => {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import '@babel/polyfill';
|
import '@babel/polyfill';
|
||||||
import SemVer from 'semver';
|
import SemVer from 'semver';
|
||||||
import https from 'https';
|
import https from 'https';
|
||||||
import { app, dialog, ipcMain, session, shell, BrowserWindow } from 'electron';
|
import { app, dialog, ipcMain, session, shell } from 'electron';
|
||||||
import { autoUpdater } from 'electron-updater';
|
import { autoUpdater } from 'electron-updater';
|
||||||
import Lbry from 'lbry';
|
import Lbry from 'lbry';
|
||||||
import LbryFirstInstance from './LbryFirstInstance';
|
import LbryFirstInstance from './LbryFirstInstance';
|
||||||
|
@ -17,17 +17,6 @@ import startSandbox from './startSandbox';
|
||||||
import installDevtools from './installDevtools';
|
import installDevtools from './installDevtools';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { diskSpaceLinux, diskSpaceWindows, diskSpaceMac } from '../ui/util/diskspace';
|
|
||||||
|
|
||||||
const { download } = require('electron-dl');
|
|
||||||
const mime = require('mime');
|
|
||||||
const remote = require('@electron/remote/main');
|
|
||||||
const os = require('os');
|
|
||||||
const sudo = require('sudo-prompt');
|
|
||||||
const probe = require('ffmpeg-probe');
|
|
||||||
const MAX_IPC_SEND_BUFFER_SIZE = 500000000; // large files crash when serialized for ipc message
|
|
||||||
|
|
||||||
remote.initialize();
|
|
||||||
const filePath = path.join(process.resourcesPath, 'static', 'upgradeDisabled');
|
const filePath = path.join(process.resourcesPath, 'static', 'upgradeDisabled');
|
||||||
let upgradeDisabled;
|
let upgradeDisabled;
|
||||||
try {
|
try {
|
||||||
|
@ -37,18 +26,11 @@ try {
|
||||||
upgradeDisabled = false;
|
upgradeDisabled = false;
|
||||||
}
|
}
|
||||||
autoUpdater.autoDownload = !upgradeDisabled;
|
autoUpdater.autoDownload = !upgradeDisabled;
|
||||||
autoUpdater.allowPrerelease = false;
|
|
||||||
|
|
||||||
const UPDATE_STATE_INIT = 0;
|
// This is set to true if an auto update has been downloaded through the Electron
|
||||||
const UPDATE_STATE_CHECKING = 1;
|
// auto-update system and is ready to install. If the user declined an update earlier,
|
||||||
const UPDATE_STATE_UPDATES_FOUND = 2;
|
// it will still install on shutdown.
|
||||||
const UPDATE_STATE_NO_UPDATES_FOUND = 3;
|
let autoUpdateDownloaded = false;
|
||||||
const UPDATE_STATE_DOWNLOADING = 4;
|
|
||||||
const UPDATE_STATE_DOWNLOADED = 5;
|
|
||||||
let updateState = UPDATE_STATE_INIT;
|
|
||||||
let updateDownloadItem;
|
|
||||||
|
|
||||||
const isAutoUpdateSupported = ['win32', 'darwin'].includes(process.platform) || !!process.env.APPIMAGE;
|
|
||||||
|
|
||||||
// This is used to keep track of whether we are showing the special dialog
|
// This is used to keep track of whether we are showing the special dialog
|
||||||
// that we show on Windows after you decline an upgrade and close the app later.
|
// that we show on Windows after you decline an upgrade and close the app later.
|
||||||
|
@ -70,7 +52,7 @@ if (isDev && process.platform === 'win32') {
|
||||||
app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, [
|
app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, [
|
||||||
path.resolve(process.argv[1]),
|
path.resolve(process.argv[1]),
|
||||||
]);
|
]);
|
||||||
} else if (process.platform !== 'linux') {
|
} else {
|
||||||
app.setAsDefaultProtocolClient(PROTOCOL);
|
app.setAsDefaultProtocolClient(PROTOCOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,8 +223,7 @@ app.on('activate', () => {
|
||||||
app.on('will-quit', event => {
|
app.on('will-quit', event => {
|
||||||
if (
|
if (
|
||||||
process.platform === 'win32' &&
|
process.platform === 'win32' &&
|
||||||
updateState === UPDATE_STATE_DOWNLOADED &&
|
autoUpdateDownloaded &&
|
||||||
isAutoUpdateSupported &&
|
|
||||||
!appState.autoUpdateAccepted &&
|
!appState.autoUpdateAccepted &&
|
||||||
!showingAutoUpdateCloseAlert
|
!showingAutoUpdateCloseAlert
|
||||||
) {
|
) {
|
||||||
|
@ -302,118 +283,27 @@ app.on('before-quit', () => {
|
||||||
appState.isQuitting = true;
|
appState.isQuitting = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get the content of a file as a raw buffer of bytes.
|
ipcMain.on('upgrade', (event, installerPath) => {
|
||||||
// Useful to convert a file path to a File instance.
|
app.on('quit', () => {
|
||||||
// Example:
|
console.log('Launching upgrade installer at', installerPath);
|
||||||
// const result = await ipcMain.invoke('get-file-from-path', 'path/to/file');
|
// This gets triggered called after *all* other quit-related events, so
|
||||||
// const file = new File([result.buffer], result.name);
|
// we'll only get here if we're fully prepared and quitting for real.
|
||||||
// NOTE: if path points to a folder, an empty
|
shell.openPath(installerPath);
|
||||||
// file will be given.
|
|
||||||
ipcMain.handle('get-file-from-path', (event, path, readContents = true) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
fs.stat(path, (error, stats) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Separate folders considering "\" and "/"
|
|
||||||
// as separators (cross platform)
|
|
||||||
const folders = path.split(/[\\/]/);
|
|
||||||
const name = folders[folders.length - 1];
|
|
||||||
if (stats.isDirectory()) {
|
|
||||||
resolve({
|
|
||||||
name,
|
|
||||||
mime: undefined,
|
|
||||||
path,
|
|
||||||
buffer: new ArrayBuffer(0),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!readContents) {
|
|
||||||
resolve({
|
|
||||||
name,
|
|
||||||
mime: mime.getType(name) || undefined,
|
|
||||||
path,
|
|
||||||
buffer: new ArrayBuffer(0),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Encoding null ensures data results in a Buffer.
|
|
||||||
fs.readFile(path, { encoding: null }, (err, data) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resolve({
|
|
||||||
name,
|
|
||||||
mime: mime.getType(name) || undefined,
|
|
||||||
path,
|
|
||||||
buffer: data,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
// what to do if no shutdown in a long time?
|
||||||
|
console.log('Update downloaded to', installerPath);
|
||||||
|
console.log('The app will close and you will be prompted to install the latest version of LBRY.');
|
||||||
|
console.log('After the install is complete, please reopen the app.');
|
||||||
|
app.quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('get-file-details-from-path', async (event, path) => {
|
autoUpdater.on('update-downloaded', () => {
|
||||||
const isFfMp4 = (ffprobeResults) => {
|
autoUpdateDownloaded = true;
|
||||||
return ffprobeResults &&
|
|
||||||
ffprobeResults.format &&
|
|
||||||
ffprobeResults.format.format_name &&
|
|
||||||
ffprobeResults.format.format_name.includes('mp4');
|
|
||||||
};
|
|
||||||
const folders = path.split(/[\\/]/);
|
|
||||||
const name = folders[folders.length - 1];
|
|
||||||
let duration = 0, size = 0, mimeType;
|
|
||||||
try {
|
|
||||||
await fs.promises.stat(path);
|
|
||||||
let ffprobeResults;
|
|
||||||
try {
|
|
||||||
ffprobeResults = await probe(path);
|
|
||||||
duration = ffprobeResults.format.duration;
|
|
||||||
size = ffprobeResults.format.size;
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
let fileReadResult;
|
|
||||||
if (size < MAX_IPC_SEND_BUFFER_SIZE) {
|
|
||||||
try {
|
|
||||||
fileReadResult = await fs.promises.readFile(path);
|
|
||||||
} catch (e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: use mmmagic to inspect file and get mime type
|
|
||||||
mimeType = isFfMp4(ffprobeResults) ? 'video/mp4' : mime.getType(name);
|
|
||||||
const fileData = {name, mime: mimeType || undefined, path, duration: duration, size, buffer: fileReadResult };
|
|
||||||
return fileData;
|
|
||||||
} catch (e) {
|
|
||||||
// no stat
|
|
||||||
return { error: 'no file' };
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('get-disk-space', async (event) => {
|
ipcMain.on('autoUpdateAccepted', () => {
|
||||||
try {
|
appState.autoUpdateAccepted = true;
|
||||||
const { data_dir } = await Lbry.settings_get();
|
autoUpdater.quitAndInstall();
|
||||||
let diskSpace;
|
|
||||||
switch (os.platform()) {
|
|
||||||
case 'linux':
|
|
||||||
diskSpace = await diskSpaceLinux(data_dir);
|
|
||||||
break;
|
|
||||||
case 'darwin':
|
|
||||||
diskSpace = await diskSpaceMac(data_dir);
|
|
||||||
break;
|
|
||||||
case 'win32':
|
|
||||||
diskSpace = await diskSpaceWindows(data_dir);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error('unknown platform');
|
|
||||||
}
|
|
||||||
rendererWindow.webContents.send('send-disk-space', { diskSpace });
|
|
||||||
} catch (e) {
|
|
||||||
rendererWindow.webContents.send('send-disk-space', { error: e.message || e });
|
|
||||||
console.log('Failed to get disk space', e);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('version-info-requested', () => {
|
ipcMain.on('version-info-requested', () => {
|
||||||
|
@ -508,162 +398,3 @@ process.on('uncaughtException', error => {
|
||||||
if (daemon) daemon.quit();
|
if (daemon) daemon.quit();
|
||||||
app.exit(1);
|
app.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Auto updater
|
|
||||||
autoUpdater.on('download-progress', () => {
|
|
||||||
updateState = UPDATE_STATE_DOWNLOADING;
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on('update-downloaded', () => {
|
|
||||||
updateState = UPDATE_STATE_DOWNLOADED;
|
|
||||||
|
|
||||||
// If this download was trigger by
|
|
||||||
// autoUpdateAccepted it means, the user
|
|
||||||
// wants to install the new update but
|
|
||||||
// needed to downloaded the files first.
|
|
||||||
if (appState.autoUpdateAccepted) {
|
|
||||||
autoUpdater.quitAndInstall();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on('update-available', () => {
|
|
||||||
if (updateState === UPDATE_STATE_DOWNLOADING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateState = UPDATE_STATE_UPDATES_FOUND;
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on('update-not-available', () => {
|
|
||||||
updateState = UPDATE_STATE_NO_UPDATES_FOUND;
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on('error', () => {
|
|
||||||
if (updateState === UPDATE_STATE_DOWNLOADING) {
|
|
||||||
updateState = UPDATE_STATE_UPDATES_FOUND;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateState = UPDATE_STATE_INIT;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Manual (.deb) update
|
|
||||||
ipcMain.on('cancel-download-upgrade', () => {
|
|
||||||
if (updateDownloadItem) {
|
|
||||||
// Cancel the download and execute the onCancel
|
|
||||||
// callback set in the options.
|
|
||||||
updateDownloadItem.cancel();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('download-upgrade', (event, params) => {
|
|
||||||
if (updateState !== UPDATE_STATE_UPDATES_FOUND) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isAutoUpdateSupported) {
|
|
||||||
updateState = UPDATE_STATE_DOWNLOADING;
|
|
||||||
autoUpdater.downloadUpdate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { url, options } = params;
|
|
||||||
const dir = fs.mkdtempSync(app.getPath('temp') + path.sep);
|
|
||||||
|
|
||||||
updateState = UPDATE_STATE_DOWNLOADING;
|
|
||||||
|
|
||||||
// Grab the download item's handler to allow
|
|
||||||
// cancelling the operation if required.
|
|
||||||
options.onStarted = function(downloadItem) {
|
|
||||||
updateDownloadItem = downloadItem;
|
|
||||||
};
|
|
||||||
options.onCancel = function() {
|
|
||||||
updateState = UPDATE_STATE_UPDATES_FOUND;
|
|
||||||
updateDownloadItem = undefined;
|
|
||||||
};
|
|
||||||
options.onProgress = function(p) {
|
|
||||||
rendererWindow.webContents.send('download-progress-update', p);
|
|
||||||
};
|
|
||||||
options.onCompleted = function(c) {
|
|
||||||
updateState = UPDATE_STATE_DOWNLOADED;
|
|
||||||
updateDownloadItem = undefined;
|
|
||||||
rendererWindow.webContents.send('download-update-complete', c);
|
|
||||||
};
|
|
||||||
options.directory = dir;
|
|
||||||
const win = BrowserWindow.getFocusedWindow();
|
|
||||||
download(win, url, options).catch(e => {
|
|
||||||
updateState = UPDATE_STATE_UPDATES_FOUND;
|
|
||||||
console.log('e', e);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update behavior
|
|
||||||
ipcMain.on('autoUpdateAccepted', () => {
|
|
||||||
appState.autoUpdateAccepted = true;
|
|
||||||
|
|
||||||
// quitAndInstall can only be called if the
|
|
||||||
// update has been downloaded. Since the user
|
|
||||||
// can disable auto updates, we have to make
|
|
||||||
// sure it has been downloaded first.
|
|
||||||
if (updateState === UPDATE_STATE_DOWNLOADED) {
|
|
||||||
autoUpdater.quitAndInstall();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updateState !== UPDATE_STATE_UPDATES_FOUND) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the update hasn't been downloaded,
|
|
||||||
// start downloading it. After it's done, the
|
|
||||||
// event 'update-downloaded' will be triggered,
|
|
||||||
// where we will be able to resume the
|
|
||||||
// update installation.
|
|
||||||
updateState = UPDATE_STATE_DOWNLOADING;
|
|
||||||
autoUpdater.downloadUpdate();
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('check-for-updates', (event, autoDownload) => {
|
|
||||||
if (![UPDATE_STATE_INIT, UPDATE_STATE_NO_UPDATES_FOUND].includes(updateState)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateState = UPDATE_STATE_CHECKING;
|
|
||||||
|
|
||||||
// If autoDownload is true, checkForUpdates will begin the
|
|
||||||
// download automatically.
|
|
||||||
if (autoDownload) {
|
|
||||||
updateState = UPDATE_STATE_DOWNLOADING;
|
|
||||||
}
|
|
||||||
|
|
||||||
autoUpdater.autoDownload = autoDownload;
|
|
||||||
autoUpdater.checkForUpdates();
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('upgrade', (event, installerPath) => {
|
|
||||||
// what to do if no shutdown in a long time?
|
|
||||||
console.log('Update downloaded to', installerPath);
|
|
||||||
console.log('The app will close and you will be prompted to install the latest version of LBRY.');
|
|
||||||
console.log('After the install is complete, please reopen the app.');
|
|
||||||
|
|
||||||
// Prevent .deb package from opening with archive manager (Ubuntu >= 20)
|
|
||||||
if (process.platform === 'linux' && !process.env.APPIMAGE) {
|
|
||||||
sudo.exec(`dpkg -i ${installerPath}`, { name: app.name }, (err, stdout, stderr) => {
|
|
||||||
if (err || stderr) {
|
|
||||||
rendererWindow.webContents.send('upgrade-installing-error');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-launch the application when the installation finishes.
|
|
||||||
app.relaunch();
|
|
||||||
app.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.on('quit', () => {
|
|
||||||
console.log('Launching upgrade installer at', installerPath);
|
|
||||||
// This gets triggered called after *all* other quit-related events, so
|
|
||||||
// we'll only get here if we're fully prepared and quitting for real.
|
|
||||||
shell.openPath(installerPath);
|
|
||||||
});
|
|
||||||
app.quit();
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// import express from 'express';
|
import express from 'express';
|
||||||
|
import unpackByOutpoint from './unpackByOutpoint';
|
||||||
|
|
||||||
// Polyfills and `lbry-redux`
|
// Polyfills and `lbry-redux`
|
||||||
global.fetch = require('node-fetch');
|
global.fetch = require('node-fetch');
|
||||||
|
@ -7,31 +8,31 @@ if (typeof global.fetch === 'object') {
|
||||||
global.fetch = global.fetch.default;
|
global.fetch = global.fetch.default;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const Lbry = require('lbry');
|
const Lbry = require('lbry');
|
||||||
|
|
||||||
delete global.window;
|
delete global.window;
|
||||||
|
|
||||||
export default async function startSandbox() {
|
export default async function startSandbox() {
|
||||||
// const port = 5278;
|
const port = 5278;
|
||||||
// const sandbox = express();
|
const sandbox = express();
|
||||||
|
|
||||||
// sandbox.get('/set/:outpoint', async (req, res) => {
|
sandbox.get('/set/:outpoint', async (req, res) => {
|
||||||
// const { outpoint } = req.params;
|
const { outpoint } = req.params;
|
||||||
//
|
|
||||||
// const resolvedPath = await unpackByOutpoint(Lbry, outpoint);
|
const resolvedPath = await unpackByOutpoint(Lbry, outpoint);
|
||||||
//
|
|
||||||
// sandbox.use(`/sandbox/${outpoint}/`, express.static(resolvedPath));
|
sandbox.use(`/sandbox/${outpoint}/`, express.static(resolvedPath));
|
||||||
//
|
|
||||||
// res.send(`/sandbox/${outpoint}/`);
|
res.send(`/sandbox/${outpoint}/`);
|
||||||
// });
|
});
|
||||||
//
|
|
||||||
// sandbox
|
sandbox
|
||||||
// .listen(port, 'localhost', () => console.log(`Sandbox listening on port ${port}.`))
|
.listen(port, 'localhost', () => console.log(`Sandbox listening on port ${port}.`))
|
||||||
// .on('error', err => {
|
.on('error', err => {
|
||||||
// if (err.code === 'EADDRINUSE') {
|
if (err.code === 'EADDRINUSE') {
|
||||||
// console.log(
|
console.log(
|
||||||
// `Server already listening at localhost:${port}. This is probably another LBRY app running. If not, games in the app will not work.`
|
`Server already listening at localhost:${port}. This is probably another LBRY app running. If not, games in the app will not work.`
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
}
|
}
|
||||||
|
|
23
electron/unpackByOutpoint.js
Normal file
23
electron/unpackByOutpoint.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { unpackDirectory } from 'lbry-format';
|
||||||
|
|
||||||
|
async function unpackByOutpoint(lbry, outpoint) {
|
||||||
|
const { items: claimFiles } = await lbry.file_list({ outpoint, full_status: true, page: 1, page_size: 1 });
|
||||||
|
|
||||||
|
if (claimFiles && claimFiles.length) {
|
||||||
|
const claimFileInfo = claimFiles[0];
|
||||||
|
const packFilePath = path.resolve(claimFileInfo.download_path);
|
||||||
|
const unpackPath = path.normalize(path.join(claimFileInfo.download_directory, claimFileInfo.claim_name));
|
||||||
|
|
||||||
|
if (!fs.existsSync(unpackPath)) {
|
||||||
|
await unpackDirectory(unpackPath, {
|
||||||
|
fileName: packFilePath,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return unpackPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default unpackByOutpoint;
|
|
@ -17,9 +17,6 @@ export const FETCH_CHANNEL_LIST_STARTED = 'FETCH_CHANNEL_LIST_STARTED';
|
||||||
export const FETCH_CHANNEL_LIST_COMPLETED = 'FETCH_CHANNEL_LIST_COMPLETED';
|
export const FETCH_CHANNEL_LIST_COMPLETED = 'FETCH_CHANNEL_LIST_COMPLETED';
|
||||||
export const CREATE_CHANNEL_STARTED = 'CREATE_CHANNEL_STARTED';
|
export const CREATE_CHANNEL_STARTED = 'CREATE_CHANNEL_STARTED';
|
||||||
export const CREATE_CHANNEL_COMPLETED = 'CREATE_CHANNEL_COMPLETED';
|
export const CREATE_CHANNEL_COMPLETED = 'CREATE_CHANNEL_COMPLETED';
|
||||||
export const PUBLISH_STARTED = 'PUBLISH_STARTED';
|
|
||||||
export const PUBLISH_COMPLETED = 'PUBLISH_COMPLETED';
|
|
||||||
export const PUBLISH_FAILED = 'PUBLISH_FAILED';
|
|
||||||
export const SET_PLAYING_URI = 'SET_PLAYING_URI';
|
export const SET_PLAYING_URI = 'SET_PLAYING_URI';
|
||||||
export const SET_CONTENT_POSITION = 'SET_CONTENT_POSITION';
|
export const SET_CONTENT_POSITION = 'SET_CONTENT_POSITION';
|
||||||
export const SET_CONTENT_LAST_VIEWED = 'SET_CONTENT_LAST_VIEWED';
|
export const SET_CONTENT_LAST_VIEWED = 'SET_CONTENT_LAST_VIEWED';
|
||||||
|
@ -29,10 +26,8 @@ export const CLEAR_CONTENT_HISTORY_ALL = 'CLEAR_CONTENT_HISTORY_ALL';
|
||||||
// Subscriptions
|
// Subscriptions
|
||||||
export const CHANNEL_SUBSCRIBE = 'CHANNEL_SUBSCRIBE';
|
export const CHANNEL_SUBSCRIBE = 'CHANNEL_SUBSCRIBE';
|
||||||
export const CHANNEL_UNSUBSCRIBE = 'CHANNEL_UNSUBSCRIBE';
|
export const CHANNEL_UNSUBSCRIBE = 'CHANNEL_UNSUBSCRIBE';
|
||||||
export const CHANNEL_SUBSCRIPTION_ENABLE_NOTIFICATIONS =
|
export const CHANNEL_SUBSCRIPTION_ENABLE_NOTIFICATIONS = 'CHANNEL_SUBSCRIPTION_ENABLE_NOTIFICATIONS';
|
||||||
'CHANNEL_SUBSCRIPTION_ENABLE_NOTIFICATIONS';
|
export const CHANNEL_SUBSCRIPTION_DISABLE_NOTIFICATIONS = 'CHANNEL_SUBSCRIPTION_DISABLE_NOTIFICATIONS';
|
||||||
export const CHANNEL_SUBSCRIPTION_DISABLE_NOTIFICATIONS =
|
|
||||||
'CHANNEL_SUBSCRIPTION_DISABLE_NOTIFICATIONS';
|
|
||||||
export const HAS_FETCHED_SUBSCRIPTIONS = 'HAS_FETCHED_SUBSCRIPTIONS';
|
export const HAS_FETCHED_SUBSCRIPTIONS = 'HAS_FETCHED_SUBSCRIPTIONS';
|
||||||
export const SET_SUBSCRIPTION_LATEST = 'SET_SUBSCRIPTION_LATEST';
|
export const SET_SUBSCRIPTION_LATEST = 'SET_SUBSCRIPTION_LATEST';
|
||||||
export const UPDATE_SUBSCRIPTION_UNREADS = 'UPDATE_SUBSCRIPTION_UNREADS';
|
export const UPDATE_SUBSCRIPTION_UNREADS = 'UPDATE_SUBSCRIPTION_UNREADS';
|
||||||
|
|
|
@ -16,6 +16,7 @@ export { doGenerateAuthToken } from './redux/actions/auth';
|
||||||
export { doFetchCostInfoForUri } from './redux/actions/cost_info';
|
export { doFetchCostInfoForUri } from './redux/actions/cost_info';
|
||||||
export { doBlackListedOutpointsSubscribe } from './redux/actions/blacklist';
|
export { doBlackListedOutpointsSubscribe } from './redux/actions/blacklist';
|
||||||
export { doFilteredOutpointsSubscribe } from './redux/actions/filtered';
|
export { doFilteredOutpointsSubscribe } from './redux/actions/filtered';
|
||||||
|
// export { doFetchFeaturedUris, doFetchTrendingUris } from './redux/actions/homepage';
|
||||||
export { doFetchViewCount, doFetchSubCount } from './redux/actions/stats';
|
export { doFetchViewCount, doFetchSubCount } from './redux/actions/stats';
|
||||||
export {
|
export {
|
||||||
doCheckSync,
|
doCheckSync,
|
||||||
|
@ -26,35 +27,35 @@ export {
|
||||||
doResetSync,
|
doResetSync,
|
||||||
doSyncEncryptAndDecrypt,
|
doSyncEncryptAndDecrypt,
|
||||||
} from 'redux/actions/sync';
|
} from 'redux/actions/sync';
|
||||||
|
export { doUpdateUploadProgress } from './redux/actions/web';
|
||||||
|
|
||||||
// reducers
|
// reducers
|
||||||
export { authReducer } from './redux/reducers/auth';
|
export { authReducer } from './redux/reducers/auth';
|
||||||
export { costInfoReducer } from './redux/reducers/cost_info';
|
export { costInfoReducer } from './redux/reducers/cost_info';
|
||||||
export { blacklistReducer } from './redux/reducers/blacklist';
|
export { blacklistReducer } from './redux/reducers/blacklist';
|
||||||
export { filteredReducer } from './redux/reducers/filtered';
|
export { filteredReducer } from './redux/reducers/filtered';
|
||||||
|
// export { homepageReducer } from './redux/reducers/homepage';
|
||||||
export { statsReducer } from './redux/reducers/stats';
|
export { statsReducer } from './redux/reducers/stats';
|
||||||
export { syncReducer } from './redux/reducers/sync';
|
export { syncReducer } from './redux/reducers/sync';
|
||||||
|
export { webReducer } from './redux/reducers/web';
|
||||||
|
|
||||||
// selectors
|
// selectors
|
||||||
export { selectAuthToken, selectIsAuthenticating } from './redux/selectors/auth';
|
export { selectAuthToken, selectIsAuthenticating } from './redux/selectors/auth';
|
||||||
export {
|
export {
|
||||||
selectFetchingCostInfoForUri,
|
makeSelectFetchingCostInfoForUri,
|
||||||
selectCostInfoForUri,
|
makeSelectCostInfoForUri,
|
||||||
selectAllCostInfoByUri,
|
selectAllCostInfoByUri,
|
||||||
selectFetchingCostInfo,
|
selectFetchingCostInfo,
|
||||||
} from './redux/selectors/cost_info';
|
} from './redux/selectors/cost_info';
|
||||||
export {
|
export { selectBlackListedOutpoints, selectBlacklistedOutpointMap } from './redux/selectors/blacklist';
|
||||||
selectBlackListedOutpoints,
|
|
||||||
selectBlacklistedOutpointMap,
|
|
||||||
} from './redux/selectors/blacklist';
|
|
||||||
export { selectFilteredOutpoints, selectFilteredOutpointMap } from './redux/selectors/filtered';
|
export { selectFilteredOutpoints, selectFilteredOutpointMap } from './redux/selectors/filtered';
|
||||||
export {
|
// export {
|
||||||
selectViewCount,
|
// selectFeaturedUris,
|
||||||
selectViewCountForUri,
|
// selectFetchingFeaturedUris,
|
||||||
// makeSelectViewCountForUri, // deprecated
|
// selectTrendingUris,
|
||||||
selectSubCountForUri,
|
// selectFetchingTrendingUris,
|
||||||
// makeSelectSubCountForUri, // deprecated
|
// } from './redux/selectors/homepage';
|
||||||
} from './redux/selectors/stats';
|
export { selectViewCount, makeSelectViewCountForUri, makeSelectSubCountForUri } from './redux/selectors/stats';
|
||||||
export { selectBanStateForUri } from './redux/selectors/ban';
|
export { selectBanStateForUri } from './redux/selectors/ban';
|
||||||
export {
|
export {
|
||||||
selectHasSyncedWallet,
|
selectHasSyncedWallet,
|
||||||
|
@ -69,3 +70,4 @@ export {
|
||||||
selectSyncApplyErrorMessage,
|
selectSyncApplyErrorMessage,
|
||||||
selectSyncApplyPasswordError,
|
selectSyncApplyPasswordError,
|
||||||
} from './redux/selectors/sync';
|
} from './redux/selectors/sync';
|
||||||
|
export { selectCurrentUploads, selectUploadCount } from './redux/selectors/web';
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import Lbry from 'lbry';
|
import Lbry from 'lbry';
|
||||||
import querystring from 'querystring';
|
import querystring from 'querystring';
|
||||||
|
import analytics from 'analytics';
|
||||||
|
|
||||||
const Lbryio = {
|
const Lbryio = {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -14,7 +15,7 @@ const EXCHANGE_RATE_TIMEOUT = 20 * 60 * 1000;
|
||||||
const INTERNAL_APIS_DOWN = 'internal_apis_down';
|
const INTERNAL_APIS_DOWN = 'internal_apis_down';
|
||||||
|
|
||||||
// We can't use env's because they aren't passed into node_modules
|
// We can't use env's because they aren't passed into node_modules
|
||||||
Lbryio.setLocalApi = endpoint => {
|
Lbryio.setLocalApi = (endpoint) => {
|
||||||
Lbryio.CONNECTION_STRING = endpoint.replace(/\/*$/, '/'); // exactly one slash at the end;
|
Lbryio.CONNECTION_STRING = endpoint.replace(/\/*$/, '/'); // exactly one slash at the end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,8 +37,8 @@ Lbryio.call = (resource, action, params = {}, method = 'get') => {
|
||||||
return Promise.reject(INTERNAL_APIS_DOWN);
|
return Promise.reject(INTERNAL_APIS_DOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response)
|
if (response) {
|
||||||
return response.json().then(json => {
|
return response.json().then((json) => {
|
||||||
let error;
|
let error;
|
||||||
if (json.error) {
|
if (json.error) {
|
||||||
error = new Error(json.error);
|
error = new Error(json.error);
|
||||||
|
@ -48,14 +49,15 @@ Lbryio.call = (resource, action, params = {}, method = 'get') => {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function makeRequest(url, options) {
|
function makeRequest(url, options) {
|
||||||
return fetch(url, options).then(checkAndParse);
|
return fetch(url, options).then(checkAndParse);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Lbryio.getAuthToken().then(token => {
|
return Lbryio.getAuthToken().then((token) => {
|
||||||
const fullParams = { auth_token: token, ...params };
|
const fullParams = { auth_token: token, ...params };
|
||||||
Object.keys(fullParams).forEach(key => {
|
Object.keys(fullParams).forEach((key) => {
|
||||||
const value = fullParams[key];
|
const value = fullParams[key];
|
||||||
if (typeof value === 'object') {
|
if (typeof value === 'object') {
|
||||||
fullParams[key] = JSON.stringify(value);
|
fullParams[key] = JSON.stringify(value);
|
||||||
|
@ -80,18 +82,21 @@ Lbryio.call = (resource, action, params = {}, method = 'get') => {
|
||||||
url = `${Lbryio.CONNECTION_STRING}${resource}/${action}`;
|
url = `${Lbryio.CONNECTION_STRING}${resource}/${action}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeRequest(url, options).then(response => response.data);
|
return makeRequest(url, options).then((response) => {
|
||||||
|
sendCallAnalytics(resource, action, params);
|
||||||
|
return response.data;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Lbryio.authToken = null;
|
Lbryio.authToken = null;
|
||||||
|
|
||||||
Lbryio.getAuthToken = () =>
|
Lbryio.getAuthToken = () =>
|
||||||
new Promise(resolve => {
|
new Promise((resolve) => {
|
||||||
if (Lbryio.authToken) {
|
if (Lbryio.authToken) {
|
||||||
resolve(Lbryio.authToken);
|
resolve(Lbryio.authToken);
|
||||||
} else if (Lbryio.overrides.getAuthToken) {
|
} else if (Lbryio.overrides.getAuthToken) {
|
||||||
Lbryio.overrides.getAuthToken().then(token => {
|
Lbryio.overrides.getAuthToken().then((token) => {
|
||||||
resolve(token);
|
resolve(token);
|
||||||
});
|
});
|
||||||
} else if (typeof window !== 'undefined') {
|
} else if (typeof window !== 'undefined') {
|
||||||
|
@ -122,7 +127,7 @@ Lbryio.authenticate = (domain, language) => {
|
||||||
language: language || 'en',
|
language: language || 'en',
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Promise(resolve => {
|
return new Promise((resolve) => {
|
||||||
resolve(params);
|
resolve(params);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -130,15 +135,15 @@ Lbryio.authenticate = (domain, language) => {
|
||||||
if (Lbryio.authenticationPromise === null) {
|
if (Lbryio.authenticationPromise === null) {
|
||||||
Lbryio.authenticationPromise = new Promise((resolve, reject) => {
|
Lbryio.authenticationPromise = new Promise((resolve, reject) => {
|
||||||
Lbryio.getAuthToken()
|
Lbryio.getAuthToken()
|
||||||
.then(token => {
|
.then((token) => {
|
||||||
if (!token || token.length > 60) {
|
if (!token || token.length > 60) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that token works
|
// check that token works
|
||||||
return Lbryio.getCurrentUser()
|
return Lbryio.getCurrentUser()
|
||||||
.then(user => user)
|
.then((user) => user)
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
if (error === INTERNAL_APIS_DOWN) {
|
if (error === INTERNAL_APIS_DOWN) {
|
||||||
throw new Error('Internal APIS down');
|
throw new Error('Internal APIS down');
|
||||||
}
|
}
|
||||||
|
@ -146,14 +151,14 @@ Lbryio.authenticate = (domain, language) => {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(user => {
|
.then((user) => {
|
||||||
if (user) {
|
if (user) {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Lbry.status()
|
return Lbry.status()
|
||||||
.then(
|
.then(
|
||||||
status =>
|
(status) =>
|
||||||
new Promise((res, rej) => {
|
new Promise((res, rej) => {
|
||||||
const appId =
|
const appId =
|
||||||
domain && domain !== 'lbry.tv'
|
domain && domain !== 'lbry.tv'
|
||||||
|
@ -169,7 +174,7 @@ Lbryio.authenticate = (domain, language) => {
|
||||||
},
|
},
|
||||||
'post'
|
'post'
|
||||||
)
|
)
|
||||||
.then(response => {
|
.then((response) => {
|
||||||
if (!response.auth_token) {
|
if (!response.auth_token) {
|
||||||
throw new Error('auth_token was not set in the response');
|
throw new Error('auth_token was not set in the response');
|
||||||
}
|
}
|
||||||
|
@ -188,10 +193,10 @@ Lbryio.authenticate = (domain, language) => {
|
||||||
Lbryio.authToken = response.auth_token;
|
Lbryio.authToken = response.auth_token;
|
||||||
return res(response);
|
return res(response);
|
||||||
})
|
})
|
||||||
.catch(error => rej(error));
|
.catch((error) => rej(error));
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.then(newUser => {
|
.then((newUser) => {
|
||||||
if (!newUser) {
|
if (!newUser) {
|
||||||
return Lbryio.getCurrentUser();
|
return Lbryio.getCurrentUser();
|
||||||
}
|
}
|
||||||
|
@ -211,10 +216,7 @@ Lbryio.getStripeToken = () =>
|
||||||
: 'pk_live_e8M4dRNnCCbmpZzduEUZBgJO';
|
: 'pk_live_e8M4dRNnCCbmpZzduEUZBgJO';
|
||||||
|
|
||||||
Lbryio.getExchangeRates = () => {
|
Lbryio.getExchangeRates = () => {
|
||||||
if (
|
if (!Lbryio.exchangeLastFetched || Date.now() - Lbryio.exchangeLastFetched > EXCHANGE_RATE_TIMEOUT) {
|
||||||
!Lbryio.exchangeLastFetched ||
|
|
||||||
Date.now() - Lbryio.exchangeLastFetched > EXCHANGE_RATE_TIMEOUT
|
|
||||||
) {
|
|
||||||
Lbryio.exchangePromise = new Promise((resolve, reject) => {
|
Lbryio.exchangePromise = new Promise((resolve, reject) => {
|
||||||
Lbryio.call('lbc', 'exchange_rate', {}, 'get', true)
|
Lbryio.call('lbc', 'exchange_rate', {}, 'get', true)
|
||||||
.then(({ lbc_usd: LBC_USD, lbc_btc: LBC_BTC, btc_usd: BTC_USD }) => {
|
.then(({ lbc_usd: LBC_USD, lbc_btc: LBC_BTC, btc_usd: BTC_USD }) => {
|
||||||
|
@ -235,4 +237,23 @@ Lbryio.setOverride = (methodName, newMethod) => {
|
||||||
Lbryio.overrides[methodName] = newMethod;
|
Lbryio.overrides[methodName] = newMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function sendCallAnalytics(resource, action, params) {
|
||||||
|
switch (resource) {
|
||||||
|
case 'customer':
|
||||||
|
if (action === 'tip') {
|
||||||
|
analytics.reportEvent('spend_virtual_currency', {
|
||||||
|
// https://developers.google.com/analytics/devguides/collection/ga4/reference/events#spend_virtual_currency
|
||||||
|
value: params.amount,
|
||||||
|
virtual_currency_name: params.currency.toLowerCase(),
|
||||||
|
item_name: 'tip',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Do nothing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default Lbryio;
|
export default Lbryio;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import { Lbryio } from 'lbryinc';
|
import { Lbryio } from 'lbryinc';
|
||||||
import { selectClaimForUri } from 'redux/selectors/claims';
|
import { selectClaimsByUri } from 'redux/selectors/claims';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export function doFetchCostInfoForUri(uri) {
|
export function doFetchCostInfoForUri(uri) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const claim = selectClaimForUri(state, uri);
|
const claim = selectClaimsByUri(state)[uri];
|
||||||
|
|
||||||
if (!claim) return;
|
if (!claim) return;
|
||||||
|
|
||||||
|
|
79
extras/lbryinc/redux/actions/homepage.js
Normal file
79
extras/lbryinc/redux/actions/homepage.js
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import { Lbryio } from 'lbryinc';
|
||||||
|
import { batchActions } from 'util/batch-actions';
|
||||||
|
import { doResolveUris } from 'util/lbryURI';
|
||||||
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
|
export function doFetchFeaturedUris(offloadResolve = false) {
|
||||||
|
return dispatch => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.FETCH_FEATURED_CONTENT_STARTED,
|
||||||
|
});
|
||||||
|
|
||||||
|
const success = ({ Uris }) => {
|
||||||
|
let urisToResolve = [];
|
||||||
|
Object.keys(Uris).forEach(category => {
|
||||||
|
urisToResolve = [...urisToResolve, ...Uris[category]];
|
||||||
|
});
|
||||||
|
|
||||||
|
const actions = [
|
||||||
|
{
|
||||||
|
type: ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED,
|
||||||
|
data: {
|
||||||
|
uris: Uris,
|
||||||
|
success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
if (urisToResolve.length && !offloadResolve) {
|
||||||
|
actions.push(doResolveUris(urisToResolve));
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(batchActions(...actions));
|
||||||
|
};
|
||||||
|
|
||||||
|
const failure = () => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED,
|
||||||
|
data: {
|
||||||
|
uris: {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Lbryio.call('file', 'list_homepage').then(success, failure);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doFetchTrendingUris() {
|
||||||
|
return dispatch => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.FETCH_TRENDING_CONTENT_STARTED,
|
||||||
|
});
|
||||||
|
|
||||||
|
const success = data => {
|
||||||
|
const urisToResolve = data.map(uri => uri.url);
|
||||||
|
const actions = [
|
||||||
|
doResolveUris(urisToResolve),
|
||||||
|
{
|
||||||
|
type: ACTIONS.FETCH_TRENDING_CONTENT_COMPLETED,
|
||||||
|
data: {
|
||||||
|
uris: data,
|
||||||
|
success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
dispatch(batchActions(...actions));
|
||||||
|
};
|
||||||
|
|
||||||
|
const failure = () => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.FETCH_TRENDING_CONTENT_COMPLETED,
|
||||||
|
data: {
|
||||||
|
uris: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Lbryio.call('file', 'list_trending').then(success, failure);
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,6 +2,9 @@
|
||||||
import { Lbryio } from 'lbryinc';
|
import { Lbryio } from 'lbryinc';
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
|
const FETCH_SUB_COUNT_MIN_INTERVAL_MS = 5 * 60 * 1000;
|
||||||
|
const FETCH_SUB_COUNT_IDLE_FIRE_MS = 100;
|
||||||
|
|
||||||
export const doFetchViewCount = (claimIdCsv: string) => (dispatch: Dispatch) => {
|
export const doFetchViewCount = (claimIdCsv: string) => (dispatch: Dispatch) => {
|
||||||
dispatch({ type: ACTIONS.FETCH_VIEW_COUNT_STARTED });
|
dispatch({ type: ACTIONS.FETCH_VIEW_COUNT_STARTED });
|
||||||
|
|
||||||
|
@ -10,23 +13,56 @@ export const doFetchViewCount = (claimIdCsv: string) => (dispatch: Dispatch) =>
|
||||||
const viewCounts = result;
|
const viewCounts = result;
|
||||||
dispatch({ type: ACTIONS.FETCH_VIEW_COUNT_COMPLETED, data: { claimIdCsv, viewCounts } });
|
dispatch({ type: ACTIONS.FETCH_VIEW_COUNT_COMPLETED, data: { claimIdCsv, viewCounts } });
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
dispatch({ type: ACTIONS.FETCH_VIEW_COUNT_FAILED, data: error });
|
dispatch({ type: ACTIONS.FETCH_VIEW_COUNT_FAILED, data: error });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const doFetchSubCount = (claimId: string) => (dispatch: Dispatch) => {
|
const executeFetchSubCount = (claimIdCsv: string) => (dispatch: Dispatch, getState: GetState) => {
|
||||||
|
const state = getState();
|
||||||
|
const subCountLastFetchedById = state.stats.subCountLastFetchedById;
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
const claimIds = claimIdCsv.split(',').filter((id) => {
|
||||||
|
const prev = subCountLastFetchedById[id];
|
||||||
|
return !prev || now - prev > FETCH_SUB_COUNT_MIN_INTERVAL_MS;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (claimIds.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dispatch({ type: ACTIONS.FETCH_SUB_COUNT_STARTED });
|
dispatch({ type: ACTIONS.FETCH_SUB_COUNT_STARTED });
|
||||||
|
|
||||||
return Lbryio.call('subscription', 'sub_count', { claim_id: claimId })
|
return Lbryio.call('subscription', 'sub_count', { claim_id: claimIds.join(',') })
|
||||||
.then((result: Array<number>) => {
|
.then((result: Array<number>) => {
|
||||||
const subCount = result[0];
|
const subCounts = result;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.FETCH_SUB_COUNT_COMPLETED,
|
type: ACTIONS.FETCH_SUB_COUNT_COMPLETED,
|
||||||
data: { claimId, subCount },
|
data: { claimIdCsv, subCounts, fetchDate: now },
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
dispatch({ type: ACTIONS.FETCH_SUB_COUNT_FAILED, data: error });
|
dispatch({ type: ACTIONS.FETCH_SUB_COUNT_FAILED, data: error });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let fetchSubCountTimer;
|
||||||
|
let fetchSubCountQueue = '';
|
||||||
|
|
||||||
|
export const doFetchSubCount = (claimIdCsv: string) => (dispatch: Dispatch) => {
|
||||||
|
if (fetchSubCountTimer) {
|
||||||
|
clearTimeout(fetchSubCountTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fetchSubCountQueue && !fetchSubCountQueue.endsWith(',')) {
|
||||||
|
fetchSubCountQueue += ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchSubCountQueue += claimIdCsv;
|
||||||
|
|
||||||
|
fetchSubCountTimer = setTimeout(() => {
|
||||||
|
dispatch(executeFetchSubCount(fetchSubCountQueue));
|
||||||
|
fetchSubCountQueue = '';
|
||||||
|
}, FETCH_SUB_COUNT_IDLE_FIRE_MS);
|
||||||
|
};
|
||||||
|
|
12
extras/lbryinc/redux/actions/web.js
Normal file
12
extras/lbryinc/redux/actions/web.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// @flow
|
||||||
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
|
export const doUpdateUploadProgress = (
|
||||||
|
progress: string,
|
||||||
|
params: { [key: string]: any },
|
||||||
|
xhr: any
|
||||||
|
) => (dispatch: Dispatch) =>
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.UPDATE_UPLOAD_PROGRESS,
|
||||||
|
data: { progress, params, xhr },
|
||||||
|
});
|
48
extras/lbryinc/redux/reducers/homepage.js
Normal file
48
extras/lbryinc/redux/reducers/homepage.js
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { handleActions } from 'util/redux-utils';
|
||||||
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
|
const defaultState = {
|
||||||
|
fetchingFeaturedContent: false,
|
||||||
|
fetchingFeaturedContentFailed: false,
|
||||||
|
featuredUris: undefined,
|
||||||
|
fetchingTrendingContent: false,
|
||||||
|
fetchingTrendingContentFailed: false,
|
||||||
|
trendingUris: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const homepageReducer = handleActions(
|
||||||
|
{
|
||||||
|
[ACTIONS.FETCH_FEATURED_CONTENT_STARTED]: state => ({
|
||||||
|
...state,
|
||||||
|
fetchingFeaturedContent: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
[ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED]: (state, action) => {
|
||||||
|
const { uris, success } = action.data;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
fetchingFeaturedContent: false,
|
||||||
|
fetchingFeaturedContentFailed: !success,
|
||||||
|
featuredUris: uris,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
[ACTIONS.FETCH_TRENDING_CONTENT_STARTED]: state => ({
|
||||||
|
...state,
|
||||||
|
fetchingTrendingContent: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
[ACTIONS.FETCH_TRENDING_CONTENT_COMPLETED]: (state, action) => {
|
||||||
|
const { uris, success } = action.data;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
fetchingTrendingContent: false,
|
||||||
|
fetchingTrendingContentFailed: !success,
|
||||||
|
trendingUris: uris,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultState
|
||||||
|
);
|
|
@ -8,15 +8,18 @@ const defaultState = {
|
||||||
fetchingSubCount: false,
|
fetchingSubCount: false,
|
||||||
subCountError: undefined,
|
subCountError: undefined,
|
||||||
subCountById: {},
|
subCountById: {},
|
||||||
|
subCountLastFetchedById: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const statsReducer = handleActions(
|
export const statsReducer = handleActions(
|
||||||
{
|
{
|
||||||
[ACTIONS.FETCH_VIEW_COUNT_STARTED]: state => ({ ...state, fetchingViewCount: true }),
|
[ACTIONS.FETCH_VIEW_COUNT_STARTED]: (state) => ({ ...state, fetchingViewCount: true }),
|
||||||
|
|
||||||
[ACTIONS.FETCH_VIEW_COUNT_FAILED]: (state, action) => ({
|
[ACTIONS.FETCH_VIEW_COUNT_FAILED]: (state, action) => ({
|
||||||
...state,
|
...state,
|
||||||
viewCountError: action.data,
|
viewCountError: action.data,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
[ACTIONS.FETCH_VIEW_COUNT_COMPLETED]: (state, action) => {
|
[ACTIONS.FETCH_VIEW_COUNT_COMPLETED]: (state, action) => {
|
||||||
const { claimIdCsv, viewCounts } = action.data;
|
const { claimIdCsv, viewCounts } = action.data;
|
||||||
|
|
||||||
|
@ -35,20 +38,43 @@ export const statsReducer = handleActions(
|
||||||
viewCountById,
|
viewCountById,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[ACTIONS.FETCH_SUB_COUNT_STARTED]: state => ({ ...state, fetchingSubCount: true }),
|
|
||||||
|
[ACTIONS.FETCH_SUB_COUNT_STARTED]: (state) => ({ ...state, fetchingSubCount: true }),
|
||||||
|
|
||||||
[ACTIONS.FETCH_SUB_COUNT_FAILED]: (state, action) => ({
|
[ACTIONS.FETCH_SUB_COUNT_FAILED]: (state, action) => ({
|
||||||
...state,
|
...state,
|
||||||
subCountError: action.data,
|
subCountError: action.data,
|
||||||
}),
|
}),
|
||||||
[ACTIONS.FETCH_SUB_COUNT_COMPLETED]: (state, action) => {
|
|
||||||
const { claimId, subCount } = action.data;
|
|
||||||
|
|
||||||
const subCountById = { ...state.subCountById, [claimId]: subCount };
|
[ACTIONS.FETCH_SUB_COUNT_COMPLETED]: (state, action) => {
|
||||||
return {
|
const { claimIdCsv, subCounts, fetchDate } = action.data;
|
||||||
|
|
||||||
|
const subCountById = Object.assign({}, state.subCountById);
|
||||||
|
const subCountLastFetchedById = Object.assign({}, state.subCountLastFetchedById);
|
||||||
|
const claimIds = claimIdCsv.split(',');
|
||||||
|
let dataChanged = false;
|
||||||
|
|
||||||
|
if (claimIds.length === subCounts.length) {
|
||||||
|
claimIds.forEach((claimId, index) => {
|
||||||
|
if (subCountById[claimId] !== subCounts[index]) {
|
||||||
|
subCountById[claimId] = subCounts[index];
|
||||||
|
dataChanged = true;
|
||||||
|
}
|
||||||
|
subCountLastFetchedById[claimId] = fetchDate;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const newState = {
|
||||||
...state,
|
...state,
|
||||||
fetchingSubCount: false,
|
fetchingSubCount: false,
|
||||||
subCountById,
|
subCountLastFetchedById,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (dataChanged) {
|
||||||
|
newState.subCountById = subCountById;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultState
|
defaultState
|
||||||
|
|
62
extras/lbryinc/redux/reducers/web.js
Normal file
62
extras/lbryinc/redux/reducers/web.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// @flow
|
||||||
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
|
/*
|
||||||
|
test mock:
|
||||||
|
currentUploads: {
|
||||||
|
'test#upload': {
|
||||||
|
progress: 50,
|
||||||
|
params: {
|
||||||
|
name: 'steve',
|
||||||
|
thumbnail_url: 'https://dev2.spee.ch/4/KMNtoSZ009fawGz59VG8PrID.jpeg',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type Params = {
|
||||||
|
channel?: string,
|
||||||
|
name: string,
|
||||||
|
thumbnail_url: ?string,
|
||||||
|
title: ?string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UploadItem = {
|
||||||
|
progess: string,
|
||||||
|
params: Params,
|
||||||
|
xhr?: any,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TvState = {
|
||||||
|
currentUploads: { [key: string]: UploadItem },
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducers = {};
|
||||||
|
|
||||||
|
const defaultState: TvState = {
|
||||||
|
currentUploads: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
reducers[ACTIONS.UPDATE_UPLOAD_PROGRESS] = (state: TvState, action) => {
|
||||||
|
const { progress, params, xhr } = action.data;
|
||||||
|
const key = params.channel ? `${params.name}#${params.channel}` : `${params.name}#anonymous`;
|
||||||
|
let currentUploads;
|
||||||
|
if (!progress) {
|
||||||
|
currentUploads = Object.assign({}, state.currentUploads);
|
||||||
|
Object.keys(currentUploads).forEach(k => {
|
||||||
|
if (k === key) {
|
||||||
|
delete currentUploads[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
currentUploads = Object.assign({}, state.currentUploads);
|
||||||
|
currentUploads[key] = { progress, params, xhr };
|
||||||
|
}
|
||||||
|
return { ...state, currentUploads };
|
||||||
|
};
|
||||||
|
|
||||||
|
export function webReducer(state: TvState = defaultState, action: any) {
|
||||||
|
const handler = reducers[action.type];
|
||||||
|
if (handler) return handler(state, action);
|
||||||
|
return state;
|
||||||
|
}
|
|
@ -1,7 +1,4 @@
|
||||||
import { createSelector } from 'reselect';
|
const selectState = (state) => state.auth || {};
|
||||||
|
|
||||||
const selectState = state => state.auth || {};
|
export const selectAuthToken = (state) => selectState(state).authToken;
|
||||||
|
export const selectIsAuthenticating = (state) => selectState(state).authenticating;
|
||||||
export const selectAuthToken = createSelector(selectState, state => state.authToken);
|
|
||||||
|
|
||||||
export const selectIsAuthenticating = createSelector(selectState, state => state.authenticating);
|
|
||||||
|
|
|
@ -5,65 +5,88 @@
|
||||||
// involve moving it from 'extras' to 'ui' (big change).
|
// involve moving it from 'extras' to 'ui' (big change).
|
||||||
|
|
||||||
import { createCachedSelector } from 're-reselect';
|
import { createCachedSelector } from 're-reselect';
|
||||||
import { selectClaimForUri, makeSelectIsBlacklisted } from 'redux/selectors/claims';
|
import { selectClaimForUri } from 'redux/selectors/claims';
|
||||||
import { selectMutedChannels } from 'redux/selectors/blocked';
|
import { selectMutedChannels } from 'redux/selectors/blocked';
|
||||||
import { selectModerationBlockList } from 'redux/selectors/comments';
|
import { selectModerationBlockList } from 'redux/selectors/comments';
|
||||||
import { selectBlacklistedOutpointMap, selectFilteredOutpointMap } from 'lbryinc';
|
import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
|
||||||
import { getChannelFromClaim } from 'util/claim';
|
|
||||||
import { isURIEqual } from 'util/lbryURI';
|
import { isURIEqual } from 'util/lbryURI';
|
||||||
|
|
||||||
|
const selectClaimExistsForUri = (state, uri) => {
|
||||||
|
return Boolean(selectClaimForUri(state, uri));
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectTxidForUri = (state, uri) => {
|
||||||
|
const claim = selectClaimForUri(state, uri);
|
||||||
|
const signingChannel = claim && claim.signing_channel;
|
||||||
|
return signingChannel ? signingChannel.txid : claim ? claim.txid : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectNoutForUri = (state, uri) => {
|
||||||
|
const claim = selectClaimForUri(state, uri);
|
||||||
|
const signingChannel = claim && claim.signing_channel;
|
||||||
|
return signingChannel ? signingChannel.nout : claim ? claim.nout : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectPermanentUrlForUri = (state, uri) => {
|
||||||
|
const claim = selectClaimForUri(state, uri);
|
||||||
|
const signingChannel = claim && claim.signing_channel;
|
||||||
|
return signingChannel ? signingChannel.permanent_url : claim ? claim.permanent_url : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
export const selectBanStateForUri = createCachedSelector(
|
export const selectBanStateForUri = createCachedSelector(
|
||||||
selectClaimForUri,
|
// Break apart 'selectClaimForUri' into 4 cheaper selectors that return
|
||||||
selectBlacklistedOutpointMap,
|
// primitives for values that we care about. The Claim object itself is easily
|
||||||
selectFilteredOutpointMap,
|
// invalidated due to constantly-changing fields like 'confirmation'.
|
||||||
|
selectClaimExistsForUri,
|
||||||
|
selectTxidForUri,
|
||||||
|
selectNoutForUri,
|
||||||
|
selectPermanentUrlForUri,
|
||||||
|
selectBlackListedOutpoints,
|
||||||
|
selectFilteredOutpoints,
|
||||||
selectMutedChannels,
|
selectMutedChannels,
|
||||||
selectModerationBlockList,
|
selectModerationBlockList,
|
||||||
(state, uri) => makeSelectIsBlacklisted(uri)(state),
|
(
|
||||||
(claim, blackListedOutpointMap, filteredOutpointMap, mutedChannelUris, personalBlocklist, isBlacklisted) => {
|
claimExists,
|
||||||
|
txid,
|
||||||
|
nout,
|
||||||
|
permanentUrl,
|
||||||
|
blackListedOutpoints,
|
||||||
|
filteredOutpoints,
|
||||||
|
mutedChannelUris,
|
||||||
|
personalBlocklist
|
||||||
|
) => {
|
||||||
const banState = {};
|
const banState = {};
|
||||||
|
|
||||||
if (!claim) {
|
if (!claimExists) {
|
||||||
return banState;
|
return banState;
|
||||||
}
|
}
|
||||||
|
|
||||||
const channelClaim = getChannelFromClaim(claim);
|
|
||||||
|
|
||||||
if (isBlacklisted) {
|
|
||||||
banState['blacklisted'] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will be replaced once blocking is done at the wallet server level.
|
// This will be replaced once blocking is done at the wallet server level.
|
||||||
if (blackListedOutpointMap) {
|
if (blackListedOutpoints) {
|
||||||
if (
|
if (blackListedOutpoints.some((outpoint) => outpoint.txid === txid && outpoint.nout === nout)) {
|
||||||
(channelClaim && blackListedOutpointMap[`${channelClaim.txid}:${channelClaim.nout}`]) ||
|
|
||||||
blackListedOutpointMap[`${claim.txid}:${claim.nout}`]
|
|
||||||
) {
|
|
||||||
banState['blacklisted'] = true;
|
banState['blacklisted'] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're checking to see if the stream outpoint or signing channel outpoint
|
// We're checking to see if the stream outpoint or signing channel outpoint
|
||||||
// is in the filter list.
|
// is in the filter list.
|
||||||
if (filteredOutpointMap) {
|
if (filteredOutpoints) {
|
||||||
if (
|
if (filteredOutpoints.some((outpoint) => outpoint.txid === txid && outpoint.nout === nout)) {
|
||||||
(channelClaim && filteredOutpointMap[`${channelClaim.txid}:${channelClaim.nout}`]) ||
|
|
||||||
filteredOutpointMap[`${claim.txid}:${claim.nout}`]
|
|
||||||
) {
|
|
||||||
banState['filtered'] = true;
|
banState['filtered'] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// block stream claims
|
// block stream claims
|
||||||
// block channel claims if we can't control for them in claim search
|
// block channel claims if we can't control for them in claim search
|
||||||
if (mutedChannelUris.length && channelClaim) {
|
if (mutedChannelUris.length) {
|
||||||
if (mutedChannelUris.some((blockedUri) => isURIEqual(blockedUri, channelClaim.permanent_url))) {
|
if (mutedChannelUris.some((blockedUri) => isURIEqual(blockedUri, permanentUrl))) {
|
||||||
banState['muted'] = true;
|
banState['muted'] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commentron blocklist
|
// Commentron blocklist
|
||||||
if (personalBlocklist.length && channelClaim) {
|
if (personalBlocklist.length) {
|
||||||
if (personalBlocklist.some((blockedUri) => isURIEqual(blockedUri, channelClaim.permanent_url))) {
|
if (personalBlocklist.some((blockedUri) => isURIEqual(blockedUri, permanentUrl))) {
|
||||||
banState['blocked'] = true;
|
banState['blocked'] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
export const selectState = state => state.blacklist || {};
|
export const selectState = (state) => state.blacklist || {};
|
||||||
|
|
||||||
export const selectBlackListedOutpoints = createSelector(
|
export const selectBlackListedOutpoints = (state) => selectState(state).blackListedOutpoints;
|
||||||
selectState,
|
|
||||||
state => state.blackListedOutpoints
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectBlacklistedOutpointMap = createSelector(
|
export const selectBlacklistedOutpointMap = createSelector(selectBlackListedOutpoints, (outpoints) =>
|
||||||
selectBlackListedOutpoints,
|
|
||||||
outpoints =>
|
|
||||||
outpoints
|
outpoints
|
||||||
? outpoints.reduce((acc, val) => {
|
? outpoints.reduce((acc, val) => {
|
||||||
const outpoint = `${val.txid}:${val.nout}`;
|
const outpoint = `${val.txid}:${val.nout}`;
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
// @flow
|
import { createSelector } from 'reselect';
|
||||||
type State = { costInfo: any };
|
|
||||||
|
|
||||||
export const selectState = (state: State) => state.costInfo || {};
|
export const selectState = state => state.costInfo || {};
|
||||||
export const selectAllCostInfoByUri = (state: State) => selectState(state).byUri;
|
|
||||||
export const selectFetchingCostInfo = (state: State) => selectState(state).fetching;
|
|
||||||
|
|
||||||
export const selectCostInfoForUri = (state: State, uri: string) => {
|
export const selectAllCostInfoByUri = createSelector(selectState, state => state.byUri || {});
|
||||||
const costInfos = selectAllCostInfoByUri(state);
|
|
||||||
return costInfos && costInfos[uri];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const selectFetchingCostInfoForUri = (state: State, uri: string) => {
|
export const makeSelectCostInfoForUri = uri =>
|
||||||
const fetchingByUri = selectFetchingCostInfo(state);
|
createSelector(selectAllCostInfoByUri, costInfos => costInfos && costInfos[uri]);
|
||||||
return fetchingByUri && fetchingByUri[uri];
|
|
||||||
};
|
export const selectFetchingCostInfo = createSelector(selectState, state => state.fetching || {});
|
||||||
|
|
||||||
|
export const makeSelectFetchingCostInfoForUri = uri =>
|
||||||
|
createSelector(selectFetchingCostInfo, fetchingByUri => fetchingByUri && fetchingByUri[uri]);
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
export const selectState = state => state.filtered || {};
|
export const selectState = (state) => state.filtered || {};
|
||||||
|
|
||||||
export const selectFilteredOutpoints = createSelector(
|
export const selectFilteredOutpoints = (state) => selectState(state).filteredOutpoints;
|
||||||
selectState,
|
|
||||||
state => state.filteredOutpoints
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectFilteredOutpointMap = createSelector(
|
export const selectFilteredOutpointMap = createSelector(selectFilteredOutpoints, (outpoints) =>
|
||||||
selectFilteredOutpoints,
|
|
||||||
outpoints =>
|
|
||||||
outpoints
|
outpoints
|
||||||
? outpoints.reduce((acc, val) => {
|
? outpoints.reduce((acc, val) => {
|
||||||
const outpoint = `${val.txid}:${val.nout}`;
|
const outpoint = `${val.txid}:${val.nout}`;
|
||||||
|
|
6
extras/lbryinc/redux/selectors/homepage.js
Normal file
6
extras/lbryinc/redux/selectors/homepage.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
const selectState = (state) => state.homepage || {};
|
||||||
|
|
||||||
|
export const selectFeaturedUris = (state) => selectState(state).featuredUris;
|
||||||
|
export const selectFetchingFeaturedUris = (state) => selectState(state).fetchingFeaturedContent;
|
||||||
|
export const selectTrendingUris = (state) => selectState(state).trendingUris;
|
||||||
|
export const selectFetchingTrendingUris = (state) => selectState(state).fetchingTrendingContent;
|
|
@ -1,20 +1,20 @@
|
||||||
// @flow
|
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { selectClaimIdForUri } from 'redux/selectors/claims';
|
import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
||||||
|
|
||||||
type State = { claims: any };
|
|
||||||
const selectState = state => state.stats || {};
|
const selectState = state => state.stats || {};
|
||||||
export const selectViewCount = createSelector(selectState, state => state.viewCountById);
|
export const selectViewCount = createSelector(selectState, state => state.viewCountById);
|
||||||
export const selectSubCount = createSelector(selectState, state => state.subCountById);
|
export const selectSubCount = createSelector(selectState, state => state.subCountById);
|
||||||
|
|
||||||
export const selectViewCountForUri = (state: State, uri: string) => {
|
export const makeSelectViewCountForUri = uri =>
|
||||||
const claimId = selectClaimIdForUri(state, uri);
|
createSelector(
|
||||||
const viewCountById = selectViewCount(state);
|
makeSelectClaimForUri(uri),
|
||||||
return claimId ? viewCountById[claimId] || 0 : 0;
|
selectViewCount,
|
||||||
};
|
(claim, viewCountById) => (claim ? viewCountById[claim.claim_id] || 0 : 0)
|
||||||
|
);
|
||||||
|
|
||||||
export const selectSubCountForUri = (state: State, uri: string) => {
|
export const makeSelectSubCountForUri = uri =>
|
||||||
const claimId = selectClaimIdForUri(state, uri);
|
createSelector(
|
||||||
const subCountById = selectSubCount(state);
|
makeSelectClaimForUri(uri),
|
||||||
return claimId ? subCountById[claimId] || 0 : 0;
|
selectSubCount,
|
||||||
};
|
(claim, subCountById) => (claim ? subCountById[claim.claim_id] || 0 : 0)
|
||||||
|
);
|
||||||
|
|
|
@ -1,40 +1,13 @@
|
||||||
import { createSelector } from 'reselect';
|
const selectState = (state) => state.sync || {};
|
||||||
|
|
||||||
const selectState = state => state.sync || {};
|
export const selectHasSyncedWallet = (state) => selectState(state).hasSyncedWallet;
|
||||||
|
export const selectSyncHash = (state) => selectState(state).syncHash;
|
||||||
export const selectHasSyncedWallet = createSelector(selectState, state => state.hasSyncedWallet);
|
export const selectSyncData = (state) => selectState(state).syncData;
|
||||||
|
export const selectSetSyncErrorMessage = (state) => selectState(state).setSyncErrorMessage;
|
||||||
export const selectSyncHash = createSelector(selectState, state => state.syncHash);
|
export const selectGetSyncErrorMessage = (state) => selectState(state).getSyncErrorMessage;
|
||||||
|
export const selectGetSyncIsPending = (state) => selectState(state).getSyncIsPending;
|
||||||
export const selectSyncData = createSelector(selectState, state => state.syncData);
|
export const selectSetSyncIsPending = (state) => selectState(state).setSyncIsPending;
|
||||||
|
export const selectHashChanged = (state) => selectState(state).hashChanged;
|
||||||
export const selectSetSyncErrorMessage = createSelector(
|
export const selectSyncApplyIsPending = (state) => selectState(state).syncApplyIsPending;
|
||||||
selectState,
|
export const selectSyncApplyErrorMessage = (state) => selectState(state).syncApplyErrorMessage;
|
||||||
state => state.setSyncErrorMessage
|
export const selectSyncApplyPasswordError = (state) => selectState(state).syncApplyPasswordError;
|
||||||
);
|
|
||||||
|
|
||||||
export const selectGetSyncErrorMessage = createSelector(
|
|
||||||
selectState,
|
|
||||||
state => state.getSyncErrorMessage
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectGetSyncIsPending = createSelector(selectState, state => state.getSyncIsPending);
|
|
||||||
|
|
||||||
export const selectSetSyncIsPending = createSelector(selectState, state => state.setSyncIsPending);
|
|
||||||
|
|
||||||
export const selectHashChanged = createSelector(selectState, state => state.hashChanged);
|
|
||||||
|
|
||||||
export const selectSyncApplyIsPending = createSelector(
|
|
||||||
selectState,
|
|
||||||
state => state.syncApplyIsPending
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectSyncApplyErrorMessage = createSelector(
|
|
||||||
selectState,
|
|
||||||
state => state.syncApplyErrorMessage
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectSyncApplyPasswordError = createSelector(
|
|
||||||
selectState,
|
|
||||||
state => state.syncApplyPasswordError
|
|
||||||
);
|
|
||||||
|
|
10
extras/lbryinc/redux/selectors/web.js
Normal file
10
extras/lbryinc/redux/selectors/web.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
|
const selectState = (state) => state.web || {};
|
||||||
|
|
||||||
|
export const selectCurrentUploads = (state) => selectState(state).currentUploads;
|
||||||
|
|
||||||
|
export const selectUploadCount = createSelector(
|
||||||
|
selectCurrentUploads,
|
||||||
|
(currentUploads) => currentUploads && Object.keys(currentUploads).length
|
||||||
|
);
|
|
@ -73,7 +73,7 @@ const recsys = {
|
||||||
* Called from recommendedContent component
|
* Called from recommendedContent component
|
||||||
*/
|
*/
|
||||||
onRecsLoaded: function (claimId, uris) {
|
onRecsLoaded: function (claimId, uris) {
|
||||||
if (window.store) {
|
if (window && window.store) {
|
||||||
const state = window.store.getState();
|
const state = window.store.getState();
|
||||||
if (!recsys.entries[claimId]) {
|
if (!recsys.entries[claimId]) {
|
||||||
recsys.createRecsysEntry(claimId);
|
recsys.createRecsysEntry(claimId);
|
||||||
|
@ -92,7 +92,7 @@ const recsys = {
|
||||||
* @param: parentUuid: string (optional)
|
* @param: parentUuid: string (optional)
|
||||||
*/
|
*/
|
||||||
createRecsysEntry: function (claimId, parentUuid) {
|
createRecsysEntry: function (claimId, parentUuid) {
|
||||||
if (window.store && claimId) {
|
if (window && window.store && claimId) {
|
||||||
const state = window.store.getState();
|
const state = window.store.getState();
|
||||||
const user = selectUser(state);
|
const user = selectUser(state);
|
||||||
const userId = user ? user.id : null;
|
const userId = user ? user.id : null;
|
||||||
|
@ -173,7 +173,7 @@ const recsys = {
|
||||||
* if so, send the Entry.
|
* if so, send the Entry.
|
||||||
*/
|
*/
|
||||||
onPlayerDispose: function (claimId, isEmbedded) {
|
onPlayerDispose: function (claimId, isEmbedded) {
|
||||||
if (window.store) {
|
if (window && window.store) {
|
||||||
const state = window.store.getState();
|
const state = window.store.getState();
|
||||||
const playingUri = selectPlayingUri(state);
|
const playingUri = selectPlayingUri(state);
|
||||||
const primaryUri = selectPrimaryUri(state);
|
const primaryUri = selectPrimaryUri(state);
|
||||||
|
@ -196,7 +196,7 @@ const recsys = {
|
||||||
// * more events until player is disposed. Don't send unless floatingPlayer playingUri
|
// * more events until player is disposed. Don't send unless floatingPlayer playingUri
|
||||||
// */
|
// */
|
||||||
// onLeaveFilePage: function (primaryUri) {
|
// onLeaveFilePage: function (primaryUri) {
|
||||||
// if (window.store) {
|
// if (window && window.store) {
|
||||||
// const state = window.store.getState();
|
// const state = window.store.getState();
|
||||||
// const claim = makeSelectClaimForUri(primaryUri)(state);
|
// const claim = makeSelectClaimForUri(primaryUri)(state);
|
||||||
// const claimId = claim ? claim.claim_id : null;
|
// const claimId = claim ? claim.claim_id : null;
|
||||||
|
@ -222,7 +222,7 @@ const recsys = {
|
||||||
* Send all claimIds that aren't currently playing.
|
* Send all claimIds that aren't currently playing.
|
||||||
*/
|
*/
|
||||||
onNavigate: function () {
|
onNavigate: function () {
|
||||||
if (window.store) {
|
if (window && window.store) {
|
||||||
const state = window.store.getState();
|
const state = window.store.getState();
|
||||||
const playingUri = selectPlayingUri(state);
|
const playingUri = selectPlayingUri(state);
|
||||||
const actualPlayingUri = playingUri && playingUri.uri;
|
const actualPlayingUri = playingUri && playingUri.uri;
|
||||||
|
|
37
flow-typed/Claim.js
vendored
37
flow-typed/Claim.js
vendored
|
@ -145,49 +145,12 @@ declare type PurchaseReceipt = {
|
||||||
type: 'purchase',
|
type: 'purchase',
|
||||||
};
|
};
|
||||||
|
|
||||||
declare type ClaimErrorCensor = {
|
|
||||||
address: string,
|
|
||||||
amount: string,
|
|
||||||
canonical_url: string,
|
|
||||||
claim_id: string,
|
|
||||||
claim_op: string,
|
|
||||||
confirmations: number,
|
|
||||||
has_signing_key: boolean,
|
|
||||||
height: number,
|
|
||||||
meta: {
|
|
||||||
activation_height: number,
|
|
||||||
claims_in_channel: number,
|
|
||||||
creation_height: number,
|
|
||||||
creation_timestamp: number,
|
|
||||||
effective_amount: string,
|
|
||||||
expiration_height: number,
|
|
||||||
is_controlling: boolean,
|
|
||||||
reposted: number,
|
|
||||||
support_amount: string,
|
|
||||||
take_over_height: number,
|
|
||||||
},
|
|
||||||
name: string,
|
|
||||||
normalized_name: string,
|
|
||||||
nout: number,
|
|
||||||
permanent_url: string,
|
|
||||||
short_url: string,
|
|
||||||
timestamp: number,
|
|
||||||
txid: string,
|
|
||||||
type: string,
|
|
||||||
value: {
|
|
||||||
public_key: string,
|
|
||||||
public_key_id: string,
|
|
||||||
},
|
|
||||||
value_type: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
declare type ClaimActionResolveInfo = {
|
declare type ClaimActionResolveInfo = {
|
||||||
[string]: {
|
[string]: {
|
||||||
stream: ?StreamClaim,
|
stream: ?StreamClaim,
|
||||||
channel: ?ChannelClaim,
|
channel: ?ChannelClaim,
|
||||||
claimsInChannel: ?number,
|
claimsInChannel: ?number,
|
||||||
collection: ?CollectionClaim,
|
collection: ?CollectionClaim,
|
||||||
errorCensor: ?ClaimErrorCensor,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
flow-typed/Collections.js
vendored
3
flow-typed/Collections.js
vendored
|
@ -24,8 +24,9 @@ declare type CollectionGroup = {
|
||||||
}
|
}
|
||||||
|
|
||||||
declare type CollectionEditParams = {
|
declare type CollectionEditParams = {
|
||||||
uris?: Array<string>,
|
claims?: Array<Claim>,
|
||||||
remove?: boolean,
|
remove?: boolean,
|
||||||
|
claimIds?: Array<string>,
|
||||||
replace?: boolean,
|
replace?: boolean,
|
||||||
order?: { from: number, to: number },
|
order?: { from: number, to: number },
|
||||||
type?: string,
|
type?: string,
|
||||||
|
|
6
flow-typed/Redux.js
vendored
6
flow-typed/Redux.js
vendored
|
@ -1,6 +0,0 @@
|
||||||
// @flow
|
|
||||||
/* eslint-disable no-use-before-define */
|
|
||||||
declare type GetState = () => any;
|
|
||||||
declare type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
|
|
||||||
declare type Dispatch = (action: {} | Promise<*> | Array<{}> | ThunkAction) => any; // Need to refer to ThunkAction
|
|
||||||
/* eslint-enable */
|
|
13
flow-typed/Settings.js
vendored
13
flow-typed/Settings.js
vendored
|
@ -1,13 +0,0 @@
|
||||||
declare type CommentServerDetails = {
|
|
||||||
name: string,
|
|
||||||
url: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
declare type WalletServerDetails = {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
declare type DiskSpace = {
|
|
||||||
total: number,
|
|
||||||
free: number,
|
|
||||||
};
|
|
10
flow-typed/file-data.js
vendored
10
flow-typed/file-data.js
vendored
|
@ -1,10 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
declare type FileData = {
|
|
||||||
file?: Blob,
|
|
||||||
path: string,
|
|
||||||
duration?: number,
|
|
||||||
size?: number,
|
|
||||||
mimeType: string,
|
|
||||||
error?: string,
|
|
||||||
}
|
|
9
flow-typed/file-with-path.js
vendored
9
flow-typed/file-with-path.js
vendored
|
@ -1,9 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
declare type FileWithPath = {
|
|
||||||
file: File,
|
|
||||||
// The full path will only be available in
|
|
||||||
// the application. For browser, the name
|
|
||||||
// of the file will be used.
|
|
||||||
path: string,
|
|
||||||
}
|
|
1
flow-typed/homepage.js
vendored
1
flow-typed/homepage.js
vendored
|
@ -22,7 +22,6 @@ declare type RowDataItem = {
|
||||||
channelIds?: Array<string>,
|
channelIds?: Array<string>,
|
||||||
limitClaimsPerChannel?: number,
|
limitClaimsPerChannel?: number,
|
||||||
pageSize?: number,
|
pageSize?: number,
|
||||||
languages?: Array<string>,
|
|
||||||
},
|
},
|
||||||
route?: string,
|
route?: string,
|
||||||
hideForUnauth?: boolean,
|
hideForUnauth?: boolean,
|
||||||
|
|
6
flow-typed/redux.js
vendored
Normal file
6
flow-typed/redux.js
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
/* eslint-disable no-use-before-define */
|
||||||
|
declare type GetState = () => any;
|
||||||
|
declare type Dispatch = any;
|
||||||
|
/* eslint-enable */
|
3
flow-typed/search.js
vendored
3
flow-typed/search.js
vendored
|
@ -29,10 +29,8 @@ declare type SearchOptions = {
|
||||||
declare type SearchState = {
|
declare type SearchState = {
|
||||||
options: SearchOptions,
|
options: SearchOptions,
|
||||||
resultsByQuery: {},
|
resultsByQuery: {},
|
||||||
results: Array<string>,
|
|
||||||
hasReachedMaxResultsLength: {},
|
hasReachedMaxResultsLength: {},
|
||||||
searching: boolean,
|
searching: boolean,
|
||||||
mentionQuery: string,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
declare type SearchSuccess = {
|
declare type SearchSuccess = {
|
||||||
|
@ -43,7 +41,6 @@ declare type SearchSuccess = {
|
||||||
size: number,
|
size: number,
|
||||||
uris: Array<string>,
|
uris: Array<string>,
|
||||||
recsys: string,
|
recsys: string,
|
||||||
query: string,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
6
flow-typed/web-file.js
vendored
Normal file
6
flow-typed/web-file.js
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
declare type WebFile = File & {
|
||||||
|
path?: string,
|
||||||
|
title?: string,
|
||||||
|
}
|
111
package.json
111
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "lbry",
|
"name": "lbry",
|
||||||
"version": "0.53.9",
|
"version": "0.51.2",
|
||||||
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
|
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"lbry"
|
"lbry"
|
||||||
|
@ -20,50 +20,59 @@
|
||||||
},
|
},
|
||||||
"main": "./dist/electron/main.js",
|
"main": "./dist/electron/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"analyze": "source-map-explorer --only-mapped dist/electron/webpack/ui*.js --html dist/sourceMap.html",
|
"analyze": "yarn compile && source-map-explorer --no-border-checks web/dist/public/*.js --html analyzeResults.html",
|
||||||
"compile:electron": "node --max_old_space_size=4096 ./node_modules/webpack/bin/webpack.js --config webpack.electron.config.js",
|
"compile:electron": "node --max_old_space_size=4096 ./node_modules/webpack/bin/webpack.js --config webpack.electron.config.js",
|
||||||
"compile": "cross-env NODE_ENV=production yarn compile:electron",
|
"compile:web": "yarn copyenv && cd web && node --max_old_space_size=4096 ./node_modules/webpack/bin/webpack.js --config webpack.config.js",
|
||||||
|
"compile": "cross-env NODE_ENV=production yarn compile:electron && cross-env NODE_ENV=production yarn compile:web",
|
||||||
|
"copyenv": "copyfiles ./.env* web/",
|
||||||
"dev": "yarn dev:electron",
|
"dev": "yarn dev:electron",
|
||||||
"dev:electron": "cross-env NODE_ENV=development node ./electron/devServer.js",
|
"dev:electron": "cross-env NODE_ENV=development node ./electron/devServer.js",
|
||||||
|
"dev:web": "yarn copyenv && cd web && yarn dev",
|
||||||
|
"dev:web-server": "cross-env NODE_ENV=development yarn compile:web && concurrently \"cross-env NODE_ENV=development yarn compile:web --watch\" \"cd web && yarn dev:server\"",
|
||||||
|
"dev:internal-apis": "LBRY_API_URL='http://localhost:8080' yarn dev:electron",
|
||||||
|
"dev:iatv": "LBRY_API_URL='http://localhost:15400' SDK_API_URL='http://localhost:15100' yarn dev:web",
|
||||||
|
"run:web-server": "cross-env NODE_ENV=production yarn compile:web && cd web && yarn dev:server",
|
||||||
"pack": "electron-builder --dir",
|
"pack": "electron-builder --dir",
|
||||||
"dist": "electron-builder",
|
"dist": "electron-builder",
|
||||||
"build": "cross-env NODE_ENV=production yarn compile:electron && electron-builder build",
|
"build": "cross-env NODE_ENV=production yarn compile:electron && electron-builder build",
|
||||||
"build:dir": "yarn build -- --dir -c.compression=store -c.mac.identity=null",
|
"build:dir": "yarn build -- --dir -c.compression=store -c.mac.identity=null",
|
||||||
"crossenv": "cross-env",
|
"crossenv": "./node_modules/cross-env/dist/bin/cross-env",
|
||||||
"flow": "flow",
|
"flow": "flow",
|
||||||
"lint": "eslint 'ui/**/*.{js,jsx}' && eslint 'electron/**/*.js' && flow",
|
"lint": "eslint 'ui/**/*.{js,jsx}' && eslint 'extras/**/*.{js,jsx}' && eslint 'web/**/*.{js,jsx}' && eslint 'electron/**/*.js' && flow",
|
||||||
"lint-fix": "eslint --fix --quiet 'ui/**/*.{js,jsx}' && eslint --fix --quiet 'electron/**/*.js'",
|
"lint-fix": "eslint --fix --quiet 'ui/**/*.{js,jsx}' && eslint --fix --quiet 'extras/**/*.{js,jsx}' && eslint --fix --quiet 'web/**/*.{js,jsx}' && eslint --fix --quiet 'electron/**/*.js'",
|
||||||
"format": "prettier 'src/**/*.{js,jsx,scss,json}' --write",
|
"format": "prettier 'src/**/*.{js,jsx,scss,json}' --write",
|
||||||
"flow-defs": "flow-typed install",
|
"flow-defs": "flow-typed install",
|
||||||
"precommit": "lint-staged",
|
"precommit": "lint-staged",
|
||||||
"postinstall": "electron-builder install-app-deps && node ./build/downloadDaemon.js",
|
"preinstall": "",
|
||||||
|
"postinstall": "cd web && yarn && cd .. && if-env NODE_ENV=production && yarn postinstall:warning || if-env APP_ENV=web && echo 'Done installing deps' || yarn postinstall:electron",
|
||||||
|
"postinstall:electron": "electron-builder install-app-deps && node ./build/downloadDaemon.js && node ./build/downloadLBRYFirst.js",
|
||||||
"postinstall:warning": "echo '\n\nWARNING\n\nNot all node modules were installed because NODE_ENV is set to \"production\".\nThis should only be set after installing dependencies with \"yarn\". The app will not work.\n\n'"
|
"postinstall:warning": "echo '\n\nWARNING\n\nNot all node modules were installed because NODE_ENV is set to \"production\".\nThis should only be set after installing dependencies with \"yarn\". The app will not work.\n\n'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/remote": "^2.0.1",
|
|
||||||
"@emotion/react": "^11.10.4",
|
|
||||||
"@emotion/styled": "^11.10.4",
|
|
||||||
"@mui/material": "^5.2.1",
|
|
||||||
"@ungap/from-entries": "^0.2.1",
|
"@ungap/from-entries": "^0.2.1",
|
||||||
"auto-launch": "^5.0.5",
|
"auto-launch": "^5.0.5",
|
||||||
"electron-dl": "^3.2.0",
|
"electron-dl": "^1.11.0",
|
||||||
"electron-log": "^4.4.8",
|
"electron-log": "^2.2.12",
|
||||||
"electron-notarize": "^1.0.0",
|
"electron-notarize": "^1.0.0",
|
||||||
"electron-updater": "^4.2.4",
|
"electron-updater": "^4.2.4",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"ffmpeg-probe": "^1.0.6",
|
|
||||||
"humanize-duration": "^3.27.0",
|
"humanize-duration": "^3.27.0",
|
||||||
|
"if-env": "^1.0.4",
|
||||||
"match-sorter": "^6.3.0",
|
"match-sorter": "^6.3.0",
|
||||||
"mime": "^3.0.0",
|
|
||||||
"node-html-parser": "^5.1.0",
|
|
||||||
"parse-duration": "^1.0.0",
|
"parse-duration": "^1.0.0",
|
||||||
"proxy-polyfill": "0.1.6",
|
"proxy-polyfill": "0.1.6",
|
||||||
"re-reselect": "^4.0.0",
|
"re-reselect": "^4.0.0",
|
||||||
"react-beautiful-dnd": "^13.1.0",
|
"react-datetime-picker": "^3.2.1",
|
||||||
"react-datetime-picker": "^3.4.3",
|
"react-plastic": "^1.1.1",
|
||||||
|
"react-top-loading-bar": "^2.0.1",
|
||||||
|
"remove-markdown": "^0.3.0",
|
||||||
|
"rss": "^1.2.2",
|
||||||
"source-map-explorer": "^2.5.2",
|
"source-map-explorer": "^2.5.2",
|
||||||
"sudo-prompt": "^9.2.1",
|
"tempy": "^0.6.0",
|
||||||
"tempy": "^0.6.0"
|
"videojs-contrib-ads": "^6.9.0",
|
||||||
|
"videojs-ima": "^1.11.0",
|
||||||
|
"videojs-ima-player": "^0.5.6",
|
||||||
|
"videojs-logo": "^2.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.0.0",
|
"@babel/core": "^7.0.0",
|
||||||
|
@ -74,17 +83,17 @@
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||||
"@babel/plugin-transform-flow-strip-types": "^7.2.3",
|
"@babel/plugin-transform-flow-strip-types": "^7.2.3",
|
||||||
"@babel/plugin-transform-runtime": "^7.4.3",
|
"@babel/plugin-transform-runtime": "^7.4.3",
|
||||||
"@babel/polyfill": "^7.12.1",
|
"@babel/polyfill": "^7.2.5",
|
||||||
"@babel/preset-env": "^7.12.11",
|
"@babel/preset-env": "^7.12.11",
|
||||||
"@babel/preset-flow": "^7.12.1",
|
"@babel/preset-flow": "^7.12.1",
|
||||||
"@babel/preset-react": "^7.0.0",
|
"@babel/preset-react": "^7.0.0",
|
||||||
"@babel/register": "^7.0.0",
|
"@babel/register": "^7.0.0",
|
||||||
"@datapunt/matomo-tracker-js": "^0.1.4",
|
"@exponent/electron-cookies": "^2.0.0",
|
||||||
"@hot-loader/react-dom": "^16.13",
|
"@hot-loader/react-dom": "^16.13",
|
||||||
"@meetfranz/electron-cookies": "^3.0.2",
|
"@reach/auto-id": "^0.13.0",
|
||||||
"@reach/combobox": "^0.12.1",
|
"@reach/combobox": "^0.12.1",
|
||||||
"@reach/menu-button": "0.8.6",
|
"@reach/menu-button": "0.7.4",
|
||||||
"@reach/rect": "^0.16.0",
|
"@reach/rect": "^0.13.0",
|
||||||
"@reach/tabs": "^0.1.5",
|
"@reach/tabs": "^0.1.5",
|
||||||
"@reach/tooltip": "^0.12.1",
|
"@reach/tooltip": "^0.12.1",
|
||||||
"@reach/utils": "^0.12.1",
|
"@reach/utils": "^0.12.1",
|
||||||
|
@ -92,17 +101,21 @@
|
||||||
"@sentry/webpack-plugin": "^1.10.0",
|
"@sentry/webpack-plugin": "^1.10.0",
|
||||||
"@types/three": "^0.103.2",
|
"@types/three": "^0.103.2",
|
||||||
"adm-zip": "^0.4.13",
|
"adm-zip": "^0.4.13",
|
||||||
|
"async-exit-hook": "^2.0.1",
|
||||||
"babel-eslint": "^10.0.1",
|
"babel-eslint": "^10.0.1",
|
||||||
"babel-loader": "^8.0.5",
|
"babel-loader": "^8.0.5",
|
||||||
"babel-plugin-add-module-exports": "^1.0.4",
|
"babel-plugin-add-module-exports": "^1.0.4",
|
||||||
"babel-plugin-import-glob": "^2.0.0",
|
"babel-plugin-import-glob": "^2.0.0",
|
||||||
"babel-plugin-transform-imports": "^1.5.1",
|
"babel-plugin-transform-imports": "^1.5.1",
|
||||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||||
|
"bluebird": "^3.5.1",
|
||||||
"chalk": "^4.1.0",
|
"chalk": "^4.1.0",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"codemirror": "^5.39.2",
|
"codemirror": "^5.39.2",
|
||||||
|
"concurrently": "^4.1.2",
|
||||||
"connected-react-router": "^6.8.0",
|
"connected-react-router": "^6.8.0",
|
||||||
"copy-webpack-plugin": "^6.4.1",
|
"copy-webpack-plugin": "^5.1.2",
|
||||||
|
"copyfiles": "^2.4.1",
|
||||||
"country-data": "^0.0.31",
|
"country-data": "^0.0.31",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"crypto-js": "^4.0.0",
|
"crypto-js": "^4.0.0",
|
||||||
|
@ -113,10 +126,11 @@
|
||||||
"decompress": "^4.2.1",
|
"decompress": "^4.2.1",
|
||||||
"del": "^3.0.0",
|
"del": "^3.0.0",
|
||||||
"devtron": "^1.4.0",
|
"devtron": "^1.4.0",
|
||||||
|
"dom-scroll-into-view": "^1.2.1",
|
||||||
"dotenv-defaults": "^2.0.1",
|
"dotenv-defaults": "^2.0.1",
|
||||||
"dotenv-webpack": "^1.8.0",
|
"dotenv-webpack": "^1.8.0",
|
||||||
"electron": "17.2.0",
|
"electron": "9.4.0",
|
||||||
"electron-builder": "^22.10.5",
|
"electron-builder": "^22.9.1",
|
||||||
"electron-devtools-installer": "^3.1.1",
|
"electron-devtools-installer": "^3.1.1",
|
||||||
"electron-is-dev": "^0.3.0",
|
"electron-is-dev": "^0.3.0",
|
||||||
"electron-webpack": "^2.8.2",
|
"electron-webpack": "^2.8.2",
|
||||||
|
@ -138,19 +152,22 @@
|
||||||
"eslint-plugin-standard": "^4.0.1",
|
"eslint-plugin-standard": "^4.0.1",
|
||||||
"file-loader": "^4.2.0",
|
"file-loader": "^4.2.0",
|
||||||
"flow-bin": "^0.97.0",
|
"flow-bin": "^0.97.0",
|
||||||
"flow-typed": "^3.7.0",
|
"flow-typed": "^2.3.0",
|
||||||
"formik": "^0.10.4",
|
"formik": "^0.10.4",
|
||||||
"hast-util-sanitize": "^3.0.2",
|
"hast-util-sanitize": "^3.0.2",
|
||||||
"history": "^4.9.0",
|
"history": "^4.9.0",
|
||||||
"husky": "^3.1.0",
|
"husky": "^3.1.0",
|
||||||
"imagesloaded": "^4.1.4",
|
"imagesloaded": "^4.1.4",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
|
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||||
"lint-staged": "^7.0.2",
|
"lint-staged": "^7.0.2",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.14",
|
||||||
"mammoth": "^1.4.16",
|
"mammoth": "^1.4.16",
|
||||||
"moment": "^2.29.2",
|
"moment": "^2.22.0",
|
||||||
"node-fetch": "^2.6.7",
|
"node-abi": "^2.5.1",
|
||||||
|
"node-fetch": "^2.6.1",
|
||||||
|
"node-libs-browser": "^2.1.0",
|
||||||
"node-loader": "^0.6.0",
|
"node-loader": "^0.6.0",
|
||||||
"node-wget": "^0.4.3",
|
"node-wget": "^0.4.3",
|
||||||
"nodemon": "^1.19.1",
|
"nodemon": "^1.19.1",
|
||||||
|
@ -165,6 +182,7 @@
|
||||||
"rc-progress": "^2.0.6",
|
"rc-progress": "^2.0.6",
|
||||||
"react": "^16.8.2",
|
"react": "^16.8.2",
|
||||||
"react-awesome-lightbox": "^1.7.3",
|
"react-awesome-lightbox": "^1.7.3",
|
||||||
|
"react-confetti": "^4.0.1",
|
||||||
"react-dom": "^16.8.2",
|
"react-dom": "^16.8.2",
|
||||||
"react-draggable": "^3.3.0",
|
"react-draggable": "^3.3.0",
|
||||||
"react-google-recaptcha": "^2.0.1",
|
"react-google-recaptcha": "^2.0.1",
|
||||||
|
@ -175,6 +193,7 @@
|
||||||
"react-router": "^5.1.0",
|
"react-router": "^5.1.0",
|
||||||
"react-router-dom": "^5.1.0",
|
"react-router-dom": "^5.1.0",
|
||||||
"react-simplemde-editor": "^4.1.3",
|
"react-simplemde-editor": "^4.1.3",
|
||||||
|
"react-spring": "^8.0.20",
|
||||||
"reakit": "^1.0.0-beta.13",
|
"reakit": "^1.0.0-beta.13",
|
||||||
"redux": "^3.6.0",
|
"redux": "^3.6.0",
|
||||||
"redux-persist": "^5.10.0",
|
"redux-persist": "^5.10.0",
|
||||||
|
@ -191,17 +210,23 @@
|
||||||
"sass": "^1.29.0",
|
"sass": "^1.29.0",
|
||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^7.1.0",
|
||||||
"semver": "^5.3.0",
|
"semver": "^5.3.0",
|
||||||
|
"stream-to-blob-url": "^2.1.1",
|
||||||
"strip-markdown": "^3.0.3",
|
"strip-markdown": "^3.0.3",
|
||||||
"style-loader": "^0.23.1",
|
"style-loader": "^0.23.1",
|
||||||
"terser-webpack-plugin": "^4.2.3",
|
"terser-webpack-plugin": "^1.2.3",
|
||||||
"three-full": "^28.0.2",
|
"three": "^0.125.0",
|
||||||
|
"three-full": "^17.1.0",
|
||||||
|
"tiny-relative-date": "^1.3.0",
|
||||||
|
"tree-kill": "^1.1.0",
|
||||||
"unist-util-visit": "^2.0.3",
|
"unist-util-visit": "^2.0.3",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"video.js": "^7.14.3",
|
"vast-client": "^3.1.1",
|
||||||
|
"video.js": "^7.13.3",
|
||||||
"videojs-contrib-quality-levels": "^2.0.9",
|
"videojs-contrib-quality-levels": "^2.0.9",
|
||||||
"videojs-event-tracking": "^1.0.1",
|
"videojs-event-tracking": "^1.0.1",
|
||||||
"villain-react": "^1.0.9",
|
"villain-react": "^1.0.9",
|
||||||
"webpack": "^4.44.2",
|
"wavesurfer.js": "^2.2.1",
|
||||||
|
"webpack": "^4.28.4",
|
||||||
"webpack-bundle-analyzer": "^3.1.0",
|
"webpack-bundle-analyzer": "^3.1.0",
|
||||||
"webpack-cli": "^3.3.10",
|
"webpack-cli": "^3.3.10",
|
||||||
"webpack-config-utils": "^2.3.1",
|
"webpack-config-utils": "^2.3.1",
|
||||||
|
@ -210,17 +235,21 @@
|
||||||
"webpack-hot-middleware": "^2.24.3",
|
"webpack-hot-middleware": "^2.24.3",
|
||||||
"webpack-merge": "^4.2.1",
|
"webpack-merge": "^4.2.1",
|
||||||
"webpack-node-externals": "^1.7.2",
|
"webpack-node-externals": "^1.7.2",
|
||||||
|
"y18n": "^4.0.1",
|
||||||
"yarnhook": "^0.2.0"
|
"yarnhook": "^0.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.13",
|
"node": ">=7",
|
||||||
"yarn": "^1.3"
|
"yarn": "^1.3"
|
||||||
},
|
},
|
||||||
"lbrySettings": {
|
"lbrySettings": {
|
||||||
"lbrynetDaemonVersion": "0.113.0",
|
"lbrynetDaemonVersion": "0.99.0",
|
||||||
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip",
|
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip",
|
||||||
"lbrynetDaemonDir": "static/daemon",
|
"lbrynetDaemonDir": "static/daemon",
|
||||||
"lbrynetDaemonFileName": "lbrynet"
|
"lbrynetDaemonFileName": "lbrynet",
|
||||||
},
|
"LBRYFirstVersion": "0.0.20",
|
||||||
"packageManager": "yarn@3.2.0"
|
"LBRYFirstUrlTemplate": "https://github.com/lbryio/lbry-first/releases/download/vLBRYFIRSTVER/lbry-first_OSNAME_amd64.zip",
|
||||||
|
"LBRYFirstDir": "static/lbry-first",
|
||||||
|
"LBRYFirstFileName": "lbry-first"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@
|
||||||
"About --[tab title in Channel Page]--": "About",
|
"About --[tab title in Channel Page]--": "About",
|
||||||
"About --[link title in Sidebar or Footer]--": "About",
|
"About --[link title in Sidebar or Footer]--": "About",
|
||||||
"Community Guidelines": "Community Guidelines",
|
"Community Guidelines": "Community Guidelines",
|
||||||
|
"FAQ and Support": "FAQ and Support",
|
||||||
"Share Channel": "Share Channel",
|
"Share Channel": "Share Channel",
|
||||||
"Go to page:": "Go to page:",
|
"Go to page:": "Go to page:",
|
||||||
"Enter a URL for your thumbnail.": "Enter a URL for your thumbnail.",
|
"Enter a URL for your thumbnail.": "Enter a URL for your thumbnail.",
|
||||||
|
@ -468,11 +469,8 @@
|
||||||
"New --[clears Publish Form]--": "New",
|
"New --[clears Publish Form]--": "New",
|
||||||
"Loading": "Loading",
|
"Loading": "Loading",
|
||||||
"This file is in your library.": "This file is in your library.",
|
"This file is in your library.": "This file is in your library.",
|
||||||
"'claimName', 'channelName', and 'streamName' are all empty. One must be present to build a url.": "'claimName', 'channelName', and 'streamName' are all empty. One must be present to build a url.",
|
|
||||||
"Invalid claim ID %s.": "Invalid claim ID %s.",
|
"Invalid claim ID %s.": "Invalid claim ID %s.",
|
||||||
"'claimId' should no longer be used. Use 'streamClaimId' or 'channelClaimId' instead": "'claimId' should no longer be used. Use 'streamClaimId' or 'channelClaimId' instead",
|
|
||||||
"View Tag": "View Tag",
|
"View Tag": "View Tag",
|
||||||
"'claimName' should no longer be used. Use 'streamClaimName' or 'channelClaimName' instead": "'claimName' should no longer be used. Use 'streamClaimName' or 'channelClaimName' instead",
|
|
||||||
"Vietnamese": "Vietnamese",
|
"Vietnamese": "Vietnamese",
|
||||||
"Thai": "Thai",
|
"Thai": "Thai",
|
||||||
"Arabic": "Arabic",
|
"Arabic": "Arabic",
|
||||||
|
@ -485,7 +483,6 @@
|
||||||
"Greek": "Greek",
|
"Greek": "Greek",
|
||||||
"Hide": "Hide",
|
"Hide": "Hide",
|
||||||
"Persian": "Persian",
|
"Persian": "Persian",
|
||||||
"'contentName' should no longer be used. Use 'streamName' instead": "'contentName' should no longer be used. Use 'streamName' instead",
|
|
||||||
"Sorry, we can't preview this file.": "Sorry, we can't preview this file.",
|
"Sorry, we can't preview this file.": "Sorry, we can't preview this file.",
|
||||||
"View File": "View File",
|
"View File": "View File",
|
||||||
"Close": "Close",
|
"Close": "Close",
|
||||||
|
@ -2163,6 +2160,8 @@
|
||||||
"Bank Accounts": "Bank Accounts",
|
"Bank Accounts": "Bank Accounts",
|
||||||
"Connect a bank account to receive tips and compensation in your local currency.": "Connect a bank account to receive tips and compensation in your local currency.",
|
"Connect a bank account to receive tips and compensation in your local currency.": "Connect a bank account to receive tips and compensation in your local currency.",
|
||||||
"Payment Methods": "Payment Methods",
|
"Payment Methods": "Payment Methods",
|
||||||
|
"Total Received Tips": "Total Received Tips",
|
||||||
|
"Withdrawn": "Withdrawn",
|
||||||
"Incoming": "Incoming",
|
"Incoming": "Incoming",
|
||||||
"Outgoing": "Outgoing",
|
"Outgoing": "Outgoing",
|
||||||
"Credits --[transactions tab]--": "Credits",
|
"Credits --[transactions tab]--": "Credits",
|
||||||
|
@ -2178,149 +2177,29 @@
|
||||||
"Card Last 4": "Card Last 4",
|
"Card Last 4": "Card Last 4",
|
||||||
"Search blocked channel name": "Search blocked channel name",
|
"Search blocked channel name": "Search blocked channel name",
|
||||||
"Discuss": "Discuss",
|
"Discuss": "Discuss",
|
||||||
|
"Validating...": "Validating...",
|
||||||
|
"[Removed]": "[Removed]",
|
||||||
"lbry.tv has been retired. You have been magically transported to Odysee.com. %more%": "lbry.tv has been retired. You have been magically transported to Odysee.com. %more%",
|
"lbry.tv has been retired. You have been magically transported to Odysee.com. %more%": "lbry.tv has been retired. You have been magically transported to Odysee.com. %more%",
|
||||||
"Show more livestreams": "Show more livestreams",
|
"Show more livestreams": "Show more livestreams",
|
||||||
"Creator": "Creator",
|
"Creator": "Creator",
|
||||||
"From comments": "From comments",
|
"From comments": "From comments",
|
||||||
"From search": "From search",
|
"From search": "From search",
|
||||||
"Manage tags": "Manage tags",
|
"Manage tags": "Manage tags",
|
||||||
"No Reposts": "No Reposts",
|
"Notification Delivery": "Notification Delivery",
|
||||||
"You haven't reposted anything yet. Do it.": "You haven't reposted anything yet. Do it.",
|
"Choose how you'd like to receive your Odysee notifications.": "Choose how you'd like to receive your Odysee notifications.",
|
||||||
"Claiming credits...": "Claiming credits...",
|
"Desktop Notifications": "Desktop Notifications",
|
||||||
"%totalComments% comments": "%totalComments% comments",
|
"Browser Notifications": "Browser Notifications",
|
||||||
"(%lbc_balance% available)": "(%lbc_balance% available)",
|
"Receive push notifications in this browser, even when you're not on odysee.com": "Receive push notifications in this browser, even when you're not on odysee.com",
|
||||||
"Sending...": "Sending...",
|
"Email Notification Topics": "Email Notification Topics",
|
||||||
"Trending for #Art": "Trending for #Art",
|
"Choose which topics you’d like to be emailed about.": "Choose which topics you’d like to be emailed about.",
|
||||||
"Trending for #Btc": "Trending for #Btc",
|
"Email Notifications": "Email Notifications",
|
||||||
"Trending for #Music": "Trending for #Music",
|
"Receive notifications to the email address: %email%": "Receive notifications to the email address: %email%",
|
||||||
"You sent %lbc% as a tip, Mahalo!": "You sent %lbc% as a tip, Mahalo!",
|
"Realtime push notifications straight to your browser.": "Realtime push notifications straight to your browser.",
|
||||||
"Export All": "Export All",
|
"Don't miss another notification again.": "Don't miss another notification again.",
|
||||||
"Default share url (%name%)": "Default share url (%name%)",
|
"Enable Push Notifications": "Enable Push Notifications",
|
||||||
"Custom share url": "Custom share url",
|
"Dismiss": "Dismiss",
|
||||||
"Share url": "Share url",
|
"Heads up: browser notifications are currently blocked in this browser.": "Heads up: browser notifications are currently blocked in this browser.",
|
||||||
"Odysee Connect": "Odysee Connect",
|
"To enable push notifications please configure your browser to allow notifications on odysee.com.": "To enable push notifications please configure your browser to allow notifications on odysee.com.",
|
||||||
"Log in to %CLOUD_CONNECT_SITE_NAME%": "Log in to %CLOUD_CONNECT_SITE_NAME%",
|
"There was an error enabling browser notifications. Please make sure your browser settings allow you to subscribe to notifications.": "There was an error enabling browser notifications. Please make sure your browser settings allow you to subscribe to notifications.",
|
||||||
"Cloud Connect": "Cloud Connect",
|
|
||||||
"Connect your wallet to Odysee": "Connect your wallet to Odysee",
|
|
||||||
"Minimum time gap in seconds between comments.": "Minimum time gap in seconds between comments.",
|
|
||||||
"Enabling a minimum amount to comment will force all comments to have tips associated with them. This can help prevent spam.": "Enabling a minimum amount to comment will force all comments to have tips associated with them. This can help prevent spam.",
|
|
||||||
"Comments containing these words will be blocked.": "Comments containing these words will be blocked.",
|
|
||||||
"Enter the full channel name or URL to search.\n\nExamples:\n - @channel\n - @channel#3\n - https://odysee.com/@Odysee:8\n - lbry://@Odysee#8": "Enter the full channel name or URL to search.\n\nExamples:\n - @channel\n - @channel#3\n - https://odysee.com/@Odysee:8\n - lbry://@Odysee#8",
|
|
||||||
"Enable Data Hosting": "Enable Data Hosting",
|
|
||||||
"Data over the limit will be deleted within 30 minutes. This will make the Yrbl cry a little bit.": "Data over the limit will be deleted within 30 minutes. This will make the Yrbl cry a little bit.",
|
|
||||||
"Choose %asset%": "Choose %asset%",
|
|
||||||
"Showing %filtered% results of %total%": "Showing %filtered% results of %total%",
|
|
||||||
"filtered": "filtered",
|
|
||||||
"View All Playlists": "View All Playlists",
|
|
||||||
"Your wallet is not currently using a cloud sync service. You are in control of backing up your wallet.": "Your wallet is not currently using a cloud sync service. You are in control of backing up your wallet.",
|
|
||||||
"Sending": "Sending",
|
|
||||||
"You sent %lbc%": "You sent %lbc%",
|
|
||||||
"Buy LBC": "Buy LBC",
|
|
||||||
"This is information like error logging, performance tracking, and usage statistics. It includes your IP address and basic system details, but no other identifying information (unless you connect to a cloud service)": "This is information like error logging, performance tracking, and usage statistics. It includes your IP address and basic system details, but no other identifying information (unless you connect to a cloud service)",
|
|
||||||
"Use official LBRY wallet servers": "Use official LBRY wallet servers",
|
|
||||||
"Enable Prerelease Updates": "Enable Prerelease Updates",
|
|
||||||
"Enable Upgrade to Test Builds": "Enable Upgrade to Test Builds",
|
|
||||||
"Prereleases may break things and we may not be able to fix them for you.": "Prereleases may break things and we may not be able to fix them for you.",
|
|
||||||
"A channel is required to repost on LBRY": "A channel is required to repost on LBRY",
|
|
||||||
"Admin": "Admin",
|
|
||||||
"Stickers": "Stickers",
|
|
||||||
"Different Sticker": "Different Sticker",
|
|
||||||
"LBC": "LBC",
|
|
||||||
"Add a Card": "Add a Card",
|
|
||||||
" To Tip Creators": " To Tip Creators",
|
|
||||||
"Nothing found": "Nothing found",
|
|
||||||
"From Comments": "From Comments",
|
|
||||||
"This support is priced in $USD.": "This support is priced in $USD.",
|
|
||||||
"The current exchange rate for the submitted LBC amount is ~ $%exchange_amount%.": "The current exchange rate for the submitted LBC amount is ~ $%exchange_amount%.",
|
|
||||||
"Amount of $%input_amount% LBC in USB is lower than price of $%price_amount%": "Amount of $%input_amount% LBC in USB is lower than price of $%price_amount%",
|
|
||||||
"Hosting for content you have downloaded": "Hosting for content you have downloaded",
|
|
||||||
"Hosting content selected by the network": "Hosting content selected by the network",
|
|
||||||
"Remove all unavailable claims": "Remove all unavailable claims",
|
|
||||||
"Drag": "Drag",
|
|
||||||
"Move Top": "Move Top",
|
|
||||||
"Move Bottom": "Move Bottom",
|
|
||||||
"Move Up": "Move Up",
|
|
||||||
"Move Down": "Move Down",
|
|
||||||
"Trending for #Game": "Trending for #Game",
|
|
||||||
"Remove custom comment server": "Remove custom comment server",
|
|
||||||
"Use Https": "Use Https",
|
|
||||||
"Server URL": "Server URL",
|
|
||||||
"Use https": "Use https",
|
|
||||||
"Custom Servers": "Custom Servers",
|
|
||||||
"Add A Server": "Add A Server",
|
|
||||||
"Autoplay Next is off.": "Autoplay Next is off.",
|
|
||||||
"Shuffle is on.": "Shuffle is on.",
|
|
||||||
"Shuffle is off.": "Shuffle is off.",
|
|
||||||
"Loop is on.": "Loop is on.",
|
|
||||||
"Loop is off.": "Loop is off.",
|
|
||||||
"View History Hosting lets you choose how much storage to use helping content you've consumed.": "View History Hosting lets you choose how much storage to use helping content you've consumed.",
|
|
||||||
"Clean Now": "Clean Now",
|
|
||||||
"Enable Automatic Hosting": "Enable Automatic Hosting",
|
|
||||||
"Download and serve arbitrary data on the network.": "Download and serve arbitrary data on the network.",
|
|
||||||
"View History Hosting": "View History Hosting",
|
|
||||||
"Disable automatic updates": "Disable automatic updates",
|
|
||||||
"Preven't new updates to be downloaded automatically in the background (we will keep notifying you if there is an update)": "Preven't new updates to be downloaded automatically in the background (we will keep notifying you if there is an update)",
|
|
||||||
"Unlimited View Hosting": "Unlimited View Hosting",
|
|
||||||
"Choose View Hosting Limit": "Choose View Hosting Limit",
|
|
||||||
"View Hosting Limit (GB)": "View Hosting Limit (GB)",
|
|
||||||
"%free% of %total% available": "%free% of %total% available",
|
|
||||||
"Short (< 4 min)": "Short (< 4 min)",
|
|
||||||
"Medium (4 - 20 min)": "Medium (4 - 20 min)",
|
|
||||||
"Rename List": "Rename List",
|
|
||||||
"New Name": "New Name",
|
|
||||||
"Rename": "Rename",
|
|
||||||
"New Collection Name": "New Collection Name",
|
|
||||||
"In %collection%": "In %collection%",
|
|
||||||
"Add to %collection%": "Add to %collection%",
|
|
||||||
"Show this channel your appreciation by sending a donation of Credits. ": "Show this channel your appreciation by sending a donation of Credits. ",
|
|
||||||
"You've entered the land of content freedom! Let's make sure everything is ship shape.": "You've entered the land of content freedom! Let's make sure everything is ship shape.",
|
|
||||||
"By continuing, you agree to the %terms%": "By continuing, you agree to the %terms%",
|
|
||||||
"Privacy": "Privacy",
|
|
||||||
"LBRY takes privacy and choice seriously. Is it ok if we monitor performance and help creators track their views?": "LBRY takes privacy and choice seriously. Is it ok if we monitor performance and help creators track their views?",
|
|
||||||
"Yes, share with LBRY": "Yes, share with LBRY",
|
|
||||||
"Search Uploads": "Search Uploads",
|
|
||||||
"This refundable boost will improve the discoverability of this %claimTypeText% while active. ": "This refundable boost will improve the discoverability of this %claimTypeText% while active. ",
|
|
||||||
"Show less": "Show less",
|
|
||||||
"Elements": "Elements",
|
|
||||||
"Icons": "Icons",
|
|
||||||
"Go to": "Go to",
|
|
||||||
"Clearing...": "Clearing...",
|
|
||||||
"Clear Views": "Clear Views",
|
|
||||||
"Show Video View Progress": "Show Video View Progress",
|
|
||||||
"Display view progress on thumbnail. This setting will not hide any blockchain activity or downloads.": "Display view progress on thumbnail. This setting will not hide any blockchain activity or downloads.",
|
|
||||||
"Content Hosting": "Content Hosting",
|
|
||||||
"Hosting": "Hosting",
|
|
||||||
"Viewed Hosting": "Viewed Hosting",
|
|
||||||
"Auto Hosting": "Auto Hosting",
|
|
||||||
"Help creators and improve the P2P data network by hosting content.": "Help creators and improve the P2P data network by hosting content.",
|
|
||||||
"I'm happy with my settings": "I'm happy with my settings",
|
|
||||||
"We've noticed you already have some settings.": "We've noticed you already have some settings.",
|
|
||||||
"You choose how much data to host.": "You choose how much data to host.",
|
|
||||||
"Go back": "Go back",
|
|
||||||
"Custom Hosting": "Custom Hosting",
|
|
||||||
"Automatic Hosting (GB)": "Automatic Hosting (GB)",
|
|
||||||
"* Note that as peer-to-peer software, your IP address and potentially other system information can be sent to other users, though this information is not stored permanently.": "* Note that as peer-to-peer software, your IP address and potentially other system information can be sent to other users, though this information is not stored permanently.",
|
|
||||||
"Help improve the P2P data network (and make LBRY users happy) by hosting data.": "Help improve the P2P data network (and make LBRY users happy) by hosting data.",
|
|
||||||
"View History Hosting lets you choose how much storage to use hosting content you've consumed.": "View History Hosting lets you choose how much storage to use hosting content you've consumed.",
|
|
||||||
"Automatic Hosting downloads a small portion of content active on the network.": "Automatic Hosting downloads a small portion of content active on the network.",
|
|
||||||
"Publishes --[legend, storage category]--": "Publishes",
|
|
||||||
"Auto Hosting --[legend, storage category]--": "Auto Hosting",
|
|
||||||
"View Hosting --[legend, storage category]--": "View Hosting",
|
|
||||||
"%spaceUsed% of %limit% GB": "%spaceUsed% of %limit% GB",
|
|
||||||
"%spaceUsed% of %limit% Free GB": "%spaceUsed% of %limit% Free GB",
|
|
||||||
"Disabled": "Disabled",
|
|
||||||
"Free --[legend, unused disk space]--": "Free",
|
|
||||||
"Top content in %language%": "Top content in %language%",
|
|
||||||
"Apply": "Apply",
|
|
||||||
"Disable background": "Disable background",
|
|
||||||
"Installing, please wait...": "Installing, please wait...",
|
|
||||||
"There was an error during installation. Please, try again.": "There was an error during installation. Please, try again.",
|
|
||||||
"Odysee Connect --[Section in Help Page]--": "Odysee Connect",
|
|
||||||
"Your hub has blocked this content because it subscribes to the following blocking channel:": "Your hub has blocked this content because it subscribes to the following blocking channel:",
|
|
||||||
"Your hub has blocked access to this content do to a complaint received under the US Digital Millennium Copyright Act.": "Your hub has blocked access to this content do to a complaint received under the US Digital Millennium Copyright Act.",
|
|
||||||
"Autoplay Next is on.": "Autoplay Next is on.",
|
|
||||||
"This will be visible in a few minutes after you submit this form.": "This will be visible in a few minutes after you submit this form.",
|
|
||||||
"Anon --[used in <%anonymous% Reposted>]--": "Anon",
|
|
||||||
"Your update is now pending. It will take a few minutes to appear for other users.": "Your update is now pending. It will take a few minutes to appear for other users.",
|
|
||||||
"--end--": "--end--"
|
"--end--": "--end--"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
owner: lbryio
|
|
||||||
repo: lbry-desktop
|
|
||||||
provider: github
|
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
|
@ -1,102 +0,0 @@
|
||||||
<svg width="2859" height="3858" viewBox="0 0 2859 3858" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path opacity="0.997" d="M229.331 2573.92C227.658 2571.29 287.004 2544.38 324.218 2448.2C337.11 2414.69 347.357 2369.08 337.943 2323.16C334.776 2307.96 329.583 2292.41 320.457 2279.96C313.372 2270.39 303.743 2262.04 292.932 2259.23C281.648 2255.61 267.954 2257.93 254.626 2263.16C231.995 2270.93 211.286 2285.24 190.078 2302.35C167.021 2283.54 134.978 2268.82 104.768 2273.7C81.902 2276.54 60.511 2295.24 49.4462 2318.86C3.74465 2410.06 71.315 2519.88 150.29 2625.09C150.29 2625.09 150.29 2625.09 150.29 2625.09C230.276 2725.89 340.979 2812.76 472.956 2860.92C580.106 2900.19 698.127 2914.49 816.398 2905.34C858.558 2901.63 900.297 2891.12 931.227 2867C941.601 2859.12 950.867 2849.65 958.548 2839.11C967.767 2826.46 974.702 2812.27 978.534 2797.4C985.145 2772.44 984.014 2745.1 975.509 2720.73V2720.73C967.343 2698.01 953.089 2677.33 934.061 2665.58C910.149 2650.23 881.933 2641.07 853.199 2637.76C819.885 2634.11 785.627 2639.42 757.021 2654.45C719.662 2673.22 691.325 2709.24 671.796 2748.4C639.342 2814.04 629.429 2890.35 625.585 2963.42C620.787 3054.16 660.729 3141.58 719.642 3201.36C770.676 3252.96 831.322 3289.74 893.723 3308.69C908.697 3313.56 926.857 3313.53 945.412 3314.04C973.343 3314.51 1002.22 3313.39 1029.19 3312.46C1112.71 3309.54 1178.34 3307.56 1247.24 3311.4C1252.48 3312.55 1259.26 3308.03 1265.44 3302.94C1274.49 3294.73 1281.43 3283.17 1287.71 3271.73C1306.29 3237.38 1318.13 3197.66 1326.75 3167.88C1349.83 3064.98 1363.32 3012.13 1366.36 3012.73C1369.41 3013.33 1361.94 3067.36 1344.36 3171.88C1344.36 3171.88 1344.36 3171.88 1344.36 3171.88C1337.33 3202.62 1327.04 3243.92 1308.44 3282.33C1302.39 3294.99 1294.5 3308.84 1282.76 3320.8C1274.53 3329.67 1261.97 3337.01 1246.23 3337.34C1178.13 3335.81 1114.64 3339.62 1030.69 3344.52C1003.79 3346.11 974.453 3347.89 945.212 3348.03C926.769 3348.32 905.587 3348.33 883.825 3342.43C815.106 3322.91 748.321 3284.25 692.192 3228.84C625.184 3162.88 579.614 3066.05 583.303 2961.59C585.929 2885.84 596.46 2803.96 631.931 2729.13C653.524 2683.25 688.026 2640.3 736.117 2614.43C773.614 2594.93 816.524 2587.77 858.202 2592.39C893.307 2596.11 928.083 2607.44 958.736 2626.81C987.785 2645.66 1008.37 2674.19 1019.07 2705.51V2705.51C1030.67 2738.69 1032.2 2775.02 1023.26 2809.17C1017.73 2829.86 1008.36 2849.2 995.965 2866.3C985.637 2880.55 973.211 2893.24 959.166 2903.86C917.766 2934.55 867.899 2948.06 819.932 2951.28C695.515 2960.79 571.075 2945 457.507 2902.73C317.198 2850.29 201.177 2757.52 118.223 2650.2V2650.2C32.6442 2545.24 -32.8981 2417.48 17.6801 2303.93C33.4423 2270.48 64.451 2246.14 100.199 2240.83C136.634 2236.45 169.491 2255.33 190.178 2280.49C205.009 2262.04 222.599 2245.98 243.989 2236.31C261.83 2229.19 281.993 2227.28 301.035 2233.04C318.973 2239.12 332.793 2251.36 341.852 2265.2C353.144 2282.35 358.941 2301.28 361.69 2318.87C370.075 2371.61 356.822 2420.33 340.993 2455.25C291.994 2563.91 225.032 2567.17 229.331 2573.92V2573.92Z" fill="black"/>
|
|
||||||
<path d="M1160.62 2299.49C1160.62 2299.49 1166.66 2341.8 1118.3 2468.75C1069.94 2595.69 1066.92 2885.85 1042.74 2949.32C1018.56 3012.79 885.57 3224.37 915.795 3411.76C946.02 3599.15 1094.12 3865.13 1275.47 3798.64C1456.82 3732.14 1420.55 3744.23 1420.55 3744.23C1420.55 3744.23 1946.46 3859.09 2294.05 3659.6C2372.63 3695.87 2420.99 3726.1 2538.87 3656.58C2656.74 3587.06 2717.19 3396.65 2714.17 3266.68C2711.15 3136.71 2523.75 2852.6 2502.6 2792.15C2481.44 2731.7 2402.85 2435.5 2363.56 2311.58C2324.27 2187.66 2354.5 2166.5 2354.5 2166.5L1160.62 2299.49Z" fill="#DE5700" stroke="black" stroke-width="46.0804"/>
|
|
||||||
<path d="M2798.72 15.367C2698.4 16.4866 2391.12 184.492 2306.37 277.783C2219.35 373.579 2165.64 521.033 2148.97 571.513C2050.88 508.595 1907.17 507.155 1907.17 507.155C1907.17 507.155 1991.8 479.955 2082.48 455.775C1925.31 401.371 1722.8 449.727 1722.8 449.727C1722.8 449.727 1813.47 349.989 1895.08 277.45C1768.13 310.697 1620.04 383.233 1529.36 437.638C1553.54 401.368 1595.86 362.076 1680.49 244.199C1447.75 301.626 1160.61 528.318 1060.87 612.947C1072.96 537.385 1103.19 489.025 1139.46 404.395C1002.07 499.513 937.628 607.905 907.715 681.853C876.541 624.261 794.11 483.695 690.543 400.173C558.035 293.312 45.0981 126.611 113.489 254.844C181.88 383.077 164.781 558.322 207.525 827.611C250.27 1096.9 634.972 1250.78 634.972 1250.78C637.191 1249.99 639.395 1249.09 641.592 1248.17C619.011 1319.85 598.866 1424.54 583.679 1597.01C511.014 1706.01 478.959 1727.38 470.41 1767.99C540.938 1733.8 575.13 1708.15 626.423 1695.32C581.542 1770.13 579.407 1872.71 598.642 2035.14C634.974 1943.24 632.832 1945.37 671.302 1917.59C681.988 2026.59 705.503 2086.43 733.287 2120.63C743.973 2060.78 776.031 2037.28 776.031 2037.28C776.031 2037.28 797.404 2167.65 859.383 2257.41C872.206 2178.34 887.165 2165.51 887.165 2165.51C887.165 2165.51 1135.08 2490.37 1767.7 2456.17C2400.31 2421.98 2579.84 1985.98 2579.84 1985.98C2579.84 1985.98 2592.66 2041.56 2592.66 2062.93C2639.68 1994.54 2669.6 1853.48 2669.6 1853.48C2669.6 1853.48 2703.8 1934.69 2695.25 1985.98C2733.72 1921.86 2742.26 1763.72 2725.17 1691.05C2785.01 1755.17 2836.31 1776.54 2836.31 1776.54C2836.31 1776.54 2703.79 1545.72 2699.52 1507.25C2695.25 1468.78 2793.56 1562.81 2793.56 1562.81C2793.56 1562.81 2731.97 1460.26 2716.62 1432.45C2659.41 1328.78 2605.12 1139.43 2528.87 1011.72C2592.86 970.123 2850.88 788.773 2843.33 573.68C2834.72 328.21 2786.46 176.103 2827.99 51.0384C2836.43 25.6346 2824.3 15.0816 2798.72 15.367V15.367Z" fill="#DE5700"/>
|
|
||||||
<path d="M1160.62 2299.49C1160.62 2299.49 1166.66 2341.8 1118.3 2468.75C1069.94 2595.69 1066.92 2885.85 1042.74 2949.32C1018.56 3012.79 885.57 3224.37 915.795 3411.76C946.02 3599.15 1094.12 3865.13 1275.47 3798.64C1456.82 3732.14 1420.55 3744.23 1420.55 3744.23C1420.55 3744.23 1946.46 3859.09 2294.05 3659.6C2372.63 3695.87 2420.99 3726.1 2538.87 3656.58C2656.74 3587.06 2717.19 3396.65 2714.17 3266.68C2711.15 3136.71 2523.75 2852.6 2502.6 2792.15C2481.44 2731.7 2402.85 2435.5 2363.56 2311.58C2324.27 2187.66 2354.5 2166.5 2354.5 2166.5L1160.62 2299.49Z" fill="#DE5700"/>
|
|
||||||
<path d="M1940.31 2212.63L1557.07 2255.32C1406.21 2289.92 1288.96 2332.21 1288.96 2332.21C1288.96 2332.21 1220.57 2746.83 1233.39 2862.24C1246.22 2977.65 1173.55 3152.9 1212.02 3328.15C1245.61 3481.2 1311.83 3644.02 1558.64 3765.38C1710.04 3782.34 1960.24 3792 2176.82 3713.48C2280.67 3629.51 2354.73 3520.47 2383.21 3435.02C2447.33 3242.67 2370.39 2909.27 2340.47 2840.87C2310.55 2772.48 2344.75 2558.76 2178.04 2315.11C2132.1 2247.96 2043.91 2219.17 1940.31 2212.63Z" fill="#F7EDE9"/>
|
|
||||||
<path opacity="0.6" d="M2798.72 15.367C2698.4 16.4866 2391.12 184.492 2306.37 277.783C2219.35 373.579 2165.64 521.033 2148.97 571.513C2050.88 508.595 1907.17 507.155 1907.17 507.155C1907.17 507.155 1991.8 479.955 2082.48 455.775C1925.31 401.371 1722.8 449.727 1722.8 449.727C1722.8 449.727 1813.47 349.989 1895.08 277.45C1768.13 310.697 1620.04 383.233 1529.36 437.638C1553.54 401.368 1595.86 362.076 1680.49 244.199C1447.75 301.626 1160.61 528.318 1060.87 612.947C1072.96 537.385 1103.19 489.025 1139.46 404.395C1002.07 499.513 937.628 607.905 907.715 681.853C876.541 624.261 794.11 483.695 690.543 400.173C558.035 293.312 45.0981 126.611 113.489 254.844C181.88 383.077 164.781 558.322 207.525 827.611C250.27 1096.9 634.972 1250.78 634.972 1250.78C637.191 1249.99 639.395 1249.09 641.592 1248.17C619.011 1319.85 598.866 1424.54 583.679 1597.01C511.014 1706.01 478.959 1727.38 470.41 1767.99C540.938 1733.8 575.13 1708.15 626.423 1695.32C581.542 1770.13 579.407 1872.71 598.642 2035.14C634.974 1943.24 632.832 1945.37 671.302 1917.59C681.988 2026.59 705.503 2086.43 733.287 2120.63C743.973 2060.78 776.031 2037.28 776.031 2037.28C776.031 2037.28 797.404 2167.65 859.383 2257.41C872.206 2178.34 887.165 2165.51 887.165 2165.51C887.165 2165.51 1135.08 2490.37 1767.7 2456.17C2400.31 2421.98 2579.84 1985.98 2579.84 1985.98C2579.84 1985.98 2592.66 2041.56 2592.66 2062.93C2639.68 1994.54 2669.6 1853.48 2669.6 1853.48C2669.6 1853.48 2703.8 1934.69 2695.25 1985.98C2733.72 1921.86 2742.26 1763.72 2725.17 1691.05C2785.01 1755.17 2836.31 1776.54 2836.31 1776.54C2836.31 1776.54 2703.79 1545.72 2699.52 1507.25C2695.25 1468.78 2793.56 1562.81 2793.56 1562.81C2793.56 1562.81 2731.97 1460.26 2716.62 1432.45C2659.41 1328.78 2605.12 1139.43 2528.87 1011.72C2592.86 970.123 2850.88 788.773 2843.33 573.68C2834.72 328.21 2786.46 176.103 2827.99 51.0384C2836.43 25.6346 2824.3 15.0816 2798.72 15.367V15.367Z" fill="url(#paint0_radial_2_3)"/>
|
|
||||||
<path d="M1785.69 1777.75C1684.07 1778.04 1631.38 1822.48 1594.58 1842.79C1435.61 2029.15 1115.77 1926.47 942.736 2050.1C912.815 2071.47 871.139 2186.88 871.139 2186.88L873.322 2195.17C881.063 2170.83 887.165 2165.51 887.165 2165.51C887.165 2165.51 1135.08 2490.37 1767.7 2456.17C2277.77 2428.6 2493.17 2139.93 2557.52 2029.09C2551.52 1973.12 2534.07 1898.88 2483.67 1896.22C2402.45 1891.95 2066.9 1864.16 1964.32 1808.59C1922.64 1786.02 1855.22 1777.56 1785.69 1777.75V1777.75Z" fill="#F7EDE9"/>
|
|
||||||
<path opacity="0.993" d="M1961.57 1985.15C1963.63 1987.09 1933.18 2033.96 1856.33 2063.83V2063.83C1839.85 2070.21 1822.61 2075.45 1804.72 2079.62C1766.98 2088.41 1729.87 2091.61 1698.49 2092.27C1674.97 2092.78 1655.68 2091.74 1642.07 2090.22C1634.99 2089.43 1629.58 2088.53 1625.85 2087.62C1623.95 2087.15 1622.51 2086.68 1621.54 2086.24C1621.04 2086.01 1620.67 2085.78 1620.42 2085.57C1620.15 2085.33 1620.02 2085.11 1620.03 2084.89C1620.05 2084.67 1620.2 2084.47 1620.49 2084.27C1620.76 2084.08 1621.15 2083.91 1621.67 2083.73C1622.67 2083.4 1624.14 2083.08 1626.06 2082.78C1629.77 2082.2 1635.24 2081.66 1642.21 2081.09C1655.61 2079.99 1674.74 2078.77 1697.58 2076.59C1728.3 2073.63 1764.16 2069.35 1800.38 2060.94C1817.57 2056.95 1834.05 2052.22 1849.95 2046.59C1918.62 2022.43 1958.6 1982.34 1961.57 1985.15V1985.15Z" fill="black"/>
|
|
||||||
<path d="M1934.67 1959.27C1935.77 1956.91 1954.37 1960.97 1967.17 1981.57C1979.98 2002.16 1975.41 2020.64 1972.82 2020.59C1970 2020.53 1967.84 2002.79 1958.14 1987.19C1948.44 1971.58 1933.47 1961.83 1934.67 1959.27V1959.27Z" fill="black"/>
|
|
||||||
<path d="M1263.38 1639.08C1266.22 1756.73 1183.41 1844.17 1098.66 1852.16C951.388 1866.04 891.515 1767.76 901.935 1653.12C912.302 1539.07 1011.03 1433.96 1109.23 1430.52C1193.46 1427.58 1260.47 1518.48 1263.38 1639.08Z" fill="black"/>
|
|
||||||
<g filter="url(#filter0_f_2_3)">
|
|
||||||
<path d="M1109.1 1636.63C1138.87 1598.95 1137.08 1543.74 1105.1 1513.3C1073.11 1482.87 1023.06 1488.73 993.289 1526.41C963.521 1564.08 965.315 1619.29 997.297 1649.73C1029.28 1680.17 1079.34 1674.3 1109.1 1636.63Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M1109.1 1636.63C1138.87 1598.95 1137.08 1543.74 1105.1 1513.3C1073.11 1482.87 1023.06 1488.73 993.289 1526.41C963.521 1564.08 965.315 1619.29 997.297 1649.73C1029.28 1680.17 1079.34 1674.3 1109.1 1636.63Z" fill="#DEDEDE"/>
|
|
||||||
<g filter="url(#filter1_f_2_3)">
|
|
||||||
<path d="M1220.38 1725.27C1218.97 1703.96 1200.95 1686.44 1180.12 1686.13C1159.3 1685.82 1143.56 1702.84 1144.97 1724.14C1146.37 1745.45 1164.4 1762.98 1185.22 1763.29C1206.05 1763.6 1221.79 1746.58 1220.38 1725.27Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M1217.34 1725.22C1216.05 1705.95 1199.48 1690.11 1180.33 1689.83C1161.18 1689.54 1146.71 1704.93 1148.01 1724.2C1149.3 1743.46 1165.87 1759.31 1185.02 1759.59C1204.17 1759.87 1218.64 1744.48 1217.34 1725.22Z" fill="#DEDEDE"/>
|
|
||||||
<path d="M2111.74 1483.68C2108.91 1601.33 2191.71 1688.77 2276.47 1696.76C2423.74 1710.64 2483.61 1612.36 2473.19 1497.72C2462.82 1383.67 2364.09 1278.56 2265.89 1275.13C2181.66 1272.18 2114.65 1363.09 2111.74 1483.68Z" fill="black"/>
|
|
||||||
<g filter="url(#filter2_f_2_3)">
|
|
||||||
<path d="M2266.02 1481.23C2236.25 1443.55 2238.05 1388.34 2270.03 1357.9C2302.01 1327.47 2352.07 1333.34 2381.83 1371.01C2411.6 1408.68 2409.81 1463.9 2377.83 1494.33C2345.85 1524.77 2295.79 1518.9 2266.02 1481.23Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M2266.02 1481.23C2236.25 1443.55 2238.05 1388.34 2270.03 1357.9C2302.01 1327.47 2352.07 1333.34 2381.83 1371.01C2411.6 1408.68 2409.81 1463.9 2377.83 1494.33C2345.85 1524.77 2295.79 1518.9 2266.02 1481.23Z" fill="#DEDEDE"/>
|
|
||||||
<g filter="url(#filter3_f_2_3)">
|
|
||||||
<path d="M2154.74 1569.87C2156.15 1548.56 2174.17 1531.04 2195 1530.73C2215.82 1530.42 2231.57 1547.44 2230.16 1568.75C2228.75 1590.05 2210.72 1607.58 2189.9 1607.89C2169.07 1608.2 2153.33 1591.18 2154.74 1569.87Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M2157.78 1569.82C2159.08 1550.55 2175.65 1534.71 2194.79 1534.43C2213.94 1534.15 2228.41 1549.53 2227.12 1568.8C2225.82 1588.06 2209.25 1603.91 2190.1 1604.19C2170.96 1604.47 2156.49 1589.08 2157.78 1569.82Z" fill="#DEDEDE"/>
|
|
||||||
<path d="M1662.35 1829.49C1645.46 1787.85 1850.52 1752.32 1854.28 1791.71C1858.37 1834.59 1804.4 1912.61 1777.2 1917.14C1750 1921.68 1680.39 1873.96 1662.35 1829.49V1829.49Z" fill="black"/>
|
|
||||||
<g opacity="0.8">
|
|
||||||
<g filter="url(#filter4_f_2_3)">
|
|
||||||
<path d="M1786.9 1793.91C1788.82 1786.22 1801.15 1781.29 1814.44 1782.91C1827.74 1784.53 1836.97 1792.08 1835.05 1799.77C1833.13 1807.46 1820.8 1812.39 1807.51 1810.77C1794.21 1809.15 1784.99 1801.61 1786.9 1793.91Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M1788.84 1794.15C1790.59 1787.19 1801.91 1782.76 1814.14 1784.25C1826.36 1785.74 1834.85 1792.58 1833.11 1799.54C1831.36 1806.49 1820.04 1810.92 1807.81 1809.43C1795.59 1807.94 1787.1 1801.1 1788.84 1794.15Z" fill="#DEDEDE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M2741.41 163.935C2735.43 163.644 2728.58 173.489 2718.76 194.994C2673.88 293.306 2462.29 385.213 2381.08 483.525C2299.87 581.837 2284.9 697.243 2374.67 851.122C2421.52 931.442 2482.9 980.277 2532.12 1009.56C2600.59 964.628 2850.77 785.686 2843.33 573.68C2841.17 511.985 2836.51 456.205 2831.39 405.253C2769.94 259.579 2759.63 164.818 2741.41 163.935V163.935Z" fill="url(#paint1_radial_2_3)"/>
|
|
||||||
<path d="M181.665 291.229C163.173 289.362 174.995 366.697 171.814 505.727C180.547 595.591 187.448 701.123 207.525 827.611C246.788 1074.97 573.781 1224.58 626.915 1247.37C670.403 1199.53 739.457 1106.83 766.704 960.629C806.777 745.606 754.64 615.556 641.83 530.754C529.019 445.951 288.043 418.155 211.526 319.567C197.179 301.081 187.769 291.846 181.665 291.229V291.229Z" fill="url(#paint2_radial_2_3)"/>
|
|
||||||
<path d="M2798.72 15.367C2698.4 16.4866 2391.12 184.492 2306.37 277.783C2219.35 373.579 2165.64 521.033 2148.97 571.513C2050.88 508.595 1907.17 507.155 1907.17 507.155C1907.17 507.155 1991.8 479.955 2082.48 455.775C1925.31 401.371 1722.8 449.727 1722.8 449.727C1722.8 449.727 1813.47 349.989 1895.08 277.45C1768.13 310.697 1620.04 383.233 1529.36 437.638C1553.54 401.368 1595.86 362.076 1680.49 244.199C1447.75 301.626 1160.61 528.318 1060.87 612.947C1072.96 537.385 1103.19 489.025 1139.46 404.395C1002.07 499.513 937.628 607.905 907.715 681.853C876.541 624.261 794.11 483.695 690.543 400.173C558.035 293.312 45.0981 126.611 113.489 254.844C181.88 383.077 164.781 558.322 207.525 827.611C250.27 1096.9 634.972 1250.78 634.972 1250.78C637.191 1249.99 639.395 1249.09 641.592 1248.17C619.011 1319.85 598.866 1424.54 583.679 1597.01C511.014 1706.01 478.959 1727.38 470.41 1767.99C540.938 1733.8 575.13 1708.15 626.423 1695.32C581.542 1770.13 579.407 1872.71 598.642 2035.14C634.974 1943.24 632.832 1945.37 671.302 1917.59C681.988 2026.59 705.503 2086.43 733.287 2120.63C743.973 2060.78 776.031 2037.28 776.031 2037.28C776.031 2037.28 797.404 2167.65 859.383 2257.41C872.206 2178.34 887.165 2165.51 887.165 2165.51C887.165 2165.51 1135.08 2490.37 1767.7 2456.17C2400.31 2421.98 2579.84 1985.98 2579.84 1985.98C2579.84 1985.98 2592.66 2041.56 2592.66 2062.93C2639.68 1994.54 2669.6 1853.48 2669.6 1853.48C2669.6 1853.48 2703.8 1934.69 2695.25 1985.98C2733.72 1921.86 2742.26 1763.72 2725.17 1691.05C2785.01 1755.17 2836.31 1776.54 2836.31 1776.54C2836.31 1776.54 2703.79 1545.72 2699.52 1507.25C2695.25 1468.78 2793.56 1562.81 2793.56 1562.81C2793.56 1562.81 2731.97 1460.26 2716.62 1432.45C2659.41 1328.78 2605.12 1139.43 2528.87 1011.72C2592.86 970.123 2850.88 788.773 2843.33 573.68C2834.72 328.21 2786.46 176.103 2827.99 51.0384C2836.43 25.6346 2824.3 15.0816 2798.72 15.367V15.367Z" stroke="black" stroke-width="30.7203" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M1166.07 3775.9C1091.27 3651.94 1054.81 3567.11 1049.59 3511.42C1044.78 3460.13 1038.37 3398.15 1075.24 3428.61C1085.92 3383.72 1083.79 3358.08 1111.57 3370.9C1139.36 3383.72 1158.59 3411.51 1158.59 3411.51C1158.59 3411.51 1154.32 3347.39 1182.1 3368.76C1233.19 3399.52 1324.44 3688.35 1313.81 3770.16C1302.14 3860.06 1231.96 3879.6 1166.07 3775.9V3775.9Z" fill="url(#paint3_linear_2_3)" stroke="black" stroke-width="23.0402"/>
|
|
||||||
<path d="M2556.53 3668.47C2609.53 3533.74 2631.28 3444 2627.1 3388.22C2623.26 3336.85 2619.21 3274.67 2587.96 3310.87C2569.91 3268.41 2567.73 3242.76 2542.48 3260.06C2517.23 3277.35 2502.92 3307.96 2502.92 3307.96C2502.92 3307.96 2496.4 3244.03 2472.59 3269.75C2427.37 3308.62 2385.74 3608.66 2409.91 3687.53C2436.47 3774.21 2508.93 3781.73 2556.53 3668.47V3668.47Z" fill="url(#paint4_linear_2_3)" stroke="black" stroke-width="23.0402"/>
|
|
||||||
<path d="M1562.1 3063.57C1524.1 3059.67 1486.65 3074.05 1455.28 3094.55C1440.72 3104.25 1426.76 3115.03 1414.48 3127.52C1438.67 3156.34 1465.72 3183.02 1496.29 3205.05C1502.66 3208.89 1510.78 3214.39 1518.34 3210.58C1525.16 3205.3 1523.61 3195.64 1524.22 3188.07C1530.46 3197.06 1541.83 3202.2 1552.66 3201.65C1562.44 3199.92 1561.73 3187.56 1560.44 3180.1C1559.69 3173.07 1556.6 3166.42 1556.17 3159.41C1562.43 3160.56 1568.02 3169.72 1575.98 3167.49C1584.76 3164.88 1580.38 3153.58 1580.28 3146.94C1575.9 3118.83 1568.65 3091.24 1562.1 3063.57V3063.57Z" fill="url(#paint5_linear_2_3)"/>
|
|
||||||
<path d="M2302.03 3008.83C2271.36 3023.52 2235.53 3023.15 2203.06 3015.16C2175.5 3008.19 2149 2996.64 2125.3 2980.94C2128.65 3015.23 2131.75 3049.73 2139.6 3083.34C2140.74 3090.5 2145.31 3102 2154.43 3096.05C2163.06 3091.33 2167.94 3082.23 2175.33 3076.17C2175.86 3081.7 2172.59 3088.04 2172.97 3094.1C2172.43 3103.97 2175.25 3117.51 2186.59 3119.85C2200.16 3121.29 2212.08 3112.19 2221.11 3103.04C2227.36 3097.53 2223.84 3112.39 2227.54 3115.27C2229.88 3123.69 2240.07 3132.21 2248.05 3124.67C2257.97 3116 2262.87 3103.26 2269.34 3092.1C2283.08 3065.57 2293.72 3037.5 2302.03 3008.83V3008.83Z" fill="url(#paint6_linear_2_3)"/>
|
|
||||||
<path d="M1517.64 2663.48C1517.64 2663.48 1517.64 2663.48 1517.67 2663.48C1520.97 2664.02 1526.42 2740.85 1532.65 2874.63C1534.91 2900.48 1540.5 2925.66 1547.39 2954.9C1554.58 2985.32 1562.49 3014.75 1571.38 3047.9C1578.08 3072.85 1585.59 3099.84 1591.55 3126.74C1593.42 3135.07 1595.31 3143.95 1596.25 3153.37C1596.57 3156.1 1596.76 3159.46 1596.39 3163.39C1597.28 3165.14 1595.58 3169.34 1590.43 3175.07V3175.07C1580.39 3180.9 1569.4 3179.92 1561.47 3173.37V3173.37C1559.01 3171.29 1557.89 3169.89 1557.57 3169.88C1559.13 3171.17 1561.37 3170.83 1565.41 3169.42H1565.41C1567.06 3167.09 1567.82 3166.38 1567.48 3165.67C1567.51 3167 1568.74 3169.46 1569.97 3173.33V3173.33C1574.02 3183.37 1572.31 3196.44 1561.97 3206.72V3206.72C1550.18 3212.97 1538.44 3211.07 1531.04 3204.36V3204.36C1528.22 3202.07 1526.49 3200.26 1525.34 3199.66H1525.34C1524.94 3200.04 1525.8 3199.59 1528.79 3199.47V3199.47C1531.49 3196.56 1532.68 3197.17 1530.81 3199.19C1530.12 3201.61 1529.26 3205.67 1526.9 3210.83C1526.22 3212.23 1525.38 3213.53 1524.39 3214.71C1520.87 3218.89 1515.47 3221.56 1508.72 3222C1497.43 3220.63 1489.74 3215.57 1485.08 3211.33C1426.38 3166.73 1381.27 3109.36 1347.87 3050.36C1312.57 2987.93 1289.97 2924.54 1275.1 2870.05C1253.47 2738.94 1243.01 2664.06 1246.21 2663.48C1249.41 2662.9 1265.97 2736.63 1291.73 2866.13V2866.13C1308.09 2918.97 1331.53 2980.15 1366.49 3039.63C1399.64 3096.09 1443.21 3150.79 1498.89 3192.79C1504.65 3196.18 1508.06 3199.72 1509.67 3198.89C1507.79 3199.52 1506.9 3199.67 1506.47 3200.08C1506.35 3200.2 1506.26 3200.33 1506.2 3200.5C1506.94 3199.44 1507.34 3196.53 1508.73 3192.3C1508.67 3188.65 1512.14 3183.04 1520.37 3177.93V3177.93C1527.93 3176.03 1533.99 3177.15 1537.72 3180.15H1537.72C1541.56 3182.71 1544.07 3185.1 1545.79 3186.59V3186.59C1547.9 3187.76 1550.06 3189.47 1548.1 3188.32H1548.1C1549.88 3189.46 1549.02 3184.96 1548.23 3180.69C1547.29 3178.15 1545.76 3174.34 1544.81 3168.99C1543.68 3162.9 1546.08 3156.29 1552.14 3150.81V3150.81C1559.11 3147.32 1565.42 3147.49 1569.99 3150.72V3150.72C1573.53 3153.21 1575.53 3155.29 1576.51 3156.24C1576.77 3156.9 1578.18 3157.59 1576.82 3156.92C1573.94 3160.94 1572.68 3161.93 1573.89 3160.86C1574.1 3159.67 1573.92 3157.84 1573.76 3155.45C1573.11 3147.76 1571.43 3139.75 1569.7 3131.46C1564.19 3105.34 1557.05 3078.42 1550.71 3053.27C1542.36 3020.15 1534.87 2989.98 1528.34 2959.17C1522.03 2929.53 1516.99 2902.93 1515.44 2875.5C1513.55 2741.07 1514.34 2664.11 1517.6 2663.48C1517.63 2663.47 1517.63 2663.48 1517.63 2663.48L1517.64 2663.48Z" fill="black"/>
|
|
||||||
<path d="M2054.36 2616.63C2054.36 2616.63 2054.36 2616.63 2054.39 2616.62C2056.19 2615.89 2070.04 2637.19 2094.89 2678.94C2109.22 2707.44 2132.01 2758.35 2129.26 2813.73C2126.35 2866.49 2129.91 2919.11 2136.27 2983.73C2138.7 3008.27 2141.56 3033.66 2145.95 3058.66C2147.37 3066.7 2148.83 3074.55 2150.94 3081.92C2153.48 3086.92 2152.68 3089.64 2151.85 3087.1V3087.1C2150.35 3086.42 2149.64 3086.43 2147.76 3086.96C2148.59 3086.81 2149.83 3084.69 2152.36 3081.82C2154.18 3079.26 2156.95 3075.55 2161.56 3071.71V3071.71C2167.24 3067.27 2175.05 3066.8 2183.03 3071.14V3071.14C2189.11 3077.02 2191.46 3083.31 2190.86 3088.36C2190.8 3093.49 2190.09 3097.39 2189.91 3100.1C2189.14 3103.56 2191.72 3107.99 2194.93 3108.22C2193.44 3110.41 2195.34 3107.08 2199.65 3103.9C2200.36 3103.37 2201.14 3102.85 2201.98 3102.36C2204.18 3100.03 2207.36 3096.8 2212.18 3093.66V3093.66C2217.35 3090.16 2224.54 3089.74 2232.22 3093.32V3093.32C2239.64 3099.62 2242.27 3105.64 2242.32 3108.84V3108.84C2243.94 3113.56 2244.7 3117.24 2245.92 3119.33H2245.92C2246.6 3118.44 2244.84 3119 2239.24 3117.9C2240.48 3118.95 2242.2 3113.83 2247.17 3108.21C2313.25 3000.93 2319.46 2871.49 2314.9 2781.07C2297.57 2668.78 2289.5 2605.08 2292.54 2604.55C2295.58 2604.02 2309.48 2666.75 2331.2 2779.09C2339.6 2871.29 2335.62 3005.12 2266.47 3120.62C2263.84 3126.17 2258.15 3134.43 2246.52 3139.76V3139.76C2235.07 3140.6 2227.55 3136.27 2225.41 3129.88C2222.7 3124.33 2221.47 3119.55 2220.39 3116.09C2218.14 3112.39 2218.74 3110.5 2219.99 3112.94V3112.94C2222.91 3113.55 2223.8 3114.03 2224.18 3113.43C2222.87 3114.01 2221.12 3116.14 2218.22 3118.84C2217.57 3119.81 2216.8 3120.78 2215.9 3121.71C2210.47 3127.42 2200.54 3132.07 2187.13 3129.99C2174.17 3124.43 2166.53 3112.21 2166.89 3098.57C2167.2 3093.95 2167.9 3090.58 2167.82 3088.37C2167.22 3087.43 2167.96 3087.26 2169.25 3089.56L2169.25 3089.56C2172.81 3090.59 2174.25 3090.97 2175.57 3089.9C2174.45 3090.47 2173.01 3092.84 2170.38 3095.95C2168.41 3098.82 2165.16 3102.7 2159.8 3106.38C2152.56 3110.22 2144.7 3109.78 2138.18 3105.33L2138.18 3105.33C2130.69 3097.78 2128.79 3091.01 2129.09 3088.03V3088.03C2126.7 3079.31 2125.14 3070.69 2123.79 3062.43C2119.5 3036.46 2116.88 3010.52 2114.8 2985.7C2109.33 2920.88 2107.01 2866.34 2111.71 2812.49C2116.41 2763.32 2096.79 2712.68 2084.96 2683.93C2063.44 2641.21 2052.84 2617.95 2054.33 2616.66V2616.66C2054.36 2616.65 2054.36 2616.65 2054.36 2616.65L2054.36 2616.63Z" fill="black"/>
|
|
||||||
<path d="M1565.2 3063.14C1564.91 3065.73 1555.96 3066.2 1541.37 3069.17C1525.48 3072.41 1508.74 3077.63 1488.07 3087.53C1480.4 3091.19 1473 3095.12 1465.92 3099.1C1438.07 3119.19 1417.43 3130.85 1415.06 3127.79C1412.69 3124.73 1429.23 3107.59 1456.24 3085.16C1463.45 3080.3 1471.31 3075.72 1479.69 3071.69C1501.77 3061.09 1522.77 3056.66 1540.11 3056.79C1556.81 3056.91 1565.43 3061.05 1565.2 3063.14V3063.14Z" fill="black"/>
|
|
||||||
<path d="M2297.82 3016.57C2298.41 3019.14 2289.95 3024.6 2272.7 3028.14C2254.99 3031.77 2231.89 3032.36 2206.84 3026.95C2194.91 3024.37 2183.64 3020.67 2173.35 3016.16C2144.06 2998.71 2126.51 2984.91 2128.57 2981.06C2130.62 2977.21 2151.75 2984.02 2181.57 2998.09C2191.34 3001.25 2201.5 3004.04 2212.24 3006.34C2255.38 3015.56 2296.57 3011.08 2297.82 3016.57V3016.57Z" fill="black"/>
|
|
||||||
<defs>
|
|
||||||
<filter id="filter0_f_2_3" x="951.462" y="1473.2" width="199.468" height="216.64" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="10.3119" result="effect1_foregroundBlur_2_3"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter1_f_2_3" x="1135.42" y="1676.67" width="94.502" height="96.079" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="4.72782" result="effect1_foregroundBlur_2_3"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter2_f_2_3" x="2224.19" y="1317.8" width="199.468" height="216.64" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="10.3119" result="effect1_foregroundBlur_2_3"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter3_f_2_3" x="2145.2" y="1521.27" width="94.5021" height="96.079" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="4.72782" result="effect1_foregroundBlur_2_3"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter4_f_2_3" x="1781.61" y="1777.56" width="58.7359" height="38.5579" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="2.52106" result="effect1_foregroundBlur_2_3"/>
|
|
||||||
</filter>
|
|
||||||
<radialGradient id="paint0_radial_2_3" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(1760.99 1829.81) rotate(-0.182296) scale(306.481 287.176)">
|
|
||||||
<stop stop-color="#CC3100"/>
|
|
||||||
<stop offset="1" stop-color="#DE6B00"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint1_radial_2_3" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(2373.33 907.327) rotate(63.7909) scale(608.272 241.85)">
|
|
||||||
<stop stop-color="#FF927A"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint2_radial_2_3" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(785.008 1066.98) rotate(-157.738) scale(359.552 439.05)">
|
|
||||||
<stop stop-color="#FF927A"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint3_linear_2_3" x1="1257.34" y1="3813.75" x2="1136.44" y2="3481.28" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint4_linear_2_3" x1="2481.02" y1="3700.43" x2="2528.01" y2="3388.4" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint5_linear_2_3" x1="1465.89" y1="3071.73" x2="1527.85" y2="3160.89" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint6_linear_2_3" x1="2205.57" y1="3007.9" x2="2200.48" y2="3085.58" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 27 KiB |
|
@ -1,73 +0,0 @@
|
||||||
<svg width="2959" height="3706" viewBox="0 0 2959 3706" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path opacity="0.997" d="M316.789 2931.12C315.488 2929.29 342.101 2913.78 372.838 2868.23C384.205 2851.41 395.682 2829.37 402.48 2802.88C407.785 2782.32 410.27 2759.1 408.909 2733.66C407.69 2710.88 403.393 2686.99 395.976 2661.83V2661.83C382.3 2615.37 359.257 2568.62 326.569 2519.31C298.838 2477.58 265.182 2435.96 225.052 2395.73C208.608 2379.25 191.087 2363.05 172.444 2347.71C157.209 2335.18 141.225 2323.1 124.379 2312.5C111.765 2304.63 99.0872 2297.4 86.1465 2292.93C81.4965 2291.35 77.2099 2290.09 73.3454 2289.68C70.3614 2289.5 68.2282 2289.3 67.36 2289.79C67.103 2290.02 66.986 2289.93 67.7268 2289.46C67.8742 2288.79 67.916 2289.67 67.402 2291.25V2291.25C66.8491 2293.83 67.2734 2297.48 67.8385 2301.99C68.763 2308.14 70.6571 2314.59 72.9592 2321.43V2321.43C79.957 2342.07 90.3586 2362.14 101.941 2382.98C118.976 2413.51 138.274 2443.25 159.063 2473.54C239.086 2574.41 349.687 2660.96 481.224 2708.82C588.471 2748.15 706.505 2762.42 824.643 2753.29C866.817 2749.58 908.547 2739.08 939.471 2714.96C946.162 2709.88 952.392 2704.14 958.034 2697.88C971.642 2682.77 981.817 2664.63 986.785 2645.36C993.4 2620.4 992.269 2593.07 983.767 2568.69C975.601 2545.97 961.347 2525.28 942.318 2513.53C918.401 2498.17 890.181 2489.01 861.448 2485.7C828.124 2482.05 793.861 2487.36 765.252 2502.39C748.435 2511.06 733.146 2523.06 719.946 2537.05C703.762 2554.16 690.691 2574.62 680.006 2596.35C647.54 2662.01 637.627 2738.34 633.783 2811.39C631.492 2858.76 639.748 2905.63 657.74 2947.16C674.348 2985.79 699.212 3020.25 727.85 3049.36C755.245 3077.18 786.301 3100.41 818.625 3119.3C845.995 3135.23 873.674 3148.13 901.953 3156.71C916.938 3161.58 935.105 3161.55 953.657 3162.06C981.591 3162.53 1010.48 3161.41 1037.44 3160.48C1120.97 3157.55 1186.59 3155.58 1255.49 3159.41C1258.01 3159.67 1260.93 3159.01 1263.71 3157.85C1267.08 3156.47 1270.42 3153.91 1273.73 3150.93C1282.8 3142.7 1289.74 3131.12 1296.02 3119.67C1304.49 3103.94 1311.23 3087.27 1316.96 3071.71C1324.16 3052.16 1330.13 3032.79 1335.12 3015.45C1347.23 2973.37 1356.5 2932.2 1361.78 2909.03C1368.62 2876.64 1372.92 2860.42 1374.61 2860.7C1376.3 2860.97 1375.37 2877.73 1371.82 2910.71V2910.71C1368.73 2935.64 1362.81 2975.3 1352.55 3019.95C1348.43 3037.86 1343.3 3057.89 1336.77 3078.48C1331.6 3094.81 1325.21 3112.65 1316.67 3130.22C1310.63 3142.89 1302.73 3156.75 1290.99 3168.72C1286.56 3173.24 1281.1 3177.52 1274.47 3180.82C1268.55 3183.74 1261.74 3185.39 1254.47 3185.26C1186.38 3183.73 1122.9 3187.53 1038.93 3192.43C1012.03 3194.02 982.698 3195.8 953.459 3195.94C935.016 3196.23 913.838 3196.25 892.086 3190.34C860.467 3181.34 829.909 3167.88 800.35 3151.26C765.137 3131.53 731.042 3106.84 700.477 3076.77C668.369 3045.23 640.218 3007.16 620.629 2963.48C599.562 2916.19 589.495 2863.25 591.598 2809.55C594.222 2733.83 604.742 2651.95 640.214 2577.11C652.15 2552.07 667.567 2527.86 687.265 2506.54C703.474 2489.04 722.685 2473.88 744.379 2462.43C781.862 2442.93 824.765 2435.76 866.445 2440.38C901.541 2444.1 936.315 2455.43 966.972 2474.79C996.013 2493.63 1016.6 2522.16 1027.31 2553.48V2553.48C1038.91 2586.65 1040.44 2622.98 1031.5 2657.13C1024.34 2683.95 1010.73 2708.48 992.439 2728.83C984.857 2737.27 976.473 2744.98 967.414 2751.83C926.027 2782.52 876.166 2796.04 828.18 2799.26C703.899 2808.78 579.433 2793.06 465.731 2750.76C325.525 2698.22 209.253 2605.43 125.942 2497.69C104.813 2466.19 84.9637 2434.73 67.2313 2402.07C55.3916 2380.34 44.3348 2357.9 36.3566 2333.64V2333.64C33.6731 2325.54 31.3734 2316.86 30.0211 2307.57C28.9492 2300.97 28.6637 2293.32 29.9722 2284.91C30.8048 2278.53 33.7282 2271.54 39.1215 2264.8C44.6302 2258.8 51.1436 2255 57.9177 2253.4C65.6381 2251.65 72.5521 2251.65 78.3106 2252.64C85.8795 2253.76 92.7209 2255.75 98.8267 2258.08C115.658 2264.44 130.588 2273.11 144.014 2282.01C162.336 2294.05 179.275 2307.32 195.03 2320.84C214.373 2337.42 232.368 2354.74 249.101 2372.26C289.906 2414.94 323.84 2459.09 351.487 2503.24C384.143 2555.26 406.809 2605.59 419.621 2655.32C426.578 2682.37 430.13 2708.29 430.416 2732.98C430.737 2760.6 426.738 2785.78 419.794 2807.86C410.802 2836.34 396.954 2859.18 383.542 2876.09C346.533 2922.69 316.167 2930.24 316.792 2931.12L316.789 2931.12Z" fill="black"/>
|
|
||||||
<path d="M1168.86 2147.45C1168.86 2147.45 1174.91 2189.77 1126.55 2316.71C1078.19 2443.66 1075.16 2733.81 1050.98 2797.29C1026.8 2860.76 893.814 3072.33 924.039 3259.73C954.264 3447.12 1102.37 3713.1 1283.71 3646.6C1465.06 3580.11 1428.79 3592.2 1428.79 3592.2C1428.79 3592.2 1954.71 3707.05 2302.29 3507.57C2380.88 3543.84 2429.23 3574.06 2547.11 3504.55C2664.99 3435.03 2725.44 3244.61 2722.41 3114.65C2719.39 2984.68 2532 2700.57 2510.84 2640.12C2489.68 2579.67 2411.1 2283.46 2371.81 2159.54C2332.51 2035.62 2362.74 2014.46 2362.74 2014.46L1168.86 2147.45Z" fill="#DE5700" stroke="black" stroke-width="46.0804"/>
|
|
||||||
<path d="M2910.99 15.367C2810.67 16.4868 2399.36 32.4575 2314.62 125.748C2227.59 221.545 2173.88 368.999 2157.21 419.478C2059.12 356.561 1915.41 355.12 1915.41 355.12C1915.41 355.12 2000.05 327.92 2090.72 303.741C1933.55 249.336 1731.05 297.692 1731.05 297.692C1731.05 297.692 1816.06 254.536 1897.66 181.997C1770.72 215.244 1628.28 231.198 1537.61 285.603C1534.34 256.983 1479.51 292.115 1564.25 174.208C1331.52 231.635 1168.86 376.283 1069.11 460.912C1081.2 385.351 1085.97 396.401 1122.24 311.772C984.85 406.889 945.872 455.871 915.959 529.819C884.785 472.227 802.353 331.66 698.786 248.138C566.279 141.277 -48.0541 314.703 20.3368 442.936C88.7277 571.169 253.044 550.321 295.788 819.61C338.532 1088.9 643.216 1098.74 643.216 1098.74C645.435 1097.95 647.639 1097.05 649.836 1096.13C627.255 1167.82 607.109 1272.5 591.923 1444.97C519.258 1553.97 513.208 1597.36 504.66 1637.96C575.188 1603.77 583.374 1556.11 634.667 1543.29C589.785 1618.09 587.651 1720.68 606.886 1883.1C643.218 1791.2 641.076 1793.34 679.546 1765.56C690.232 1874.55 713.747 1934.4 741.53 1968.59C752.217 1908.75 784.275 1885.25 784.275 1885.25C784.275 1885.25 805.648 2015.62 867.627 2105.38C880.451 2026.3 895.409 2013.48 895.409 2013.48C895.409 2013.48 1143.32 2338.33 1775.94 2304.14C2408.55 2269.94 2588.08 1833.95 2588.08 1833.95C2588.08 1833.95 2600.91 1889.52 2600.91 1910.89C2647.93 1842.5 2677.85 1701.44 2677.85 1701.44C2677.85 1701.44 2712.04 1782.65 2703.49 1833.95C2741.96 1769.83 2750.51 1611.68 2733.41 1539.02C2793.25 1603.13 2844.55 1624.51 2844.55 1624.51C2844.55 1624.51 2712.04 1393.69 2707.76 1355.22C2703.49 1316.75 2801.81 1410.78 2801.81 1410.78C2801.81 1410.78 2740.21 1308.23 2724.86 1280.41C2667.66 1176.75 2613.36 987.392 2537.11 859.689C2601.1 818.088 2795.1 718.757 2787.56 503.664C2778.95 258.194 2898.72 176.103 2940.26 51.0386C2948.69 25.6348 2936.56 15.0816 2910.99 15.367V15.367Z" fill="#DE5700"/>
|
|
||||||
<path d="M1168.86 2147.45C1168.86 2147.45 1174.91 2189.77 1126.55 2316.71C1078.19 2443.66 1075.16 2733.81 1050.98 2797.29C1026.8 2860.76 893.814 3072.33 924.039 3259.73C954.264 3447.12 1102.37 3713.1 1283.71 3646.6C1465.06 3580.11 1428.79 3592.2 1428.79 3592.2C1428.79 3592.2 1954.71 3707.05 2302.29 3507.57C2380.88 3543.84 2429.23 3574.06 2547.11 3504.55C2664.99 3435.03 2725.44 3244.61 2722.41 3114.65C2719.39 2984.68 2532 2700.57 2510.84 2640.12C2489.68 2579.67 2411.1 2283.46 2371.81 2159.54C2332.51 2035.62 2362.74 2014.46 2362.74 2014.46L1168.86 2147.45Z" fill="#DE5700"/>
|
|
||||||
<path d="M1948.55 2060.6L1565.32 2103.28C1414.45 2137.89 1297.2 2180.18 1297.2 2180.18C1297.2 2180.18 1228.81 2594.8 1241.64 2710.21C1254.46 2825.62 1181.79 3000.87 1220.26 3176.12C1253.86 3329.16 1320.07 3491.98 1566.89 3613.34C1718.29 3630.31 1968.48 3639.97 2185.07 3561.45C2288.91 3477.48 2362.98 3368.43 2391.46 3282.98C2455.58 3090.63 2378.64 2757.23 2348.72 2688.84C2318.79 2620.45 2352.99 2406.72 2186.29 2163.08C2140.34 2095.93 2052.15 2067.14 1948.55 2060.6V2060.6Z" fill="#F7EDE9"/>
|
|
||||||
<path opacity="0.6" d="M2910.99 15.367C2810.67 16.4868 2399.36 32.4575 2314.62 125.748C2227.59 221.545 2173.88 368.999 2157.21 419.478C2059.12 356.561 1915.41 355.12 1915.41 355.12C1915.41 355.12 2000.05 327.92 2090.72 303.741C1933.55 249.336 1731.05 297.692 1731.05 297.692C1731.05 297.692 1816.06 254.536 1897.66 181.997C1770.72 215.244 1628.28 231.198 1537.61 285.603C1538.99 259.97 1477.23 293.202 1564.25 174.208C1331.52 231.635 1168.86 376.283 1069.11 460.912C1081.2 385.351 1085.97 396.401 1122.24 311.772C984.85 406.889 945.872 455.871 915.959 529.819C884.785 472.227 802.353 331.66 698.786 248.138C566.279 141.277 -48.0541 314.703 20.3368 442.936C88.7277 571.169 253.044 550.321 295.788 819.61C338.532 1088.9 643.216 1098.74 643.216 1098.74C645.435 1097.95 647.639 1097.05 649.836 1096.13C627.255 1167.82 607.109 1272.5 591.923 1444.97C519.258 1553.97 514.209 1598.36 505.661 1638.96C576.188 1604.77 583.374 1556.11 634.667 1543.29C589.785 1618.09 587.651 1720.68 606.886 1883.1C643.218 1791.2 641.076 1793.34 679.546 1765.56C690.232 1874.55 713.747 1934.4 741.53 1968.59C752.217 1908.75 784.275 1885.25 784.275 1885.25C784.275 1885.25 805.648 2015.62 867.627 2105.38C880.451 2026.3 895.409 2013.48 895.409 2013.48C895.409 2013.48 1143.32 2338.33 1775.94 2304.14C2408.55 2269.94 2588.08 1833.95 2588.08 1833.95C2588.08 1833.95 2600.91 1889.52 2600.91 1910.89C2647.93 1842.5 2677.85 1701.44 2677.85 1701.44C2677.85 1701.44 2712.04 1782.65 2703.49 1833.95C2741.96 1769.83 2750.51 1611.68 2733.41 1539.02C2793.25 1603.13 2844.55 1624.51 2844.55 1624.51C2844.55 1624.51 2712.04 1393.69 2707.76 1355.22C2703.49 1316.75 2801.81 1410.78 2801.81 1410.78C2801.81 1410.78 2740.21 1308.23 2724.86 1280.41C2667.66 1176.75 2613.36 987.392 2537.11 859.689C2601.1 818.088 2801.11 718.757 2793.56 503.664C2784.96 258.194 2898.72 176.103 2940.26 51.0386C2948.69 25.6348 2936.56 15.0816 2910.99 15.367V15.367Z" fill="url(#paint0_radial_28_46)"/>
|
|
||||||
<path d="M1793.93 1625.72C1692.31 1626.01 1639.62 1670.45 1602.82 1690.75C1443.85 1877.11 1124.01 1774.44 950.98 1898.07C921.059 1919.44 879.383 2034.85 879.383 2034.85L881.565 2043.13C889.307 2018.8 895.409 2013.48 895.409 2013.48C895.409 2013.48 1143.32 2338.33 1775.94 2304.14C2286.01 2276.56 2501.41 1987.9 2565.77 1877.06C2559.76 1821.08 2542.31 1746.84 2491.91 1744.19C2410.7 1739.91 2075.15 1712.12 1972.56 1656.56C1930.89 1633.98 1863.46 1625.52 1793.93 1625.72V1625.72Z" fill="#F7EDE9"/>
|
|
||||||
<path d="M1670.59 1677.46C1653.7 1635.82 1858.76 1600.28 1862.52 1639.68C1866.61 1682.55 1812.65 1760.58 1785.45 1765.11C1758.24 1769.64 1688.63 1721.93 1670.59 1677.46V1677.46Z" fill="black"/>
|
|
||||||
<g opacity="0.8" filter="url(#filter0_f_28_46)">
|
|
||||||
<path d="M1795.15 1641.88C1797.06 1634.19 1809.39 1629.26 1822.69 1630.88C1835.98 1632.49 1845.21 1640.04 1843.29 1647.73C1841.38 1655.43 1829.05 1660.35 1815.75 1658.74C1802.45 1657.12 1793.23 1649.57 1795.15 1641.88Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path opacity="0.8" d="M1797.09 1642.11C1798.83 1635.16 1810.16 1630.73 1822.38 1632.22C1834.6 1633.7 1843.1 1640.55 1841.35 1647.5C1839.61 1654.46 1828.28 1658.89 1816.06 1657.4C1803.83 1655.91 1795.34 1649.07 1797.09 1642.11Z" fill="#DEDEDE"/>
|
|
||||||
<path d="M2839.03 126.979C2750.83 205.43 2490.04 199.914 2389.32 331.49C2311.81 432.749 2293.15 545.208 2382.91 699.087C2429.76 779.407 2491.15 828.243 2540.37 857.529C2656.85 814.594 2791.93 737.805 2791.56 525.669C2791.4 431.967 2868.09 265.271 2862.97 214.318C2865.39 180.456 2897.45 75.0209 2839.03 126.979V126.979Z" fill="url(#paint1_radial_28_46)"/>
|
|
||||||
<path d="M135.341 546.877C204.087 610.736 275.71 693.122 295.788 819.61C335.05 1066.97 582.025 1072.54 635.159 1095.33C678.647 1047.5 747.7 954.793 774.947 808.594C815.021 593.571 743.572 440.231 630.27 356.086C544.242 292.197 465.345 399.217 373.009 410.597C226.391 428.666 137.346 442.883 104.936 460.272C73.1798 477.31 100.208 513.662 135.341 546.877V546.877Z" fill="url(#paint2_radial_28_46)"/>
|
|
||||||
<path d="M2910.99 15.367C2810.67 16.4868 2399.36 32.4575 2314.62 125.748C2227.59 221.545 2173.88 368.999 2157.21 419.478C2059.12 356.561 1915.41 355.12 1915.41 355.12C1915.41 355.12 2000.05 327.92 2090.72 303.741C1933.55 249.336 1731.05 297.692 1731.05 297.692C1731.05 297.692 1816.06 254.536 1897.66 181.997C1770.72 215.244 1628.28 231.198 1537.61 285.603C1544.1 286.111 1479.62 292.085 1564.25 174.208C1331.52 231.635 1168.86 376.283 1069.11 460.912C1081.2 385.351 1085.97 396.401 1122.24 311.772C984.85 406.889 945.872 455.871 915.959 529.819C884.785 472.227 802.353 331.66 698.786 248.138C566.279 141.277 -48.0541 314.703 20.3368 442.936C88.7277 571.169 253.044 550.321 295.788 819.61C338.532 1088.9 643.216 1098.74 643.216 1098.74C645.435 1097.95 647.639 1097.05 649.836 1096.13C627.255 1167.82 607.109 1272.5 591.923 1444.97C519.258 1553.97 513.208 1598.36 504.66 1638.96C575.188 1604.77 583.374 1556.11 634.667 1543.29C589.785 1618.09 587.651 1720.68 606.886 1883.1C643.218 1791.2 641.076 1793.34 679.546 1765.56C690.232 1874.55 713.747 1934.4 741.53 1968.59C752.217 1908.75 784.275 1885.25 784.275 1885.25C784.275 1885.25 805.648 2015.62 867.627 2105.38C880.451 2026.3 895.409 2013.48 895.409 2013.48C895.409 2013.48 1143.32 2338.33 1775.94 2304.14C2408.55 2269.94 2588.08 1833.95 2588.08 1833.95C2588.08 1833.95 2600.91 1889.52 2600.91 1910.89C2647.93 1842.5 2677.85 1701.44 2677.85 1701.44C2677.85 1701.44 2712.04 1782.65 2703.49 1833.95C2741.96 1769.83 2750.51 1611.68 2733.41 1539.02C2793.25 1603.13 2844.55 1624.51 2844.55 1624.51C2844.55 1624.51 2712.04 1393.69 2707.76 1355.22C2703.49 1316.75 2801.81 1410.78 2801.81 1410.78C2801.81 1410.78 2740.21 1308.23 2724.86 1280.41C2667.66 1176.75 2613.36 987.392 2537.11 859.689C2601.1 818.088 2797.11 782.772 2789.56 567.679C2780.95 322.209 2898.72 176.103 2940.26 51.0386C2948.69 25.6348 2936.56 15.0816 2910.99 15.367V15.367Z" stroke="black" stroke-width="30.7203" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M1174.32 3623.87C1099.51 3499.91 1063.06 3415.08 1057.84 3359.39C1053.03 3308.09 1046.62 3246.12 1083.48 3276.57C1094.17 3231.69 1092.03 3206.04 1119.82 3218.87C1147.6 3231.69 1166.83 3259.47 1166.83 3259.47C1166.83 3259.47 1162.56 3195.36 1190.34 3216.73C1241.43 3247.48 1332.69 3536.32 1322.06 3618.13C1310.38 3708.02 1240.21 3727.57 1174.32 3623.87V3623.87Z" fill="url(#paint3_linear_28_46)" stroke="black" stroke-width="23.0402"/>
|
|
||||||
<path d="M2564.78 3516.43C2617.78 3381.7 2639.52 3291.97 2635.35 3236.19C2631.5 3184.81 2627.45 3122.63 2596.2 3158.83C2578.16 3116.37 2575.97 3090.73 2550.72 3108.02C2525.48 3125.31 2511.17 3155.92 2511.17 3155.92C2511.17 3155.92 2504.65 3092 2480.83 3117.72C2435.61 3156.59 2393.99 3456.62 2418.16 3535.5C2444.71 3622.17 2517.17 3629.7 2564.78 3516.43V3516.43Z" fill="url(#paint4_linear_28_46)" stroke="black" stroke-width="23.0402"/>
|
|
||||||
<path d="M1547.64 2230.3C1547.64 2230.3 1409.61 2394.34 1345.59 2428.35C1281.58 2462.36 1537.64 2590.38 1537.64 2590.38C1537.64 2590.38 1687.67 2386.34 1693.67 2308.32L1699.68 2230.3H1547.64Z" fill="#F7EDE9"/>
|
|
||||||
<path d="M1552.45 2225.31C1571.48 2258.43 1605.03 2280.42 1639.99 2293.91C1656.36 2300.07 1673.27 2305.1 1690.57 2307.77C1699.84 2271.3 1705.7 2233.76 1705.72 2196.08C1705.12 2188.67 1704.84 2178.86 1697.33 2174.95C1689.06 2172.5 1682.13 2179.41 1675.63 2183.33C1679.28 2173.01 1676.81 2160.78 1670.04 2152.31C1662.92 2145.38 1653.3 2153.18 1648.01 2158.59C1642.73 2163.3 1639.14 2169.69 1633.7 2174.14C1630.98 2168.39 1635.15 2158.49 1628.69 2153.34C1621.45 2147.74 1614.83 2157.89 1609.5 2161.85C1589.24 2181.83 1571.08 2203.83 1552.45 2225.31V2225.31Z" fill="url(#paint5_linear_28_46)"/>
|
|
||||||
<path d="M1253.67 2495.08C1253.67 2495.08 1253.7 2495.06 1253.71 2494.98C1253.73 2494.91 1253.75 2494.77 1253.73 2494.55C1253.85 2494.31 1254.06 2494 1254.36 2493.63C1254.95 2492.9 1255.9 2491.91 1257.19 2490.66C1259.68 2488.27 1263.48 2484.94 1268.52 2480.67C1277.89 2472.76 1291.17 2462 1308.59 2447.97C1332.04 2429.09 1377.21 2393.23 1416.14 2359.67C1435.84 2342.71 1453.06 2323.43 1472.83 2300.71C1493.32 2277.11 1512.59 2253.5 1534.3 2226.92C1550.64 2206.9 1568.16 2185.04 1586.51 2164.5C1592.19 2158.11 1598.29 2151.39 1605.38 2145.13C1607.41 2143.27 1610.03 2141.16 1613.44 2139.16C1614.53 2138.47 1616.19 2137.74 1618.44 2137.08C1620 2136.39 1622.68 2136.37 1626.4 2137.18C1631.32 2138.25 1636.42 2142 1640.22 2148.66C1642.23 2154.09 1642.53 2158.57 1641.93 2161.68C1641.68 2164.89 1641.2 2166.62 1641.38 2166.88C1641.51 2164.86 1639.93 2163.24 1636.43 2160.78C1633.57 2160.8 1632.55 2160.6 1632.18 2161.3C1633.23 2160.49 1634.51 2158.06 1636.94 2154.8C1639.08 2151.42 1642.54 2147.44 1647.9 2143.9C1654.96 2140.17 1662.36 2139.65 1668.71 2141.79C1674.35 2143.23 1679.64 2147.46 1683.14 2154.38C1685.12 2160.15 1685.36 2164.93 1684.86 2168.28C1684.65 2171.9 1684.19 2174.36 1684.38 2175.65C1684.92 2175.76 1684.05 2175.31 1682.21 2172.96C1680.34 2172.13 1679.39 2171.73 1679.02 2171.98C1678.97 2172.08 1679.56 2171.81 1680.8 2171.48C1683.17 2170.62 1686.96 2168.95 1692.53 2167.86C1693.69 2167.59 1695.01 2167.47 1696.48 2167.52C1698.3 2167.58 1700.34 2167.9 1702.57 2168.52C1707.01 2170.25 1710.27 2172.9 1712.21 2176.09C1717.7 2186.05 1718.08 2195.25 1717.36 2201.51C1715.45 2275.24 1695.21 2345.41 1666.81 2407C1636.86 2472 1598.69 2527.26 1563.18 2571.11C1524.08 2619.42 1486.97 2655.52 1460.54 2678.9C1446.05 2691.72 1434.5 2700.95 1426.26 2707C1421.97 2710.14 1418.65 2712.38 1416.29 2713.78C1415.08 2714.49 1414.14 2714.98 1413.46 2715.25C1413.12 2715.38 1412.84 2715.46 1412.63 2715.49C1412.53 2715.5 1412.44 2715.5 1412.37 2715.49C1412.3 2715.47 1412.24 2715.44 1412.21 2715.4C1412.17 2715.35 1412.14 2715.31 1412.16 2715.22C1412.16 2715.15 1412.17 2715.06 1412.21 2714.96C1412.28 2714.77 1412.41 2714.51 1412.62 2714.21C1413.02 2713.6 1413.68 2712.78 1414.6 2711.74C1416.38 2709.72 1419.19 2706.81 1422.87 2703.08C1430.3 2695.57 1440.14 2685.87 1453.75 2671.8C1477.95 2646.79 1512.96 2609.16 1549.7 2560.56C1583.1 2516.35 1619.21 2461.46 1647.22 2398.15C1673.71 2338.25 1692.69 2270.9 1694.25 2201.13C1693.64 2194.48 1694.52 2189.65 1692.9 2188.82C1693.08 2189.33 1693.81 2189.75 1695.21 2190.46C1695.85 2190.55 1696.22 2190.64 1696.36 2190.69C1696.47 2190.73 1696.44 2190.74 1696.24 2190.7C1694.94 2190.72 1692.35 2192.09 1688.11 2193.43C1686.33 2194.1 1683.84 2194.74 1680.61 2195.05C1677.54 2195.49 1673.78 2194.67 1669.64 2192.37C1663.69 2187.36 1661.05 2181.78 1661.31 2177V2177C1661.15 2172.39 1661.62 2168.95 1661.82 2166.69C1661.73 2164.15 1662.06 2162.83 1661.8 2163.16C1662.81 2164.08 1662.41 2164.31 1661.87 2163.8C1660.62 2163.58 1659.43 2163.35 1659.67 2163.67C1658.82 2163.83 1657.66 2165.67 1655.61 2168.16V2168.16C1654.1 2170.4 1651.9 2173.87 1648.11 2177.76C1643.82 2182.24 1637.07 2184.15 1629.07 2182.43C1622.17 2178.82 1618.62 2173.59 1618.58 2168V2168C1618.53 2163.66 1619.06 2160.83 1619.25 2159.47C1619.14 2157.69 1619.49 2157.05 1619.48 2158C1620.8 2159.19 1620.41 2159.57 1619.62 2158.83C1622.22 2159.29 1623.69 2159.41 1624.13 2159.02C1624.75 2158.78 1624.9 2158.78 1624.53 2158.91C1623.44 2159.44 1622.06 2160.64 1620.22 2162.16C1614.36 2167.19 1608.83 2173.23 1603.11 2179.48C1585.13 2199.21 1567.45 2220.73 1550.73 2240.56C1528.73 2266.69 1508.62 2290.39 1487.43 2313.69C1467.11 2336.07 1448.51 2355.66 1427.18 2372.92C1384.59 2407.27 1342.02 2437.75 1315.01 2456.55C1296.77 2469.25 1282.19 2478.95 1271.97 2485.38C1266.36 2488.91 1262.02 2491.49 1258.97 2493.12C1257.38 2493.97 1256.14 2494.55 1255.26 2494.88C1254.81 2495.05 1254.45 2495.15 1254.19 2495.19C1253.98 2495.1 1253.85 2495.08 1253.77 2495.07C1253.7 2495.07 1253.67 2495.08 1253.67 2495.08L1253.67 2495.08Z" fill="black"/>
|
|
||||||
<path d="M1550.29 2223.04C1552.02 2222.06 1555.96 2226.15 1563.08 2233.04C1570.64 2240.36 1579.91 2248.83 1593.5 2258.19C1600.35 2262.92 1607.58 2267.34 1615.33 2271.58C1622.75 2275.64 1630.22 2279.3 1637.63 2282.7C1670.11 2293.53 1691.56 2303.44 1690.46 2307.15C1689.37 2310.85 1665.88 2307.47 1631.98 2298.68C1623.76 2295.61 1615.41 2291.88 1607.22 2287.42C1598.68 2282.76 1590.69 2277.53 1583.42 2271.78C1569.42 2260.68 1560.14 2248.95 1554.8 2239.31C1549.55 2229.84 1548.78 2223.89 1550.29 2223.04V2223.04Z" fill="black"/>
|
|
||||||
<path d="M2182.1 2821.65C2148.09 2821.91 2115.82 2806.33 2089.83 2785.3C2067.85 2767.28 2048.77 2745.55 2034 2721.26C2022.45 2753.72 2010.59 2786.27 2003.4 2820.03C2001.39 2826.99 2000.64 2839.35 2011.42 2837.84C2021.24 2837.24 2029.53 2831.07 2038.79 2828.73C2036.92 2833.96 2031.26 2838.31 2029.04 2843.95C2024.34 2852.66 2021.14 2866.11 2030.41 2873.05C2042.08 2880.13 2056.74 2876.96 2068.8 2872.51C2076.8 2870.19 2067.29 2882.14 2069.42 2886.32C2067.95 2894.94 2073.56 2906.98 2083.99 2903.55C2096.65 2899.92 2106.5 2890.47 2117.11 2883.12C2140.83 2864.95 2162.39 2844.07 2182.1 2821.65V2821.65Z" fill="url(#paint6_linear_28_46)"/>
|
|
||||||
<path d="M2124.7 2361.37C2124.7 2361.37 2124.69 2361.37 2124.7 2361.37C2126.63 2361.25 2130.12 2386.35 2134.88 2434.81C2135.35 2453.78 2134.73 2477.74 2130.57 2503.41C2127.18 2524.43 2120.99 2548.65 2108.67 2571.61C2096.65 2593.93 2086.27 2617.36 2075.16 2644.03C2064.04 2670.75 2053.24 2698.81 2042.73 2728.46C2034.5 2751.7 2026.3 2775.9 2019.64 2800.39C2017.5 2808.27 2015.49 2816 2014.27 2823.56C2013.89 2825.98 2013.58 2828.06 2013.57 2829.79C2014.02 2831.42 2013.52 2831.12 2012.88 2828.64C2013.06 2828.52 2012.5 2828.22 2011.21 2827.25C2009.87 2826.84 2009.31 2826.6 2009.25 2826.77C2010.06 2826.98 2012.08 2825.6 2015.59 2824.07C2018.33 2822.53 2022.41 2820.34 2028.22 2818.83C2030.63 2818.04 2034.14 2818.05 2038.54 2819.25C2043.23 2821.27 2046.38 2824.16 2047.89 2827.45C2050.9 2835.35 2050.35 2842.05 2047.66 2846.36C2045.41 2850.98 2043.12 2854.21 2041.81 2856.58C2040.65 2859.24 2039.62 2860.95 2040.01 2861.51C2039.43 2861.99 2041.07 2863.68 2042.89 2866.07C2042.2 2865.98 2042.89 2865.88 2043.64 2865.99C2044.95 2866.01 2046.72 2865.44 2049 2864.68C2049.85 2864.39 2050.77 2864.08 2051.77 2863.76C2054.75 2862.59 2059 2861.02 2064.7 2860.23C2070.87 2859.25 2077.55 2861.93 2082.98 2868.44L2082.98 2868.44C2085.37 2872.89 2086.2 2876.48 2085.97 2878.82V2878.82C2086.05 2881.94 2085.82 2884.6 2085.52 2886.78C2084.98 2891.73 2084.11 2895.39 2084.32 2897.81C2084.65 2898.69 2084.3 2898.52 2083.76 2896.92C2082.02 2894.82 2080.59 2893.78 2078.89 2893.67C2078.04 2893.95 2078.68 2893.42 2080.68 2893.01V2893.01C2083.59 2892.01 2086.71 2890.26 2090.18 2888.27L2090.18 2888.27C2140.92 2854.85 2181.84 2810.27 2213.89 2764.4C2248.17 2715.46 2272.77 2664.59 2290.65 2620.8C2322.67 2511.91 2342.43 2450.89 2345.4 2451.7C2348.38 2452.52 2334.32 2515.13 2306.25 2625.93C2289.7 2671.41 2265.85 2724.43 2231.15 2776.22C2198.69 2824.56 2156.17 2871.74 2102.37 2907.71C2098.38 2910.13 2093.86 2912.59 2088.63 2914.6C2086.06 2915.87 2081.86 2916.84 2076.18 2916.55C2071.56 2916.09 2067.33 2913.5 2064.07 2908.9C2061.84 2904.53 2061.06 2900.99 2061.27 2898.63C2061.18 2892.46 2062.1 2887.6 2062.59 2884.02C2062.78 2882.14 2062.96 2880.71 2062.88 2879.75C2062.52 2878.92 2062.91 2879.21 2063.57 2880.99L2063.57 2880.99C2065.95 2882.79 2066.56 2883.6 2067.15 2883.22C2065.73 2883.19 2063.23 2884.37 2059.46 2885.58C2058.49 2885.95 2057.43 2886.34 2056.29 2886.71C2053.25 2887.71 2049.62 2888.62 2045.35 2889.06C2039.02 2889.69 2032.31 2887.55 2026.58 2882.45C2021.64 2878.11 2017.75 2871.14 2016.92 2862.1C2017.1 2855.05 2019.1 2849.42 2021.62 2845.41C2023.87 2841.36 2025.93 2838.6 2026.8 2836.58C2026.66 2835.47 2027.4 2835.63 2027.59 2838.26C2027.8 2839.09 2028.89 2839.83 2030.96 2840.94C2032.77 2841.23 2033.43 2841.45 2033.17 2841.25C2031.91 2841.29 2029.6 2842.82 2025.89 2844.53C2022.89 2846.28 2018.3 2848.41 2011.88 2849.46C2008.88 2849.97 2005.24 2849.48 2001.23 2847.77C1996.95 2845.35 1994.14 2842.37 1992.76 2839.32C1990.7 2834.14 1990.32 2830.66 1990.83 2829.24C1990.95 2825.7 1991.39 2822.55 1991.89 2819.79C1993.44 2810.89 1995.69 2802.43 1997.98 2794.38C2005.13 2769.04 2013.8 2744.45 2022.47 2721.1C2033.56 2691.25 2045.05 2663 2056.94 2636.2C2056.94 2636.2 2056.94 2636.2 2056.94 2636.2C2068.74 2609.56 2080.15 2585.7 2093.32 2563.01C2105.09 2542.96 2111.7 2520.53 2115.92 2500.68C2121.01 2476.68 2122.93 2453.52 2123.78 2435.1C2122.46 2387.18 2122.76 2361.68 2124.68 2361.37L2124.7 2361.37Z" fill="black"/>
|
|
||||||
<path d="M2175 2826.87C2174.44 2829.44 2164.46 2830.8 2147.34 2826.66C2129.78 2822.41 2108.61 2813.13 2088.24 2797.58C2078.48 2790.13 2069.81 2781.92 2062.37 2773.42C2043.37 2745.24 2033.41 2725.37 2036.91 2722.76C2040.4 2720.15 2056.55 2735.24 2077.5 2760.58C2085.04 2767.64 2093.09 2774.53 2101.89 2781.22C2120.61 2795.44 2137.36 2804.74 2152.67 2812.56C2166.96 2819.86 2175.65 2823.9 2175 2826.87V2826.87Z" fill="black"/>
|
|
||||||
<path opacity="0.969" d="M2271.02 1481.65C2270.98 1481.7 2270.96 1481.76 2270.93 1481.82C2270.3 1482.5 2269.52 1483.07 2268.45 1483.4C2266.31 1484.06 2263.43 1484.13 2259.51 1483.48C2251.72 1482.17 2240.55 1478.45 2225.78 1472.61C2195.05 1460.45 2150 1440.05 2094.71 1417.03C2083.82 1413.11 2066.88 1406.63 2047.14 1395.61C2042.15 1394.09 2032.43 1386.77 2019.12 1373.26C2005.68 1360.16 2000.71 1338.54 2004.65 1309.48V1309.48C2015.17 1285.72 2024.38 1273.62 2031.14 1272.29C2040.81 1265.93 2048.46 1262.35 2053.94 1260.86C2072.42 1254.93 2088.82 1252.2 2103.52 1250.56C2122.55 1247.86 2141.12 1246.81 2159.25 1246.97C2184.24 1247.19 2208.15 1249.72 2230.89 1253.25C2276.78 1260.23 2318.45 1271.46 2353.6 1283.35C2444.6 1317.86 2493.15 1346 2484.81 1358.31C2477.63 1368.89 2429.3 1366.68 2351.7 1352.28C2319.35 1347.49 2279.06 1341.07 2239.34 1336.79C2204.14 1333.35 2168.81 1329.86 2134.1 1332.29C2133.42 1332.34 2132.74 1332.39 2132.06 1332.44C2117.45 1333.99 2104.62 1334.71 2092.5 1336.9C2088.86 1337.69 2086.18 1337.74 2084.54 1337.85C2083.85 1338.92 2083.97 1336.16 2085.92 1331.01C2085.96 1323.35 2084.56 1319.35 2081.58 1317.6C2079.4 1317.18 2079.97 1318.08 2081.88 1320.29C2089.26 1327.57 2100.53 1333.47 2111.5 1339.38C2169.79 1370.45 2212.91 1401.57 2241.33 1428.53C2254.76 1441.26 2263.67 1452.08 2268.92 1460.88C2271.53 1465.26 2272.96 1468.94 2273.54 1472.03C2273.83 1473.57 2273.79 1474.92 2273.58 1476.1C2273.39 1476.64 2273.09 1477.16 2272.82 1477.63V1477.63C2283.36 1455.58 2295.93 1429.3 2306.47 1407.26C2306.56 1407.07 2306.56 1407.08 2306.47 1407.26C2329.9 1358.27 2248.02 1529.51 2271.45 1480.52C2271.32 1480.9 2271.19 1481.31 2271.02 1481.65L2271.02 1481.65Z" fill="black"/>
|
|
||||||
<path opacity="0.997" d="M2062.08 1928.03C2066.08 1963.78 2031.67 1988.95 1996.69 1993.07C1952.17 1998.32 1895.66 1971.73 1812.67 1981.01C1754.15 1987.55 1699.65 2020.18 1652.86 2030.03C1581.12 2045.14 1530.79 2037.18 1525.3 1988C1516.22 1906.75 1629.02 1827.46 1777.25 1810.9C1925.48 1794.33 2053 1846.78 2062.08 1928.03V1928.03Z" fill="black"/>
|
|
||||||
<path opacity="0.969" d="M928.618 1507.23C938.738 1515.86 985.438 1505.63 1058.08 1479.04C1088.78 1468.85 1127.78 1455.32 1166.09 1444.19C1201.06 1434.49 1236.16 1424.44 1272.09 1420.85C1274.07 1420.72 1276.03 1420.58 1277.96 1420.44C1290.49 1419.5 1301.76 1418.33 1312.8 1418.39C1316.66 1418.53 1319.6 1418.1 1321.7 1417.99C1322.82 1418.82 1322.93 1416.45 1321.25 1412.65C1320.85 1406.53 1321.81 1403.64 1324 1402.45C1325.64 1402.66 1324.84 1404.21 1323.13 1406.79C1316.37 1415.86 1305.6 1423.98 1295.62 1431.73C1242.64 1472.89 1205.17 1511.48 1181.64 1543.57C1170.52 1558.73 1163.7 1571.17 1160.11 1581.02C1158.32 1585.91 1157.66 1589.9 1157.68 1593.16C1157.68 1594.78 1158.04 1596.16 1158.48 1597.34C1158.81 1597.86 1159.26 1598.34 1159.64 1598.77C1143.14 1572.13 1123.51 1540.47 1107.01 1513.83C1106.88 1513.63 1106.88 1513.63 1107.01 1513.83C1067.71 1450.43 1200.7 1665.03 1161.4 1601.63C1161.56 1602.08 1161.71 1602.62 1161.9 1603C1162.06 1603.17 1162.23 1603.33 1162.41 1603.48C1162.93 1603.91 1163.53 1604.25 1164.29 1604.43C1166.32 1604.89 1168.93 1604.66 1172.5 1603.49C1179.61 1601.16 1189.55 1595.86 1202.88 1587.73C1230.59 1570.82 1271.17 1543.07 1322 1510.73C1332.09 1505.08 1348.78 1495.65 1367.94 1481.3C1372.95 1479.1 1382.55 1469.79 1395.45 1453.3H1395.45C1408.68 1437.14 1411.42 1412.6 1403.47 1380.91V1380.91C1388.85 1356.01 1377.31 1343.97 1369.85 1343.56C1358.65 1338.09 1350.13 1335.4 1344.28 1334.74C1324.43 1331.51 1307.46 1331.4 1292.46 1332.26C1269.62 1332.69 1247.91 1335.32 1227.11 1339.44C1205.39 1343.75 1184.84 1349.64 1165.34 1356.17C1120.73 1370.95 1081.19 1389.4 1048.22 1407.42C960.49 1459.08 916.235 1496.67 928.618 1507.23V1507.23Z" fill="black"/>
|
|
||||||
<path d="M2570.51 1270.25C2570.51 1270.25 2611.95 1201.33 2707.84 1167.02C2803.74 1132.7 2924.6 1340.93 2570.51 1270.25Z" fill="#71E0E0"/>
|
|
||||||
<path opacity="0.997" d="M2773.75 1203.7C2773.35 1218.61 2757.87 1223.28 2737.72 1222.74C2717.56 1222.2 2700.36 1216.65 2700.76 1201.74C2701.16 1186.83 2717.82 1175.18 2737.98 1175.72C2758.13 1176.26 2774.15 1188.79 2773.75 1203.7V1203.7Z" fill="white"/>
|
|
||||||
<path d="M2715.89 1392.5C2715.89 1392.5 2772.4 1373.32 2843.17 1399.83C2913.95 1426.34 2882.64 1602.24 2715.89 1392.5Z" fill="#71E0E0"/>
|
|
||||||
<path opacity="0.997" d="M2862.94 1452.19C2855.56 1460.45 2844.55 1455.68 2833.39 1445.72C2822.23 1435.75 2815.15 1424.36 2822.52 1416.1C2829.89 1407.85 2844.91 1409.23 2856.08 1419.2C2867.24 1429.16 2870.31 1443.94 2862.94 1452.19V1452.19Z" fill="white"/>
|
|
||||||
<path d="M841.958 1500.18C841.958 1500.18 771.339 1461.71 671.266 1480.64C571.194 1499.57 572.326 1740.33 841.958 1500.18Z" fill="#71E0E0"/>
|
|
||||||
<path opacity="0.997" d="M632.987 1545.62C640.877 1558.28 656.592 1554.48 673.702 1543.82C690.813 1533.15 702.84 1519.65 694.949 1507C687.059 1494.34 666.792 1492.73 649.681 1503.39C632.57 1514.06 625.096 1532.97 632.987 1545.62V1545.62Z" fill="white"/>
|
|
||||||
<path d="M778.439 1679.19C778.439 1679.19 719.99 1691.24 672.36 1749.92C624.73 1808.6 740.752 1944.48 778.439 1679.19Z" fill="#71E0E0"/>
|
|
||||||
<path opacity="0.997" d="M681.813 1805.09C692.35 1808.48 699.433 1798.79 704.016 1784.55C708.599 1770.31 708.946 1756.9 698.41 1753.51C687.874 1750.12 675.617 1758.91 671.033 1773.16C666.45 1787.4 671.277 1801.7 681.813 1805.09V1805.09Z" fill="white"/>
|
|
||||||
<path d="M1833.6 1920.21C1830.99 1920.21 1828.37 1920.21 1825.74 1920.25C1816.01 1920.32 1806.14 1921.2 1796.18 1922.94C1702.44 1939.32 1636.6 1955.14 1607.38 2036.68C1621.25 2035.85 1636.48 2033.62 1652.86 2030.17C1699.65 2020.32 1754.15 1987.69 1812.67 1981.15C1895.67 1971.87 1952.17 1998.46 1996.69 1993.21C2001.8 1992.61 2006.89 1991.55 2011.86 1990.08C1974.97 1931.79 1909.4 1920.36 1833.6 1920.22V1920.21Z" fill="#DF6747"/>
|
|
||||||
<defs>
|
|
||||||
<filter id="filter0_f_28_46" x="1790.28" y="1625.95" width="57.8831" height="37.7055" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="2.30794" result="effect1_foregroundBlur_28_46"/>
|
|
||||||
</filter>
|
|
||||||
<radialGradient id="paint0_radial_28_46" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(1769.23 1677.78) rotate(-0.182296) scale(306.481 287.176)">
|
|
||||||
<stop stop-color="#CC3100"/>
|
|
||||||
<stop offset="1" stop-color="#DE6B00"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint1_radial_28_46" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(2381.57 755.292) rotate(63.7909) scale(608.272 241.85)">
|
|
||||||
<stop stop-color="#FF927A"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint2_radial_28_46" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(793.252 914.947) rotate(-157.738) scale(359.552 439.05)">
|
|
||||||
<stop stop-color="#FF927A"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint3_linear_28_46" x1="1265.58" y1="3661.71" x2="1144.68" y2="3329.24" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint4_linear_28_46" x1="2489.26" y1="3548.4" x2="2536.25" y2="3236.36" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint5_linear_28_46" x1="1615.27" y1="2298.63" x2="1651.45" y2="2196.26" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint6_linear_28_46" x1="2095.19" y1="2779.79" x2="2057.55" y2="2847.94" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 32 KiB |
|
@ -1,109 +0,0 @@
|
||||||
<svg width="2859" height="3858" viewBox="0 0 2859 3858" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<g clip-path="url(#clip0_35_87)">
|
|
||||||
<path opacity="0.997" d="M229.331 2573.92C227.658 2571.29 287.004 2544.38 324.218 2448.2C337.11 2414.69 347.357 2369.08 337.943 2323.16C334.776 2307.96 329.583 2292.41 320.457 2279.96C313.372 2270.39 303.743 2262.04 292.932 2259.23C281.648 2255.61 267.954 2257.93 254.626 2263.16C231.995 2270.93 211.286 2285.24 190.078 2302.35C167.021 2283.54 134.978 2268.82 104.768 2273.7C81.902 2276.54 60.511 2295.24 49.4462 2318.86C3.74465 2410.06 71.315 2519.88 150.29 2625.09C150.29 2625.09 150.29 2625.09 150.29 2625.09C230.276 2725.89 340.979 2812.76 472.956 2860.92C580.106 2900.19 698.127 2914.49 816.398 2905.34C858.558 2901.63 900.297 2891.12 931.227 2867C941.601 2859.12 950.867 2849.65 958.548 2839.11C967.767 2826.46 974.702 2812.27 978.534 2797.4C985.145 2772.44 984.014 2745.1 975.509 2720.73V2720.73C967.343 2698.01 953.089 2677.33 934.061 2665.58C910.149 2650.23 881.933 2641.07 853.199 2637.76C819.885 2634.11 785.627 2639.42 757.021 2654.45C719.662 2673.22 691.325 2709.24 671.796 2748.4C639.342 2814.04 629.429 2890.35 625.585 2963.42C620.787 3054.16 660.729 3141.58 719.642 3201.36C770.676 3252.96 831.322 3289.74 893.723 3308.69C908.697 3313.56 926.857 3313.53 945.412 3314.04C973.343 3314.51 1002.22 3313.39 1029.19 3312.46C1112.71 3309.54 1178.34 3307.56 1247.24 3311.4C1252.48 3312.55 1259.26 3308.03 1265.44 3302.94C1274.49 3294.73 1281.43 3283.17 1287.71 3271.73C1306.29 3237.38 1318.13 3197.66 1326.75 3167.88C1349.83 3064.98 1363.32 3012.13 1366.36 3012.73C1369.41 3013.33 1361.94 3067.36 1344.36 3171.88C1344.36 3171.88 1344.36 3171.88 1344.36 3171.88C1337.33 3202.62 1327.04 3243.92 1308.44 3282.33C1302.39 3294.99 1294.5 3308.84 1282.76 3320.8C1274.53 3329.67 1261.97 3337.01 1246.23 3337.34C1178.13 3335.81 1114.64 3339.62 1030.69 3344.52C1003.79 3346.11 974.453 3347.89 945.212 3348.03C926.769 3348.32 905.587 3348.33 883.825 3342.43C815.106 3322.91 748.321 3284.25 692.192 3228.84C625.184 3162.88 579.614 3066.05 583.303 2961.59C585.929 2885.84 596.46 2803.96 631.931 2729.13C653.524 2683.25 688.026 2640.3 736.117 2614.43C773.614 2594.93 816.524 2587.77 858.202 2592.39C893.307 2596.11 928.083 2607.44 958.736 2626.81C987.785 2645.66 1008.37 2674.19 1019.07 2705.51V2705.51C1030.67 2738.69 1032.2 2775.02 1023.26 2809.17C1017.73 2829.86 1008.36 2849.2 995.965 2866.3C985.637 2880.55 973.211 2893.24 959.166 2903.86C917.766 2934.55 867.899 2948.06 819.932 2951.28C695.515 2960.79 571.075 2945 457.507 2902.73C317.198 2850.29 201.177 2757.52 118.223 2650.2V2650.2C32.6442 2545.24 -32.8981 2417.48 17.6801 2303.93C33.4423 2270.48 64.451 2246.14 100.199 2240.83C136.634 2236.45 169.491 2255.33 190.178 2280.49C205.009 2262.04 222.599 2245.98 243.989 2236.31C261.83 2229.19 281.993 2227.28 301.035 2233.04C318.973 2239.12 332.793 2251.36 341.852 2265.2C353.144 2282.35 358.941 2301.28 361.69 2318.87C370.075 2371.61 356.822 2420.33 340.993 2455.25C291.994 2563.91 225.032 2567.17 229.331 2573.92V2573.92Z" fill="black"/>
|
|
||||||
<path d="M1160.62 2299.49C1160.62 2299.49 1166.66 2341.8 1118.3 2468.75C1069.94 2595.69 1066.92 2885.85 1042.74 2949.32C1018.56 3012.79 885.57 3224.37 915.795 3411.76C946.02 3599.15 1094.12 3865.13 1275.47 3798.64C1456.82 3732.14 1420.55 3744.23 1420.55 3744.23C1420.55 3744.23 1946.46 3859.09 2294.05 3659.6C2372.63 3695.87 2420.99 3726.1 2538.87 3656.58C2656.74 3587.06 2717.19 3396.65 2714.17 3266.68C2711.15 3136.71 2523.75 2852.6 2502.6 2792.15C2481.44 2731.7 2402.86 2435.5 2363.56 2311.58C2324.27 2187.66 2354.5 2166.5 2354.5 2166.5L1160.62 2299.49Z" fill="#DE5700" stroke="black" stroke-width="46.0804"/>
|
|
||||||
<path d="M2798.72 15.367C2698.4 16.4866 2391.12 184.492 2306.37 277.783C2219.35 373.579 2165.64 521.033 2148.97 571.513C2050.88 508.595 1907.17 507.155 1907.17 507.155C1907.17 507.155 1991.8 479.955 2082.48 455.775C1925.31 401.371 1722.8 449.727 1722.8 449.727C1722.8 449.727 1813.47 349.989 1895.08 277.45C1768.13 310.697 1620.04 383.233 1529.36 437.638C1553.54 401.368 1595.86 362.076 1680.49 244.199C1447.75 301.626 1160.61 528.318 1060.87 612.947C1072.96 537.385 1103.19 489.025 1139.46 404.395C1002.07 499.513 937.628 607.905 907.715 681.853C876.542 624.261 794.11 483.695 690.543 400.173C558.035 293.312 45.0983 126.611 113.489 254.844C181.88 383.077 164.781 558.322 207.526 827.611C250.27 1096.9 634.972 1250.78 634.972 1250.78C637.192 1249.99 639.395 1249.09 641.592 1248.17C619.011 1319.85 598.866 1424.54 583.679 1597.01C511.014 1706.01 478.959 1727.38 470.41 1767.99C540.938 1733.8 575.13 1708.15 626.423 1695.32C581.542 1770.13 579.407 1872.71 598.642 2035.14C634.975 1943.24 632.833 1945.37 671.303 1917.59C681.988 2026.59 705.503 2086.43 733.287 2120.63C743.973 2060.78 776.031 2037.28 776.031 2037.28C776.031 2037.28 797.404 2167.65 859.383 2257.41C872.207 2178.34 887.165 2165.51 887.165 2165.51C887.165 2165.51 1135.08 2490.37 1767.7 2456.17C2400.31 2421.98 2579.84 1985.98 2579.84 1985.98C2579.84 1985.98 2592.66 2041.56 2592.66 2062.93C2639.68 1994.54 2669.6 1853.48 2669.6 1853.48C2669.6 1853.48 2703.8 1934.69 2695.25 1985.98C2733.72 1921.86 2742.26 1763.72 2725.17 1691.05C2785.01 1755.17 2836.31 1776.54 2836.31 1776.54C2836.31 1776.54 2703.79 1545.72 2699.52 1507.25C2695.25 1468.78 2793.56 1562.81 2793.56 1562.81C2793.56 1562.81 2731.97 1460.26 2716.62 1432.45C2659.41 1328.78 2605.12 1139.43 2528.87 1011.72C2592.86 970.123 2850.88 788.773 2843.33 573.68C2834.72 328.21 2786.46 176.103 2827.99 51.0384C2836.43 25.6346 2824.3 15.0816 2798.72 15.367V15.367Z" fill="#DE5700"/>
|
|
||||||
<path d="M1160.62 2299.49C1160.62 2299.49 1166.66 2341.8 1118.3 2468.75C1069.94 2595.69 1066.92 2885.85 1042.74 2949.32C1018.56 3012.79 885.57 3224.37 915.795 3411.76C946.02 3599.15 1094.12 3865.13 1275.47 3798.64C1456.82 3732.14 1420.55 3744.23 1420.55 3744.23C1420.55 3744.23 1946.46 3859.09 2294.05 3659.6C2372.63 3695.87 2420.99 3726.1 2538.87 3656.58C2656.74 3587.06 2717.19 3396.65 2714.17 3266.68C2711.15 3136.71 2523.75 2852.6 2502.6 2792.15C2481.44 2731.7 2402.86 2435.5 2363.56 2311.58C2324.27 2187.66 2354.5 2166.5 2354.5 2166.5L1160.62 2299.49Z" fill="#DE5700"/>
|
|
||||||
<path d="M1940.31 2212.63L1557.07 2255.32C1406.21 2289.92 1288.96 2332.21 1288.96 2332.21C1288.96 2332.21 1220.57 2746.83 1233.39 2862.24C1246.22 2977.65 1173.55 3152.9 1212.02 3328.15C1245.61 3481.2 1311.83 3644.02 1558.64 3765.38C1710.04 3782.34 1960.24 3792 2176.82 3713.48C2280.67 3629.51 2354.73 3520.47 2383.22 3435.02C2447.33 3242.67 2370.39 2909.27 2340.47 2840.87C2310.55 2772.48 2344.75 2558.76 2178.04 2315.11C2132.1 2247.96 2043.91 2219.17 1940.31 2212.63Z" fill="#F7EDE9"/>
|
|
||||||
<path opacity="0.6" d="M2798.72 15.367C2698.4 16.4866 2391.12 184.492 2306.37 277.783C2219.35 373.579 2165.64 521.033 2148.97 571.513C2050.88 508.595 1907.17 507.155 1907.17 507.155C1907.17 507.155 1991.8 479.955 2082.48 455.775C1925.31 401.371 1722.8 449.727 1722.8 449.727C1722.8 449.727 1813.47 349.989 1895.08 277.45C1768.13 310.697 1620.04 383.233 1529.36 437.638C1553.54 401.368 1595.86 362.076 1680.49 244.199C1447.75 301.626 1160.61 528.318 1060.87 612.947C1072.96 537.385 1103.19 489.025 1139.46 404.395C1002.07 499.513 937.628 607.905 907.715 681.853C876.542 624.261 794.11 483.695 690.543 400.173C558.035 293.312 45.0983 126.611 113.489 254.844C181.88 383.077 164.781 558.322 207.526 827.611C250.27 1096.9 634.972 1250.78 634.972 1250.78C637.192 1249.99 639.395 1249.09 641.592 1248.17C619.011 1319.85 598.866 1424.54 583.679 1597.01C511.014 1706.01 478.959 1727.38 470.41 1767.99C540.938 1733.8 575.13 1708.15 626.423 1695.32C581.542 1770.13 579.407 1872.71 598.642 2035.14C634.975 1943.24 632.833 1945.37 671.303 1917.59C681.988 2026.59 705.503 2086.43 733.287 2120.63C743.973 2060.78 776.031 2037.28 776.031 2037.28C776.031 2037.28 797.404 2167.65 859.383 2257.41C872.207 2178.34 887.165 2165.51 887.165 2165.51C887.165 2165.51 1135.08 2490.37 1767.7 2456.17C2400.31 2421.98 2579.84 1985.98 2579.84 1985.98C2579.84 1985.98 2592.66 2041.56 2592.66 2062.93C2639.68 1994.54 2669.6 1853.48 2669.6 1853.48C2669.6 1853.48 2703.8 1934.69 2695.25 1985.98C2733.72 1921.86 2742.26 1763.72 2725.17 1691.05C2785.01 1755.17 2836.31 1776.54 2836.31 1776.54C2836.31 1776.54 2703.79 1545.72 2699.52 1507.25C2695.25 1468.78 2793.56 1562.81 2793.56 1562.81C2793.56 1562.81 2731.97 1460.26 2716.62 1432.45C2659.41 1328.78 2605.12 1139.43 2528.87 1011.72C2592.86 970.123 2850.88 788.773 2843.33 573.68C2834.72 328.21 2786.46 176.103 2827.99 51.0384C2836.43 25.6346 2824.3 15.0816 2798.72 15.367V15.367Z" fill="url(#paint0_radial_35_87)"/>
|
|
||||||
<path d="M1785.69 1777.75C1684.07 1778.04 1631.38 1822.48 1594.58 1842.79C1435.61 2029.15 1115.77 1926.47 942.736 2050.1C912.815 2071.47 871.139 2186.88 871.139 2186.88L873.322 2195.17C881.064 2170.83 887.165 2165.51 887.165 2165.51C887.165 2165.51 1135.08 2490.37 1767.7 2456.17C2277.77 2428.6 2493.17 2139.93 2557.52 2029.09C2551.52 1973.12 2534.07 1898.88 2483.67 1896.22C2402.45 1891.95 2066.9 1864.16 1964.32 1808.59C1922.64 1786.02 1855.22 1777.56 1785.69 1777.75V1777.75Z" fill="#F7EDE9"/>
|
|
||||||
<path opacity="0.993" d="M1961.57 1985.15C1963.63 1987.09 1933.18 2033.96 1856.33 2063.83V2063.83C1839.85 2070.21 1822.61 2075.45 1804.72 2079.62C1766.98 2088.41 1729.87 2091.61 1698.49 2092.27C1674.97 2092.78 1655.68 2091.74 1642.07 2090.22C1635 2089.43 1629.58 2088.53 1625.85 2087.62C1623.95 2087.15 1622.51 2086.68 1621.54 2086.24C1621.04 2086.01 1620.67 2085.78 1620.42 2085.57C1620.15 2085.33 1620.02 2085.11 1620.03 2084.89C1620.05 2084.67 1620.2 2084.47 1620.49 2084.27C1620.76 2084.08 1621.15 2083.91 1621.67 2083.73C1622.67 2083.4 1624.14 2083.08 1626.06 2082.78C1629.77 2082.2 1635.24 2081.66 1642.21 2081.09C1655.61 2079.99 1674.75 2078.77 1697.58 2076.59C1728.3 2073.63 1764.16 2069.35 1800.38 2060.94C1817.58 2056.95 1834.05 2052.22 1849.95 2046.59C1918.62 2022.43 1958.6 1982.34 1961.57 1985.15V1985.15Z" fill="black"/>
|
|
||||||
<path d="M1934.67 1959.27C1935.77 1956.91 1954.37 1960.97 1967.17 1981.57C1979.98 2002.16 1975.41 2020.64 1972.82 2020.59C1970 2020.53 1967.84 2002.79 1958.14 1987.19C1948.44 1971.58 1933.47 1961.83 1934.67 1959.27V1959.27Z" fill="black"/>
|
|
||||||
<path d="M1263.38 1639.08C1266.22 1756.73 1183.41 1844.17 1098.66 1852.16C951.388 1866.04 891.515 1767.76 901.936 1653.12C912.303 1539.07 1011.03 1433.96 1109.23 1430.52C1193.46 1427.58 1260.47 1518.48 1263.38 1639.08Z" fill="black"/>
|
|
||||||
<g filter="url(#filter0_f_35_87)">
|
|
||||||
<path d="M1109.1 1636.63C1138.87 1598.95 1137.08 1543.74 1105.1 1513.3C1073.11 1482.87 1023.06 1488.73 993.29 1526.41C963.522 1564.08 965.316 1619.29 997.297 1649.73C1029.28 1680.17 1079.34 1674.3 1109.1 1636.63Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M1109.1 1636.63C1138.87 1598.95 1137.08 1543.74 1105.1 1513.3C1073.11 1482.87 1023.06 1488.73 993.29 1526.41C963.522 1564.08 965.316 1619.29 997.297 1649.73C1029.28 1680.17 1079.34 1674.3 1109.1 1636.63Z" fill="#DEDEDE"/>
|
|
||||||
<g filter="url(#filter1_f_35_87)">
|
|
||||||
<path d="M1220.38 1725.27C1218.97 1703.96 1200.95 1686.44 1180.12 1686.13C1159.3 1685.82 1143.56 1702.84 1144.97 1724.14C1146.38 1745.45 1164.4 1762.98 1185.22 1763.29C1206.05 1763.6 1221.79 1746.58 1220.38 1725.27Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M1217.34 1725.22C1216.05 1705.95 1199.48 1690.11 1180.33 1689.83C1161.18 1689.54 1146.71 1704.93 1148.01 1724.2C1149.3 1743.46 1165.87 1759.31 1185.02 1759.59C1204.17 1759.87 1218.64 1744.48 1217.34 1725.22Z" fill="#DEDEDE"/>
|
|
||||||
<path d="M2111.74 1483.68C2108.91 1601.33 2191.71 1688.77 2276.47 1696.76C2423.74 1710.64 2483.61 1612.36 2473.19 1497.72C2462.82 1383.67 2364.09 1278.56 2265.89 1275.13C2181.66 1272.18 2114.65 1363.09 2111.74 1483.68Z" fill="black"/>
|
|
||||||
<g filter="url(#filter2_f_35_87)">
|
|
||||||
<path d="M2266.02 1481.23C2236.25 1443.55 2238.05 1388.34 2270.03 1357.9C2302.01 1327.47 2352.07 1333.34 2381.83 1371.01C2411.6 1408.68 2409.81 1463.9 2377.83 1494.33C2345.85 1524.77 2295.79 1518.9 2266.02 1481.23Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M2266.02 1481.23C2236.25 1443.55 2238.05 1388.34 2270.03 1357.9C2302.01 1327.47 2352.07 1333.34 2381.83 1371.01C2411.6 1408.68 2409.81 1463.9 2377.83 1494.33C2345.85 1524.77 2295.79 1518.9 2266.02 1481.23Z" fill="#DEDEDE"/>
|
|
||||||
<g filter="url(#filter3_f_35_87)">
|
|
||||||
<path d="M2154.74 1569.87C2156.15 1548.56 2174.17 1531.04 2195 1530.73C2215.83 1530.42 2231.57 1547.44 2230.16 1568.75C2228.75 1590.05 2210.72 1607.58 2189.9 1607.89C2169.07 1608.2 2153.33 1591.18 2154.74 1569.87Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M2157.78 1569.82C2159.08 1550.55 2175.65 1534.71 2194.79 1534.43C2213.94 1534.15 2228.41 1549.53 2227.12 1568.8C2225.82 1588.06 2209.25 1603.91 2190.1 1604.19C2170.96 1604.47 2156.49 1589.08 2157.78 1569.82Z" fill="#DEDEDE"/>
|
|
||||||
<path d="M1662.35 1829.49C1645.46 1787.85 1850.52 1752.32 1854.28 1791.71C1858.37 1834.59 1804.4 1912.61 1777.2 1917.14C1750 1921.68 1680.39 1873.96 1662.35 1829.49V1829.49Z" fill="black"/>
|
|
||||||
<g opacity="0.8">
|
|
||||||
<g filter="url(#filter4_f_35_87)">
|
|
||||||
<path d="M1786.9 1793.91C1788.82 1786.22 1801.15 1781.29 1814.45 1782.91C1827.74 1784.53 1836.97 1792.08 1835.05 1799.77C1833.13 1807.46 1820.8 1812.39 1807.51 1810.77C1794.21 1809.15 1784.99 1801.61 1786.9 1793.91Z" fill="#BEBEBE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M1788.84 1794.15C1790.59 1787.19 1801.91 1782.76 1814.14 1784.25C1826.36 1785.74 1834.85 1792.58 1833.11 1799.54C1831.36 1806.49 1820.04 1810.92 1807.81 1809.43C1795.59 1807.94 1787.1 1801.1 1788.84 1794.15Z" fill="#DEDEDE"/>
|
|
||||||
</g>
|
|
||||||
<path d="M2741.41 163.935C2735.43 163.645 2728.58 173.489 2718.76 194.994C2673.88 293.306 2462.29 385.213 2381.08 483.525C2299.87 581.837 2284.9 697.243 2374.67 851.122C2421.52 931.442 2482.9 980.277 2532.12 1009.56C2600.59 964.628 2850.77 785.686 2843.33 573.68C2841.17 511.985 2836.51 456.206 2831.39 405.253C2769.94 259.579 2759.63 164.818 2741.41 163.935V163.935Z" fill="url(#paint1_radial_35_87)"/>
|
|
||||||
<path d="M181.665 291.229C163.173 289.362 174.995 366.697 171.814 505.727C180.547 595.591 187.448 701.123 207.526 827.611C246.789 1074.97 573.781 1224.58 626.915 1247.37C670.403 1199.53 739.457 1106.83 766.704 960.629C806.777 745.606 754.64 615.556 641.83 530.754C529.02 445.951 288.043 418.155 211.526 319.567C197.179 301.081 187.769 291.846 181.665 291.229V291.229Z" fill="url(#paint2_radial_35_87)"/>
|
|
||||||
<path d="M2798.72 15.367C2698.4 16.4866 2391.12 184.492 2306.37 277.783C2219.35 373.579 2165.64 521.033 2148.97 571.513C2050.88 508.595 1907.17 507.155 1907.17 507.155C1907.17 507.155 1991.8 479.955 2082.48 455.775C1925.31 401.371 1722.8 449.727 1722.8 449.727C1722.8 449.727 1813.47 349.989 1895.08 277.45C1768.13 310.697 1620.04 383.233 1529.36 437.638C1553.54 401.368 1595.86 362.076 1680.49 244.199C1447.75 301.626 1160.61 528.318 1060.87 612.947C1072.96 537.385 1103.19 489.025 1139.46 404.395C1002.07 499.513 937.628 607.905 907.715 681.853C876.542 624.261 794.11 483.695 690.543 400.173C558.035 293.312 45.0983 126.611 113.489 254.844C181.88 383.077 164.781 558.322 207.526 827.611C250.27 1096.9 634.972 1250.78 634.972 1250.78C637.192 1249.99 639.395 1249.09 641.592 1248.17C619.011 1319.85 598.866 1424.54 583.679 1597.01C511.014 1706.01 478.959 1727.38 470.41 1767.99C540.938 1733.8 575.13 1708.15 626.423 1695.32C581.542 1770.13 579.407 1872.71 598.642 2035.14C634.975 1943.24 632.833 1945.37 671.303 1917.59C681.988 2026.59 705.503 2086.43 733.287 2120.63C743.973 2060.78 776.031 2037.28 776.031 2037.28C776.031 2037.28 797.404 2167.65 859.383 2257.41C872.207 2178.34 887.165 2165.51 887.165 2165.51C887.165 2165.51 1135.08 2490.37 1767.7 2456.17C2400.31 2421.98 2579.84 1985.98 2579.84 1985.98C2579.84 1985.98 2592.66 2041.56 2592.66 2062.93C2639.68 1994.54 2669.6 1853.48 2669.6 1853.48C2669.6 1853.48 2703.8 1934.69 2695.25 1985.98C2733.72 1921.86 2742.26 1763.72 2725.17 1691.05C2785.01 1755.17 2836.31 1776.54 2836.31 1776.54C2836.31 1776.54 2703.79 1545.72 2699.52 1507.25C2695.25 1468.78 2793.56 1562.81 2793.56 1562.81C2793.56 1562.81 2731.97 1460.26 2716.62 1432.45C2659.41 1328.78 2605.12 1139.43 2528.87 1011.72C2592.86 970.123 2850.88 788.773 2843.33 573.68C2834.72 328.21 2786.46 176.103 2827.99 51.0384C2836.43 25.6346 2824.3 15.0816 2798.72 15.367V15.367Z" stroke="black" stroke-width="30.7203" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M1166.07 3775.9C1091.27 3651.94 1054.81 3567.11 1049.59 3511.42C1044.78 3460.13 1038.37 3398.15 1075.24 3428.61C1085.93 3383.72 1083.79 3358.08 1111.57 3370.9C1139.36 3383.72 1158.59 3411.51 1158.59 3411.51C1158.59 3411.51 1154.32 3347.39 1182.1 3368.76C1233.19 3399.52 1324.44 3688.35 1313.81 3770.16C1302.14 3860.06 1231.96 3879.6 1166.07 3775.9V3775.9Z" fill="url(#paint3_linear_35_87)" stroke="black" stroke-width="23.0402"/>
|
|
||||||
<path d="M2556.53 3668.47C2609.53 3533.74 2631.28 3444 2627.1 3388.22C2623.26 3336.85 2619.21 3274.67 2587.96 3310.87C2569.91 3268.41 2567.73 3242.76 2542.48 3260.06C2517.23 3277.35 2502.92 3307.96 2502.92 3307.96C2502.92 3307.96 2496.4 3244.03 2472.59 3269.75C2427.37 3308.62 2385.74 3608.66 2409.91 3687.53C2436.47 3774.21 2508.93 3781.73 2556.53 3668.47V3668.47Z" fill="url(#paint4_linear_35_87)" stroke="black" stroke-width="23.0402"/>
|
|
||||||
<path d="M1562.1 3063.57C1524.1 3059.67 1486.65 3074.05 1455.28 3094.55C1440.72 3104.25 1426.76 3115.03 1414.48 3127.52C1438.67 3156.34 1465.72 3183.02 1496.29 3205.05C1502.66 3208.89 1510.79 3214.39 1518.35 3210.58C1525.16 3205.3 1523.61 3195.64 1524.22 3188.07C1530.46 3197.06 1541.84 3202.2 1552.66 3201.65C1562.44 3199.92 1561.73 3187.56 1560.44 3180.1C1559.69 3173.07 1556.6 3166.42 1556.17 3159.41C1562.43 3160.56 1568.02 3169.72 1575.98 3167.49C1584.76 3164.88 1580.38 3153.58 1580.28 3146.94C1575.9 3118.83 1568.65 3091.24 1562.1 3063.57V3063.57Z" fill="url(#paint5_linear_35_87)"/>
|
|
||||||
<path d="M1517.64 2663.48C1517.64 2663.48 1517.64 2663.48 1517.67 2663.48C1520.97 2664.02 1526.42 2740.85 1532.65 2874.63C1534.91 2900.48 1540.5 2925.66 1547.39 2954.9C1554.58 2985.32 1562.49 3014.75 1571.38 3047.9C1578.08 3072.85 1585.59 3099.84 1591.55 3126.74C1593.42 3135.07 1595.31 3143.95 1596.25 3153.37C1596.57 3156.1 1596.76 3159.46 1596.39 3163.39C1597.28 3165.14 1595.58 3169.34 1590.43 3175.07V3175.07C1580.39 3180.9 1569.4 3179.92 1561.47 3173.37V3173.37C1559.01 3171.29 1557.89 3169.89 1557.57 3169.88C1559.13 3171.17 1561.37 3170.83 1565.41 3169.42H1565.41C1567.07 3167.09 1567.82 3166.38 1567.48 3165.67C1567.51 3167 1568.74 3169.46 1569.97 3173.33V3173.33C1574.02 3183.37 1572.31 3196.44 1561.97 3206.72V3206.72C1550.18 3212.97 1538.44 3211.07 1531.04 3204.36V3204.36C1528.22 3202.07 1526.49 3200.26 1525.34 3199.66H1525.34C1524.94 3200.04 1525.8 3199.59 1528.79 3199.47V3199.47C1531.49 3196.56 1532.68 3197.17 1530.81 3199.19C1530.12 3201.61 1529.26 3205.67 1526.9 3210.83C1526.22 3212.23 1525.38 3213.53 1524.39 3214.71C1520.87 3218.89 1515.47 3221.56 1508.72 3222C1497.43 3220.63 1489.74 3215.57 1485.08 3211.33C1426.38 3166.73 1381.27 3109.36 1347.87 3050.36C1312.57 2987.93 1289.98 2924.54 1275.1 2870.05C1253.47 2738.94 1243.01 2664.06 1246.21 2663.48C1249.41 2662.9 1265.97 2736.63 1291.73 2866.13V2866.13C1308.09 2918.97 1331.53 2980.15 1366.49 3039.63C1399.64 3096.09 1443.21 3150.79 1498.89 3192.79C1504.65 3196.18 1508.06 3199.72 1509.67 3198.89C1507.79 3199.52 1506.9 3199.67 1506.47 3200.08C1506.35 3200.2 1506.26 3200.33 1506.2 3200.5C1506.94 3199.44 1507.34 3196.53 1508.73 3192.3C1508.67 3188.65 1512.14 3183.04 1520.37 3177.93V3177.93C1527.93 3176.03 1533.99 3177.15 1537.72 3180.15H1537.72C1541.56 3182.71 1544.07 3185.1 1545.79 3186.59V3186.59C1547.9 3187.76 1550.06 3189.47 1548.1 3188.32H1548.1C1549.89 3189.46 1549.02 3184.96 1548.23 3180.69C1547.29 3178.15 1545.76 3174.34 1544.81 3168.99C1543.68 3162.9 1546.08 3156.29 1552.14 3150.81V3150.81C1559.11 3147.32 1565.42 3147.49 1569.99 3150.72V3150.72C1573.53 3153.21 1575.53 3155.29 1576.51 3156.24C1576.77 3156.9 1578.18 3157.59 1576.82 3156.92C1573.94 3160.94 1572.68 3161.93 1573.89 3160.86C1574.1 3159.67 1573.92 3157.84 1573.76 3155.45C1573.11 3147.76 1571.43 3139.75 1569.7 3131.46C1564.19 3105.34 1557.05 3078.42 1550.71 3053.27C1542.36 3020.15 1534.87 2989.98 1528.34 2959.17C1522.03 2929.53 1516.99 2902.93 1515.44 2875.5C1513.55 2741.07 1514.34 2664.11 1517.6 2663.48C1517.63 2663.47 1517.63 2663.48 1517.63 2663.48L1517.64 2663.48Z" fill="black"/>
|
|
||||||
<path d="M1565.2 3063.14C1564.91 3065.73 1555.96 3066.2 1541.37 3069.17C1525.48 3072.41 1508.74 3077.63 1488.07 3087.53C1480.4 3091.19 1473 3095.12 1465.92 3099.1C1438.07 3119.19 1417.43 3130.85 1415.06 3127.79C1412.69 3124.73 1429.23 3107.59 1456.25 3085.16C1463.45 3080.3 1471.31 3075.72 1479.69 3071.69C1501.77 3061.09 1522.77 3056.66 1540.11 3056.79C1556.81 3056.91 1565.43 3061.05 1565.2 3063.14V3063.14Z" fill="black"/>
|
|
||||||
<path d="M2047.1 3038.3C2015.08 3027.25 1989.62 3002.03 1971.75 2973.82C1956.72 2949.74 1945.57 2923.17 1939.25 2895.65C1918.3 2922.05 1897.04 2948.41 1879.78 2977.47C1875.73 2983.29 1871.18 2994.54 1881.77 2996.72C1891.18 2999.42 1900.88 2996.43 1910.31 2997.32C1906.93 3001.57 1900.26 3003.74 1896.41 3008.26C1889.29 3014.81 1882.1 3026.28 1888.65 3035.81C1897.4 3046.28 1912.16 3048.19 1924.86 3048.06C1933.1 3048.55 1920.45 3056.52 1921.15 3061.12C1917.09 3068.66 1918.61 3081.73 1929.47 3082C1942.49 3082.82 1954.68 3077.29 1966.93 3073.96C1994.86 3064.92 2021.6 3052.63 2047.1 3038.3V3038.3Z" fill="url(#paint6_linear_35_87)"/>
|
|
||||||
<path d="M2136.43 2590.6C2136.43 2590.6 2136.43 2590.6 2136.46 2590.61C2138.25 2591.35 2133.68 2615.94 2123.09 2662.55C2113.97 2692.52 2095.65 2744.12 2055.96 2781.07C2017.94 2816.07 1984.67 2855.47 1945.22 2905.25C1930.26 2924.17 1915.03 2943.97 1901.15 2964.57C1896.69 2971.21 1892.4 2977.73 1888.9 2984.37C1887.31 2989.65 1884.88 2991 1886.02 2988.64C1885.41 2987.11 1884.89 2986.63 1883.18 2985.7C1883.88 2986.16 1886.21 2985.54 1889.98 2985.28C1893.03 2984.76 1897.54 2984.08 1903.47 2984.6C1910.57 2985.44 1916.49 2990.55 1919.26 2999.16C1919.62 3007.51 1917.02 3013.57 1913.15 3016.69C1909.61 3020.25 1906.45 3022.49 1904.48 3024.27C1901.57 3026.15 1900.4 3031.06 1902.55 3033.46C1899.98 3033.96 1903.61 3032.95 1908.88 3033.72C1909.75 3033.84 1910.66 3034.02 1911.6 3034.26C1914.77 3034.15 1919.24 3034.1 1924.84 3035.26C1930.94 3036.4 1936.38 3041.11 1939.46 3048.98C1940.49 3058.56 1938.28 3064.62 1936.14 3066.9C1934.09 3071.33 1932.13 3074.45 1931.58 3076.77C1932.68 3076.62 1931.02 3075.79 1927.76 3071.11C1927.93 3072.71 1932.65 3070.31 1940.05 3069.84C2060.52 3040.57 2153.12 2954.06 2211.42 2887.43C2275.45 2796.57 2313.04 2746.24 2315.58 2747.99C2318.13 2749.74 2285.39 2803.44 2224.48 2897.39C2167.72 2967.95 2073.72 3059.09 1945.44 3091.98C1939.78 3094.05 1930.07 3095.88 1918.09 3091.52C1909.3 3084.14 1906.86 3075.86 1909.67 3069.89C1911.51 3064.11 1913.88 3059.89 1915.46 3056.71C1916.37 3052.55 1918.09 3051.64 1917.32 3054.22C1919 3056.69 1919.32 3057.64 1919.99 3057.49C1918.66 3056.99 1915.95 3057.25 1912.03 3057.13C1910.91 3057.36 1909.69 3057.5 1908.41 3057.54C1900.62 3057.76 1890.34 3054.11 1882.13 3043.31C1876.61 3030.37 1879.45 3016.48 1889 3007.16C1892.37 3004.14 1895.17 3002.25 1896.61 3000.66C1896.82 2999.58 1897.47 2999.97 1896.83 3002.48C1898.68 3005.68 1899.46 3006.96 1901.14 3007.12C1899.94 3006.74 1897.3 3007.4 1893.29 3007.76C1889.92 3008.39 1884.94 3008.85 1878.59 3007.7C1870.78 3005.36 1865.44 2999.58 1863.79 2991.91C1863.56 2981.4 1866.8 2975.32 1869.05 2973.44C1873.27 2965.66 1878.02 2958.53 1882.67 2951.79C1897.28 2930.57 1913.07 2910.54 1928.48 2891.68C1968.69 2842.39 2004.17 2802.5 2044.22 2767.98C2081.07 2736.75 2101.47 2687.54 2112.56 2659.14C2126.21 2614.17 2134.44 2590.46 2136.39 2590.6C2136.42 2590.61 2136.42 2590.61 2136.42 2590.61L2136.43 2590.6Z" fill="black"/>
|
|
||||||
<path d="M2038.8 3040.8C2037.48 3043.01 2027.68 3040.96 2012.89 3031.42C1997.72 3021.64 1980.73 3005.97 1966.44 2984.73C1959.64 2974.61 1954.07 2964.16 1949.75 2953.83C1940.62 2921.19 1937.42 2899.28 1941.52 2898.01C1945.61 2896.74 1956.14 2916.23 1967.96 2946.88C1972.82 2955.89 1978.21 2964.93 1984.35 2974.02C2009.03 3010.53 2041.64 3036.08 2038.8 3040.8V3040.8Z" fill="black"/>
|
|
||||||
<path d="M1643 3039.5V3096H1697.5V3039.5C1697.5 3039.5 1697.5 2974.5 1764.5 2974.5C1831.5 2974.5 1823.5 3039.5 1823.5 3039.5V3096H1874V3039.5C1869.33 3003.67 1850 2922 1764.5 2922C1678.44 2922 1643.67 3001 1643 3039.5Z" fill="#C4C4C4" stroke="black" stroke-width="14"/>
|
|
||||||
<rect x="1604.5" y="3089.5" width="333" height="269" fill="#F7CF45" stroke="black" stroke-width="15"/>
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<filter id="filter0_f_35_87" x="951.462" y="1473.2" width="199.468" height="216.64" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="10.3119" result="effect1_foregroundBlur_35_87"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter1_f_35_87" x="1135.42" y="1676.67" width="94.5019" height="96.079" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="4.72782" result="effect1_foregroundBlur_35_87"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter2_f_35_87" x="2224.19" y="1317.8" width="199.468" height="216.64" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="10.3119" result="effect1_foregroundBlur_35_87"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter3_f_35_87" x="2145.2" y="1521.27" width="94.5019" height="96.079" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="4.72782" result="effect1_foregroundBlur_35_87"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter4_f_35_87" x="1781.61" y="1777.56" width="58.7359" height="38.5579" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="2.52106" result="effect1_foregroundBlur_35_87"/>
|
|
||||||
</filter>
|
|
||||||
<radialGradient id="paint0_radial_35_87" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(1760.99 1829.81) rotate(-0.182296) scale(306.481 287.176)">
|
|
||||||
<stop stop-color="#CC3100"/>
|
|
||||||
<stop offset="1" stop-color="#DE6B00"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint1_radial_35_87" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(2373.33 907.327) rotate(63.7909) scale(608.272 241.85)">
|
|
||||||
<stop stop-color="#FF927A"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint2_radial_35_87" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(785.008 1066.98) rotate(-157.738) scale(359.552 439.05)">
|
|
||||||
<stop stop-color="#FF927A"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint3_linear_35_87" x1="1257.34" y1="3813.75" x2="1136.44" y2="3481.28" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint4_linear_35_87" x1="2481.02" y1="3700.43" x2="2528.01" y2="3388.4" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint5_linear_35_87" x1="1465.89" y1="3071.73" x2="1527.85" y2="3160.89" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint6_linear_35_87" x1="1978.5" y1="2970.47" x2="1922.1" y2="3021.61" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#F79041"/>
|
|
||||||
<stop offset="1" stop-color="#F7C199"/>
|
|
||||||
</linearGradient>
|
|
||||||
<clipPath id="clip0_35_87">
|
|
||||||
<rect width="2858.86" height="3857.48" fill="white"/>
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 28 KiB |
|
@ -1,6 +1,19 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html dir="ltr">
|
<html dir="ltr">
|
||||||
<head>
|
<head>
|
||||||
|
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-BB8DNPB73F"></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){dataLayer.push(arguments);}
|
||||||
|
gtag('consent', 'default', {
|
||||||
|
'ad_storage': 'denied',
|
||||||
|
'analytics_storage': 'denied',
|
||||||
|
});
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', 'G-BB8DNPB73F');
|
||||||
|
</script>
|
||||||
|
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta http-equiv="Pragma" content="no-cache" />
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
|
420
ui/analytics.js
420
ui/analytics.js
|
@ -1,44 +1,69 @@
|
||||||
// @flow
|
// @flow
|
||||||
/*
|
|
||||||
Removed Watchman (internal view tracking) code.
|
|
||||||
This file may eventually implement cantina
|
|
||||||
Refer to 0cc0e213a5c5bf9e2a76316df5d9da4b250a13c3 for initial integration commit
|
|
||||||
refer to ___ for removal commit.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Lbryio } from 'lbryinc';
|
import { Lbryio } from 'lbryinc';
|
||||||
import * as Sentry from '@sentry/browser';
|
import * as Sentry from '@sentry/browser';
|
||||||
import MatomoTracker from '@datapunt/matomo-tracker-js';
|
import * as RENDER_MODES from 'constants/file_render_modes';
|
||||||
import { history } from './store';
|
import { SDK_API_PATH } from './index';
|
||||||
import Native from 'native';
|
|
||||||
import ElectronCookies from '@meetfranz/electron-cookies';
|
// --- GA ---
|
||||||
import { generateInitialUrl } from 'util/url';
|
// - Events: 500 max (cannot be deleted).
|
||||||
import { MATOMO_ID, MATOMO_URL } from 'config';
|
// - Dimensions: 25 max (cannot be deleted, but can be "archived"). Usually
|
||||||
|
// tied to an event parameter for reporting purposes.
|
||||||
|
//
|
||||||
|
// Given the limitations above, we need to plan ahead before adding new Events
|
||||||
|
// and Parameters.
|
||||||
|
//
|
||||||
|
// Events:
|
||||||
|
// - Find a Recommended Event that is closest to what you need.
|
||||||
|
// https://support.google.com/analytics/answer/9267735?hl=en
|
||||||
|
// - If doesn't exist, use a Custom Event.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - Custom parameters don't appear in automated reports until they are tied to
|
||||||
|
// a Dimension.
|
||||||
|
// - Add your entry to GA_DIMENSIONS below -- tt allows us to keep track so that
|
||||||
|
// we don't exceed the limit. Re-use existing parameters if possible.
|
||||||
|
// - Register the Dimension in GA Console to make it visible in reports.
|
||||||
|
|
||||||
|
export const GA_DIMENSIONS = {
|
||||||
|
TYPE: 'type',
|
||||||
|
ACTION: 'action',
|
||||||
|
VALUE: 'value',
|
||||||
|
START_TIME_MS: 'start_time_ms',
|
||||||
|
DURATION_MS: 'duration_ms',
|
||||||
|
END_TIME_MS: 'end_time_ms',
|
||||||
|
};
|
||||||
|
|
||||||
|
// import getConnectionSpeed from 'util/detect-user-bandwidth';
|
||||||
|
|
||||||
|
// let userDownloadBandwidthInBitsPerSecond;
|
||||||
|
// async function getUserBandwidth() {
|
||||||
|
// userDownloadBandwidthInBitsPerSecond = await getConnectionSpeed();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// get user bandwidth every minute, starting after an initial one minute wait
|
||||||
|
// setInterval(getUserBandwidth, 1000 * 60);
|
||||||
|
|
||||||
const isProduction = process.env.NODE_ENV === 'production';
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
const devInternalApis = process.env.LBRY_API_URL && process.env.LBRY_API_URL.includes('dev');
|
const devInternalApis = process.env.LBRY_API_URL && process.env.LBRY_API_URL.includes('dev');
|
||||||
|
|
||||||
export const SHARE_INTERNAL = 'shareInternal';
|
export const SHARE_INTERNAL = 'shareInternal';
|
||||||
const SHARE_THIRD_PARTY = 'shareThirdParty';
|
|
||||||
|
|
||||||
if (isProduction) {
|
const WATCHMAN_BACKEND_ENDPOINT = 'https://watchman.na-backend.odysee.com/reports/playback';
|
||||||
ElectronCookies.enable({
|
const SEND_DATA_TO_WATCHMAN_INTERVAL = 10; // in seconds
|
||||||
origin: 'https://lbry.tv',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
type Analytics = {
|
type Analytics = {
|
||||||
|
appStartTime: number,
|
||||||
|
eventStartTime: any,
|
||||||
error: (string) => Promise<any>,
|
error: (string) => Promise<any>,
|
||||||
sentryError: ({} | string, {}) => Promise<any>,
|
sentryError: ({} | string, {}) => Promise<any>,
|
||||||
pageView: (string, ?string) => void,
|
|
||||||
setUser: (Object) => void,
|
setUser: (Object) => void,
|
||||||
toggleInternal: (boolean, ?boolean) => void,
|
toggleInternal: (boolean, ?boolean) => void,
|
||||||
apiLogView: (string, string, string, ?number, ?() => void) => Promise<any>,
|
apiLogView: (string, string, string, ?number, ?() => void) => Promise<any>,
|
||||||
apiLogPublish: (ChannelClaim | StreamClaim) => void,
|
apiLogPublish: (ChannelClaim | StreamClaim) => void,
|
||||||
apiSyncTags: ({}) => void,
|
apiSyncTags: ({}) => void,
|
||||||
tagFollowEvent: (string, boolean, ?string) => void,
|
tagFollowEvent: (string, boolean, ?string) => void,
|
||||||
playerLoadedEvent: (?boolean) => void,
|
playerLoadedEvent: (string, ?boolean) => void,
|
||||||
playerStartedEvent: (?boolean) => void,
|
playerVideoStartedEvent: (?boolean) => void,
|
||||||
videoStartEvent: (string, number, string, number, string, any, number) => void,
|
videoStartEvent: (string, number, string, number, string, any, number) => void,
|
||||||
videoIsPlaying: (boolean, any) => void,
|
videoIsPlaying: (boolean, any) => void,
|
||||||
videoBufferEvent: (
|
videoBufferEvent: (
|
||||||
|
@ -53,13 +78,17 @@ type Analytics = {
|
||||||
readyState: number,
|
readyState: number,
|
||||||
}
|
}
|
||||||
) => Promise<any>,
|
) => Promise<any>,
|
||||||
|
adsFetchedEvent: () => void,
|
||||||
emailProvidedEvent: () => void,
|
emailProvidedEvent: () => void,
|
||||||
emailVerifiedEvent: () => void,
|
emailVerifiedEvent: () => void,
|
||||||
rewardEligibleEvent: () => void,
|
rewardEligibleEvent: () => void,
|
||||||
startupEvent: () => void,
|
initAppStartTime: (startTime: number) => void,
|
||||||
|
startupEvent: (time: number) => void,
|
||||||
|
eventStarted: (name: string, time: number, id?: string) => void,
|
||||||
|
eventCompleted: (name: string, time: number, id?: string) => void,
|
||||||
purchaseEvent: (number) => void,
|
purchaseEvent: (number) => void,
|
||||||
readyEvent: (number) => void,
|
|
||||||
openUrlEvent: (string) => void,
|
openUrlEvent: (string) => void,
|
||||||
|
reportEvent: (string, any) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
type LogPublishParams = {
|
type LogPublishParams = {
|
||||||
|
@ -69,13 +98,145 @@ type LogPublishParams = {
|
||||||
channel_claim_id?: string,
|
channel_claim_id?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
let internalAnalyticsEnabled: boolean = false;
|
let internalAnalyticsEnabled: boolean = IS_WEB || false;
|
||||||
if (window.localStorage.getItem(SHARE_INTERNAL) === 'true') internalAnalyticsEnabled = true;
|
// let thirdPartyAnalyticsEnabled: boolean = IS_WEB || false;
|
||||||
|
|
||||||
|
const isGaAllowed = internalAnalyticsEnabled && isProduction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the mobile device type viewing the data
|
||||||
|
* This function returns one of 'and' (Android), 'ios', or 'web'.
|
||||||
|
*
|
||||||
|
* @returns {String}
|
||||||
|
*/
|
||||||
|
function getDeviceType() {
|
||||||
|
// We may not care what the device is if it's in a web browser. Commenting out for now.
|
||||||
|
// if (!IS_WEB) {
|
||||||
|
// return 'elt';
|
||||||
|
// }
|
||||||
|
// const userAgent = navigator.userAgent || navigator.vendor || window.opera;
|
||||||
|
//
|
||||||
|
// if (/android/i.test(userAgent)) {
|
||||||
|
// return 'adr';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // iOS detection from: http://stackoverflow.com/a/9039885/177710
|
||||||
|
// if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
|
||||||
|
// return 'ios';
|
||||||
|
// }
|
||||||
|
|
||||||
|
// default as web, this can be optimized
|
||||||
|
if (!IS_WEB) {
|
||||||
|
return 'dsk';
|
||||||
|
}
|
||||||
|
return 'web';
|
||||||
|
}
|
||||||
|
// variables initialized for watchman
|
||||||
|
let amountOfBufferEvents = 0;
|
||||||
|
let amountOfBufferTimeInMS = 0;
|
||||||
|
let videoType, userId, claimUrl, playerPoweredBy, videoPlayer, bitrateAsBitsPerSecond;
|
||||||
|
let lastSentTime;
|
||||||
|
|
||||||
|
// calculate data for backend, send them, and reset buffer data for next interval
|
||||||
|
async function sendAndResetWatchmanData() {
|
||||||
|
if (!userId) {
|
||||||
|
return 'Can only be used with a user id';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!videoPlayer) {
|
||||||
|
return 'Video player not initialized';
|
||||||
|
}
|
||||||
|
|
||||||
|
let timeSinceLastIntervalSend = new Date() - lastSentTime;
|
||||||
|
lastSentTime = new Date();
|
||||||
|
|
||||||
|
let protocol;
|
||||||
|
if (videoType === 'application/x-mpegURL') {
|
||||||
|
protocol = 'hls';
|
||||||
|
// get bandwidth if it exists from the texttrack (so it's accurate if user changes quality)
|
||||||
|
// $FlowFixMe
|
||||||
|
bitrateAsBitsPerSecond = videoPlayer.textTracks?.().tracks_[0]?.activeCues[0]?.value?.bandwidth;
|
||||||
|
} else {
|
||||||
|
protocol = 'stb';
|
||||||
|
}
|
||||||
|
|
||||||
|
// current position in video in MS
|
||||||
|
const positionInVideo = Math.round(videoPlayer.currentTime()) * 1000;
|
||||||
|
|
||||||
|
// get the duration marking the time in the video for relative position calculation
|
||||||
|
const totalDurationInSeconds = Math.round(videoPlayer.duration());
|
||||||
|
|
||||||
|
// build object for watchman backend
|
||||||
|
const objectToSend = {
|
||||||
|
rebuf_count: amountOfBufferEvents,
|
||||||
|
rebuf_duration: amountOfBufferTimeInMS,
|
||||||
|
url: claimUrl.replace('lbry://', ''),
|
||||||
|
device: getDeviceType(),
|
||||||
|
duration: timeSinceLastIntervalSend,
|
||||||
|
protocol,
|
||||||
|
player: playerPoweredBy,
|
||||||
|
user_id: userId.toString(),
|
||||||
|
position: Math.round(positionInVideo),
|
||||||
|
rel_position: Math.round((positionInVideo / (totalDurationInSeconds * 1000)) * 100),
|
||||||
|
bitrate: bitrateAsBitsPerSecond,
|
||||||
|
bandwidth: undefined,
|
||||||
|
// ...(userDownloadBandwidthInBitsPerSecond && {bandwidth: userDownloadBandwidthInBitsPerSecond}), // add bandwidth if populated
|
||||||
|
};
|
||||||
|
|
||||||
|
// post to watchman
|
||||||
|
await sendWatchmanData(objectToSend);
|
||||||
|
|
||||||
|
// reset buffer data
|
||||||
|
amountOfBufferEvents = 0;
|
||||||
|
amountOfBufferTimeInMS = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let watchmanInterval;
|
||||||
|
// clear watchman interval and mark it as null (when video paused)
|
||||||
|
function stopWatchmanInterval() {
|
||||||
|
clearInterval(watchmanInterval);
|
||||||
|
watchmanInterval = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates the setInterval that will run send to watchman on recurring basis
|
||||||
|
function startWatchmanIntervalIfNotRunning() {
|
||||||
|
if (!watchmanInterval) {
|
||||||
|
// instantiate the first time to calculate duration from
|
||||||
|
lastSentTime = new Date();
|
||||||
|
|
||||||
|
// only set an interval if analytics are enabled and is prod
|
||||||
|
if (isProduction && IS_WEB) {
|
||||||
|
watchmanInterval = setInterval(sendAndResetWatchmanData, 1000 * SEND_DATA_TO_WATCHMAN_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// post data to the backend
|
||||||
|
async function sendWatchmanData(body) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(WATCHMAN_BACKEND_ENDPOINT, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
} catch (err) {}
|
||||||
|
}
|
||||||
|
|
||||||
const analytics: Analytics = {
|
const analytics: Analytics = {
|
||||||
|
appStartTime: 0,
|
||||||
|
eventStartTime: {},
|
||||||
|
|
||||||
// receive buffer events from tracking plugin and save buffer amounts and times for backend call
|
// receive buffer events from tracking plugin and save buffer amounts and times for backend call
|
||||||
videoBufferEvent: async (claim, data) => {
|
videoBufferEvent: async (claim, data) => {
|
||||||
// stub
|
amountOfBufferEvents = amountOfBufferEvents + 1;
|
||||||
|
amountOfBufferTimeInMS = amountOfBufferTimeInMS + data.bufferDuration;
|
||||||
|
},
|
||||||
|
onDispose: () => {
|
||||||
|
stopWatchmanInterval();
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Is told whether video is being started or paused, and adjusts interval accordingly
|
* Is told whether video is being started or paused, and adjusts interval accordingly
|
||||||
|
@ -83,11 +244,41 @@ const analytics: Analytics = {
|
||||||
* @param {object} passedPlayer - VideoJS Player object
|
* @param {object} passedPlayer - VideoJS Player object
|
||||||
*/
|
*/
|
||||||
videoIsPlaying: (isPlaying, passedPlayer) => {
|
videoIsPlaying: (isPlaying, passedPlayer) => {
|
||||||
// stub
|
let playerIsSeeking = false;
|
||||||
|
// have to use this because videojs pauses/unpauses during seek
|
||||||
|
// sometimes the seeking function isn't populated yet so check for it as well
|
||||||
|
if (passedPlayer && passedPlayer.seeking) {
|
||||||
|
playerIsSeeking = passedPlayer.seeking();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if being paused, and not seeking, send existing data and stop interval
|
||||||
|
if (!isPlaying && !playerIsSeeking) {
|
||||||
|
sendAndResetWatchmanData();
|
||||||
|
stopWatchmanInterval();
|
||||||
|
// if being told to pause, and seeking, send and restart interval
|
||||||
|
} else if (!isPlaying && playerIsSeeking) {
|
||||||
|
sendAndResetWatchmanData();
|
||||||
|
stopWatchmanInterval();
|
||||||
|
startWatchmanIntervalIfNotRunning();
|
||||||
|
// is being told to play, and seeking, don't do anything,
|
||||||
|
// assume it's been started already from pause
|
||||||
|
} else if (isPlaying && playerIsSeeking) {
|
||||||
|
// start but not a seek, assuming a start from paused content
|
||||||
|
} else if (isPlaying && !playerIsSeeking) {
|
||||||
|
startWatchmanIntervalIfNotRunning();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
videoStartEvent: (claimId, timeToStartVideo, poweredBy, passedUserId, canonicalUrl, passedPlayer, videoBitrate) => {
|
videoStartEvent: (claimId, timeToStartVideo, poweredBy, passedUserId, canonicalUrl, passedPlayer, videoBitrate) => {
|
||||||
// sendPromMetric('time_to_start', duration);
|
// populate values for watchman when video starts
|
||||||
sendMatomoEvent('Media', 'TimeToStart', claimId, timeToStartVideo);
|
userId = passedUserId;
|
||||||
|
claimUrl = canonicalUrl;
|
||||||
|
playerPoweredBy = poweredBy;
|
||||||
|
|
||||||
|
videoType = passedPlayer.currentSource().type;
|
||||||
|
videoPlayer = passedPlayer;
|
||||||
|
bitrateAsBitsPerSecond = videoBitrate;
|
||||||
|
|
||||||
|
sendPromMetric('time_to_start', timeToStartVideo);
|
||||||
},
|
},
|
||||||
error: (message) => {
|
error: (message) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
@ -113,36 +304,17 @@ const analytics: Analytics = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
pageView: (path, search) => {
|
|
||||||
if (internalAnalyticsEnabled) {
|
|
||||||
const params: { href: string, customDimensions?: Array<{ id: number, value: ?string }> } = { href: `${path}` };
|
|
||||||
const dimensions = [];
|
|
||||||
const searchParams = search && new URLSearchParams(search);
|
|
||||||
|
|
||||||
if (searchParams && searchParams.get('src')) {
|
|
||||||
dimensions.push({ id: 1, value: searchParams.get('src') });
|
|
||||||
}
|
|
||||||
if (dimensions.length) {
|
|
||||||
params['customDimensions'] = dimensions;
|
|
||||||
}
|
|
||||||
MatomoInstance.trackPageView(params);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setUser: (userId) => {
|
setUser: (userId) => {
|
||||||
if (internalAnalyticsEnabled && userId) {
|
if (isGaAllowed && userId && window.gtag) {
|
||||||
window._paq.push(['setUserId', String(userId)]);
|
window.gtag('set', { user_id: userId });
|
||||||
Native.getAppVersionInfo().then(({ localVersion }) => {
|
|
||||||
sendMatomoEvent('Version', 'Desktop-Version', localVersion);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleInternal: (enabled: boolean): void => {
|
toggleInternal: (enabled: boolean): void => {
|
||||||
internalAnalyticsEnabled = enabled;
|
// Always collect analytics on Odysee for now.
|
||||||
window.localStorage.setItem(SHARE_INTERNAL, enabled);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleThirdParty: (enabled: boolean): void => {
|
toggleThirdParty: (enabled: boolean): void => {
|
||||||
window.localStorage.setItem(SHARE_THIRD_PARTY, enabled);
|
// Always collect analytics on Odysee for now.
|
||||||
},
|
},
|
||||||
|
|
||||||
apiLogView: (uri, outpoint, claimId, timeToStart) => {
|
apiLogView: (uri, outpoint, claimId, timeToStart) => {
|
||||||
|
@ -159,7 +331,8 @@ const analytics: Analytics = {
|
||||||
claim_id: claimId,
|
claim_id: claimId,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (timeToStart) {
|
// lbry.tv streams from AWS so we don't care about the time to start
|
||||||
|
if (timeToStart && !IS_WEB) {
|
||||||
params.time_to_start = timeToStart;
|
params.time_to_start = timeToStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,73 +371,126 @@ const analytics: Analytics = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
adsFetchedEvent: () => {
|
adsFetchedEvent: () => {
|
||||||
sendMatomoEvent('Media', 'AdsFetched');
|
sendGaEvent('ad_fetched');
|
||||||
},
|
},
|
||||||
adsReceivedEvent: (response) => {
|
playerLoadedEvent: (renderMode, embedded) => {
|
||||||
sendMatomoEvent('Media', 'AdsReceived', JSON.stringify(response));
|
const RENDER_MODE_TO_EVENT = (renderMode) => {
|
||||||
|
switch (renderMode) {
|
||||||
|
case RENDER_MODES.VIDEO:
|
||||||
|
return 'loaded_video';
|
||||||
|
case RENDER_MODES.AUDIO:
|
||||||
|
return 'loaded_audio';
|
||||||
|
case RENDER_MODES.MARKDOWN:
|
||||||
|
return 'loaded_markdown';
|
||||||
|
case RENDER_MODES.IMAGE:
|
||||||
|
return 'loaded_image';
|
||||||
|
default:
|
||||||
|
return 'loaded_misc';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sendGaEvent('player', {
|
||||||
|
[GA_DIMENSIONS.ACTION]: RENDER_MODE_TO_EVENT(renderMode),
|
||||||
|
[GA_DIMENSIONS.TYPE]: embedded ? 'embedded' : 'onsite',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
adsErrorEvent: (response) => {
|
playerVideoStartedEvent: (embedded) => {
|
||||||
sendMatomoEvent('Media', 'AdsError', JSON.stringify(response));
|
sendGaEvent('player', {
|
||||||
},
|
[GA_DIMENSIONS.ACTION]: 'started_video',
|
||||||
playerLoadedEvent: (embedded) => {
|
[GA_DIMENSIONS.TYPE]: embedded ? 'embedded' : 'onsite',
|
||||||
sendMatomoEvent('Player', 'Loaded', embedded ? 'embedded' : 'onsite');
|
});
|
||||||
},
|
|
||||||
playerStartedEvent: (embedded) => {
|
|
||||||
sendMatomoEvent('Player', 'Started', embedded ? 'embedded' : 'onsite');
|
|
||||||
},
|
},
|
||||||
tagFollowEvent: (tag, following) => {
|
tagFollowEvent: (tag, following) => {
|
||||||
sendMatomoEvent('Tag', following ? 'Tag-Follow' : 'Tag-Unfollow', tag);
|
sendGaEvent('tags', {
|
||||||
},
|
[GA_DIMENSIONS.ACTION]: following ? 'follow' : 'unfollow',
|
||||||
channelBlockEvent: (uri, blocked, location) => {
|
[GA_DIMENSIONS.VALUE]: tag,
|
||||||
sendMatomoEvent(blocked ? 'Channel-Hidden' : 'Channel-Unhidden', uri);
|
});
|
||||||
},
|
},
|
||||||
emailProvidedEvent: () => {
|
emailProvidedEvent: () => {
|
||||||
sendMatomoEvent('Engagement', 'Email-Provided');
|
sendGaEvent('engagement', {
|
||||||
|
[GA_DIMENSIONS.TYPE]: 'email_provided',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
emailVerifiedEvent: () => {
|
emailVerifiedEvent: () => {
|
||||||
sendMatomoEvent('Engagement', 'Email-Verified');
|
sendGaEvent('engagement', {
|
||||||
|
[GA_DIMENSIONS.TYPE]: 'email_verified',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
rewardEligibleEvent: () => {
|
rewardEligibleEvent: () => {
|
||||||
sendMatomoEvent('Engagement', 'Reward-Eligible');
|
sendGaEvent('engagement', {
|
||||||
|
[GA_DIMENSIONS.TYPE]: 'reward_eligible',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
openUrlEvent: (url: string) => {
|
openUrlEvent: (url: string) => {
|
||||||
sendMatomoEvent('Engagement', 'Open-Url', url);
|
sendGaEvent('engagement', {
|
||||||
|
[GA_DIMENSIONS.TYPE]: 'open_url',
|
||||||
|
url,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
trendingAlgorithmEvent: (trendingAlgorithm: string) => {
|
trendingAlgorithmEvent: (trendingAlgorithm: string) => {
|
||||||
sendMatomoEvent('Engagement', 'Trending-Algorithm', trendingAlgorithm);
|
sendGaEvent('engagement', {
|
||||||
|
[GA_DIMENSIONS.TYPE]: 'trending_algorithm',
|
||||||
|
trending_algorithm: trendingAlgorithm,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
startupEvent: () => {
|
initAppStartTime: (startTime: number) => {
|
||||||
sendMatomoEvent('Startup', 'Startup');
|
analytics.appStartTime = startTime;
|
||||||
},
|
},
|
||||||
readyEvent: (timeToReady: number) => {
|
startupEvent: (time: number) => {
|
||||||
sendMatomoEvent('Startup', 'App-Ready', 'Time', timeToReady);
|
if (analytics.appStartTime !== 0) {
|
||||||
|
sendGaEvent('diag_app_ready', {
|
||||||
|
[GA_DIMENSIONS.DURATION_MS]: time - analytics.appStartTime,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
eventStarted: (name: string, time: number, id?: string) => {
|
||||||
|
const key = id || name;
|
||||||
|
analytics.eventStartTime[key] = time;
|
||||||
|
},
|
||||||
|
eventCompleted: (name: string, time: number, id?: string) => {
|
||||||
|
const key = id || name;
|
||||||
|
if (analytics.eventStartTime[key]) {
|
||||||
|
sendGaEvent(name, {
|
||||||
|
[GA_DIMENSIONS.START_TIME_MS]: analytics.eventStartTime[key] - analytics.appStartTime,
|
||||||
|
[GA_DIMENSIONS.DURATION_MS]: time - analytics.eventStartTime[key],
|
||||||
|
[GA_DIMENSIONS.END_TIME_MS]: time - analytics.appStartTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
delete analytics.eventStartTime[key];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
purchaseEvent: (purchaseInt: number) => {
|
purchaseEvent: (purchaseInt: number) => {
|
||||||
sendMatomoEvent('Purchase', 'Purchase-Complete', 'someLabel', purchaseInt);
|
sendGaEvent('purchase', {
|
||||||
|
// https://developers.google.com/analytics/devguides/collection/ga4/reference/events#purchase
|
||||||
|
[GA_DIMENSIONS.VALUE]: purchaseInt,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
reportEvent: (event: string, params?: { [string]: string | number }) => {
|
||||||
|
sendGaEvent(event, params);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function sendMatomoEvent(category, action, name, value) {
|
function sendGaEvent(event: string, params?: { [string]: string | number }) {
|
||||||
if (internalAnalyticsEnabled) {
|
if (isGaAllowed && window.gtag) {
|
||||||
const event = { category, action, name, value };
|
window.gtag('event', event, params);
|
||||||
MatomoInstance.trackEvent(event);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MatomoInstance = new MatomoTracker({
|
function sendPromMetric(name: string, value?: number) {
|
||||||
urlBase: MATOMO_URL,
|
if (IS_WEB) {
|
||||||
siteId: MATOMO_ID, // optional, default value: `1`
|
let url = new URL(SDK_API_PATH + '/metric/ui');
|
||||||
});
|
const params = { name: name, value: value ? value.toString() : '' };
|
||||||
|
url.search = new URLSearchParams(params).toString();
|
||||||
analytics.pageView(generateInitialUrl(window.location.hash));
|
return fetch(url, { method: 'post' });
|
||||||
|
}
|
||||||
// Listen for url changes and report
|
}
|
||||||
// This will include search queries
|
|
||||||
history.listen((location) => {
|
// Activate
|
||||||
const { pathname, search } = location;
|
if (isGaAllowed && window.gtag) {
|
||||||
|
window.gtag('consent', 'update', {
|
||||||
const page = `${pathname}${search}`;
|
ad_storage: 'granted',
|
||||||
analytics.pageView(page, search);
|
analytics_storage: 'granted',
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export default analytics;
|
export default analytics;
|
||||||
|
|
|
@ -1,8 +1,3 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import IframeReact from './view';
|
import IframeReact from './view';
|
||||||
|
|
||||||
const select = state => ({});
|
export default IframeReact;
|
||||||
|
|
||||||
const perform = () => ({});
|
|
||||||
|
|
||||||
export default connect(select, perform)(IframeReact);
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import AbandonedChannelPreview from './view';
|
import AbandonedChannelPreview from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({});
|
export default AbandonedChannelPreview;
|
||||||
|
|
||||||
export default connect(select)(AbandonedChannelPreview);
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { hot } from 'react-hot-loader/root';
|
import { hot } from 'react-hot-loader/root';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { selectUploadCount } from 'lbryinc';
|
||||||
import { selectGetSyncErrorMessage, selectSyncFatalError } from 'redux/selectors/sync';
|
import { selectGetSyncErrorMessage, selectSyncFatalError } from 'redux/selectors/sync';
|
||||||
import { doFetchAccessToken, doUserSetReferrer } from 'redux/actions/user';
|
import { doFetchAccessToken, doUserSetReferrer } from 'redux/actions/user';
|
||||||
import { selectUser, selectAccessToken, selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUser, selectAccessToken, selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
import { selectUnclaimedRewards } from 'redux/selectors/rewards';
|
import { selectUnclaimedRewards } from 'redux/selectors/rewards';
|
||||||
import { doFetchChannelListMine, doFetchCollectionListMine, doResolveUris } from 'redux/actions/claims';
|
import { doFetchChannelListMine, doFetchCollectionListMine, doResolveUris } from 'redux/actions/claims';
|
||||||
import { selectMyChannelUrls, selectMyChannelClaimIds } from 'redux/selectors/claims';
|
import { selectMyChannelUrls } from 'redux/selectors/claims';
|
||||||
import * as SETTINGS from 'constants/settings';
|
import * as SETTINGS from 'constants/settings';
|
||||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
import {
|
import {
|
||||||
|
@ -19,7 +20,7 @@ import {
|
||||||
selectAutoUpdateDownloaded,
|
selectAutoUpdateDownloaded,
|
||||||
selectModal,
|
selectModal,
|
||||||
selectActiveChannelClaim,
|
selectActiveChannelClaim,
|
||||||
selectIsUpdateModalDisplayed,
|
selectIsReloadRequired,
|
||||||
} from 'redux/selectors/app';
|
} from 'redux/selectors/app';
|
||||||
import { doGetWalletSyncPreference, doSetLanguage } from 'redux/actions/settings';
|
import { doGetWalletSyncPreference, doSetLanguage } from 'redux/actions/settings';
|
||||||
import { doSyncLoop } from 'redux/actions/sync';
|
import { doSyncLoop } from 'redux/actions/sync';
|
||||||
|
@ -42,16 +43,16 @@ const select = (state) => ({
|
||||||
languages: selectLoadedLanguages(state),
|
languages: selectLoadedLanguages(state),
|
||||||
autoUpdateDownloaded: selectAutoUpdateDownloaded(state),
|
autoUpdateDownloaded: selectAutoUpdateDownloaded(state),
|
||||||
isUpgradeAvailable: selectIsUpgradeAvailable(state),
|
isUpgradeAvailable: selectIsUpgradeAvailable(state),
|
||||||
|
isReloadRequired: selectIsReloadRequired(state),
|
||||||
syncError: selectGetSyncErrorMessage(state),
|
syncError: selectGetSyncErrorMessage(state),
|
||||||
|
uploadCount: selectUploadCount(state),
|
||||||
rewards: selectUnclaimedRewards(state),
|
rewards: selectUnclaimedRewards(state),
|
||||||
isAuthenticated: selectUserVerifiedEmail(state),
|
isAuthenticated: selectUserVerifiedEmail(state),
|
||||||
currentModal: selectModal(state),
|
currentModal: selectModal(state),
|
||||||
syncFatalError: selectSyncFatalError(state),
|
syncFatalError: selectSyncFatalError(state),
|
||||||
activeChannelClaim: selectActiveChannelClaim(state),
|
activeChannelClaim: selectActiveChannelClaim(state),
|
||||||
myChannelUrls: selectMyChannelUrls(state),
|
myChannelUrls: selectMyChannelUrls(state),
|
||||||
myChannelClaimIds: selectMyChannelClaimIds(state),
|
|
||||||
subscriptions: selectSubscriptions(state),
|
subscriptions: selectSubscriptions(state),
|
||||||
isUpdateModalDisplayed: selectIsUpdateModalDisplayed(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import React, { useEffect, useRef, useState, useLayoutEffect } from 'react';
|
import React, { useEffect, useRef, useState, useLayoutEffect } from 'react';
|
||||||
|
import { lazyImport } from 'util/lazyImport';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
import { buildURI, parseURI } from 'util/lbryURI';
|
||||||
|
import { SIMPLE_SITE } from 'config';
|
||||||
|
import Nag from 'component/common/nag';
|
||||||
import Router from 'component/router/index';
|
import Router from 'component/router/index';
|
||||||
import ReactModal from 'react-modal';
|
import ReactModal from 'react-modal';
|
||||||
import { openContextMenu } from 'util/context-menu';
|
import { openContextMenu } from 'util/context-menu';
|
||||||
|
@ -12,17 +16,50 @@ import { withRouter } from 'react-router';
|
||||||
import usePrevious from 'effects/use-previous';
|
import usePrevious from 'effects/use-previous';
|
||||||
import REWARDS from 'rewards';
|
import REWARDS from 'rewards';
|
||||||
import usePersistedState from 'effects/use-persisted-state';
|
import usePersistedState from 'effects/use-persisted-state';
|
||||||
|
import Spinner from 'component/spinner';
|
||||||
import LANGUAGES from 'constants/languages';
|
import LANGUAGES from 'constants/languages';
|
||||||
|
|
||||||
|
// @if TARGET='app'
|
||||||
import useZoom from 'effects/use-zoom';
|
import useZoom from 'effects/use-zoom';
|
||||||
import useHistoryNav from 'effects/use-history-nav';
|
import useHistoryNav from 'effects/use-history-nav';
|
||||||
|
// @endif
|
||||||
|
|
||||||
|
// @if TARGET='web'
|
||||||
|
import {
|
||||||
|
useDegradedPerformance,
|
||||||
|
STATUS_OK,
|
||||||
|
STATUS_DEGRADED,
|
||||||
|
STATUS_FAILING,
|
||||||
|
STATUS_DOWN,
|
||||||
|
} from 'web/effects/use-degraded-performance';
|
||||||
|
// @endif
|
||||||
|
|
||||||
import LANGUAGE_MIGRATIONS from 'constants/language-migrations';
|
import LANGUAGE_MIGRATIONS from 'constants/language-migrations';
|
||||||
|
|
||||||
import FileDrop from 'component/fileDrop';
|
const FileDrop = lazyImport(() => import('component/fileDrop' /* webpackChunkName: "secondary" */));
|
||||||
import ModalRouter from 'modal/modalRouter';
|
const ModalRouter = lazyImport(() => import('modal/modalRouter' /* webpackChunkName: "secondary" */));
|
||||||
import Nag from 'component/common/nag';
|
const NagContinueFirstRun = lazyImport(() =>
|
||||||
|
import('component/nagContinueFirstRun' /* webpackChunkName: "secondary" */)
|
||||||
|
);
|
||||||
|
const OpenInAppLink = lazyImport(() => import('web/component/openInAppLink' /* webpackChunkName: "secondary" */));
|
||||||
|
|
||||||
import SyncFatalError from 'component/syncFatalError';
|
// @if TARGET='web'
|
||||||
import Yrbl from 'component/yrbl';
|
const NagDataCollection = lazyImport(() =>
|
||||||
|
import('web/component/nag-data-collection' /* webpackChunkName: "secondary" */)
|
||||||
|
);
|
||||||
|
const NagDegradedPerformance = lazyImport(() =>
|
||||||
|
import('web/component/nag-degraded-performance' /* webpackChunkName: "secondary" */)
|
||||||
|
);
|
||||||
|
const NagNoUser = lazyImport(() => import('web/component/nag-no-user' /* webpackChunkName: "nag-no-user" */));
|
||||||
|
const NagSunset = lazyImport(() => import('web/component/nag-sunset' /* webpackChunkName: "nag-no-user" */));
|
||||||
|
const YoutubeWelcome = lazyImport(() =>
|
||||||
|
import('web/component/youtubeReferralWelcome' /* webpackChunkName: "secondary" */)
|
||||||
|
);
|
||||||
|
|
||||||
|
// @endif
|
||||||
|
|
||||||
|
const SyncFatalError = lazyImport(() => import('component/syncFatalError' /* webpackChunkName: "syncFatalError" */));
|
||||||
|
const Yrbl = lazyImport(() => import('component/yrbl' /* webpackChunkName: "yrbl" */));
|
||||||
|
|
||||||
// ****************************************************************************
|
// ****************************************************************************
|
||||||
|
|
||||||
|
@ -33,6 +70,8 @@ export const IS_MAC = navigator.userAgent.indexOf('Mac OS X') !== -1;
|
||||||
const MOUSE_BACK_BTN = 3;
|
const MOUSE_BACK_BTN = 3;
|
||||||
const MOUSE_FORWARD_BTN = 4;
|
const MOUSE_FORWARD_BTN = 4;
|
||||||
|
|
||||||
|
const imaLibraryPath = 'https://imasdk.googleapis.com/js/sdkloader/ima3.js';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
language: string,
|
language: string,
|
||||||
languages: Array<string>,
|
languages: Array<string>,
|
||||||
|
@ -54,6 +93,7 @@ type Props = {
|
||||||
onSignedIn: () => void,
|
onSignedIn: () => void,
|
||||||
setLanguage: (string) => void,
|
setLanguage: (string) => void,
|
||||||
isUpgradeAvailable: boolean,
|
isUpgradeAvailable: boolean,
|
||||||
|
isReloadRequired: boolean,
|
||||||
autoUpdateDownloaded: boolean,
|
autoUpdateDownloaded: boolean,
|
||||||
updatePreferences: () => Promise<any>,
|
updatePreferences: () => Promise<any>,
|
||||||
getWalletSyncPref: () => Promise<any>,
|
getWalletSyncPref: () => Promise<any>,
|
||||||
|
@ -68,15 +108,14 @@ type Props = {
|
||||||
syncLoop: (?boolean) => void,
|
syncLoop: (?boolean) => void,
|
||||||
currentModal: any,
|
currentModal: any,
|
||||||
syncFatalError: boolean,
|
syncFatalError: boolean,
|
||||||
activeChannelId: ?string,
|
activeChannelClaim: ?ChannelClaim,
|
||||||
myChannelClaimIds: ?Array<string>,
|
myChannelUrls: ?Array<string>,
|
||||||
subscriptions: Array<Subscription>,
|
subscriptions: Array<Subscription>,
|
||||||
setActiveChannelIfNotSet: () => void,
|
setActiveChannelIfNotSet: () => void,
|
||||||
setIncognito: (boolean) => void,
|
setIncognito: (boolean) => void,
|
||||||
fetchModBlockedList: () => void,
|
fetchModBlockedList: () => void,
|
||||||
resolveUris: (Array<string>) => void,
|
resolveUris: (Array<string>) => void,
|
||||||
fetchModAmIList: () => void,
|
fetchModAmIList: () => void,
|
||||||
isUpdateModalDisplayed: boolean,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function App(props: Props) {
|
function App(props: Props) {
|
||||||
|
@ -89,6 +128,7 @@ function App(props: Props) {
|
||||||
signIn,
|
signIn,
|
||||||
autoUpdateDownloaded,
|
autoUpdateDownloaded,
|
||||||
isUpgradeAvailable,
|
isUpgradeAvailable,
|
||||||
|
isReloadRequired,
|
||||||
requestDownloadUpgrade,
|
requestDownloadUpgrade,
|
||||||
uploadCount,
|
uploadCount,
|
||||||
history,
|
history,
|
||||||
|
@ -104,15 +144,14 @@ function App(props: Props) {
|
||||||
syncLoop,
|
syncLoop,
|
||||||
currentModal,
|
currentModal,
|
||||||
syncFatalError,
|
syncFatalError,
|
||||||
myChannelClaimIds,
|
myChannelUrls,
|
||||||
activeChannelId,
|
activeChannelClaim,
|
||||||
setActiveChannelIfNotSet,
|
setActiveChannelIfNotSet,
|
||||||
setIncognito,
|
setIncognito,
|
||||||
fetchModBlockedList,
|
fetchModBlockedList,
|
||||||
resolveUris,
|
resolveUris,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
fetchModAmIList,
|
fetchModAmIList,
|
||||||
isUpdateModalDisplayed,
|
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const appRef = useRef();
|
const appRef = useRef();
|
||||||
|
@ -124,26 +163,45 @@ function App(props: Props) {
|
||||||
const isRewardApproved = user && user.is_reward_approved;
|
const isRewardApproved = user && user.is_reward_approved;
|
||||||
const previousHasVerifiedEmail = usePrevious(hasVerifiedEmail);
|
const previousHasVerifiedEmail = usePrevious(hasVerifiedEmail);
|
||||||
const previousRewardApproved = usePrevious(isRewardApproved);
|
const previousRewardApproved = usePrevious(isRewardApproved);
|
||||||
const { pathname, search } = props.location;
|
// @if TARGET='web'
|
||||||
|
const [showAnalyticsNag, setShowAnalyticsNag] = usePersistedState('analytics-nag', true);
|
||||||
|
const [lbryTvApiStatus, setLbryTvApiStatus] = useState(STATUS_OK);
|
||||||
|
// @endif
|
||||||
|
const { pathname, hash, search } = props.location;
|
||||||
const [upgradeNagClosed, setUpgradeNagClosed] = useState(false);
|
const [upgradeNagClosed, setUpgradeNagClosed] = useState(false);
|
||||||
const [resolvedSubscriptions, setResolvedSubscriptions] = useState(false);
|
const [resolvedSubscriptions, setResolvedSubscriptions] = useState(false);
|
||||||
// const [retryingSync, setRetryingSync] = useState(false);
|
|
||||||
const [langRenderKey, setLangRenderKey] = useState(0);
|
|
||||||
const [sidebarOpen] = usePersistedState('sidebar', true);
|
const [sidebarOpen] = usePersistedState('sidebar', true);
|
||||||
const showUpgradeButton = (autoUpdateDownloaded || isUpgradeAvailable) && !upgradeNagClosed;
|
const [seenSunsestMessage, setSeenSunsetMessage] = usePersistedState('lbrytv-sunset', false);
|
||||||
|
const showUpgradeButton =
|
||||||
|
(autoUpdateDownloaded || (process.platform === 'linux' && isUpgradeAvailable)) && !upgradeNagClosed;
|
||||||
// referral claiming
|
// referral claiming
|
||||||
const referredRewardAvailable = rewards && rewards.some((reward) => reward.reward_type === REWARDS.TYPE_REFEREE);
|
const referredRewardAvailable = rewards && rewards.some((reward) => reward.reward_type === REWARDS.TYPE_REFEREE);
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
const rawReferrerParam = urlParams.get('r');
|
const rawReferrerParam = urlParams.get('r');
|
||||||
|
const fromLbrytvParam = urlParams.get('sunset');
|
||||||
const sanitizedReferrerParam = rawReferrerParam && rawReferrerParam.replace(':', '#');
|
const sanitizedReferrerParam = rawReferrerParam && rawReferrerParam.replace(':', '#');
|
||||||
|
const shouldHideNag = pathname.startsWith(`/$/${PAGES.EMBED}`) || pathname.startsWith(`/$/${PAGES.AUTH_VERIFY}`);
|
||||||
const userId = user && user.id;
|
const userId = user && user.id;
|
||||||
const useCustomScrollbar = !IS_MAC;
|
const useCustomScrollbar = !IS_MAC;
|
||||||
const hasMyChannels = myChannelClaimIds && myChannelClaimIds.length > 0;
|
const hasMyChannels = myChannelUrls && myChannelUrls.length > 0;
|
||||||
const hasNoChannels = myChannelClaimIds && myChannelClaimIds.length === 0;
|
const hasNoChannels = myChannelUrls && myChannelUrls.length === 0;
|
||||||
const shouldMigrateLanguage = LANGUAGE_MIGRATIONS[language];
|
const shouldMigrateLanguage = LANGUAGE_MIGRATIONS[language];
|
||||||
const hasActiveChannelClaim = activeChannelId !== undefined;
|
const hasActiveChannelClaim = activeChannelClaim !== undefined;
|
||||||
const isPersonalized = hasVerifiedEmail;
|
const isPersonalized = !IS_WEB || hasVerifiedEmail;
|
||||||
|
const renderFiledrop = !IS_WEB || isAuthenticated;
|
||||||
|
|
||||||
|
let uri;
|
||||||
|
try {
|
||||||
|
const newpath = buildURI(parseURI(pathname.slice(1).replace(/:/g, '#')));
|
||||||
|
uri = newpath + hash;
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
// @if TARGET='web'
|
||||||
|
function handleAnalyticsDismiss() {
|
||||||
|
setShowAnalyticsNag(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @endif
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userId) {
|
if (userId) {
|
||||||
analytics.setUser(userId);
|
analytics.setUser(userId);
|
||||||
|
@ -154,7 +212,7 @@ function App(props: Props) {
|
||||||
if (!uploadCount) return;
|
if (!uploadCount) return;
|
||||||
const handleBeforeUnload = (event) => {
|
const handleBeforeUnload = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.returnValue = __('There are pending uploads.'); // without setting this to something it doesn't work
|
event.returnValue = 'magic'; // without setting this to something it doesn't work
|
||||||
};
|
};
|
||||||
window.addEventListener('beforeunload', handleBeforeUnload);
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||||
return () => window.removeEventListener('beforeunload', handleBeforeUnload);
|
return () => window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
@ -274,6 +332,22 @@ function App(props: Props) {
|
||||||
}
|
}
|
||||||
}, [previousRewardApproved, isRewardApproved]);
|
}, [previousRewardApproved, isRewardApproved]);
|
||||||
|
|
||||||
|
// Load IMA3 SDK for aniview
|
||||||
|
// @if TARGET='web'
|
||||||
|
useEffect(() => {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = imaLibraryPath;
|
||||||
|
script.async = true;
|
||||||
|
// $FlowFixMe
|
||||||
|
document.body.appendChild(script);
|
||||||
|
return () => {
|
||||||
|
// $FlowFixMe
|
||||||
|
document.body.removeChild(script);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
// @endif
|
||||||
|
|
||||||
|
// @if TARGET='app'
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (updatePreferences && getWalletSyncPref && readyForPrefs) {
|
if (updatePreferences && getWalletSyncPref && readyForPrefs) {
|
||||||
getWalletSyncPref()
|
getWalletSyncPref()
|
||||||
|
@ -283,14 +357,24 @@ function App(props: Props) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [updatePreferences, getWalletSyncPref, setReadyForSync, readyForPrefs, hasVerifiedEmail]);
|
}, [updatePreferences, getWalletSyncPref, setReadyForSync, readyForPrefs, hasVerifiedEmail]);
|
||||||
|
// @endif
|
||||||
|
|
||||||
// ready for sync syncs, however after signin when hasVerifiedEmail, that syncs too.
|
// ready for sync syncs, however after signin when hasVerifiedEmail, that syncs too.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// signInSyncPref is cleared after sharedState loop.
|
// signInSyncPref is cleared after sharedState loop.
|
||||||
|
const syncLoopWithoutInterval = () => syncLoop(true);
|
||||||
if (readyForSync && hasVerifiedEmail) {
|
if (readyForSync && hasVerifiedEmail) {
|
||||||
// In case we are syncing.
|
// In case we are syncing.
|
||||||
syncLoop();
|
syncLoop();
|
||||||
|
// @if TARGET='web'
|
||||||
|
window.addEventListener('focus', syncLoopWithoutInterval);
|
||||||
|
// @endif
|
||||||
}
|
}
|
||||||
|
// @if TARGET='web'
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('focus', syncLoopWithoutInterval);
|
||||||
|
};
|
||||||
|
// @endif
|
||||||
}, [readyForSync, hasVerifiedEmail, syncLoop]);
|
}, [readyForSync, hasVerifiedEmail, syncLoop]);
|
||||||
|
|
||||||
// We know someone is logging in or not when we get their user object
|
// We know someone is logging in or not when we get their user object
|
||||||
|
@ -314,6 +398,7 @@ function App(props: Props) {
|
||||||
if (!hasSignedIn && hasVerifiedEmail) {
|
if (!hasSignedIn && hasVerifiedEmail) {
|
||||||
signIn();
|
signIn();
|
||||||
setHasSignedIn(true);
|
setHasSignedIn(true);
|
||||||
|
if (IS_WEB) setReadyForSync(true);
|
||||||
}
|
}
|
||||||
}, [hasVerifiedEmail, signIn, hasSignedIn]);
|
}, [hasVerifiedEmail, signIn, hasSignedIn]);
|
||||||
|
|
||||||
|
@ -327,32 +412,67 @@ function App(props: Props) {
|
||||||
}
|
}
|
||||||
}, [sidebarOpen, isPersonalized, resolvedSubscriptions, subscriptions, resolveUris, setResolvedSubscriptions]);
|
}, [sidebarOpen, isPersonalized, resolvedSubscriptions, subscriptions, resolveUris, setResolvedSubscriptions]);
|
||||||
|
|
||||||
useEffect(() => {
|
// @if TARGET='web'
|
||||||
// When language is changed or translations are fetched, we render.
|
useDegradedPerformance(setLbryTvApiStatus, user);
|
||||||
setLangRenderKey(Date.now());
|
// @endif
|
||||||
}, [language, languages]);
|
|
||||||
|
// @if TARGET='web'
|
||||||
|
// Require an internal-api user on lbry.tv
|
||||||
|
// This also prevents the site from loading in the un-authed state while we wait for internal-apis to return for the first time
|
||||||
|
// It's not needed on desktop since there is no un-authed state
|
||||||
|
if (user === undefined) {
|
||||||
|
return (
|
||||||
|
<div className="main--empty">
|
||||||
|
<Spinner delayed />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// @endif
|
||||||
|
|
||||||
if (syncFatalError) {
|
if (syncFatalError) {
|
||||||
return <SyncFatalError />;
|
return (
|
||||||
|
<React.Suspense fallback={null}>
|
||||||
|
<SyncFatalError
|
||||||
|
// @if TARGET='web'
|
||||||
|
lbryTvApiStatus={lbryTvApiStatus}
|
||||||
|
// @endif
|
||||||
|
/>
|
||||||
|
</React.Suspense>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classnames(MAIN_WRAPPER_CLASS, {
|
className={classnames(MAIN_WRAPPER_CLASS, {
|
||||||
|
// @if TARGET='app'
|
||||||
[`${MAIN_WRAPPER_CLASS}--mac`]: IS_MAC,
|
[`${MAIN_WRAPPER_CLASS}--mac`]: IS_MAC,
|
||||||
|
// @endif
|
||||||
[`${MAIN_WRAPPER_CLASS}--scrollbar`]: useCustomScrollbar,
|
[`${MAIN_WRAPPER_CLASS}--scrollbar`]: useCustomScrollbar,
|
||||||
})}
|
})}
|
||||||
ref={appRef}
|
ref={appRef}
|
||||||
key={langRenderKey}
|
onContextMenu={IS_WEB ? undefined : (e) => openContextMenu(e)}
|
||||||
onContextMenu={(e) => openContextMenu(e)}
|
|
||||||
>
|
>
|
||||||
|
{IS_WEB && lbryTvApiStatus === STATUS_DOWN ? (
|
||||||
|
<React.Suspense fallback={null}>
|
||||||
|
<Yrbl
|
||||||
|
className="main--empty"
|
||||||
|
title={__('lbry.tv is currently down')}
|
||||||
|
subtitle={__('My wheel broke, but the good news is that someone from LBRY is working on it.')}
|
||||||
|
/>
|
||||||
|
</React.Suspense>
|
||||||
|
) : (
|
||||||
|
<React.Fragment>
|
||||||
<Router />
|
<Router />
|
||||||
|
<React.Suspense fallback={null}>
|
||||||
<ModalRouter />
|
<ModalRouter />
|
||||||
<FileDrop />
|
{renderFiledrop && <FileDrop />}
|
||||||
|
</React.Suspense>
|
||||||
<FileRenderFloating />
|
<FileRenderFloating />
|
||||||
|
<React.Suspense fallback={null}>
|
||||||
{isEnhancedLayout && <Yrbl className="yrbl--enhanced" />}
|
{isEnhancedLayout && <Yrbl className="yrbl--enhanced" />}
|
||||||
|
|
||||||
{showUpgradeButton && !isUpdateModalDisplayed && (
|
{/* @if TARGET='app' */}
|
||||||
|
{showUpgradeButton && (
|
||||||
<Nag
|
<Nag
|
||||||
message={__('An upgrade is available.')}
|
message={__('An upgrade is available.')}
|
||||||
actionText={__('Install Now')}
|
actionText={__('Install Now')}
|
||||||
|
@ -360,6 +480,34 @@ function App(props: Props) {
|
||||||
onClose={() => setUpgradeNagClosed(true)}
|
onClose={() => setUpgradeNagClosed(true)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{/* @endif */}
|
||||||
|
|
||||||
|
{/* @if TARGET='web' */}
|
||||||
|
<YoutubeWelcome />
|
||||||
|
{!SIMPLE_SITE && !shouldHideNag && <OpenInAppLink uri={uri} />}
|
||||||
|
{!shouldHideNag && <NagContinueFirstRun />}
|
||||||
|
{fromLbrytvParam && !seenSunsestMessage && !shouldHideNag && (
|
||||||
|
<NagSunset email={hasVerifiedEmail} onClose={() => setSeenSunsetMessage(true)} />
|
||||||
|
)}
|
||||||
|
{(lbryTvApiStatus === STATUS_DEGRADED || lbryTvApiStatus === STATUS_FAILING) && !shouldHideNag && (
|
||||||
|
<NagDegradedPerformance onClose={() => setLbryTvApiStatus(STATUS_OK)} />
|
||||||
|
)}
|
||||||
|
{!SIMPLE_SITE && lbryTvApiStatus === STATUS_OK && showAnalyticsNag && !shouldHideNag && (
|
||||||
|
<NagDataCollection onClose={handleAnalyticsDismiss} />
|
||||||
|
)}
|
||||||
|
{user === null && <NagNoUser />}
|
||||||
|
{/* @endif */}
|
||||||
|
</React.Suspense>
|
||||||
|
|
||||||
|
{isReloadRequired && (
|
||||||
|
<Nag
|
||||||
|
message={__('A new version of Odysee is available.')}
|
||||||
|
actionText={__('Refresh')}
|
||||||
|
onClick={() => window.location.reload()}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import StorageViz from './view';
|
|
||||||
import {
|
|
||||||
selectViewBlobSpace,
|
|
||||||
selectViewHostingLimit,
|
|
||||||
selectAutoBlobSpace,
|
|
||||||
selectPrivateBlobSpace,
|
|
||||||
selectAutoHostingLimit,
|
|
||||||
} from 'redux/selectors/settings';
|
|
||||||
import { selectDiskSpace } from 'redux/selectors/app';
|
|
||||||
|
|
||||||
const select = (state) => ({
|
|
||||||
diskSpace: selectDiskSpace(state),
|
|
||||||
viewHostingLimit: selectViewHostingLimit(state),
|
|
||||||
autoHostingLimit: selectAutoHostingLimit(state),
|
|
||||||
viewBlobSpace: selectViewBlobSpace(state),
|
|
||||||
autoBlobSpace: selectAutoBlobSpace(state),
|
|
||||||
privateBlobSpace: selectPrivateBlobSpace(state),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(select)(StorageViz);
|
|
|
@ -1,130 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from 'react';
|
|
||||||
import I18nMessage from 'component/i18nMessage';
|
|
||||||
import { ipcRenderer } from 'electron';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
// --- select ---
|
|
||||||
diskSpace: DiskSpace, // KB
|
|
||||||
viewHostingLimit: number, // MB
|
|
||||||
autoHostingLimit: number,
|
|
||||||
viewBlobSpace: number,
|
|
||||||
autoBlobSpace: number,
|
|
||||||
privateBlobSpace: number,
|
|
||||||
};
|
|
||||||
|
|
||||||
function StorageViz(props: Props) {
|
|
||||||
const { diskSpace, viewHostingLimit, autoHostingLimit, viewBlobSpace, autoBlobSpace, privateBlobSpace } = props;
|
|
||||||
React.useEffect(() => {
|
|
||||||
ipcRenderer.send('get-disk-space');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (!diskSpace || !diskSpace.total) {
|
|
||||||
return (
|
|
||||||
<div className={'storage__wrapper'}>
|
|
||||||
<div className={'storage__bar'}>
|
|
||||||
<div className="help">{__('Cannot get disk space information.')}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalMB = diskSpace && Math.floor(diskSpace.total / 1024);
|
|
||||||
const freeMB = diskSpace && Math.floor(diskSpace.free / 1024);
|
|
||||||
const otherMB = totalMB - (freeMB + viewBlobSpace + autoBlobSpace + privateBlobSpace);
|
|
||||||
const autoFree = autoHostingLimit - autoBlobSpace;
|
|
||||||
const viewFree = viewHostingLimit > 0 ? viewHostingLimit - viewBlobSpace : freeMB - autoFree;
|
|
||||||
const unallocFree = freeMB - viewFree - autoFree;
|
|
||||||
const viewLimit =
|
|
||||||
viewHostingLimit === 0
|
|
||||||
? freeMB - (autoHostingLimit - autoBlobSpace) + viewBlobSpace
|
|
||||||
: viewHostingLimit + viewBlobSpace;
|
|
||||||
|
|
||||||
const getPercent = (val, lim = totalMB) => (val / lim) * 100;
|
|
||||||
const getGB = (val) => (Number(val) / 1024).toFixed(2);
|
|
||||||
|
|
||||||
const otherPercent = getPercent(otherMB);
|
|
||||||
const privatePercent = getPercent(privateBlobSpace);
|
|
||||||
const autoLimitPercent = getPercent(autoHostingLimit);
|
|
||||||
const viewLimitPercent = getPercent(viewLimit);
|
|
||||||
const viewUsedPercentOfLimit = getPercent(viewBlobSpace, viewLimit);
|
|
||||||
const autoUsedPercentOfLimit = getPercent(autoBlobSpace, autoHostingLimit);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={'storage__wrapper'}>
|
|
||||||
<div className={'storage__bar'}>
|
|
||||||
<div className={'storage__other'} style={{ width: `${otherPercent}%` }} />
|
|
||||||
<div className={'storage__private'} style={{ width: `${privatePercent}%` }} />
|
|
||||||
<div className={'storage__auto'} style={{ width: `${autoLimitPercent}%` }}>
|
|
||||||
<div className={'storage__auto--used'} style={{ width: `${autoUsedPercentOfLimit}%` }} />
|
|
||||||
<div className={'storage__auto--free'} />
|
|
||||||
</div>
|
|
||||||
<div className={'storage__viewed'} style={{ width: `${viewLimitPercent}%` }}>
|
|
||||||
<div className={'storage__viewed--used'} style={{ width: `${viewUsedPercentOfLimit}%` }} />
|
|
||||||
<div className={'storage__viewed--free'} />
|
|
||||||
</div>
|
|
||||||
{viewHostingLimit !== 0 && <div style={{ 'background-color': 'unset' }} />}
|
|
||||||
</div>
|
|
||||||
<div className={'storage__legend-wrapper'}>
|
|
||||||
<div className={'storage__legend-item'}>
|
|
||||||
<div className={'storage__legend-item-swatch storage__legend-item-swatch--private'} />
|
|
||||||
<div className={'storage__legend-item-label'}>
|
|
||||||
<label>{__('Publishes --[legend, storage category]--')}</label>
|
|
||||||
<div className={'help'}>{`${getGB(privateBlobSpace)} GB`}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={'storage__legend-item'}>
|
|
||||||
<div className={'storage__legend-item-swatch storage__legend-item-swatch--auto'} />
|
|
||||||
<div className={'storage__legend-item-label'}>
|
|
||||||
<label>{__('Auto Hosting --[legend, storage category]--')}</label>
|
|
||||||
<div className={'help'}>
|
|
||||||
{autoHostingLimit === 0 ? (
|
|
||||||
__('Disabled')
|
|
||||||
) : (
|
|
||||||
<I18nMessage
|
|
||||||
tokens={{
|
|
||||||
spaceUsed: getGB(autoBlobSpace),
|
|
||||||
limit: getGB(autoHostingLimit),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
%spaceUsed% of %limit% GB
|
|
||||||
</I18nMessage>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={'storage__legend-item'}>
|
|
||||||
<div className={'storage__legend-item-swatch storage__legend-item-swatch--viewed'} />
|
|
||||||
<div className={'storage__legend-item-label'}>
|
|
||||||
<label>{__('View Hosting --[legend, storage category]--')}</label>
|
|
||||||
<div className={'help'}>
|
|
||||||
{viewHostingLimit === 1 ? (
|
|
||||||
__('Disabled')
|
|
||||||
) : (
|
|
||||||
<I18nMessage
|
|
||||||
tokens={{
|
|
||||||
spaceUsed: getGB(viewBlobSpace),
|
|
||||||
limit: viewHostingLimit !== 0 ? getGB(viewHostingLimit) : getGB(viewFree),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
%spaceUsed% of %limit% Free GB
|
|
||||||
</I18nMessage>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{viewHostingLimit !== 0 && (
|
|
||||||
<div className={'storage__legend-item'}>
|
|
||||||
<div className={'storage__legend-item-swatch storage__legend-item-swatch--free'} />
|
|
||||||
<div className={'storage__legend-item-label'}>
|
|
||||||
<label>{__('Free --[legend, unused disk space]--')}</label>
|
|
||||||
<div className={'help'}>{`${getGB(unallocFree)} GB`}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default StorageViz;
|
|
|
@ -1,5 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { Combobox, ComboboxInput, ComboboxPopover, ComboboxList, ComboboxOption } from '@reach/combobox';
|
import { Combobox, ComboboxInput, ComboboxPopover, ComboboxList, ComboboxOption } from '@reach/combobox';
|
||||||
|
// import '@reach/combobox/styles.css'; --> 'scss/third-party.scss'
|
||||||
import { matchSorter } from 'match-sorter';
|
import { matchSorter } from 'match-sorter';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
@ -117,7 +118,7 @@ export default function BlockList(props: Props) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="help--notice">{help}</div>
|
<div className="help--notice">{help}</div>
|
||||||
<div className="section" style={{ zIndex: '4' }}>
|
<div className="section">
|
||||||
<SearchList
|
<SearchList
|
||||||
list={localList}
|
list={localList}
|
||||||
placeholder={__('e.g. odysee')}
|
placeholder={__('e.g. odysee')}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Icon from 'component/common/icon';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import { formatLbryUrlForWeb } from 'util/url';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
|
import * as PAGES from 'constants/pages';
|
||||||
import useCombinedRefs from 'effects/use-combined-refs';
|
import useCombinedRefs from 'effects/use-combined-refs';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -33,6 +34,7 @@ type Props = {
|
||||||
onMouseLeave: ?(any) => any,
|
onMouseLeave: ?(any) => any,
|
||||||
pathname: string,
|
pathname: string,
|
||||||
emailVerified: boolean,
|
emailVerified: boolean,
|
||||||
|
requiresAuth: ?boolean,
|
||||||
myref: any,
|
myref: any,
|
||||||
dispatch: any,
|
dispatch: any,
|
||||||
'aria-label'?: string,
|
'aria-label'?: string,
|
||||||
|
@ -64,6 +66,7 @@ const Button = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
iconColor,
|
iconColor,
|
||||||
activeClass,
|
activeClass,
|
||||||
emailVerified,
|
emailVerified,
|
||||||
|
requiresAuth,
|
||||||
myref,
|
myref,
|
||||||
dispatch, // <button> doesn't know what to do with dispatch
|
dispatch, // <button> doesn't know what to do with dispatch
|
||||||
pathname,
|
pathname,
|
||||||
|
@ -72,7 +75,7 @@ const Button = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
...otherProps
|
...otherProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const disable = disabled;
|
const disable = disabled || (user === null && requiresAuth);
|
||||||
|
|
||||||
const combinedClassName = classnames(
|
const combinedClassName = classnames(
|
||||||
'button',
|
'button',
|
||||||
|
@ -180,6 +183,31 @@ const Button = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requiresAuth && !emailVerified) {
|
||||||
|
let redirectUrl = `/$/${PAGES.AUTH}?redirect=${pathname}`;
|
||||||
|
|
||||||
|
if (authSrc) {
|
||||||
|
redirectUrl += `&src=${authSrc}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavLink
|
||||||
|
exact
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
to={redirectUrl}
|
||||||
|
title={title || defaultTooltip}
|
||||||
|
disabled={disable}
|
||||||
|
className={combinedClassName}
|
||||||
|
activeClassName={activeClass}
|
||||||
|
aria-label={ariaLabel}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</NavLink>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return path ? (
|
return path ? (
|
||||||
<NavLink
|
<NavLink
|
||||||
exact
|
exact
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import { SIMPLE_SITE } from 'config';
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import MarkdownPreview from 'component/common/markdown-preview';
|
import MarkdownPreview from 'component/common/markdown-preview';
|
||||||
import ClaimTags from 'component/claimTags';
|
import ClaimTags from 'component/claimTags';
|
||||||
import CreditAmount from 'component/common/credit-amount';
|
import CreditAmount from 'component/common/credit-amount';
|
||||||
|
import Button from 'component/button';
|
||||||
|
import * as PAGES from 'constants/pages';
|
||||||
import DateTime from 'component/dateTime';
|
import DateTime from 'component/dateTime';
|
||||||
import YoutubeBadge from 'component/youtubeBadge';
|
import YoutubeBadge from 'component/youtubeBadge';
|
||||||
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
||||||
import { formatNumber } from 'util/number';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claim: ChannelClaim,
|
claim: ChannelClaim,
|
||||||
|
@ -75,7 +77,7 @@ function ChannelAbout(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label>{__('Total Uploads')}</label>
|
<label>{__('Total Uploads')}</label>
|
||||||
<div className="media__info-text">{formatNumber(claim.meta.claims_in_channel || 0, 2, true)}</div>
|
<div className="media__info-text">{claim.meta.claims_in_channel}</div>
|
||||||
|
|
||||||
<label>{__('Last Updated')}</label>
|
<label>{__('Last Updated')}</label>
|
||||||
<div className="media__info-text">
|
<div className="media__info-text">
|
||||||
|
@ -99,6 +101,15 @@ function ChannelAbout(props: Props) {
|
||||||
amount={parseFloat(claim.amount) + parseFloat(claim.meta.support_amount)}
|
amount={parseFloat(claim.amount) + parseFloat(claim.meta.support_amount)}
|
||||||
precision={8}
|
precision={8}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
|
{SIMPLE_SITE && (
|
||||||
|
<Button
|
||||||
|
button="link"
|
||||||
|
label={__('view other claims at lbry://%name%', {
|
||||||
|
name: claim.name,
|
||||||
|
})}
|
||||||
|
navigate={`/$/${PAGES.TOP}?name=${claim.name}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<YoutubeBadge channelClaimId={claimId} />
|
<YoutubeBadge channelClaimId={claimId} />
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectClaimIdForUri } from 'redux/selectors/claims';
|
import { makeSelectClaimIdForUri } from 'redux/selectors/claims';
|
||||||
import {
|
import {
|
||||||
doCommentModUnBlock,
|
doCommentModUnBlock,
|
||||||
doCommentModBlock,
|
doCommentModBlock,
|
||||||
|
@ -43,7 +43,7 @@ const select = (state, props) => {
|
||||||
isBlocked,
|
isBlocked,
|
||||||
isToggling,
|
isToggling,
|
||||||
isBlockingOrUnBlocking: makeSelectUriIsBlockingOrUnBlocking(props.uri)(state),
|
isBlockingOrUnBlocking: makeSelectUriIsBlockingOrUnBlocking(props.uri)(state),
|
||||||
creatorId: selectClaimIdForUri(state, props.creatorUri),
|
creatorId: makeSelectClaimIdForUri(props.creatorUri)(state),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ import { PAGE_SIZE } from 'constants/claim';
|
||||||
import {
|
import {
|
||||||
makeSelectClaimsInChannelForPage,
|
makeSelectClaimsInChannelForPage,
|
||||||
makeSelectFetchingChannelClaims,
|
makeSelectFetchingChannelClaims,
|
||||||
selectClaimIsMine,
|
makeSelectClaimIsMine,
|
||||||
makeSelectTotalPagesInChannelSearch,
|
makeSelectTotalPagesInChannelSearch,
|
||||||
selectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
} from 'redux/selectors/claims';
|
} from 'redux/selectors/claims';
|
||||||
import { doResolveUris } from 'redux/actions/claims';
|
import { doResolveUris } from 'redux/actions/claims';
|
||||||
import * as SETTINGS from 'constants/settings';
|
import * as SETTINGS from 'constants/settings';
|
||||||
|
@ -20,15 +20,13 @@ const select = (state, props) => {
|
||||||
const { search } = props.location;
|
const { search } = props.location;
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
const page = urlParams.get('page') || 0;
|
const page = urlParams.get('page') || 0;
|
||||||
const claim = props.uri && selectClaimForUri(state, props.uri);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pageOfClaimsInChannel: makeSelectClaimsInChannelForPage(props.uri, page)(state),
|
pageOfClaimsInChannel: makeSelectClaimsInChannelForPage(props.uri, page)(state),
|
||||||
fetching: makeSelectFetchingChannelClaims(props.uri)(state),
|
fetching: makeSelectFetchingChannelClaims(props.uri)(state),
|
||||||
totalPages: makeSelectTotalPagesInChannelSearch(props.uri, PAGE_SIZE)(state),
|
totalPages: makeSelectTotalPagesInChannelSearch(props.uri, PAGE_SIZE)(state),
|
||||||
channelIsMine: selectClaimIsMine(state, claim),
|
channelIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||||
channelIsBlocked: makeSelectChannelIsMuted(props.uri)(state),
|
channelIsBlocked: makeSelectChannelIsMuted(props.uri)(state),
|
||||||
claim,
|
claim: props.uri && makeSelectClaimForUri(props.uri)(state),
|
||||||
isAuthenticated: selectUserVerifiedEmail(state),
|
isAuthenticated: selectUserVerifiedEmail(state),
|
||||||
showMature: selectShowMatureContent(state),
|
showMature: selectShowMatureContent(state),
|
||||||
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),
|
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import { SHOW_ADS, SIMPLE_SITE } from 'config';
|
||||||
import * as CS from 'constants/claim_search';
|
import * as CS from 'constants/claim_search';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
|
@ -6,7 +7,9 @@ import HiddenNsfwClaims from 'component/hiddenNsfwClaims';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import ClaimListDiscover from 'component/claimListDiscover';
|
import ClaimListDiscover from 'component/claimListDiscover';
|
||||||
|
import Ads from 'web/component/ads';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
|
import LivestreamLink from 'component/livestreamLink';
|
||||||
import { Form, FormField } from 'component/common/form';
|
import { Form, FormField } from 'component/common/form';
|
||||||
import { DEBOUNCE_WAIT_DURATION_MS } from 'constants/search';
|
import { DEBOUNCE_WAIT_DURATION_MS } from 'constants/search';
|
||||||
import { lighthouse } from 'redux/actions/search';
|
import { lighthouse } from 'redux/actions/search';
|
||||||
|
@ -43,6 +46,7 @@ function ChannelContent(props: Props) {
|
||||||
channelIsBlocked,
|
channelIsBlocked,
|
||||||
channelIsBlackListed,
|
channelIsBlackListed,
|
||||||
claim,
|
claim,
|
||||||
|
isAuthenticated,
|
||||||
defaultPageSize = CS.PAGE_SIZE,
|
defaultPageSize = CS.PAGE_SIZE,
|
||||||
defaultInfiniteScroll = true,
|
defaultInfiniteScroll = true,
|
||||||
showMature,
|
showMature,
|
||||||
|
@ -114,15 +118,18 @@ function ChannelContent(props: Props) {
|
||||||
{!fetching && Boolean(claimsInChannel) && !channelIsBlocked && !channelIsBlackListed && (
|
{!fetching && Boolean(claimsInChannel) && !channelIsBlocked && !channelIsBlackListed && (
|
||||||
<HiddenNsfwClaims uri={uri} />
|
<HiddenNsfwClaims uri={uri} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<LivestreamLink uri={uri} />
|
||||||
|
|
||||||
{!fetching && channelIsBlackListed && (
|
{!fetching && channelIsBlackListed && (
|
||||||
<section className="card card--section">
|
<section className="card card--section">
|
||||||
<p>
|
<p>
|
||||||
{__(
|
{__(
|
||||||
'In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this channel from our applications.'
|
'In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this channel from our applications. Content may also be blocked due to DMCA Red Flag rules which are obvious copyright violations we come across, are discussed in public channels, or reported to us.'
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<div className="section__actions">
|
<div className="section__actions">
|
||||||
<Button button="link" href="https://lbry.com/faq/dmca" label={__('Read More')} />
|
<Button button="link" href="https://odysee.com/@OdyseeHelp:b/copyright:f" label={__('Read More')} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
@ -145,12 +152,14 @@ function ChannelContent(props: Props) {
|
||||||
hideAdvancedFilter={!showFilters}
|
hideAdvancedFilter={!showFilters}
|
||||||
tileLayout={tileLayout}
|
tileLayout={tileLayout}
|
||||||
uris={searchResults}
|
uris={searchResults}
|
||||||
|
streamType={SIMPLE_SITE ? CS.CONTENT_ALL : undefined}
|
||||||
channelIds={[claimId]}
|
channelIds={[claimId]}
|
||||||
claimType={claimType}
|
claimType={claimType}
|
||||||
feeAmount={CS.FEE_AMOUNT_ANY}
|
feeAmount={CS.FEE_AMOUNT_ANY}
|
||||||
defaultOrderBy={CS.ORDER_BY_NEW}
|
defaultOrderBy={CS.ORDER_BY_NEW}
|
||||||
pageSize={defaultPageSize}
|
pageSize={defaultPageSize}
|
||||||
infiniteScroll={defaultInfiniteScroll}
|
infiniteScroll={defaultInfiniteScroll}
|
||||||
|
injectedItem={SHOW_ADS && !isAuthenticated && IS_WEB && <Ads type="video" />}
|
||||||
meta={
|
meta={
|
||||||
showFilters && (
|
showFilters && (
|
||||||
<Form onSubmit={() => {}} className="wunderbar--inline">
|
<Form onSubmit={() => {}} className="wunderbar--inline">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
selectTitleForUri,
|
makeSelectTitleForUri,
|
||||||
selectThumbnailForUri,
|
makeSelectThumbnailForUri,
|
||||||
makeSelectCoverForUri,
|
makeSelectCoverForUri,
|
||||||
makeSelectMetadataItemForUri,
|
makeSelectMetadataItemForUri,
|
||||||
makeSelectAmountForUri,
|
makeSelectAmountForUri,
|
||||||
|
@ -21,8 +21,8 @@ import ChannelForm from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
title: selectTitleForUri(state, props.uri),
|
title: makeSelectTitleForUri(props.uri)(state),
|
||||||
thumbnailUrl: selectThumbnailForUri(state, props.uri),
|
thumbnailUrl: makeSelectThumbnailForUri(props.uri)(state),
|
||||||
coverUrl: makeSelectCoverForUri(props.uri)(state),
|
coverUrl: makeSelectCoverForUri(props.uri)(state),
|
||||||
description: makeSelectMetadataItemForUri(props.uri, 'description')(state),
|
description: makeSelectMetadataItemForUri(props.uri, 'description')(state),
|
||||||
website: makeSelectMetadataItemForUri(props.uri, 'website_url')(state),
|
website: makeSelectMetadataItemForUri(props.uri, 'website_url')(state),
|
|
@ -3,9 +3,10 @@ import * as MODALS from 'constants/modal_types';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { FormField, FormFieldAreaAdvanced } from 'component/common/form';
|
import { FormField } from 'component/common/form';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import TagsSearch from 'component/tagsSearch';
|
import TagsSearch from 'component/tagsSearch';
|
||||||
|
import { FF_MAX_CHARS_IN_DESCRIPTION } from 'constants/form-field';
|
||||||
import ErrorText from 'component/common/error-text';
|
import ErrorText from 'component/common/error-text';
|
||||||
import ChannelThumbnail from 'component/channelThumbnail';
|
import ChannelThumbnail from 'component/channelThumbnail';
|
||||||
import { isNameValid, parseURI } from 'util/lbryURI';
|
import { isNameValid, parseURI } from 'util/lbryURI';
|
||||||
|
@ -19,6 +20,7 @@ import analytics from 'analytics';
|
||||||
import LbcSymbol from 'component/common/lbc-symbol';
|
import LbcSymbol from 'component/common/lbc-symbol';
|
||||||
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
||||||
import WalletSpendableBalanceHelp from 'component/walletSpendableBalanceHelp';
|
import WalletSpendableBalanceHelp from 'component/walletSpendableBalanceHelp';
|
||||||
|
import { SIMPLE_SITE } from 'config';
|
||||||
import { sortLanguageMap } from 'util/default-languages';
|
import { sortLanguageMap } from 'util/default-languages';
|
||||||
import ThumbnailBrokenImage from 'component/selectThumbnail/thumbnail-broken.png';
|
import ThumbnailBrokenImage from 'component/selectThumbnail/thumbnail-broken.png';
|
||||||
import Gerbil from 'component/channelThumbnail/gerbil.png';
|
import Gerbil from 'component/channelThumbnail/gerbil.png';
|
||||||
|
@ -26,9 +28,6 @@ import Gerbil from 'component/channelThumbnail/gerbil.png';
|
||||||
const LANG_NONE = 'none';
|
const LANG_NONE = 'none';
|
||||||
|
|
||||||
const MAX_TAG_SELECT = 5;
|
const MAX_TAG_SELECT = 5;
|
||||||
const MAX_NAME_LEN = 128;
|
|
||||||
const MAX_TITLE_LEN = 255;
|
|
||||||
const MAX_DESCRIPTION_LEN = 2056;
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claim: ChannelClaim,
|
claim: ChannelClaim,
|
||||||
|
@ -94,11 +93,10 @@ function ChannelForm(props: Props) {
|
||||||
const [nameError, setNameError] = React.useState(undefined);
|
const [nameError, setNameError] = React.useState(undefined);
|
||||||
const [bidError, setBidError] = React.useState('');
|
const [bidError, setBidError] = React.useState('');
|
||||||
const [isUpload, setIsUpload] = React.useState({ cover: false, thumbnail: false });
|
const [isUpload, setIsUpload] = React.useState({ cover: false, thumbnail: false });
|
||||||
|
const [coverError, setCoverError] = React.useState(false);
|
||||||
const [thumbError, setThumbError] = React.useState(false);
|
const [thumbError, setThumbError] = React.useState(false);
|
||||||
const { claim_id: claimId } = claim || {};
|
const { claim_id: claimId } = claim || {};
|
||||||
const [params, setParams]: [any, (any) => void] = React.useState(getChannelParams());
|
const [params, setParams]: [any, (any) => void] = React.useState(getChannelParams());
|
||||||
const [coverError, setCoverError] = React.useState(false);
|
|
||||||
const [coverPreview, setCoverPreview] = React.useState(params.coverUrl);
|
|
||||||
const { channelName } = parseURI(uri);
|
const { channelName } = parseURI(uri);
|
||||||
const name = params.name;
|
const name = params.name;
|
||||||
const isNewChannel = !uri;
|
const isNewChannel = !uri;
|
||||||
|
@ -117,11 +115,23 @@ function ChannelForm(props: Props) {
|
||||||
isClaimingInitialRewards ||
|
isClaimingInitialRewards ||
|
||||||
creatingChannel ||
|
creatingChannel ||
|
||||||
updatingChannel ||
|
updatingChannel ||
|
||||||
|
nameError ||
|
||||||
|
thumbError ||
|
||||||
coverError ||
|
coverError ||
|
||||||
bidError ||
|
bidError ||
|
||||||
(isNewChannel && !params.name)
|
(isNewChannel && !params.name)
|
||||||
);
|
);
|
||||||
}, [isClaimingInitialRewards, creatingChannel, updatingChannel, nameError, bidError, isNewChannel, params.name]);
|
}, [
|
||||||
|
isClaimingInitialRewards,
|
||||||
|
creatingChannel,
|
||||||
|
updatingChannel,
|
||||||
|
nameError,
|
||||||
|
thumbError,
|
||||||
|
coverError,
|
||||||
|
bidError,
|
||||||
|
isNewChannel,
|
||||||
|
params.name,
|
||||||
|
]);
|
||||||
|
|
||||||
function getChannelParams() {
|
function getChannelParams() {
|
||||||
// fill this in with sdk data
|
// fill this in with sdk data
|
||||||
|
@ -207,8 +217,7 @@ function ChannelForm(props: Props) {
|
||||||
setThumbError(false);
|
setThumbError(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCoverChange(coverUrl: string, uploadSelected: boolean, preview: ?string) {
|
function handleCoverChange(coverUrl: string, uploadSelected: boolean) {
|
||||||
setCoverPreview(preview || '');
|
|
||||||
setParams({ ...params, coverUrl });
|
setParams({ ...params, coverUrl });
|
||||||
setIsUpload({ ...isUpload, cover: uploadSelected });
|
setIsUpload({ ...isUpload, cover: uploadSelected });
|
||||||
setCoverError(false);
|
setCoverError(false);
|
||||||
|
@ -261,7 +270,7 @@ function ChannelForm(props: Props) {
|
||||||
}
|
}
|
||||||
}, [hasClaimedInitialRewards, claimInitialRewards]);
|
}, [hasClaimedInitialRewards, claimInitialRewards]);
|
||||||
|
|
||||||
const coverSrc = coverError ? ThumbnailBrokenImage : coverPreview;
|
const coverSrc = coverError ? ThumbnailBrokenImage : params.coverUrl;
|
||||||
|
|
||||||
let thumbnailPreview;
|
let thumbnailPreview;
|
||||||
if (!params.thumbnailUrl) {
|
if (!params.thumbnailUrl) {
|
||||||
|
@ -275,7 +284,7 @@ function ChannelForm(props: Props) {
|
||||||
// TODO clear and bail after submit
|
// TODO clear and bail after submit
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={classnames({ 'card--disabled': disabled })}>
|
<div className={classnames('main--contained', { 'card--disabled': disabled })}>
|
||||||
<header className="channel-cover">
|
<header className="channel-cover">
|
||||||
<div className="channel__quick-actions">
|
<div className="channel__quick-actions">
|
||||||
<Button
|
<Button
|
||||||
|
@ -283,7 +292,7 @@ function ChannelForm(props: Props) {
|
||||||
title={__('Cover')}
|
title={__('Cover')}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
openModal(MODALS.IMAGE_UPLOAD, {
|
openModal(MODALS.IMAGE_UPLOAD, {
|
||||||
onUpdate: (coverUrl, isUpload, preview) => handleCoverChange(coverUrl, isUpload, preview),
|
onUpdate: (coverUrl, isUpload) => handleCoverChange(coverUrl, isUpload),
|
||||||
title: __('Edit Cover Image'),
|
title: __('Edit Cover Image'),
|
||||||
helpText: __('(6.25:1)'),
|
helpText: __('(6.25:1)'),
|
||||||
assetName: __('Cover Image'),
|
assetName: __('Cover Image'),
|
||||||
|
@ -296,9 +305,7 @@ function ChannelForm(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
{params.coverUrl &&
|
{params.coverUrl &&
|
||||||
(coverError && isUpload.cover ? (
|
(coverError && isUpload.cover ? (
|
||||||
<div className="channel-cover__custom--waiting">
|
<div className="channel-cover__custom--waiting">{__('This will be visible in a few minutes.')}</div>
|
||||||
<p>{__('Uploaded image will be visible in a few minutes.')}</p>
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<img className="channel-cover__custom" src={coverSrc} onError={() => setCoverError(true)} />
|
<img className="channel-cover__custom" src={coverSrc} onError={() => setCoverError(true)} />
|
||||||
))}
|
))}
|
||||||
|
@ -325,6 +332,7 @@ function ChannelForm(props: Props) {
|
||||||
uri={uri}
|
uri={uri}
|
||||||
thumbnailPreview={thumbnailPreview}
|
thumbnailPreview={thumbnailPreview}
|
||||||
allowGifs
|
allowGifs
|
||||||
|
showDelayedMessage={isUpload.thumbnail}
|
||||||
setThumbUploadError={setThumbError}
|
setThumbUploadError={setThumbError}
|
||||||
thumbUploadError={thumbError}
|
thumbUploadError={thumbError}
|
||||||
/>
|
/>
|
||||||
|
@ -335,7 +343,7 @@ function ChannelForm(props: Props) {
|
||||||
<div className="channel-cover__gradient" />
|
<div className="channel-cover__gradient" />
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<Tabs className="channelPage-wrapper">
|
<Tabs>
|
||||||
<TabList className="tabs__list--channel-page">
|
<TabList className="tabs__list--channel-page">
|
||||||
<Tab>{__('General')}</Tab>
|
<Tab>{__('General')}</Tab>
|
||||||
<Tab>{__('Credit Details')}</Tab>
|
<Tab>{__('Credit Details')}</Tab>
|
||||||
|
@ -362,7 +370,6 @@ function ChannelForm(props: Props) {
|
||||||
error={nameError}
|
error={nameError}
|
||||||
disabled={!isNewChannel}
|
disabled={!isNewChannel}
|
||||||
onChange={(e) => setParams({ ...params, name: e.target.value })}
|
onChange={(e) => setParams({ ...params, name: e.target.value })}
|
||||||
maxLength={MAX_NAME_LEN}
|
|
||||||
/>
|
/>
|
||||||
</fieldset-group>
|
</fieldset-group>
|
||||||
{!isNewChannel && <span className="form-field__help">{__('This field cannot be changed.')}</span>}
|
{!isNewChannel && <span className="form-field__help">{__('This field cannot be changed.')}</span>}
|
||||||
|
@ -374,16 +381,15 @@ function ChannelForm(props: Props) {
|
||||||
placeholder={__('My Awesome Channel')}
|
placeholder={__('My Awesome Channel')}
|
||||||
value={params.title}
|
value={params.title}
|
||||||
onChange={(e) => setParams({ ...params, title: e.target.value })}
|
onChange={(e) => setParams({ ...params, title: e.target.value })}
|
||||||
maxLength={MAX_TITLE_LEN}
|
|
||||||
/>
|
/>
|
||||||
<FormFieldAreaAdvanced
|
<FormField
|
||||||
type="markdown"
|
type="markdown"
|
||||||
name="content_description2"
|
name="content_description2"
|
||||||
label={__('Description')}
|
label={__('Description')}
|
||||||
placeholder={__('Description of your content')}
|
placeholder={__('Description of your content')}
|
||||||
value={params.description}
|
value={params.description}
|
||||||
onChange={(text) => setParams({ ...params, description: text })}
|
onChange={(text) => setParams({ ...params, description: text })}
|
||||||
textAreaMaxLength={MAX_DESCRIPTION_LEN}
|
textAreaMaxLength={FF_MAX_CHARS_IN_DESCRIPTION}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -418,7 +424,7 @@ function ChannelForm(props: Props) {
|
||||||
<Card
|
<Card
|
||||||
body={
|
body={
|
||||||
<TagsSearch
|
<TagsSearch
|
||||||
suggestMature
|
suggestMature={!SIMPLE_SITE}
|
||||||
disableAutoFocus
|
disableAutoFocus
|
||||||
disableControlTags
|
disableControlTags
|
||||||
limitSelect={MAX_TAG_SELECT}
|
limitSelect={MAX_TAG_SELECT}
|
10
ui/component/channelMentionSuggestion/index.js
Normal file
10
ui/component/channelMentionSuggestion/index.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { makeSelectClaimForUri, makeSelectIsUriResolving } from 'redux/selectors/claims';
|
||||||
|
import ChannelMentionSuggestion from './view';
|
||||||
|
|
||||||
|
const select = (state, props) => ({
|
||||||
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
|
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(select)(ChannelMentionSuggestion);
|
32
ui/component/channelMentionSuggestion/view.jsx
Normal file
32
ui/component/channelMentionSuggestion/view.jsx
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// @flow
|
||||||
|
import { ComboboxOption } from '@reach/combobox';
|
||||||
|
import ChannelThumbnail from 'component/channelThumbnail';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
claim: ?Claim,
|
||||||
|
uri?: string,
|
||||||
|
isResolvingUri: boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ChannelMentionSuggestion(props: Props) {
|
||||||
|
const { claim, uri, isResolvingUri } = props;
|
||||||
|
|
||||||
|
return !claim ? null : (
|
||||||
|
<ComboboxOption value={uri}>
|
||||||
|
{isResolvingUri ? (
|
||||||
|
<div className="channel-mention__suggestion">
|
||||||
|
<div className="media__thumb media__thumb--resolving" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="channel-mention__suggestion">
|
||||||
|
<ChannelThumbnail xsmall uri={uri} />
|
||||||
|
<span className="channel-mention__suggestion-label">
|
||||||
|
<div className="channel-mention__suggestion-title">{(claim.value && claim.value.title) || claim.name}</div>
|
||||||
|
<div className="channel-mention__suggestion-name">{claim.name}</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</ComboboxOption>
|
||||||
|
);
|
||||||
|
}
|
37
ui/component/channelMentionSuggestions/index.js
Normal file
37
ui/component/channelMentionSuggestions/index.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { selectShowMatureContent } from 'redux/selectors/settings';
|
||||||
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
|
import { withRouter } from 'react-router';
|
||||||
|
import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
||||||
|
import { doResolveUris } from 'redux/actions/claims';
|
||||||
|
import { selectTopLevelCommentsForUri } from 'redux/selectors/comments';
|
||||||
|
import ChannelMentionSuggestions from './view';
|
||||||
|
|
||||||
|
const select = (state, props) => {
|
||||||
|
const subscriptionUris = selectSubscriptions(state).map(({ uri }) => uri);
|
||||||
|
const topLevelComments = selectTopLevelCommentsForUri(state, props.uri);
|
||||||
|
|
||||||
|
const commentorUris = [];
|
||||||
|
// Avoid repeated commentors
|
||||||
|
topLevelComments.map(({ channel_url }) => !commentorUris.includes(channel_url) && commentorUris.push(channel_url));
|
||||||
|
|
||||||
|
const getUnresolved = (uris) =>
|
||||||
|
uris.map((uri) => !makeSelectClaimForUri(uri)(state) && uri).filter((uri) => uri !== false);
|
||||||
|
const getCanonical = (uris) =>
|
||||||
|
uris
|
||||||
|
.map((uri) => makeSelectClaimForUri(uri)(state) && makeSelectClaimForUri(uri)(state).canonical_url)
|
||||||
|
.filter((uri) => Boolean(uri));
|
||||||
|
|
||||||
|
return {
|
||||||
|
commentorUris,
|
||||||
|
subscriptionUris,
|
||||||
|
unresolvedCommentors: getUnresolved(commentorUris),
|
||||||
|
unresolvedSubscriptions: getUnresolved(subscriptionUris),
|
||||||
|
canonicalCreator: getCanonical([props.creatorUri])[0],
|
||||||
|
canonicalCommentors: getCanonical(commentorUris),
|
||||||
|
canonicalSubscriptions: getCanonical(subscriptionUris),
|
||||||
|
showMature: selectShowMatureContent(state),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withRouter(connect(select, { doResolveUris })(ChannelMentionSuggestions));
|
286
ui/component/channelMentionSuggestions/view.jsx
Normal file
286
ui/component/channelMentionSuggestions/view.jsx
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
// @flow
|
||||||
|
import { Combobox, ComboboxInput, ComboboxPopover, ComboboxList } from '@reach/combobox';
|
||||||
|
import { Form } from 'component/common/form';
|
||||||
|
import { parseURI, regexInvalidURI } from 'util/lbryURI';
|
||||||
|
import { SEARCH_OPTIONS } from 'constants/search';
|
||||||
|
import * as KEYCODES from 'constants/keycodes';
|
||||||
|
import ChannelMentionSuggestion from 'component/channelMentionSuggestion';
|
||||||
|
import ChannelMentionTopSuggestion from 'component/channelMentionTopSuggestion';
|
||||||
|
import React from 'react';
|
||||||
|
import Spinner from 'component/spinner';
|
||||||
|
import type { ElementRef } from 'react';
|
||||||
|
import useLighthouse from 'effects/use-lighthouse';
|
||||||
|
|
||||||
|
const INPUT_DEBOUNCE_MS = 1000;
|
||||||
|
const LIGHTHOUSE_MIN_CHARACTERS = 3;
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
inputRef: any,
|
||||||
|
mentionTerm: string,
|
||||||
|
noTopSuggestion?: boolean,
|
||||||
|
showMature: boolean,
|
||||||
|
isLivestream: boolean,
|
||||||
|
creatorUri: string,
|
||||||
|
commentorUris: Array<string>,
|
||||||
|
subscriptionUris: Array<string>,
|
||||||
|
unresolvedCommentors: Array<string>,
|
||||||
|
unresolvedSubscriptions: Array<string>,
|
||||||
|
canonicalCreator: string,
|
||||||
|
canonicalCommentors: Array<string>,
|
||||||
|
canonicalSubscriptions: Array<string>,
|
||||||
|
doResolveUris: (Array<string>) => void,
|
||||||
|
customSelectAction?: (string, number) => void,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ChannelMentionSuggestions(props: Props) {
|
||||||
|
const {
|
||||||
|
unresolvedCommentors,
|
||||||
|
unresolvedSubscriptions,
|
||||||
|
canonicalCreator,
|
||||||
|
isLivestream,
|
||||||
|
creatorUri,
|
||||||
|
inputRef,
|
||||||
|
showMature,
|
||||||
|
noTopSuggestion,
|
||||||
|
mentionTerm,
|
||||||
|
doResolveUris,
|
||||||
|
customSelectAction,
|
||||||
|
} = props;
|
||||||
|
const comboboxInputRef: ElementRef<any> = React.useRef();
|
||||||
|
const comboboxListRef: ElementRef<any> = React.useRef();
|
||||||
|
|
||||||
|
const mainEl = document.querySelector('.channel-mention__suggestions');
|
||||||
|
|
||||||
|
const [debouncedTerm, setDebouncedTerm] = React.useState('');
|
||||||
|
const [mostSupported, setMostSupported] = React.useState('');
|
||||||
|
const [canonicalResults, setCanonicalResults] = React.useState([]);
|
||||||
|
|
||||||
|
const isRefFocused = (ref) => ref && ref.current === document.activeElement;
|
||||||
|
|
||||||
|
const subscriptionUris = props.subscriptionUris.filter((uri) => uri !== creatorUri);
|
||||||
|
const canonicalSubscriptions = props.canonicalSubscriptions.filter((uri) => uri !== canonicalCreator);
|
||||||
|
const commentorUris = props.commentorUris.filter((uri) => uri !== creatorUri && !subscriptionUris.includes(uri));
|
||||||
|
const canonicalCommentors = props.canonicalCommentors.filter(
|
||||||
|
(uri) => uri !== canonicalCreator && !canonicalSubscriptions.includes(uri)
|
||||||
|
);
|
||||||
|
|
||||||
|
const termToMatch = mentionTerm && mentionTerm.replace('@', '').toLowerCase();
|
||||||
|
const allShownUris = [creatorUri, ...subscriptionUris, ...commentorUris];
|
||||||
|
const allShownCanonical = [canonicalCreator, ...canonicalSubscriptions, ...canonicalCommentors];
|
||||||
|
const possibleMatches = allShownUris.filter((uri) => {
|
||||||
|
try {
|
||||||
|
// yuck a try catch in a filter?
|
||||||
|
const { channelName } = parseURI(uri);
|
||||||
|
return channelName && channelName.toLowerCase().includes(termToMatch);
|
||||||
|
} catch (e) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchSize = 5;
|
||||||
|
const additionalOptions = { isBackgroundSearch: false, [SEARCH_OPTIONS.CLAIM_TYPE]: SEARCH_OPTIONS.INCLUDE_CHANNELS };
|
||||||
|
const { results, loading } = useLighthouse(debouncedTerm, showMature, searchSize, additionalOptions, 0);
|
||||||
|
const stringifiedResults = JSON.stringify(results);
|
||||||
|
|
||||||
|
const hasMinLength = mentionTerm && mentionTerm.length >= LIGHTHOUSE_MIN_CHARACTERS;
|
||||||
|
const isTyping = debouncedTerm !== mentionTerm;
|
||||||
|
const showPlaceholder = isTyping || loading;
|
||||||
|
|
||||||
|
const isUriFromTermValid = !regexInvalidURI.test(mentionTerm.substring(1));
|
||||||
|
|
||||||
|
const handleSelect = React.useCallback(
|
||||||
|
(value, key) => {
|
||||||
|
if (customSelectAction) {
|
||||||
|
// Give them full results, as our resolved one might truncate the claimId.
|
||||||
|
customSelectAction(value || (results && results.find((r) => r.startsWith(value))) || '', Number(key));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[customSelectAction, results]
|
||||||
|
);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
if (isTyping) setDebouncedTerm(!hasMinLength ? '' : mentionTerm);
|
||||||
|
}, INPUT_DEBOUNCE_MS);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, [hasMinLength, isTyping, mentionTerm]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!mainEl) return;
|
||||||
|
const header = document.querySelector('.header__navigation');
|
||||||
|
|
||||||
|
function handleReflow() {
|
||||||
|
const boxAtTopOfPage = header && mainEl.getBoundingClientRect().top <= header.offsetHeight;
|
||||||
|
const boxAtBottomOfPage = mainEl.getBoundingClientRect().bottom >= window.innerHeight;
|
||||||
|
|
||||||
|
if (boxAtTopOfPage) {
|
||||||
|
mainEl.setAttribute('flow-bottom', '');
|
||||||
|
}
|
||||||
|
if (mainEl.getAttribute('flow-bottom') !== null && boxAtBottomOfPage) {
|
||||||
|
mainEl.removeAttribute('flow-bottom');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleReflow();
|
||||||
|
|
||||||
|
window.addEventListener('scroll', handleReflow);
|
||||||
|
return () => window.removeEventListener('scroll', handleReflow);
|
||||||
|
}, [mainEl]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!inputRef || !comboboxInputRef || !mentionTerm) return;
|
||||||
|
|
||||||
|
function handleKeyDown(event) {
|
||||||
|
const { keyCode } = event;
|
||||||
|
const activeElement = document.activeElement;
|
||||||
|
|
||||||
|
if (keyCode === KEYCODES.UP || keyCode === KEYCODES.DOWN) {
|
||||||
|
if (isRefFocused(comboboxInputRef)) {
|
||||||
|
const selectedId = activeElement && activeElement.getAttribute('aria-activedescendant');
|
||||||
|
const selectedItem = selectedId && document.querySelector(`li[id="${selectedId}"]`);
|
||||||
|
if (selectedItem) selectedItem.scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
||||||
|
} else {
|
||||||
|
// $FlowFixMe
|
||||||
|
comboboxInputRef.current.focus();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((isRefFocused(comboboxInputRef) || isRefFocused(inputRef)) && keyCode === KEYCODES.TAB) {
|
||||||
|
event.preventDefault();
|
||||||
|
const activeValue = activeElement && activeElement.getAttribute('value');
|
||||||
|
|
||||||
|
if (activeValue) {
|
||||||
|
handleSelect(activeValue, keyCode);
|
||||||
|
} else if (possibleMatches.length) {
|
||||||
|
// $FlowFixMe
|
||||||
|
const suggest = allShownCanonical.find((matchUri) => possibleMatches.find((uri) => uri.includes(matchUri)));
|
||||||
|
if (suggest) handleSelect(suggest, keyCode);
|
||||||
|
} else if (results) {
|
||||||
|
handleSelect(mentionTerm, keyCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isRefFocused(comboboxInputRef)) {
|
||||||
|
// $FlowFixMe
|
||||||
|
inputRef.current.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
|
|
||||||
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||||
|
}, [allShownCanonical, handleSelect, inputRef, mentionTerm, possibleMatches, results]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!stringifiedResults) return;
|
||||||
|
|
||||||
|
const arrayResults = JSON.parse(stringifiedResults);
|
||||||
|
if (arrayResults && arrayResults.length > 0) {
|
||||||
|
// $FlowFixMe
|
||||||
|
doResolveUris(arrayResults).then((response) => {
|
||||||
|
try {
|
||||||
|
// $FlowFixMe
|
||||||
|
const canonical_urls = Object.values(response).map(({ canonical_url }) => canonical_url);
|
||||||
|
setCanonicalResults(canonical_urls);
|
||||||
|
} catch (e) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [doResolveUris, stringifiedResults]);
|
||||||
|
|
||||||
|
// Only resolve commentors on Livestreams when actually mentioning/looking for it
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (isLivestream && unresolvedCommentors && mentionTerm) doResolveUris(unresolvedCommentors);
|
||||||
|
}, [doResolveUris, isLivestream, mentionTerm, unresolvedCommentors]);
|
||||||
|
|
||||||
|
// Only resolve the subscriptions that match the mention term, instead of all
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (isTyping) return;
|
||||||
|
|
||||||
|
const urisToResolve = [];
|
||||||
|
subscriptionUris.map(
|
||||||
|
(uri) =>
|
||||||
|
hasMinLength &&
|
||||||
|
possibleMatches.includes(uri) &&
|
||||||
|
unresolvedSubscriptions.includes(uri) &&
|
||||||
|
urisToResolve.push(uri)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (urisToResolve.length > 0) doResolveUris(urisToResolve);
|
||||||
|
}, [doResolveUris, hasMinLength, isTyping, possibleMatches, subscriptionUris, unresolvedSubscriptions]);
|
||||||
|
|
||||||
|
const suggestionsRow = (
|
||||||
|
label: string,
|
||||||
|
suggestions: Array<string>,
|
||||||
|
canonical: Array<string>,
|
||||||
|
hasSuggestionsBelow: boolean
|
||||||
|
) => {
|
||||||
|
if (mentionTerm.length > 1 && suggestions !== results) {
|
||||||
|
suggestions = suggestions.filter((uri) => possibleMatches.includes(uri));
|
||||||
|
} else if (suggestions === results) {
|
||||||
|
suggestions = suggestions.filter((uri) => !allShownUris.includes(uri));
|
||||||
|
}
|
||||||
|
// $FlowFixMe
|
||||||
|
suggestions = suggestions
|
||||||
|
.map((matchUri) => canonical.find((uri) => matchUri.includes(uri)))
|
||||||
|
.filter((uri) => Boolean(uri));
|
||||||
|
|
||||||
|
if (canonical === canonicalResults) {
|
||||||
|
suggestions = suggestions.filter((uri) => uri !== mostSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !suggestions.length ? null : (
|
||||||
|
<>
|
||||||
|
<div className="channel-mention__label">{label}</div>
|
||||||
|
{suggestions.map((uri) => (
|
||||||
|
<ChannelMentionSuggestion key={uri} uri={uri} />
|
||||||
|
))}
|
||||||
|
{hasSuggestionsBelow && <hr className="channel-mention__top-separator" />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return isRefFocused(inputRef) || isRefFocused(comboboxInputRef) ? (
|
||||||
|
<Form onSubmit={() => handleSelect(mentionTerm)}>
|
||||||
|
<Combobox className="channel-mention" onSelect={handleSelect}>
|
||||||
|
<ComboboxInput ref={comboboxInputRef} className="channel-mention__input--none" value={mentionTerm} />
|
||||||
|
{mentionTerm && isUriFromTermValid && (
|
||||||
|
<ComboboxPopover portal={false} className="channel-mention__suggestions">
|
||||||
|
<ComboboxList ref={comboboxListRef}>
|
||||||
|
{creatorUri &&
|
||||||
|
suggestionsRow(
|
||||||
|
__('Creator'),
|
||||||
|
[creatorUri],
|
||||||
|
[canonicalCreator],
|
||||||
|
canonicalSubscriptions.length > 0 || commentorUris.length > 0 || !showPlaceholder
|
||||||
|
)}
|
||||||
|
{canonicalSubscriptions.length > 0 &&
|
||||||
|
suggestionsRow(
|
||||||
|
__('Following'),
|
||||||
|
subscriptionUris,
|
||||||
|
canonicalSubscriptions,
|
||||||
|
commentorUris.length > 0 || !showPlaceholder
|
||||||
|
)}
|
||||||
|
{commentorUris.length > 0 &&
|
||||||
|
suggestionsRow(__('From comments'), commentorUris, canonicalCommentors, !showPlaceholder)}
|
||||||
|
|
||||||
|
{hasMinLength &&
|
||||||
|
(showPlaceholder ? (
|
||||||
|
<Spinner type="small" />
|
||||||
|
) : (
|
||||||
|
results && (
|
||||||
|
<>
|
||||||
|
{!noTopSuggestion && (
|
||||||
|
<ChannelMentionTopSuggestion
|
||||||
|
query={debouncedTerm}
|
||||||
|
shownUris={allShownCanonical}
|
||||||
|
setMostSupported={(winningUri) => setMostSupported(winningUri)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{suggestionsRow(__('From search'), results, canonicalResults, false)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
))}
|
||||||
|
</ComboboxList>
|
||||||
|
</ComboboxPopover>
|
||||||
|
)}
|
||||||
|
</Combobox>
|
||||||
|
</Form>
|
||||||
|
) : null;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue