feat: Create new progress slider from scratch
This commit is contained in:
@@ -135,7 +135,7 @@ android {
|
|||||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.rndiffapp"
|
applicationId "com.jellyfinaudioplayer"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 8
|
versionCode 8
|
||||||
@@ -300,6 +300,10 @@ if (isNewArchitectureEnabled()) {
|
|||||||
substitute(module("com.facebook.react:react-native"))
|
substitute(module("com.facebook.react:react-native"))
|
||||||
.using(project(":ReactAndroid")).because("On New Architecture we're building React Native from source")
|
.using(project(":ReactAndroid")).because("On New Architecture we're building React Native from source")
|
||||||
}
|
}
|
||||||
|
resolutionStrategy {
|
||||||
|
force 'com.google.android.exoplayer:exoplayer-core:2.11.4'
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import com.facebook.soloader.SoLoader;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.facebook.react.bridge.JSIModulePackage;
|
||||||
|
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
|
||||||
|
|
||||||
public class MainApplication extends Application implements ReactApplication {
|
public class MainApplication extends Application implements ReactApplication {
|
||||||
|
|
||||||
private final ReactNativeHost mReactNativeHost =
|
private final ReactNativeHost mReactNativeHost =
|
||||||
@@ -33,6 +36,11 @@ public class MainApplication extends Application implements ReactApplication {
|
|||||||
protected String getJSMainModuleName() {
|
protected String getJSMainModuleName() {
|
||||||
return "index";
|
return "index";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JSIModulePackage getJSIModulePackage() {
|
||||||
|
return new ReanimatedJSIModulePackage();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ allprojects {
|
|||||||
jcenter() {
|
jcenter() {
|
||||||
content {
|
content {
|
||||||
includeGroup("com.google.android.exoplayer")
|
includeGroup("com.google.android.exoplayer")
|
||||||
|
includeGroupByRegex("com.eightbitlab.*")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'module:react-native-dotenv'
|
'module:react-native-dotenv'
|
||||||
]
|
],
|
||||||
|
'react-native-reanimated/plugin'
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -422,6 +422,33 @@ PODS:
|
|||||||
- React-Core
|
- React-Core
|
||||||
- RNLocalize (2.2.1):
|
- RNLocalize (2.2.1):
|
||||||
- React-Core
|
- React-Core
|
||||||
|
- RNReanimated (2.8.0):
|
||||||
|
- DoubleConversion
|
||||||
|
- FBLazyVector
|
||||||
|
- FBReactNativeSpec
|
||||||
|
- glog
|
||||||
|
- RCT-Folly
|
||||||
|
- RCTRequired
|
||||||
|
- RCTTypeSafety
|
||||||
|
- React-callinvoker
|
||||||
|
- React-Core
|
||||||
|
- React-Core/DevSupport
|
||||||
|
- React-Core/RCTWebSocket
|
||||||
|
- React-CoreModules
|
||||||
|
- React-cxxreact
|
||||||
|
- React-jsi
|
||||||
|
- React-jsiexecutor
|
||||||
|
- React-jsinspector
|
||||||
|
- React-RCTActionSheet
|
||||||
|
- React-RCTAnimation
|
||||||
|
- React-RCTBlob
|
||||||
|
- React-RCTImage
|
||||||
|
- React-RCTLinking
|
||||||
|
- React-RCTNetwork
|
||||||
|
- React-RCTSettings
|
||||||
|
- React-RCTText
|
||||||
|
- ReactCommon/turbomodule/core
|
||||||
|
- Yoga
|
||||||
- RNScreens (3.13.1):
|
- RNScreens (3.13.1):
|
||||||
- React-Core
|
- React-Core
|
||||||
- React-RCTImage
|
- React-RCTImage
|
||||||
@@ -516,6 +543,7 @@ DEPENDENCIES:
|
|||||||
- RNFS (from `../node_modules/react-native-fs`)
|
- RNFS (from `../node_modules/react-native-fs`)
|
||||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||||
- RNLocalize (from `../node_modules/react-native-localize`)
|
- RNLocalize (from `../node_modules/react-native-localize`)
|
||||||
|
- RNReanimated (from `../node_modules/react-native-reanimated`)
|
||||||
- RNScreens (from `../node_modules/react-native-screens`)
|
- RNScreens (from `../node_modules/react-native-screens`)
|
||||||
- "RNSentry (from `../node_modules/@sentry/react-native`)"
|
- "RNSentry (from `../node_modules/@sentry/react-native`)"
|
||||||
- RNSVG (from `../node_modules/react-native-svg`)
|
- RNSVG (from `../node_modules/react-native-svg`)
|
||||||
@@ -637,6 +665,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../node_modules/react-native-gesture-handler"
|
:path: "../node_modules/react-native-gesture-handler"
|
||||||
RNLocalize:
|
RNLocalize:
|
||||||
:path: "../node_modules/react-native-localize"
|
:path: "../node_modules/react-native-localize"
|
||||||
|
RNReanimated:
|
||||||
|
:path: "../node_modules/react-native-reanimated"
|
||||||
RNScreens:
|
RNScreens:
|
||||||
:path: "../node_modules/react-native-screens"
|
:path: "../node_modules/react-native-screens"
|
||||||
RNSentry:
|
RNSentry:
|
||||||
@@ -707,6 +737,7 @@ SPEC CHECKSUMS:
|
|||||||
RNFS: fc610f78fdf8bfc89a9e5cc2f898519f4dba1002
|
RNFS: fc610f78fdf8bfc89a9e5cc2f898519f4dba1002
|
||||||
RNGestureHandler: 4f4986408310a43f1606c391f38f76e0d6e790d5
|
RNGestureHandler: 4f4986408310a43f1606c391f38f76e0d6e790d5
|
||||||
RNLocalize: cbcb55d0e19c78086ea4eea20e03fe8000bbbced
|
RNLocalize: cbcb55d0e19c78086ea4eea20e03fe8000bbbced
|
||||||
|
RNReanimated: 64573e25e078ae6bec03b891586d50b9ec284393
|
||||||
RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
|
RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
|
||||||
RNSentry: 2cd1daa124b0d9fd0dfc2cb6094fdd168cb579bc
|
RNSentry: 2cd1daa124b0d9fd0dfc2cb6094fdd168cb579bc
|
||||||
RNSVG: 302bfc9905bd8122f08966dc2ce2d07b7b52b9f8
|
RNSVG: 302bfc9905bd8122f08966dc2ce2d07b7b52b9f8
|
||||||
|
|||||||
62
package-lock.json
generated
62
package-lock.json
generated
@@ -26,6 +26,7 @@
|
|||||||
"date-fns": "^2.28.0",
|
"date-fns": "^2.28.0",
|
||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
"fuse.js": "^6.6.0",
|
"fuse.js": "^6.6.0",
|
||||||
|
"hermes-engine": "^0.11.0",
|
||||||
"i18n-js": "^3.9.2",
|
"i18n-js": "^3.9.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
@@ -38,12 +39,13 @@
|
|||||||
"react-native-fs": "^2.19.0",
|
"react-native-fs": "^2.19.0",
|
||||||
"react-native-gesture-handler": "^2.4.1",
|
"react-native-gesture-handler": "^2.4.1",
|
||||||
"react-native-localize": "^2.2.1",
|
"react-native-localize": "^2.2.1",
|
||||||
|
"react-native-reanimated": "^2.8.0",
|
||||||
"react-native-safe-area-context": "^4.2.5",
|
"react-native-safe-area-context": "^4.2.5",
|
||||||
"react-native-screens": "^3.13.1",
|
"react-native-screens": "^3.13.1",
|
||||||
"react-native-shadow-2": "^6.0.5",
|
"react-native-shadow-2": "^6.0.5",
|
||||||
"react-native-svg": "^12.3.0",
|
"react-native-svg": "^12.3.0",
|
||||||
"react-native-svg-transformer": "^1.0.0",
|
"react-native-svg-transformer": "^1.0.0",
|
||||||
"react-native-track-player": "^2.1.3",
|
"react-native-track-player": "^2.2.0-rc3",
|
||||||
"react-native-webview": "^11.18.2",
|
"react-native-webview": "^11.18.2",
|
||||||
"react-redux": "^7.2.6",
|
"react-redux": "^7.2.6",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.0",
|
||||||
@@ -4911,8 +4913,7 @@
|
|||||||
"node_modules/@types/invariant": {
|
"node_modules/@types/invariant": {
|
||||||
"version": "2.2.35",
|
"version": "2.2.35",
|
||||||
"resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz",
|
"resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz",
|
||||||
"integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg==",
|
"integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg=="
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@types/istanbul-lib-coverage": {
|
"node_modules/@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
@@ -8772,6 +8773,11 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hermes-engine": {
|
||||||
|
"version": "0.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hermes-engine/-/hermes-engine-0.11.0.tgz",
|
||||||
|
"integrity": "sha512-7aMUlZja2IyLYAcZ69NBnwJAR5ZOYlSllj0oMpx08a8HzxHOys0eKCzfphrf6D0vX1JGO1QQvVsQKe6TkYherw=="
|
||||||
|
},
|
||||||
"node_modules/hermes-estree": {
|
"node_modules/hermes-estree": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.5.0.tgz",
|
||||||
@@ -12456,8 +12462,7 @@
|
|||||||
"node_modules/lodash.isequal": {
|
"node_modules/lodash.isequal": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||||
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
|
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/lodash.merge": {
|
"node_modules/lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
@@ -14427,7 +14432,6 @@
|
|||||||
"version": "2.8.0",
|
"version": "2.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.8.0.tgz",
|
||||||
"integrity": "sha512-kJvf/UWLBMaGCs9X66MKq5zdFMgwx8D0nHnolbHR7s8ZnbLdb7TlQ/yuzIXqn/9wABfnwtNRI3CyaP1aHWMmZg==",
|
"integrity": "sha512-kJvf/UWLBMaGCs9X66MKq5zdFMgwx8D0nHnolbHR7s8ZnbLdb7TlQ/yuzIXqn/9wABfnwtNRI3CyaP1aHWMmZg==",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/plugin-transform-object-assign": "^7.16.7",
|
"@babel/plugin-transform-object-assign": "^7.16.7",
|
||||||
"@babel/preset-typescript": "^7.16.7",
|
"@babel/preset-typescript": "^7.16.7",
|
||||||
@@ -14505,9 +14509,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-track-player": {
|
"node_modules/react-native-track-player": {
|
||||||
"version": "2.1.3",
|
"version": "2.2.0-rc3",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-track-player/-/react-native-track-player-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-track-player/-/react-native-track-player-2.2.0-rc3.tgz",
|
||||||
"integrity": "sha512-JWKFRu+hr1ECN339RH+c+XDM7HfwvdvS4H1p4cJbhg/9b1CQGPJSrYXEhYkngN0msoxBxAjFyFIhjT2fWDCltA==",
|
"integrity": "sha512-Pvmum3MQ5PE8/yOIIPsk00zZk3EzdocUuVUwuBKSCmdKK/3O9YhnZRC3EuT59XCDm23pZZJZDSR44VeXN6Gamg==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=16.8.6",
|
"react": ">=16.8.6",
|
||||||
"react-native": ">=0.60.0-rc.2",
|
"react-native": ">=0.60.0-rc.2",
|
||||||
@@ -14806,11 +14810,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native/node_modules/hermes-engine": {
|
|
||||||
"version": "0.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/hermes-engine/-/hermes-engine-0.11.0.tgz",
|
|
||||||
"integrity": "sha512-7aMUlZja2IyLYAcZ69NBnwJAR5ZOYlSllj0oMpx08a8HzxHOys0eKCzfphrf6D0vX1JGO1QQvVsQKe6TkYherw=="
|
|
||||||
},
|
|
||||||
"node_modules/react-native/node_modules/hermes-parser": {
|
"node_modules/react-native/node_modules/hermes-parser": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.5.0.tgz",
|
||||||
@@ -15879,8 +15878,7 @@
|
|||||||
"node_modules/setimmediate": {
|
"node_modules/setimmediate": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||||
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
|
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/setprototypeof": {
|
"node_modules/setprototypeof": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
@@ -16385,8 +16383,7 @@
|
|||||||
"node_modules/string-hash-64": {
|
"node_modules/string-hash-64": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string-hash-64/-/string-hash-64-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string-hash-64/-/string-hash-64-1.0.3.tgz",
|
||||||
"integrity": "sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw==",
|
"integrity": "sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw=="
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/string-length": {
|
"node_modules/string-length": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
@@ -20895,8 +20892,7 @@
|
|||||||
"@types/invariant": {
|
"@types/invariant": {
|
||||||
"version": "2.2.35",
|
"version": "2.2.35",
|
||||||
"resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz",
|
"resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz",
|
||||||
"integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg==",
|
"integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg=="
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"@types/istanbul-lib-coverage": {
|
"@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
@@ -23834,6 +23830,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hermes-engine": {
|
||||||
|
"version": "0.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hermes-engine/-/hermes-engine-0.11.0.tgz",
|
||||||
|
"integrity": "sha512-7aMUlZja2IyLYAcZ69NBnwJAR5ZOYlSllj0oMpx08a8HzxHOys0eKCzfphrf6D0vX1JGO1QQvVsQKe6TkYherw=="
|
||||||
|
},
|
||||||
"hermes-estree": {
|
"hermes-estree": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.5.0.tgz",
|
||||||
@@ -26684,8 +26685,7 @@
|
|||||||
"lodash.isequal": {
|
"lodash.isequal": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||||
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
|
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"lodash.merge": {
|
"lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
@@ -28377,11 +28377,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz",
|
||||||
"integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA=="
|
"integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA=="
|
||||||
},
|
},
|
||||||
"hermes-engine": {
|
|
||||||
"version": "0.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/hermes-engine/-/hermes-engine-0.11.0.tgz",
|
|
||||||
"integrity": "sha512-7aMUlZja2IyLYAcZ69NBnwJAR5ZOYlSllj0oMpx08a8HzxHOys0eKCzfphrf6D0vX1JGO1QQvVsQKe6TkYherw=="
|
|
||||||
},
|
|
||||||
"hermes-parser": {
|
"hermes-parser": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.5.0.tgz",
|
||||||
@@ -28817,7 +28812,6 @@
|
|||||||
"version": "2.8.0",
|
"version": "2.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.8.0.tgz",
|
||||||
"integrity": "sha512-kJvf/UWLBMaGCs9X66MKq5zdFMgwx8D0nHnolbHR7s8ZnbLdb7TlQ/yuzIXqn/9wABfnwtNRI3CyaP1aHWMmZg==",
|
"integrity": "sha512-kJvf/UWLBMaGCs9X66MKq5zdFMgwx8D0nHnolbHR7s8ZnbLdb7TlQ/yuzIXqn/9wABfnwtNRI3CyaP1aHWMmZg==",
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/plugin-transform-object-assign": "^7.16.7",
|
"@babel/plugin-transform-object-assign": "^7.16.7",
|
||||||
"@babel/preset-typescript": "^7.16.7",
|
"@babel/preset-typescript": "^7.16.7",
|
||||||
@@ -28871,9 +28865,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-native-track-player": {
|
"react-native-track-player": {
|
||||||
"version": "2.1.3",
|
"version": "2.2.0-rc3",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-track-player/-/react-native-track-player-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-track-player/-/react-native-track-player-2.2.0-rc3.tgz",
|
||||||
"integrity": "sha512-JWKFRu+hr1ECN339RH+c+XDM7HfwvdvS4H1p4cJbhg/9b1CQGPJSrYXEhYkngN0msoxBxAjFyFIhjT2fWDCltA==",
|
"integrity": "sha512-Pvmum3MQ5PE8/yOIIPsk00zZk3EzdocUuVUwuBKSCmdKK/3O9YhnZRC3EuT59XCDm23pZZJZDSR44VeXN6Gamg==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"react-native-webview": {
|
"react-native-webview": {
|
||||||
@@ -29401,8 +29395,7 @@
|
|||||||
"setimmediate": {
|
"setimmediate": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||||
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
|
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"setprototypeof": {
|
"setprototypeof": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
@@ -29816,8 +29809,7 @@
|
|||||||
"string-hash-64": {
|
"string-hash-64": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string-hash-64/-/string-hash-64-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string-hash-64/-/string-hash-64-1.0.3.tgz",
|
||||||
"integrity": "sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw==",
|
"integrity": "sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw=="
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"string-length": {
|
"string-length": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
"date-fns": "^2.28.0",
|
"date-fns": "^2.28.0",
|
||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
"fuse.js": "^6.6.0",
|
"fuse.js": "^6.6.0",
|
||||||
|
"hermes-engine": "^0.11.0",
|
||||||
"i18n-js": "^3.9.2",
|
"i18n-js": "^3.9.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
@@ -42,12 +43,13 @@
|
|||||||
"react-native-fs": "^2.19.0",
|
"react-native-fs": "^2.19.0",
|
||||||
"react-native-gesture-handler": "^2.4.1",
|
"react-native-gesture-handler": "^2.4.1",
|
||||||
"react-native-localize": "^2.2.1",
|
"react-native-localize": "^2.2.1",
|
||||||
|
"react-native-reanimated": "^2.8.0",
|
||||||
"react-native-safe-area-context": "^4.2.5",
|
"react-native-safe-area-context": "^4.2.5",
|
||||||
"react-native-screens": "^3.13.1",
|
"react-native-screens": "^3.13.1",
|
||||||
"react-native-shadow-2": "^6.0.5",
|
"react-native-shadow-2": "^6.0.5",
|
||||||
"react-native-svg": "^12.3.0",
|
"react-native-svg": "^12.3.0",
|
||||||
"react-native-svg-transformer": "^1.0.0",
|
"react-native-svg-transformer": "^1.0.0",
|
||||||
"react-native-track-player": "^2.1.3",
|
"react-native-track-player": "^2.2.0-rc3",
|
||||||
"react-native-webview": "^11.18.2",
|
"react-native-webview": "^11.18.2",
|
||||||
"react-redux": "^7.2.6",
|
"react-redux": "^7.2.6",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.0",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
import { useColorScheme } from 'react-native';
|
import { useColorScheme } from 'react-native';
|
||||||
import { ColorSchemeContext, themes } from './Colors';
|
import { ColorSchemeContext, themes } from './Colors';
|
||||||
import DownloadManager from './DownloadManager';
|
import DownloadManager from './DownloadManager';
|
||||||
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||||
// import ErrorReportingAlert from 'utility/ErrorReportingAlert';
|
// import ErrorReportingAlert from 'utility/ErrorReportingAlert';
|
||||||
|
|
||||||
export default function App(): JSX.Element {
|
export default function App(): JSX.Element {
|
||||||
@@ -30,7 +31,8 @@ export default function App(): JSX.Element {
|
|||||||
Capability.SkipToPrevious,
|
Capability.SkipToPrevious,
|
||||||
Capability.Stop,
|
Capability.Stop,
|
||||||
Capability.SeekTo,
|
Capability.SeekTo,
|
||||||
]
|
],
|
||||||
|
stopWithApp: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setupTrackPlayer();
|
setupTrackPlayer();
|
||||||
@@ -41,8 +43,10 @@ export default function App(): JSX.Element {
|
|||||||
<PersistGate loading={null} persistor={persistedStore}>
|
<PersistGate loading={null} persistor={persistedStore}>
|
||||||
<ColorSchemeContext.Provider value={theme}>
|
<ColorSchemeContext.Provider value={theme}>
|
||||||
<NavigationContainer theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
<NavigationContainer theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||||
<Routes />
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
||||||
<DownloadManager />
|
<Routes />
|
||||||
|
<DownloadManager />
|
||||||
|
</GestureHandlerRootView>
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
</ColorSchemeContext.Provider>
|
</ColorSchemeContext.Provider>
|
||||||
</PersistGate>
|
</PersistGate>
|
||||||
|
|||||||
52
src/components/Progresstrack.tsx
Normal file
52
src/components/Progresstrack.tsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { THEME_COLOR } from 'CONSTANTS';
|
||||||
|
import styled from 'styled-components/native';
|
||||||
|
import Animated from 'react-native-reanimated';
|
||||||
|
|
||||||
|
export function getSeconds(seconds: number): string {
|
||||||
|
'worklet';
|
||||||
|
return Math.floor(seconds % 60).toString().padStart(2, '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMinutes(seconds: number): number {
|
||||||
|
'worklet';
|
||||||
|
return Math.floor(seconds / 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calculateProgressTranslation(
|
||||||
|
position: number,
|
||||||
|
reference: number,
|
||||||
|
width: number,
|
||||||
|
) {
|
||||||
|
'worklet';
|
||||||
|
const completion = position / reference;
|
||||||
|
const output = (1 - (completion || 0)) * -1 * width;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ProgressTrackContainer = styled.View`
|
||||||
|
overflow: hidden;
|
||||||
|
height: 5px;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 6px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export interface ProgressTrackProps {
|
||||||
|
opacity?: number;
|
||||||
|
stroke?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProgressTrack = styled(Animated.View)<ProgressTrackProps>`
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: ${(props) => props.stroke ? props.stroke + 'px' : '100%'};
|
||||||
|
background-color: ${THEME_COLOR};
|
||||||
|
opacity: ${(props) => props.opacity || 1};
|
||||||
|
border-radius: 99px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default ProgressTrack;
|
||||||
40
src/components/ReText.tsx
Normal file
40
src/components/ReText.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import type { TextProps as RNTextProps } from 'react-native';
|
||||||
|
import { StyleSheet, TextInput } from 'react-native';
|
||||||
|
import Animated, { useAnimatedProps } from 'react-native-reanimated';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
baseStyle: {
|
||||||
|
color: 'black',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Animated.addWhitelistedNativeProps({ text: true });
|
||||||
|
|
||||||
|
interface TextProps {
|
||||||
|
text: Animated.SharedValue<string>;
|
||||||
|
style?: Animated.AnimateProps<RNTextProps>['style'];
|
||||||
|
}
|
||||||
|
|
||||||
|
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);
|
||||||
|
|
||||||
|
const ReText = (props: TextProps) => {
|
||||||
|
const { text, style } = { style: {}, ...props };
|
||||||
|
const animatedProps = useAnimatedProps(() => {
|
||||||
|
return {
|
||||||
|
text: text.value,
|
||||||
|
// Here we use any because the text prop is not available in the type
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
} as any;
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<AnimatedTextInput
|
||||||
|
underlineColorAndroid="transparent"
|
||||||
|
editable={false}
|
||||||
|
value={text.value}
|
||||||
|
style={[styles.baseStyle, style]}
|
||||||
|
{...{ animatedProps }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ReText;
|
||||||
@@ -3,12 +3,12 @@ import Text from './Text';
|
|||||||
|
|
||||||
export const Header = styled(Text)`
|
export const Header = styled(Text)`
|
||||||
margin: 0 0 6px 0;
|
margin: 0 0 6px 0;
|
||||||
font-size: 24px;
|
font-size: 28px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const SubHeader = styled(Text)`
|
export const SubHeader = styled(Text)`
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
margin: 0 0 6px 0;
|
margin: 0 0 6px 0;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ import PlayIcon from 'assets/icons/play.svg';
|
|||||||
import PauseIcon from 'assets/icons/pause.svg';
|
import PauseIcon from 'assets/icons/pause.svg';
|
||||||
import useCurrentTrack from 'utility/useCurrentTrack';
|
import useCurrentTrack from 'utility/useCurrentTrack';
|
||||||
import TrackPlayer, { State, usePlaybackState, useProgress } from 'react-native-track-player';
|
import TrackPlayer, { State, usePlaybackState, useProgress } from 'react-native-track-player';
|
||||||
import { THEME_COLOR } from 'CONSTANTS';
|
|
||||||
import { Shadow } from 'react-native-shadow-2';
|
import { Shadow } from 'react-native-shadow-2';
|
||||||
import usePrevious from 'utility/usePrevious';
|
import usePrevious from 'utility/usePrevious';
|
||||||
import Text from 'components/Text';
|
import Text from 'components/Text';
|
||||||
import useDefaultStyles, { ColoredBlurView } from 'components/Colors';
|
import useDefaultStyles, { ColoredBlurView } from 'components/Colors';
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
|
import { calculateProgressTranslation } from 'components/Progresstrack';
|
||||||
|
import { THEME_COLOR } from 'CONSTANTS';
|
||||||
|
|
||||||
const NOW_PLAYING_POPOVER_MARGIN = 6;
|
const NOW_PLAYING_POPOVER_MARGIN = 6;
|
||||||
const NOW_PLAYING_POPOVER_WIDTH = Dimensions.get('screen').width - 2 * NOW_PLAYING_POPOVER_MARGIN;
|
const NOW_PLAYING_POPOVER_WIDTH = Dimensions.get('screen').width - 2 * NOW_PLAYING_POPOVER_MARGIN;
|
||||||
@@ -38,6 +39,17 @@ const InnerContainer = styled.Pressable`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const ProgressTrack = styled(Animated.View)<{ stroke?: number; opacity?: number}>`
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: ${(props) => props.stroke ? props.stroke + 'px' : '100%'};
|
||||||
|
background-color: ${THEME_COLOR};
|
||||||
|
opacity: ${(props) => props.opacity || 1};
|
||||||
|
border-radius: 99px;
|
||||||
|
`;
|
||||||
|
|
||||||
const ShadowOverlay = styled.View`
|
const ShadowOverlay = styled.View`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -61,21 +73,6 @@ const ActionButton = styled.Pressable`
|
|||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
interface ProgressTrackProps {
|
|
||||||
opacity?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ProgressTrack = styled(Animated.View)<ProgressTrackProps>`
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
height: 2px;
|
|
||||||
background-color: ${THEME_COLOR};
|
|
||||||
opacity: ${(props) => props.opacity || 1};
|
|
||||||
border-radius: 99px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
function SelectActionButton() {
|
function SelectActionButton() {
|
||||||
const state = usePlaybackState();
|
const state = usePlaybackState();
|
||||||
const defaultStyles = useDefaultStyles();
|
const defaultStyles = useDefaultStyles();
|
||||||
@@ -108,11 +105,6 @@ function SelectActionButton() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateProgressTranslation(position: number, reference: number) {
|
|
||||||
const completion = position / reference;
|
|
||||||
return (1 - (completion || 0)) * -1 * NOW_PLAYING_POPOVER_WIDTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
function NowPlaying() {
|
function NowPlaying() {
|
||||||
const { index, track } = useCurrentTrack();
|
const { index, track } = useCurrentTrack();
|
||||||
const { buffered, duration, position } = useProgress();
|
const { buffered, duration, position } = useProgress();
|
||||||
@@ -130,13 +122,13 @@ function NowPlaying() {
|
|||||||
const hasChangedTrack = previousIndex !== index || duration === 0;
|
const hasChangedTrack = previousIndex !== index || duration === 0;
|
||||||
|
|
||||||
Animated.timing(bufferAnimation.current, {
|
Animated.timing(bufferAnimation.current, {
|
||||||
toValue: calculateProgressTranslation(buffered, duration),
|
toValue: calculateProgressTranslation(buffered, duration, NOW_PLAYING_POPOVER_WIDTH),
|
||||||
duration: hasChangedTrack ? 0 : 500,
|
duration: hasChangedTrack ? 0 : 500,
|
||||||
useNativeDriver: true,
|
useNativeDriver: true,
|
||||||
easing: Easing.ease,
|
easing: Easing.ease,
|
||||||
}).start();
|
}).start();
|
||||||
Animated.timing(progressAnimation.current, {
|
Animated.timing(progressAnimation.current, {
|
||||||
toValue: calculateProgressTranslation(position, duration),
|
toValue: calculateProgressTranslation(position, duration, NOW_PLAYING_POPOVER_WIDTH),
|
||||||
duration: hasChangedTrack ? 0 : 500,
|
duration: hasChangedTrack ? 0 : 500,
|
||||||
useNativeDriver: true,
|
useNativeDriver: true,
|
||||||
}).start();
|
}).start();
|
||||||
@@ -168,9 +160,11 @@ function NowPlaying() {
|
|||||||
<ProgressTrack
|
<ProgressTrack
|
||||||
style={{ transform: [{ translateX: bufferAnimation.current }]}}
|
style={{ transform: [{ translateX: bufferAnimation.current }]}}
|
||||||
opacity={0.15}
|
opacity={0.15}
|
||||||
|
stroke={4}
|
||||||
/>
|
/>
|
||||||
<ProgressTrack
|
<ProgressTrack
|
||||||
style={{ transform: [{ translateX: progressAnimation.current }]}}
|
style={{ transform: [{ translateX: progressAnimation.current }]}}
|
||||||
|
stroke={4}
|
||||||
/>
|
/>
|
||||||
</InnerContainer>
|
</InnerContainer>
|
||||||
</ColoredBlurView>
|
</ColoredBlurView>
|
||||||
|
|||||||
@@ -1,95 +1,187 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import TrackPlayer from 'react-native-track-player';
|
import TrackPlayer, { useProgress } from 'react-native-track-player';
|
||||||
import styled from 'styled-components/native';
|
import styled from 'styled-components/native';
|
||||||
import { Text, Platform } from 'react-native';
|
import ProgressTrack, {
|
||||||
import Slider from '@react-native-community/slider';
|
calculateProgressTranslation,
|
||||||
|
getMinutes,
|
||||||
|
getSeconds,
|
||||||
|
ProgressTrackContainer
|
||||||
|
} from 'components/Progresstrack';
|
||||||
|
import { Gesture, GestureDetector, gestureHandlerRootHOC } from 'react-native-gesture-handler';
|
||||||
import { THEME_COLOR } from 'CONSTANTS';
|
import { THEME_COLOR } from 'CONSTANTS';
|
||||||
import { DefaultStylesProvider } from 'components/Colors';
|
import Reanimated, {
|
||||||
|
useSharedValue,
|
||||||
|
useAnimatedStyle,
|
||||||
|
withTiming,
|
||||||
|
Easing,
|
||||||
|
useDerivedValue,
|
||||||
|
runOnJS,
|
||||||
|
} from 'react-native-reanimated';
|
||||||
|
import ReText from 'components/ReText';
|
||||||
|
|
||||||
|
const DRAG_HANDLE_SIZE = 20;
|
||||||
|
|
||||||
|
const Container = styled.View`
|
||||||
|
margin-top: 28px;
|
||||||
|
`;
|
||||||
|
|
||||||
const NumberBar = styled.View`
|
const NumberBar = styled.View`
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 20px 0;
|
padding: 8px 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function getSeconds(seconds: number): string {
|
const Number = styled(ReText)`
|
||||||
return Math.floor(seconds % 60).toString().padStart(2, '0');
|
font-size: 13px;
|
||||||
}
|
`;
|
||||||
|
|
||||||
function getMinutes(seconds: number): number {
|
const DragHandle = styled(Reanimated.View)`
|
||||||
return Math.floor(seconds / 60);
|
width: ${DRAG_HANDLE_SIZE}px;
|
||||||
}
|
height: ${DRAG_HANDLE_SIZE}px;
|
||||||
|
border-radius: ${DRAG_HANDLE_SIZE}px;
|
||||||
|
background-color: ${THEME_COLOR};
|
||||||
|
position: absolute;
|
||||||
|
left: -${DRAG_HANDLE_SIZE / 2}px;
|
||||||
|
top: -${DRAG_HANDLE_SIZE / 2 - 2.5}px;
|
||||||
|
z-index: 14;
|
||||||
|
`;
|
||||||
|
|
||||||
interface State {
|
function ProgressBar() {
|
||||||
position: number;
|
const { position, buffered, duration } = useProgress();
|
||||||
duration: number;
|
|
||||||
gesture?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class ProgressBar extends Component<{}, State> {
|
const width = useSharedValue(0);
|
||||||
state: State = {
|
const pos = useSharedValue(0);
|
||||||
position: 0,
|
const buf = useSharedValue(0);
|
||||||
duration: 0,
|
const dur = useSharedValue(0);
|
||||||
};
|
|
||||||
|
|
||||||
timer: number | null = null;
|
const isDragging = useSharedValue(false);
|
||||||
|
const offset = useSharedValue(0);
|
||||||
|
|
||||||
componentDidMount() {
|
const bufferAnimation = useDerivedValue(() => {
|
||||||
this.timer = setInterval(this.updateProgress, 500);
|
return calculateProgressTranslation(buf.value, dur.value, width.value);
|
||||||
}
|
}, [[dur, buf, width.value]]);
|
||||||
|
|
||||||
componentWillUnmount() {
|
const progressAnimation = useDerivedValue(() => {
|
||||||
if (this.timer) {
|
if (isDragging.value) {
|
||||||
clearInterval(this.timer);
|
return calculateProgressTranslation(offset.value, width.value, width.value);
|
||||||
|
} else {
|
||||||
|
return calculateProgressTranslation(pos.value, dur.value, width.value);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
updateProgress = async () => {
|
const timePassed = useDerivedValue(() => {
|
||||||
const [position, duration] = await Promise.all([
|
if (isDragging.value) {
|
||||||
TrackPlayer.getPosition(),
|
const currentPosition = (offset.value - DRAG_HANDLE_SIZE / 2) / (width.value - DRAG_HANDLE_SIZE) * dur.value;
|
||||||
TrackPlayer.getDuration(),
|
return getMinutes(currentPosition) + ':' + getSeconds(currentPosition);
|
||||||
]);
|
} else {
|
||||||
|
return getMinutes(pos.value) + ':' + getSeconds(pos.value);
|
||||||
|
}
|
||||||
|
}, [pos]);
|
||||||
|
|
||||||
this.setState({ position, duration });
|
const timeRemaining = useDerivedValue(() => {
|
||||||
};
|
if (isDragging.value) {
|
||||||
|
const currentPosition = (offset.value - DRAG_HANDLE_SIZE / 2) / (width.value - DRAG_HANDLE_SIZE) * dur.value;
|
||||||
|
const remaining = (currentPosition - dur.value) * -1;
|
||||||
|
return `-${getMinutes(remaining)}:${getSeconds((remaining))}`;
|
||||||
|
} else {
|
||||||
|
const remaining = (pos.value - dur.value) * -1;
|
||||||
|
return `-${getMinutes(remaining)}:${getSeconds((remaining))}`;
|
||||||
|
}
|
||||||
|
}, [pos, dur]);
|
||||||
|
|
||||||
|
const gesture = Gesture.Pan()
|
||||||
|
.onBegin(() => {
|
||||||
|
isDragging.value = true;
|
||||||
|
}).onUpdate((e) => {
|
||||||
|
offset.value = Math.min(Math.max(DRAG_HANDLE_SIZE / 2, e.x), width.value - DRAG_HANDLE_SIZE / 2);
|
||||||
|
}).onFinalize(() => {
|
||||||
|
pos.value = (offset.value - DRAG_HANDLE_SIZE / 2) / (width.value - DRAG_HANDLE_SIZE) * dur.value;
|
||||||
|
isDragging.value = false;
|
||||||
|
runOnJS(TrackPlayer.seekTo)(pos.value);
|
||||||
|
});
|
||||||
|
|
||||||
handleGesture = async (gesture: number) => {
|
useEffect(() => {
|
||||||
// Set relative translation in state
|
pos.value = position;
|
||||||
this.setState({ gesture });
|
buf.value = buffered;
|
||||||
};
|
dur.value = duration;
|
||||||
|
}, [position, buffered, duration]);
|
||||||
|
|
||||||
handleEndOfGesture = (position: number) => {
|
const dragHandleStyles = useAnimatedStyle(() => {
|
||||||
// Calculate and set the new position
|
return {
|
||||||
TrackPlayer.seekTo(position);
|
transform: [
|
||||||
this.setState({ gesture: undefined, position });
|
{ translateX: offset.value },
|
||||||
};
|
{
|
||||||
|
scale: withTiming(isDragging.value ? 1 : 0.05, {
|
||||||
render() {
|
duration: 100,
|
||||||
const { position, duration, gesture } = this.state;
|
easing: Easing.out(Easing.ease),
|
||||||
|
})
|
||||||
return (
|
|
||||||
<DefaultStylesProvider>
|
|
||||||
{defaultStyle => (
|
|
||||||
<>
|
|
||||||
<Slider
|
|
||||||
value={gesture || position}
|
|
||||||
minimumValue={0}
|
|
||||||
maximumValue={duration || 0}
|
|
||||||
onValueChange={this.handleGesture}
|
|
||||||
onSlidingComplete={this.handleEndOfGesture}
|
|
||||||
minimumTrackTintColor={THEME_COLOR}
|
|
||||||
thumbTintColor={Platform.OS === 'android' ? THEME_COLOR : undefined}
|
|
||||||
disabled={!duration}
|
|
||||||
/>
|
|
||||||
<NumberBar>
|
|
||||||
<Text style={defaultStyle.text}>{getMinutes(gesture || position)}:{getSeconds(gesture || position)}</Text>
|
|
||||||
<Text style={defaultStyle.text}>{getMinutes(duration)}:{getSeconds(duration)}</Text>
|
|
||||||
</NumberBar>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
</DefaultStylesProvider>
|
],
|
||||||
);
|
};
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
const bufferStyles = useAnimatedStyle(() => ({
|
||||||
|
transform: [
|
||||||
|
{ translateX: bufferAnimation.value }
|
||||||
|
]
|
||||||
|
}));
|
||||||
|
|
||||||
|
const progressStyles = useAnimatedStyle(() => {
|
||||||
|
return {
|
||||||
|
transform: [
|
||||||
|
{ translateX: progressAnimation.value }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const timePassedStyles = useAnimatedStyle(() => {
|
||||||
|
return {
|
||||||
|
transform: [
|
||||||
|
{ translateY: withTiming(isDragging.value && offset.value < 48 ? 12 : 0, {
|
||||||
|
duration: 145,
|
||||||
|
easing: Easing.ease
|
||||||
|
}) },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const timeRemainingStyles = useAnimatedStyle(() => {
|
||||||
|
return {
|
||||||
|
transform: [
|
||||||
|
{ translateY: withTiming(isDragging.value && offset.value > width.value - 48 ? 12 : 0, {
|
||||||
|
duration: 150,
|
||||||
|
easing: Easing.ease
|
||||||
|
}) },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container onLayout={(e) => { width.value = e.nativeEvent.layout.width; }}>
|
||||||
|
<GestureDetector gesture={gesture}>
|
||||||
|
<>
|
||||||
|
<ProgressTrackContainer>
|
||||||
|
<ProgressTrack
|
||||||
|
opacity={0.15}
|
||||||
|
/>
|
||||||
|
<ProgressTrack
|
||||||
|
style={bufferStyles}
|
||||||
|
opacity={0.15}
|
||||||
|
/>
|
||||||
|
<ProgressTrack
|
||||||
|
style={progressStyles}
|
||||||
|
/>
|
||||||
|
</ProgressTrackContainer>
|
||||||
|
<DragHandle style={dragHandleStyles} />
|
||||||
|
<NumberBar style={{ flex: 1 }}>
|
||||||
|
<Number text={timePassed} style={timePassedStyles} />
|
||||||
|
<Number text={timeRemaining} style={timeRemainingStyles} />
|
||||||
|
</NumberBar>
|
||||||
|
</>
|
||||||
|
</GestureDetector>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default gestureHandlerRootHOC(ProgressBar);
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ export default function Player() {
|
|||||||
<ScrollView contentContainerStyle={styles.inner} style={defaultStyles.view}>
|
<ScrollView contentContainerStyle={styles.inner} style={defaultStyles.view}>
|
||||||
<NowPlaying />
|
<NowPlaying />
|
||||||
<ConnectionNotice />
|
<ConnectionNotice />
|
||||||
<MediaControls />
|
|
||||||
<ProgressBar />
|
<ProgressBar />
|
||||||
|
<MediaControls />
|
||||||
<Queue />
|
<Queue />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user