fix: missing images
This commit is contained in:
@@ -319,6 +319,7 @@
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/Sentry/Sentry.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle",
|
||||
@@ -330,6 +331,7 @@
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Sentry.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle",
|
||||
@@ -390,7 +392,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
CURRENT_PROJECT_VERSION = 117;
|
||||
DEVELOPMENT_TEAM = HD2D35G9Y4;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
@@ -427,7 +429,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
CURRENT_PROJECT_VERSION = 117;
|
||||
DEVELOPMENT_TEAM = HD2D35G9Y4;
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = HD2D35G9Y4;
|
||||
INFOPLIST_FILE = Fintunes/Info.plist;
|
||||
@@ -607,7 +609,7 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
CURRENT_PROJECT_VERSION = 117;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = HD2D35G9Y4;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
@@ -642,7 +644,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
CURRENT_PROJECT_VERSION = 117;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = HD2D35G9Y4;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.4.5</string>
|
||||
<string>2.4.6</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>115</string>
|
||||
<string>117</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
|
||||
@@ -8,6 +8,11 @@ PODS:
|
||||
- hermes-engine (0.79.2):
|
||||
- hermes-engine/Pre-built (= 0.79.2)
|
||||
- hermes-engine/Pre-built (0.79.2)
|
||||
- libavif/core (0.11.1)
|
||||
- libavif/libdav1d (0.11.1):
|
||||
- libavif/core
|
||||
- libdav1d (>= 0.6.0)
|
||||
- libdav1d (1.2.0)
|
||||
- libwebp (1.3.2):
|
||||
- libwebp/demux (= 1.3.2)
|
||||
- libwebp/mux (= 1.3.2)
|
||||
@@ -1894,10 +1899,35 @@ PODS:
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNFastImage (8.6.3):
|
||||
- RNFastImage (8.9.2):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- libavif/core (~> 0.11.1)
|
||||
- libavif/libdav1d (~> 0.11.1)
|
||||
- RCT-Folly (= 2024.11.18.00)
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- SDWebImage (~> 5.11.1)
|
||||
- SDWebImageWebPCoder (~> 0.8.4)
|
||||
- React-debug
|
||||
- React-Fabric
|
||||
- React-featureflags
|
||||
- React-graphics
|
||||
- React-hermes
|
||||
- React-ImageManager
|
||||
- React-jsi
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-renderercss
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- SDWebImage (>= 5.19.1)
|
||||
- SDWebImageAVIFCoder (~> 0.11.0)
|
||||
- SDWebImageWebPCoder (~> 0.14)
|
||||
- Yoga
|
||||
- RNFlashList (1.8.0):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
@@ -2221,12 +2251,15 @@ PODS:
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- SDWebImage (5.11.1):
|
||||
- SDWebImage/Core (= 5.11.1)
|
||||
- SDWebImage/Core (5.11.1)
|
||||
- SDWebImageWebPCoder (0.8.5):
|
||||
- SDWebImage (5.21.0):
|
||||
- SDWebImage/Core (= 5.21.0)
|
||||
- SDWebImage/Core (5.21.0)
|
||||
- SDWebImageAVIFCoder (0.11.0):
|
||||
- libavif/core (>= 0.11.0)
|
||||
- SDWebImage (~> 5.10)
|
||||
- SDWebImageWebPCoder (0.14.6):
|
||||
- libwebp (~> 1.0)
|
||||
- SDWebImage/Core (~> 5.10)
|
||||
- SDWebImage/Core (~> 5.17)
|
||||
- Sentry/HybridSDK (8.49.2)
|
||||
- SocketRocket (0.7.1)
|
||||
- SwiftAudioEx (1.1.0)
|
||||
@@ -2315,7 +2348,7 @@ DEPENDENCIES:
|
||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
||||
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
|
||||
- RNFastImage (from `../node_modules/react-native-fast-image`)
|
||||
- "RNFastImage (from `../node_modules/@d11/react-native-fast-image`)"
|
||||
- "RNFlashList (from `../node_modules/@shopify/flash-list`)"
|
||||
- RNFS (from `../node_modules/react-native-fs`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
@@ -2328,8 +2361,11 @@ DEPENDENCIES:
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- libavif
|
||||
- libdav1d
|
||||
- libwebp
|
||||
- SDWebImage
|
||||
- SDWebImageAVIFCoder
|
||||
- SDWebImageWebPCoder
|
||||
- Sentry
|
||||
- SocketRocket
|
||||
@@ -2496,7 +2532,7 @@ EXTERNAL SOURCES:
|
||||
RNDateTimePicker:
|
||||
:path: "../node_modules/@react-native-community/datetimepicker"
|
||||
RNFastImage:
|
||||
:path: "../node_modules/react-native-fast-image"
|
||||
:path: "../node_modules/@d11/react-native-fast-image"
|
||||
RNFlashList:
|
||||
:path: "../node_modules/@shopify/flash-list"
|
||||
RNFS:
|
||||
@@ -2524,6 +2560,8 @@ SPEC CHECKSUMS:
|
||||
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
|
||||
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
|
||||
hermes-engine: 314be5250afa5692b57b4dd1705959e1973a8ebe
|
||||
libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
|
||||
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
|
||||
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
|
||||
RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82
|
||||
RCTDeprecation: 83ffb90c23ee5cea353bd32008a7bca100908f8c
|
||||
@@ -2597,7 +2635,7 @@ SPEC CHECKSUMS:
|
||||
ReactCommon: 76d2dc87136d0a667678668b86f0fca0c16fdeb0
|
||||
RNCAsyncStorage: 39c42c1e478e1f5166d1db52b5055e090e85ad66
|
||||
RNDateTimePicker: 43ee3de2bc639bc0d9b77564961060a54dfc7111
|
||||
RNFastImage: 462a183c4b0b6b26fdfd639e1ed6ba37536c3b87
|
||||
RNFastImage: 72769fac450a8a7d111378433111d8e52f2b251e
|
||||
RNFlashList: 5001dd06f0003a497de3e2035653c54cf8b48e96
|
||||
RNFS: 89de7d7f4c0f6bafa05343c578f61118c8282ed8
|
||||
RNGestureHandler: ebef699ea17e7c0006c1074e1e423ead60ce0121
|
||||
@@ -2606,8 +2644,9 @@ SPEC CHECKSUMS:
|
||||
RNScreens: 5621e3ad5a329fbd16de683344ac5af4192b40d3
|
||||
RNSentry: f444779917ac0314ecffea5e8bd1041d1be06c31
|
||||
RNSVG: 794f269526df9ddc1f79b3d1a202b619df0368e3
|
||||
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
|
||||
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
|
||||
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
|
||||
SDWebImageAVIFCoder: 00310d246aab3232ce77f1d8f0076f8c4b021d90
|
||||
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
|
||||
Sentry: 47021097466aa130802420d485a34da445963d99
|
||||
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
||||
SwiftAudioEx: f6aa653770f3a0d3851edaf8d834a30aee4a7646
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fintunes",
|
||||
"version": "2.4.5",
|
||||
"version": "2.4.6",
|
||||
"main": "src/index.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -12,6 +12,7 @@
|
||||
"postinstall": "patch-package"
|
||||
},
|
||||
"dependencies": {
|
||||
"@d11/react-native-fast-image": "^8.9.2",
|
||||
"@react-native-async-storage/async-storage": "^2.1.2",
|
||||
"@react-native-community/blur": "^4.4.1",
|
||||
"@react-native-community/datetimepicker": "^8.3.0",
|
||||
@@ -36,7 +37,6 @@
|
||||
"react-native-accessibility-settings": "^0.1.2",
|
||||
"react-native-collapsible": "^1.6.2",
|
||||
"react-native-dotenv": "^3.4.11",
|
||||
"react-native-fast-image": "^8.6.3",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "^2.25.0",
|
||||
"react-native-localize": "^3.4.1",
|
||||
|
||||
28
pnpm-lock.yaml
generated
28
pnpm-lock.yaml
generated
@@ -19,6 +19,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@d11/react-native-fast-image':
|
||||
specifier: ^8.9.2
|
||||
version: 8.9.2(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@18.0.0(typescript@5.8.3))(@types/react@18.3.20)(react@19.0.0))(react@19.0.0)
|
||||
'@react-native-async-storage/async-storage':
|
||||
specifier: ^2.1.2
|
||||
version: 2.1.2(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@18.0.0(typescript@5.8.3))(@types/react@18.3.20)(react@19.0.0))
|
||||
@@ -91,9 +94,6 @@ importers:
|
||||
react-native-dotenv:
|
||||
specifier: ^3.4.11
|
||||
version: 3.4.11(@babel/runtime@7.27.1)
|
||||
react-native-fast-image:
|
||||
specifier: ^8.6.3
|
||||
version: 8.6.3(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@18.0.0(typescript@5.8.3))(@types/react@18.3.20)(react@19.0.0))(react@19.0.0)
|
||||
react-native-fs:
|
||||
specifier: ^2.20.0
|
||||
version: 2.20.0(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@18.0.0(typescript@5.8.3))(@types/react@18.3.20)(react@19.0.0))
|
||||
@@ -794,6 +794,12 @@ packages:
|
||||
resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@d11/react-native-fast-image@8.9.2':
|
||||
resolution: {integrity: sha512-7d0O5mA17SCbIAYq9D0WxDlS3HXf5v9vg9ltphDfP/3R57sBEf6/wby/sHkOmrQGwvgUlz2oSo5Ld8hgocLJeQ==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
|
||||
'@egjs/hammerjs@2.0.17':
|
||||
resolution: {integrity: sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==}
|
||||
engines: {node: '>=0.8.0'}
|
||||
@@ -3840,12 +3846,6 @@ packages:
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
|
||||
react-native-fast-image@8.6.3:
|
||||
resolution: {integrity: sha512-Sdw4ESidXCXOmQ9EcYguNY2swyoWmx53kym2zRsvi+VeFCHEdkO+WG1DK+6W81juot40bbfLNhkc63QnWtesNg==}
|
||||
peerDependencies:
|
||||
react: ^17 || ^18
|
||||
react-native: '>=0.60.0'
|
||||
|
||||
react-native-fs@2.20.0:
|
||||
resolution: {integrity: sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==}
|
||||
peerDependencies:
|
||||
@@ -5444,6 +5444,11 @@ snapshots:
|
||||
'@babel/helper-string-parser': 7.27.1
|
||||
'@babel/helper-validator-identifier': 7.27.1
|
||||
|
||||
'@d11/react-native-fast-image@8.9.2(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@18.0.0(typescript@5.8.3))(@types/react@18.3.20)(react@19.0.0))(react@19.0.0)':
|
||||
dependencies:
|
||||
react: 19.0.0
|
||||
react-native: 0.79.2(@babel/core@7.27.1)(@react-native-community/cli@18.0.0(typescript@5.8.3))(@types/react@18.3.20)(react@19.0.0)
|
||||
|
||||
'@egjs/hammerjs@2.0.17':
|
||||
dependencies:
|
||||
'@types/hammerjs': 2.0.46
|
||||
@@ -9377,11 +9382,6 @@ snapshots:
|
||||
react-native: 0.79.2(@babel/core@7.27.1)(@react-native-community/cli@18.0.0(typescript@5.8.3))(@types/react@18.3.20)(react@19.0.0)
|
||||
optional: true
|
||||
|
||||
react-native-fast-image@8.6.3(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@18.0.0(typescript@5.8.3))(@types/react@18.3.20)(react@19.0.0))(react@19.0.0):
|
||||
dependencies:
|
||||
react: 19.0.0
|
||||
react-native: 0.79.2(@babel/core@7.27.1)(@react-native-community/cli@18.0.0(typescript@5.8.3))(@types/react@18.3.20)(react@19.0.0)
|
||||
|
||||
react-native-fs@2.20.0(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@18.0.0(typescript@5.8.3))(@types/react@18.3.20)(react@19.0.0)):
|
||||
dependencies:
|
||||
base-64: 0.1.0
|
||||
|
||||
@@ -28,7 +28,7 @@ interface Props {
|
||||
margin?: number;
|
||||
radius?: number;
|
||||
style?: ViewProps['style'];
|
||||
src: string;
|
||||
src?: string;
|
||||
}
|
||||
|
||||
const emptyAlbumLight = require('@/assets/images/empty-album-light.png');
|
||||
@@ -59,6 +59,8 @@ function CoverImage({
|
||||
return { imageSize, canvasSize };
|
||||
}, [blurRadius, margin]);
|
||||
|
||||
console.log({ src, hasFailed });
|
||||
|
||||
return (
|
||||
<Container size={imageSize} style={style}>
|
||||
<BlurContainer size={canvasSize} offset={blurRadius}>
|
||||
@@ -69,7 +71,7 @@ function CoverImage({
|
||||
<Shadow dx={0} dy={8} blur={16} color="#0000000d" />
|
||||
<Shadow dx={0} dy={16} blur={32} color="#0000000d" />
|
||||
</RoundedRect>
|
||||
{src && (
|
||||
{src ? (
|
||||
<>
|
||||
<SkiaImage
|
||||
image={image}
|
||||
@@ -97,8 +99,7 @@ function CoverImage({
|
||||
</SkiaImage>
|
||||
</Mask>
|
||||
</>
|
||||
)}
|
||||
{(!src || hasFailed) && (
|
||||
) : (
|
||||
<Mask
|
||||
mask={
|
||||
<RoundedRect
|
||||
|
||||
@@ -136,7 +136,7 @@ function Downloads() {
|
||||
<DownloadedTrack>
|
||||
<View style={{ marginRight: 12 }}>
|
||||
<ShadowWrapper size="small">
|
||||
<AlbumImage source={{ uri: getImage(item) }} style={defaultStyles.imageBackground} />
|
||||
<AlbumImage source={{ uri: getImage(tracks[item]) }} style={defaultStyles.imageBackground} />
|
||||
</ShadowWrapper>
|
||||
</View>
|
||||
<View style={{ flexShrink: 1, marginRight: 8 }}>
|
||||
|
||||
@@ -48,7 +48,7 @@ const SectionHeading = React.memo(function SectionHeading(props: {
|
||||
|
||||
interface GeneratedAlbumItemProps {
|
||||
id: ReactText;
|
||||
imageUrl: string;
|
||||
imageUrl: string | null;
|
||||
name: string;
|
||||
artist: string;
|
||||
onPress: (id: string) => void;
|
||||
@@ -66,7 +66,7 @@ const GeneratedAlbumItem = React.memo(function GeneratedAlbumItem(props: Generat
|
||||
<TouchableHandler id={id as string} onPress={onPress}>
|
||||
<AlbumItem>
|
||||
<ShadowWrapper size="medium">
|
||||
<AlbumImage source={{ uri: imageUrl }} style={[defaultStyles.imageBackground]} />
|
||||
<AlbumImage source={imageUrl ? { uri: imageUrl } : undefined} style={[defaultStyles.imageBackground]} />
|
||||
</ShadowWrapper>
|
||||
<Text numberOfLines={1} style={defaultStyles.text}>{name}</Text>
|
||||
<HalfOpacity style={defaultStyles.text} numberOfLines={1}>{artist}</HalfOpacity>
|
||||
@@ -136,7 +136,7 @@ const Albums: React.FC = () => {
|
||||
<GeneratedAlbumItem
|
||||
key={i}
|
||||
id={id}
|
||||
imageUrl={getImage(albums[id])}
|
||||
imageUrl={albums[id].ImageTags.Primary ? getImage(albums[id]) : null}
|
||||
name={albums[id]?.Name || ''}
|
||||
artist={albums[id]?.AlbumArtist || ''}
|
||||
onPress={selectAlbum}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { SafeFlatList, useNavigationOffsets } from '@/components/SafeNavigatorVi
|
||||
|
||||
interface GeneratedAlbumItemProps {
|
||||
id: ReactText;
|
||||
imageUrl: string;
|
||||
imageUrl?: string | null;
|
||||
name: string;
|
||||
onPress: (id: string) => void;
|
||||
}
|
||||
@@ -26,7 +26,7 @@ const GeneratedPlaylistItem = React.memo(function GeneratedPlaylistItem(props: G
|
||||
return (
|
||||
<TouchableHandler id={id as string} onPress={onPress}>
|
||||
<AlbumItem>
|
||||
<AlbumImage source={{ uri: imageUrl }} style={defaultStyles.imageBackground} />
|
||||
<AlbumImage source={{ uri: imageUrl || undefined }} style={defaultStyles.imageBackground} />
|
||||
<Text numberOfLines={1} style={defaultStyles.text}>{name}</Text>
|
||||
</AlbumItem>
|
||||
</TouchableHandler>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components/native';
|
||||
import FastImage, { FastImageProps } from 'react-native-fast-image';
|
||||
import FastImage, { FastImageProps, Source } from '@d11/react-native-fast-image';
|
||||
import { Dimensions } from 'react-native';
|
||||
import { useUserOrSystemScheme } from '@/components/Colors';
|
||||
|
||||
@@ -22,24 +22,29 @@ const Container = styled(FastImage)`
|
||||
margin-bottom: 5px;
|
||||
`;
|
||||
|
||||
function AlbumImage(props: FastImageProps) {
|
||||
const [hasError, setError] = useState(false);
|
||||
const colorScheme = useUserOrSystemScheme();
|
||||
export interface AlbumImageProps extends FastImageProps {
|
||||
source: number | Omit<Source, 'uri'> & {
|
||||
uri?: string;
|
||||
};
|
||||
}
|
||||
|
||||
if (!props.source || hasError) {
|
||||
return (
|
||||
<Container
|
||||
{...props}
|
||||
source={colorScheme === 'light'
|
||||
? require('@/assets/images/empty-album-light.png')
|
||||
: require('@/assets/images/empty-album-dark.png')
|
||||
}
|
||||
/>
|
||||
);
|
||||
const defaultImageDark = require('@/assets/images/empty-album-dark.png');
|
||||
const defaultImageLight = require('@/assets/images/empty-album-light.png');
|
||||
|
||||
function AlbumImage(props: FastImageProps) {
|
||||
const colorScheme = useUserOrSystemScheme();
|
||||
const defaultImage = colorScheme === 'light' ? defaultImageLight : defaultImageDark;
|
||||
|
||||
// If no source is provided, use the default image as the main source
|
||||
if (!props.source || (typeof props.source === 'object' && 'uri' in props.source && !props.source.uri)) {
|
||||
return <Container {...props} source={defaultImage} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container {...props} onError={() => setError(true)} />
|
||||
<Container
|
||||
{...props}
|
||||
defaultSource={defaultImage}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ const TrackListView: React.FC<TrackListViewProps> = ({
|
||||
const tracks = useTypedSelector((state) => state.music.tracks.entities);
|
||||
const isLoading = useTypedSelector((state) => state.music.tracks.isLoading);
|
||||
const downloadedTracks = useTypedSelector(selectDownloadedTracks(trackIds));
|
||||
const entity = useTypedSelector((state) => itemDisplayStyle === 'album' ? state.music.albums.entities[entityId] : state.music.playlists.entities[entityId]);
|
||||
const totalDuration = useMemo(() => (
|
||||
trackIds.reduce<number>((sum, trackId) => (
|
||||
sum + (tracks[trackId]?.RunTimeTicks || 0)
|
||||
@@ -173,7 +174,7 @@ const TrackListView: React.FC<TrackListViewProps> = ({
|
||||
>
|
||||
<View style={{ padding: 24, paddingTop: 32, paddingBottom: 32 }}>
|
||||
<AlbumImageContainer>
|
||||
<CoverImage src={getImage(entityId)} />
|
||||
<CoverImage src={getImage(entity)} />
|
||||
</AlbumImageContainer>
|
||||
<Header>{title}</Header>
|
||||
<SubHeader>{artist}</SubHeader>
|
||||
|
||||
@@ -46,7 +46,7 @@ export async function fetchApi<T>(
|
||||
path: PathOrCredentialInserter,
|
||||
providedConfig?: RequestInit,
|
||||
parseResponse = true
|
||||
) {
|
||||
) {
|
||||
// Retrieve the latest credentials from the Redux store
|
||||
const credentials = asyncFetchStore().getState().settings.credentials;
|
||||
|
||||
@@ -67,11 +67,11 @@ export async function fetchApi<T>(
|
||||
...generateConfig(credentials).headers,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Actually perform the request
|
||||
const response = await fetch(url, config);
|
||||
|
||||
if (__DEV__) {
|
||||
if (__DEV__) {
|
||||
console.log(`%c[HTTP] → [${response.status}] ${url}`, 'font-weight:bold;');
|
||||
console.log('\t', config);
|
||||
}
|
||||
@@ -96,24 +96,44 @@ export async function fetchApi<T>(
|
||||
if (parseResponse) {
|
||||
// Parse body as JSON
|
||||
const data = await response.json() as Promise<T>;
|
||||
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function formatImageUri(ItemId: string | number, baseUri: string): string {
|
||||
return encodeURI(`${baseUri}/Items/${ItemId}/Images/Primary?format=jpeg`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an image URL for a given ItemId
|
||||
*/
|
||||
export function getImage(ItemId: string | number, credentials?: AppState['settings']['credentials']): string {
|
||||
export function getImage(item: string | number | Album | AlbumTrack | Playlist | ArtistItem | null, credentials?: AppState['settings']['credentials']): string | undefined {
|
||||
// Either accept provided credentials, or retrieve them directly from the store
|
||||
const { uri: serverUri } = credentials
|
||||
const { uri: serverUri } = credentials
|
||||
?? asyncFetchStore().getState().settings.credentials ?? {};
|
||||
|
||||
// Generate the uri and return
|
||||
const uri = encodeURI(`${serverUri}/Items/${ItemId}/Images/Primary?format=jpeg`);
|
||||
return uri;
|
||||
|
||||
if (!item || !serverUri) {
|
||||
return undefined;
|
||||
// GUARD: If the item's just the id, we'll pass it on directly.
|
||||
} else if (typeof item === 'string' || typeof item === 'number') {
|
||||
if (__DEV__) {
|
||||
console.warn('useGetImage: supplied item is string or number. Please submit an item object instead.', { item });
|
||||
}
|
||||
return formatImageUri(item, serverUri);
|
||||
// GUARD: If the item has an `PrimaryImageItemId` (for Emby servers),
|
||||
// we'll attemp to return that
|
||||
} else if ('PrimaryImageItemId' in item) {
|
||||
return formatImageUri(item.PrimaryImageItemId || item.Id, serverUri);
|
||||
} else {
|
||||
if ('ImageTags' in item && item.ImageTags.Primary) {
|
||||
return formatImageUri(item.Id, serverUri);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,18 +142,7 @@ export function getImage(ItemId: string | number, credentials?: AppState['settin
|
||||
export function useGetImage() {
|
||||
const credentials = useTypedSelector((state) => state.settings.credentials);
|
||||
|
||||
return (item: string | number | Album | AlbumTrack | Playlist | ArtistItem | null) => {
|
||||
if (!item) {
|
||||
return '';
|
||||
// GUARD: If the item's just the id, we'll pass it on directly.
|
||||
} else if (typeof item === 'string' || typeof item === 'number') {
|
||||
return getImage(item, credentials);
|
||||
// GUARD: If the item has an `PrimaryImageItemId` (for Emby servers),
|
||||
// we'll attemp to return that
|
||||
} else if ('PrimaryImageItemId' in item) {
|
||||
return getImage(item.PrimaryImageItemId || item.Id, credentials);
|
||||
} else {
|
||||
return getImage(item.Id);
|
||||
}
|
||||
return (item: Parameters<typeof getImage>[0]) => {
|
||||
return getImage(item, credentials);
|
||||
};
|
||||
}
|
||||
@@ -57,7 +57,7 @@ export async function generateTrack(track: AlbumTrack): Promise<Track> {
|
||||
artist: track.Artists.join(', '),
|
||||
album: track.Album,
|
||||
duration: track.RunTimeTicks,
|
||||
artwork: getImage(track.Id),
|
||||
artwork: getImage(track),
|
||||
bitRate: baseTrackOptions.audioBitRate,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user