mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	Test #700
This commit is contained in:
		| @@ -1,363 +0,0 @@ | ||||
| diff --git a/RNFastImage.podspec b/RNFastImage.podspec | ||||
| index db0fada63fc06191f8620d336d244edde6c3dba3..9c22c36f6978530da21afe143324ff79b4e96454 100644 | ||||
| --- a/RNFastImage.podspec | ||||
| +++ b/RNFastImage.podspec | ||||
| @@ -16,6 +16,6 @@ Pod::Spec.new do |s| | ||||
|    s.source_files  = "ios/**/*.{h,m}" | ||||
|   | ||||
|    s.dependency 'React-Core' | ||||
| -  s.dependency 'SDWebImage', '~> 5.11.1' | ||||
| -  s.dependency 'SDWebImageWebPCoder', '~> 0.8.4' | ||||
| +  s.dependency 'SDWebImage', '~> 5.15.0' | ||||
| +  s.dependency 'SDWebImageWebPCoder', '~> 0.9.1' | ||||
|  end | ||||
| diff --git a/android/build.gradle b/android/build.gradle | ||||
| index 5b21cd59c40a5754f5d19c77e2a0eb0229925911..19d82f826e88125c5e6d87ee7c348fac621f548c 100644 | ||||
| --- a/android/build.gradle | ||||
| +++ b/android/build.gradle | ||||
| @@ -65,4 +65,5 @@ dependencies { | ||||
|      implementation "com.github.bumptech.glide:glide:${glideVersion}" | ||||
|      implementation "com.github.bumptech.glide:okhttp3-integration:${glideVersion}" | ||||
|      annotationProcessor "com.github.bumptech.glide:compiler:${glideVersion}" | ||||
| +    implementation 'com.github.penfeizhou.android.animation:glide-plugin:2.12.0' | ||||
|  } | ||||
| diff --git a/android/src/main/java/com/dylanvann/fastimage/FastImageEnterTransition.java b/android/src/main/java/com/dylanvann/fastimage/FastImageEnterTransition.java | ||||
| new file mode 100644 | ||||
| index 0000000000000000000000000000000000000000..55e3b4e0d463654f62d942ba05c2a5e51ae9d6d7 | ||||
| --- /dev/null | ||||
| +++ b/android/src/main/java/com/dylanvann/fastimage/FastImageEnterTransition.java | ||||
| @@ -0,0 +1,6 @@ | ||||
| +package com.dylanvann.fastimage; | ||||
| + | ||||
| +public enum FastImageEnterTransition { | ||||
| +    TRANSITION_NONE, | ||||
| +    FADE_IN | ||||
| +} | ||||
| diff --git a/android/src/main/java/com/dylanvann/fastimage/FastImageTransitions.java b/android/src/main/java/com/dylanvann/fastimage/FastImageTransitions.java | ||||
| new file mode 100644 | ||||
| index 0000000000000000000000000000000000000000..d764cc4b8d110f087120a4f0dc5d986754806dec | ||||
| --- /dev/null | ||||
| +++ b/android/src/main/java/com/dylanvann/fastimage/FastImageTransitions.java | ||||
| @@ -0,0 +1,20 @@ | ||||
| +package com.dylanvann.fastimage; | ||||
| + | ||||
| +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; | ||||
| +import com.bumptech.glide.TransitionOptions; | ||||
| +import com.facebook.react.bridge.JSApplicationIllegalArgumentException; | ||||
| +import android.view.animation.DecelerateInterpolator; | ||||
| + | ||||
| +public class FastImageTransitions { | ||||
| +    static final DecelerateInterpolator mInterpolator = new DecelerateInterpolator(); | ||||
| + | ||||
| +    public static TransitionOptions getEnterTransition(FastImageEnterTransition transition, int duration) { | ||||
| +        switch (transition) { | ||||
| +            case FADE_IN: | ||||
| +                return DrawableTransitionOptions.withCrossFade(duration); | ||||
| + | ||||
| +            default: | ||||
| +                throw new JSApplicationIllegalArgumentException("FastImage, invalid enterTransition argument"); | ||||
| +        } | ||||
| +    } | ||||
| +} | ||||
| \ No newline at end of file | ||||
| diff --git a/android/src/main/java/com/dylanvann/fastimage/FastImageViewConverter.java b/android/src/main/java/com/dylanvann/fastimage/FastImageViewConverter.java | ||||
| index 86ca00d018d7ded0edff733373d80976c8dbb961..e6220f57b38a3fe3ae9d5a75228f791e0ec978bb 100644 | ||||
| --- a/android/src/main/java/com/dylanvann/fastimage/FastImageViewConverter.java | ||||
| +++ b/android/src/main/java/com/dylanvann/fastimage/FastImageViewConverter.java | ||||
| @@ -50,6 +50,12 @@ class FastImageViewConverter { | ||||
|                  put("center", ScaleType.CENTER_INSIDE); | ||||
|              }}; | ||||
|   | ||||
| +    private static final Map<String, FastImageEnterTransition> FAST_IMAGE_ENTER_TRANSITION_MAP = | ||||
| +            new HashMap<String, FastImageEnterTransition>() {{ | ||||
| +                put("none", FastImageEnterTransition.TRANSITION_NONE); | ||||
| +                put("fadeIn", FastImageEnterTransition.FADE_IN); | ||||
| +            }}; | ||||
| + | ||||
|      // Resolve the source uri to a file path that android understands. | ||||
|      static @Nullable | ||||
|      FastImageSource getImageSource(Context context, @Nullable ReadableMap source) { | ||||
| @@ -125,6 +131,10 @@ class FastImageViewConverter { | ||||
|          return getValueFromSource("cache", "immutable", FAST_IMAGE_CACHE_CONTROL_MAP, source); | ||||
|      } | ||||
|   | ||||
| +    static FastImageEnterTransition getEnterTransition(String propValue) { | ||||
| +        return getValue("enterTransition", "none", FAST_IMAGE_ENTER_TRANSITION_MAP, propValue); | ||||
| +    } | ||||
| + | ||||
|      private static Priority getPriority(ReadableMap source) { | ||||
|          return getValueFromSource("priority", "normal", FAST_IMAGE_PRIORITY_MAP, source); | ||||
|      } | ||||
| diff --git a/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java b/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java | ||||
| index c7a795471c8f8b48163c778836406bc5ead75dab..53b481547b44224e7791a8d3f39815c9c9a4be59 100644 | ||||
| --- a/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java | ||||
| +++ b/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java | ||||
| @@ -83,6 +83,17 @@ class FastImageViewManager extends SimpleViewManager<FastImageViewWithUrl> imple | ||||
|          view.setScaleType(scaleType); | ||||
|      } | ||||
|   | ||||
| +    @ReactProp(name = "enterTransition") | ||||
| +    public void setEnterTransition(FastImageViewWithUrl view, String enterTransition) { | ||||
| +        final FastImageEnterTransition transition = FastImageViewConverter.getEnterTransition(enterTransition); | ||||
| +        view.setEnterTransition(transition); | ||||
| +    } | ||||
| + | ||||
| +    @ReactProp(name = "transitionDuration") | ||||
| +    public void setTransitionDuration(FastImageViewWithUrl view, int transitionDuration) { | ||||
| +        view.setTransitionDuration(transitionDuration); | ||||
| +    } | ||||
| + | ||||
|      @Override | ||||
|      public void onDropViewInstance(@NonNull FastImageViewWithUrl view) { | ||||
|          // This will cancel existing requests. | ||||
| diff --git a/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java b/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java | ||||
| index 34fcf898d17d82fd52375e9028b71ad815b9b15b..fd57ac68de093d2a8ee53aeede45328c8d52aa39 100644 | ||||
| --- a/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java | ||||
| +++ b/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java | ||||
| @@ -30,6 +30,8 @@ class FastImageViewWithUrl extends AppCompatImageView { | ||||
|      private boolean mNeedsReload = false; | ||||
|      private ReadableMap mSource = null; | ||||
|      private Drawable mDefaultSource = null; | ||||
| +    private FastImageEnterTransition mEnterTransition = FastImageEnterTransition.TRANSITION_NONE; | ||||
| +    private int mTransitionDuration = 350; | ||||
|   | ||||
|      public GlideUrl glideUrl; | ||||
|   | ||||
| @@ -47,6 +49,14 @@ class FastImageViewWithUrl extends AppCompatImageView { | ||||
|          mDefaultSource = source; | ||||
|      } | ||||
|   | ||||
| +    public void setEnterTransition(@Nullable FastImageEnterTransition transition) { | ||||
| +        mEnterTransition = transition; | ||||
| +    } | ||||
| + | ||||
| +    public void setTransitionDuration(int duration) { | ||||
| +        mTransitionDuration = duration == 0 ? 350 : duration; | ||||
| +    } | ||||
| + | ||||
|      private boolean isNullOrEmpty(final String url) { | ||||
|          return url == null || url.trim().isEmpty(); | ||||
|      } | ||||
| @@ -147,6 +157,10 @@ class FastImageViewWithUrl extends AppCompatImageView { | ||||
|              if (key != null) | ||||
|                  builder.listener(new FastImageRequestListener(key)); | ||||
|   | ||||
| +            if (mEnterTransition != FastImageEnterTransition.TRANSITION_NONE) { | ||||
| +                builder.transition(FastImageTransitions.getEnterTransition(mEnterTransition, mTransitionDuration)); | ||||
| +            } | ||||
| + | ||||
|              builder.into(this); | ||||
|          } | ||||
|      } | ||||
| diff --git a/dist/index.cjs.js b/dist/index.cjs.js | ||||
| index 2df6a29769978d8d947dfb50b422e1f56bd97fb6..f3904e20edac5f19cc26f41a4ff02eecd73ac627 100644 | ||||
| --- a/dist/index.cjs.js | ||||
| +++ b/dist/index.cjs.js | ||||
| @@ -9,6 +9,10 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau | ||||
|  var _extends__default = /*#__PURE__*/_interopDefaultLegacy(_extends); | ||||
|  var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||||
|   | ||||
| +const enterTransition = { | ||||
| +  none: 'none', | ||||
| +  fadeIn: 'fadeIn' | ||||
| +} | ||||
|  const resizeMode = { | ||||
|    contain: 'contain', | ||||
|    cover: 'cover', | ||||
| @@ -115,6 +119,7 @@ const FastImageComponent = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PU | ||||
|  }, props))); | ||||
|  FastImageComponent.displayName = 'FastImage'; | ||||
|  const FastImage = FastImageComponent; | ||||
| +FastImage.enterTransition = enterTransition | ||||
|  FastImage.resizeMode = resizeMode; | ||||
|  FastImage.cacheControl = cacheControl; | ||||
|  FastImage.priority = priority; | ||||
| diff --git a/dist/index.d.ts b/dist/index.d.ts | ||||
| index 5abb7c98b767cd0709b53f5ab2dd50c752a9377b..2da22817e3136673d40a177ae8c9fc2209f143d8 100644 | ||||
| --- a/dist/index.d.ts | ||||
| +++ b/dist/index.d.ts | ||||
| @@ -1,5 +1,10 @@ | ||||
|  import React from 'react'; | ||||
|  import { FlexStyle, LayoutChangeEvent, ShadowStyleIOS, StyleProp, TransformsStyle, ImageRequireSource, AccessibilityProps, ViewProps, ColorValue } from 'react-native'; | ||||
| +export declare type EnterTransition = 'none' | 'fadeIn'; | ||||
| +declare const enterTransition: { | ||||
| +    readonly none: "none"; | ||||
| +    readonly fadeIn: "fadeIn"; | ||||
| +}; | ||||
|  export declare type ResizeMode = 'contain' | 'cover' | 'stretch' | 'center'; | ||||
|  declare const resizeMode: { | ||||
|      readonly contain: "contain"; | ||||
| @@ -57,6 +62,16 @@ export interface FastImageProps extends AccessibilityProps, ViewProps { | ||||
|      defaultSource?: ImageRequireSource; | ||||
|      resizeMode?: ResizeMode; | ||||
|      fallback?: boolean; | ||||
| +    /** | ||||
| +     * Transition durations. | ||||
| +     * @default none | ||||
| +     */ | ||||
| +    enterTransition?: EnterTransition | ||||
| +    /** | ||||
| +     * Enter transition duration in ms. | ||||
| +     * @default 500ms | ||||
| +     */ | ||||
| +    transitionDuration?: number | ||||
|      onLoadStart?(): void; | ||||
|      onProgress?(event: OnProgressEvent): void; | ||||
|      onLoad?(event: OnLoadEvent): void; | ||||
| @@ -91,6 +106,7 @@ export interface FastImageProps extends AccessibilityProps, ViewProps { | ||||
|      children?: React.ReactNode; | ||||
|  } | ||||
|  export interface FastImageStaticProperties { | ||||
| +    enterTransition: typeof enterTransition; | ||||
|      resizeMode: typeof resizeMode; | ||||
|      priority: typeof priority; | ||||
|      cacheControl: typeof cacheControl; | ||||
| diff --git a/dist/index.js b/dist/index.js | ||||
| index 58e0308bd44836aad3e4979b5c1151083956c295..5853b3b2fd05c91be8c70819fe6fc45606f26f8d 100644 | ||||
| --- a/dist/index.js | ||||
| +++ b/dist/index.js | ||||
| @@ -2,6 +2,10 @@ import _extends from '@babel/runtime/helpers/extends'; | ||||
|  import React, { forwardRef, memo } from 'react'; | ||||
|  import { NativeModules, StyleSheet, requireNativeComponent, Image, View, Platform } from 'react-native'; | ||||
|   | ||||
| +const enterTransition = { | ||||
| +  none: 'none', | ||||
| +  fadeIn: 'fadeIn' | ||||
| +} | ||||
|  const resizeMode = { | ||||
|    contain: 'contain', | ||||
|    cover: 'cover', | ||||
| @@ -57,6 +61,8 @@ function FastImageBase({ | ||||
|    children, | ||||
|    // eslint-disable-next-line no-shadow | ||||
|    resizeMode = 'cover', | ||||
| +  enterTransition = 'none', | ||||
| +  transitionDuration = 350, | ||||
|    forwardedRef, | ||||
|    ...props | ||||
|  }) { | ||||
| @@ -79,7 +85,9 @@ function FastImageBase({ | ||||
|        onLoad: onLoad, | ||||
|        onError: onError, | ||||
|        onLoadEnd: onLoadEnd, | ||||
| -      resizeMode: resizeMode | ||||
| +      resizeMode: resizeMode, | ||||
| +      enterTransition: enterTransition, | ||||
| +      transitionDuration: transitionDuration | ||||
|      })), children); | ||||
|    } | ||||
|   | ||||
| @@ -98,7 +106,9 @@ function FastImageBase({ | ||||
|      onFastImageLoad: onLoad, | ||||
|      onFastImageError: onError, | ||||
|      onFastImageLoadEnd: onLoadEnd, | ||||
| -    resizeMode: resizeMode | ||||
| +    resizeMode: resizeMode, | ||||
| +    enterTransition: enterTransition, | ||||
| +    transitionDuration: transitionDuration | ||||
|    })), children); | ||||
|  } | ||||
|   | ||||
| @@ -108,6 +118,7 @@ const FastImageComponent = /*#__PURE__*/forwardRef((props, ref) => /*#__PURE__*/ | ||||
|  }, props))); | ||||
|  FastImageComponent.displayName = 'FastImage'; | ||||
|  const FastImage = FastImageComponent; | ||||
| +FastImage.enterTransition = enterTransition | ||||
|  FastImage.resizeMode = resizeMode; | ||||
|  FastImage.cacheControl = cacheControl; | ||||
|  FastImage.priority = priority; | ||||
| diff --git a/ios/FastImage/FFFastImageView.h b/ios/FastImage/FFFastImageView.h | ||||
| index e52fca79882ad2a678487a46b2fe158427e06f3a..6c9c41b0b1a3c967a3715a24bb692447b76ef365 100644 | ||||
| --- a/ios/FastImage/FFFastImageView.h | ||||
| +++ b/ios/FastImage/FFFastImageView.h | ||||
| @@ -7,6 +7,7 @@ | ||||
|  #import <React/RCTResizeMode.h> | ||||
|   | ||||
|  #import "FFFastImageSource.h" | ||||
| +#import "FFFastImageViewManager.h" | ||||
|   | ||||
|  @interface FFFastImageView : SDAnimatedImageView | ||||
|   | ||||
| @@ -16,6 +17,8 @@ | ||||
|  @property (nonatomic, copy) RCTDirectEventBlock onFastImageLoad; | ||||
|  @property (nonatomic, copy) RCTDirectEventBlock onFastImageLoadEnd; | ||||
|  @property (nonatomic, assign) RCTResizeMode resizeMode; | ||||
| +@property (nonatomic, assign) FFFEnterTransition enterTransition; | ||||
| +@property (nonatomic, assign) NSTimeInterval transitionDuration; | ||||
|  @property (nonatomic, strong) FFFastImageSource *source; | ||||
|  @property (nonatomic, strong) UIImage *defaultSource; | ||||
|  @property (nonatomic, strong) UIColor *imageColor; | ||||
| diff --git a/ios/FastImage/FFFastImageView.m b/ios/FastImage/FFFastImageView.m | ||||
| index f7100815e652539b29b1fa70ff1477c5f5db08dc..ecb79eafe566fe52090adada3cdf16eb10a67513 100644 | ||||
| --- a/ios/FastImage/FFFastImageView.m | ||||
| +++ b/ios/FastImage/FFFastImageView.m | ||||
| @@ -71,6 +71,18 @@ - (void) setImageColor: (UIColor*)imageColor { | ||||
|      } | ||||
|  } | ||||
|   | ||||
| +- (void) setTransitionDuration: (NSTimeInterval)transitionDuration { | ||||
| +   self.sd_imageTransition.duration = transitionDuration; | ||||
| +} | ||||
| + | ||||
| +- (void) setEnterTransition: (FFFEnterTransition)enterTransition { | ||||
| +    switch (enterTransition) { | ||||
| +        case FFFFadeIn: | ||||
| +            self.sd_imageTransition = SDWebImageTransition.fadeTransition; | ||||
| +            break; | ||||
| +    } | ||||
| +} | ||||
| + | ||||
|  - (UIImage*) makeImage: (UIImage*)image withTint: (UIColor*)color { | ||||
|      UIImage* newImage = [image imageWithRenderingMode: UIImageRenderingModeAlwaysTemplate]; | ||||
|      UIGraphicsBeginImageContextWithOptions(image.size, NO, newImage.scale); | ||||
| diff --git a/ios/FastImage/FFFastImageViewManager.h b/ios/FastImage/FFFastImageViewManager.h | ||||
| index 8ba6020e2c6e5757ed778d00e3f43a6ff4c1d50a..a269669301ea00ef3c2714123d17e822094635d6 100644 | ||||
| --- a/ios/FastImage/FFFastImageViewManager.h | ||||
| +++ b/ios/FastImage/FFFastImageViewManager.h | ||||
| @@ -1,5 +1,10 @@ | ||||
|  #import <React/RCTViewManager.h> | ||||
|   | ||||
| +typedef NS_ENUM(NSInteger, FFFEnterTransition) { | ||||
| +    FFFTransitionNone, | ||||
| +    FFFFadeIn, | ||||
| +}; | ||||
| + | ||||
|  @interface FFFastImageViewManager : RCTViewManager | ||||
|   | ||||
|  @end | ||||
| diff --git a/ios/FastImage/FFFastImageViewManager.m b/ios/FastImage/FFFastImageViewManager.m | ||||
| index 84ca94e26e546d4d139dabca6c3efd0a890eda63..2184bac31f0d547e6119356bb4fc7931be87446d 100644 | ||||
| --- a/ios/FastImage/FFFastImageViewManager.m | ||||
| +++ b/ios/FastImage/FFFastImageViewManager.m | ||||
| @@ -13,6 +13,8 @@ - (FFFastImageView*)view { | ||||
|  } | ||||
|   | ||||
|  RCT_EXPORT_VIEW_PROPERTY(source, FFFastImageSource) | ||||
| +RCT_EXPORT_VIEW_PROPERTY(enterTransition, FFFEnterTransition) | ||||
| +RCT_EXPORT_VIEW_PROPERTY(transitionDuration, NSTimeInterval) | ||||
|  RCT_EXPORT_VIEW_PROPERTY(defaultSource, UIImage) | ||||
|  RCT_EXPORT_VIEW_PROPERTY(resizeMode, RCTResizeMode) | ||||
|  RCT_EXPORT_VIEW_PROPERTY(onFastImageLoadStart, RCTDirectEventBlock) | ||||
| diff --git a/ios/FastImage/RCTConvert+FFFastImage.m b/ios/FastImage/RCTConvert+FFFastImage.m | ||||
| index 43f8922157655a7497f56a3909ef6b2a886f07d8..0705f8e05f44f3053e7239fcc9a30d986e7aaab7 100644 | ||||
| --- a/ios/FastImage/RCTConvert+FFFastImage.m | ||||
| +++ b/ios/FastImage/RCTConvert+FFFastImage.m | ||||
| @@ -1,5 +1,6 @@ | ||||
|  #import "RCTConvert+FFFastImage.h" | ||||
|  #import "FFFastImageSource.h" | ||||
| +#import "FFFastImageViewManager.h" | ||||
|   | ||||
|  @implementation RCTConvert (FFFastImage) | ||||
|   | ||||
| @@ -15,6 +16,11 @@ @implementation RCTConvert (FFFastImage) | ||||
|                                         @"cacheOnly": @(FFFCacheControlCacheOnly), | ||||
|                                         }), FFFCacheControlImmutable, integerValue); | ||||
|   | ||||
| +RCT_ENUM_CONVERTER(FFFEnterTransition, (@{ | ||||
| +                                          @"none": @(FFFTransitionNone), | ||||
| +                                          @"fadeIn": @(FFFFadeIn), | ||||
| +                                          }), FFFTransitionNone, integerValue); | ||||
| + | ||||
|  + (FFFastImageSource *)FFFastImageSource:(id)json { | ||||
|      if (!json) { | ||||
|          return nil; | ||||
| @@ -22,6 +22,12 @@ PODS: | ||||
|     - ExpoModulesCore | ||||
|   - ExpoHaptics (12.1.0): | ||||
|     - ExpoModulesCore | ||||
|   - ExpoImage (1.0.0-beta.6): | ||||
|     - ExpoModulesCore | ||||
|     - SDWebImage (~> 5.15.0) | ||||
|     - SDWebImageAVIFCoder (~> 0.9.4) | ||||
|     - SDWebImageSVGCoder (~> 1.6.1) | ||||
|     - SDWebImageWebPCoder (~> 0.9.1) | ||||
|   - ExpoKeepAwake (11.0.1): | ||||
|     - ExpoModulesCore | ||||
|   - ExpoLocalization (14.0.0): | ||||
| @@ -58,7 +64,16 @@ PODS: | ||||
|   - fmt (6.2.1) | ||||
|   - glog (0.3.5) | ||||
|   - hermes-engine (0.70.7) | ||||
|   - libaom (2.0.2): | ||||
|     - libvmaf | ||||
|   - libavif (0.10.1): | ||||
|     - libavif/libaom (= 0.10.1) | ||||
|   - libavif/core (0.10.1) | ||||
|   - libavif/libaom (0.10.1): | ||||
|     - libaom (>= 2.0.0) | ||||
|     - libavif/core | ||||
|   - libevent (2.1.12) | ||||
|   - libvmaf (2.2.0) | ||||
|   - libwebp (1.2.4): | ||||
|     - libwebp/demux (= 1.2.4) | ||||
|     - libwebp/mux (= 1.2.4) | ||||
| @@ -299,8 +314,6 @@ PODS: | ||||
|     - glog | ||||
|   - react-native-blur (4.3.0): | ||||
|     - React-Core | ||||
|   - react-native-blurhash (1.1.10): | ||||
|     - React-Core | ||||
|   - react-native-cameraroll (5.2.3): | ||||
|     - React-Core | ||||
|   - react-native-image-picker (5.0.1): | ||||
| @@ -401,10 +414,6 @@ PODS: | ||||
|     - React-Core | ||||
|   - RNCClipboard (1.11.1): | ||||
|     - React-Core | ||||
|   - RNFastImage (8.6.3): | ||||
|     - React-Core | ||||
|     - SDWebImage (~> 5.15.0) | ||||
|     - SDWebImageWebPCoder (~> 0.9.1) | ||||
|   - RNGestureHandler (2.9.0): | ||||
|     - React-Core | ||||
|   - RNReanimated (2.14.4): | ||||
| @@ -447,6 +456,11 @@ PODS: | ||||
|   - SDWebImage (5.15.0): | ||||
|     - SDWebImage/Core (= 5.15.0) | ||||
|   - SDWebImage/Core (5.15.0) | ||||
|   - SDWebImageAVIFCoder (0.9.5): | ||||
|     - libavif (>= 0.9.1) | ||||
|     - SDWebImage (~> 5.10) | ||||
|   - SDWebImageSVGCoder (1.6.1): | ||||
|     - SDWebImage/Core (~> 5.6) | ||||
|   - SDWebImageWebPCoder (0.9.1): | ||||
|     - libwebp (~> 1.0) | ||||
|     - SDWebImage/Core (~> 5.13) | ||||
| @@ -467,6 +481,7 @@ DEPENDENCIES: | ||||
|   - Expo (from `../node_modules/expo`) | ||||
|   - ExpoCrypto (from `../node_modules/expo-crypto/ios`) | ||||
|   - ExpoHaptics (from `../node_modules/expo-haptics/ios`) | ||||
|   - ExpoImage (from `../node_modules/expo-image/ios`) | ||||
|   - ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`) | ||||
|   - ExpoLocalization (from `../node_modules/expo-localization/ios`) | ||||
|   - ExpoModulesCore (from `../node_modules/expo-modules-core`) | ||||
| @@ -500,7 +515,6 @@ DEPENDENCIES: | ||||
|   - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) | ||||
|   - React-logger (from `../node_modules/react-native/ReactCommon/logger`) | ||||
|   - "react-native-blur (from `../node_modules/@react-native-community/blur`)" | ||||
|   - react-native-blurhash (from `../node_modules/react-native-blurhash`) | ||||
|   - "react-native-cameraroll (from `../node_modules/@react-native-camera-roll/camera-roll`)" | ||||
|   - react-native-image-picker (from `../node_modules/react-native-image-picker`) | ||||
|   - react-native-ios-context-menu (from `../node_modules/react-native-ios-context-menu`) | ||||
| @@ -527,7 +541,6 @@ DEPENDENCIES: | ||||
|   - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) | ||||
|   - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" | ||||
|   - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" | ||||
|   - RNFastImage (from `../node_modules/react-native-fast-image`) | ||||
|   - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) | ||||
|   - RNReanimated (from `../node_modules/react-native-reanimated`) | ||||
|   - RNScreens (from `../node_modules/react-native-screens`) | ||||
| @@ -539,11 +552,16 @@ DEPENDENCIES: | ||||
| SPEC REPOS: | ||||
|   trunk: | ||||
|     - fmt | ||||
|     - libaom | ||||
|     - libavif | ||||
|     - libevent | ||||
|     - libvmaf | ||||
|     - libwebp | ||||
|     - MMKV | ||||
|     - MMKVCore | ||||
|     - SDWebImage | ||||
|     - SDWebImageAVIFCoder | ||||
|     - SDWebImageSVGCoder | ||||
|     - SDWebImageWebPCoder | ||||
|     - Sentry | ||||
|     - Swime | ||||
| @@ -573,6 +591,8 @@ EXTERNAL SOURCES: | ||||
|     :path: "../node_modules/expo-crypto/ios" | ||||
|   ExpoHaptics: | ||||
|     :path: "../node_modules/expo-haptics/ios" | ||||
|   ExpoImage: | ||||
|     :path: "../node_modules/expo-image/ios" | ||||
|   ExpoKeepAwake: | ||||
|     :path: "../node_modules/expo-keep-awake/ios" | ||||
|   ExpoLocalization: | ||||
| @@ -635,8 +655,6 @@ EXTERNAL SOURCES: | ||||
|     :path: "../node_modules/react-native/ReactCommon/logger" | ||||
|   react-native-blur: | ||||
|     :path: "../node_modules/@react-native-community/blur" | ||||
|   react-native-blurhash: | ||||
|     :path: "../node_modules/react-native-blurhash" | ||||
|   react-native-cameraroll: | ||||
|     :path: "../node_modules/@react-native-camera-roll/camera-roll" | ||||
|   react-native-image-picker: | ||||
| @@ -689,8 +707,6 @@ EXTERNAL SOURCES: | ||||
|     :path: "../node_modules/@react-native-async-storage/async-storage" | ||||
|   RNCClipboard: | ||||
|     :path: "../node_modules/@react-native-clipboard/clipboard" | ||||
|   RNFastImage: | ||||
|     :path: "../node_modules/react-native-fast-image" | ||||
|   RNGestureHandler: | ||||
|     :path: "../node_modules/react-native-gesture-handler" | ||||
|   RNReanimated: | ||||
| @@ -719,6 +735,7 @@ SPEC CHECKSUMS: | ||||
|   Expo: b9fa98bf260992312ee3c424400819fb9beadafe | ||||
|   ExpoCrypto: 6eb2a5ede7d95b7359a5f0391ee0c5d2ecd144b3 | ||||
|   ExpoHaptics: 129d3f8d44c2205adcdf8db760602818463d5437 | ||||
|   ExpoImage: 748f2b8d3974f1d51c7706fd61057b93241738aa | ||||
|   ExpoKeepAwake: 69b59d0a8d2b24de9f82759c39b3821fec030318 | ||||
|   ExpoLocalization: e202d1e2a4950df17ac8d0889d65a1ffd7532d7e | ||||
|   ExpoModulesCore: 485dff3a59b036a33b6050c0a5aea3cf1037fdd1 | ||||
| @@ -735,7 +752,10 @@ SPEC CHECKSUMS: | ||||
|   fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 | ||||
|   glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b | ||||
|   hermes-engine: 566e656aa95456a3f3f739fd76ea9a9656f2633f | ||||
|   libaom: 9bb51e0f8f9192245e3ca2a1c9e4375d9cbccc52 | ||||
|   libavif: e242998ccec1c83bcba0bbdc256f460ad5077348 | ||||
|   libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 | ||||
|   libvmaf: 8d61aabc2f4ed3e6591cf7406fa00a223ec11289 | ||||
|   libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef | ||||
|   MMKV: 7f34558bbb5a33b0eaefae2de4b6a20a2ffdad6f | ||||
|   MMKVCore: ddf41b9d9262f058419f9ba7598719af56c02cd3 | ||||
| @@ -755,7 +775,6 @@ SPEC CHECKSUMS: | ||||
|   React-jsinspector: 1c34fea1868136ecde647bc11fae9266d4143693 | ||||
|   React-logger: e9f407f9fdf3f3ce7749ae6f88affe63e8446019 | ||||
|   react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3 | ||||
|   react-native-blurhash: add4df9a937b4e021a24bc67a0714f13e0bd40b7 | ||||
|   react-native-cameraroll: 5b25d0be40185d02e522bf2abf8a1ba4e8faa107 | ||||
|   react-native-image-picker: 8cb4280e2c1efc3daeb2d9d597f9429a60472e40 | ||||
|   react-native-ios-context-menu: e529171ba760a1af7f2ef0729f5a7f4d226171c5 | ||||
| @@ -782,7 +801,6 @@ SPEC CHECKSUMS: | ||||
|   ReactCommon: 0253d197eaa7f6689dcd3e7d5360449ab93e10df | ||||
|   RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60 | ||||
|   RNCClipboard: 2834e1c4af68697089cdd455ee4a4cdd198fa7dd | ||||
|   RNFastImage: bd611b5635f1e0f43c8ccf597b1ef6ee0d0f966d | ||||
|   RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39 | ||||
|   RNReanimated: 6668b0587bebd4b15dd849b99e5a9c70fc12ed95 | ||||
|   RNScreens: ea4cd3a853063cda19a4e3c28d2e52180c80f4eb | ||||
| @@ -790,6 +808,8 @@ SPEC CHECKSUMS: | ||||
|   RNShareMenu: cb9dac548c8bf147d06f0bf07296ad51ea9f5fc3 | ||||
|   RNSVG: c1e76b81c76cdcd34b4e1188852892dc280eb902 | ||||
|   SDWebImage: 9bec4c5cdd9579e1f57104735ee0c37df274d593 | ||||
|   SDWebImageAVIFCoder: d759e21cf4efb640cc97250566aa556ad8bb877c | ||||
|   SDWebImageSVGCoder: 6fc109f9c2a82ab44510fff410b88b1a6c271ee8 | ||||
|   SDWebImageWebPCoder: 18503de6621dd2c420d680e33d46bf8e1d5169b0 | ||||
|   Sentry: 4c9babff9034785067c896fd580b1f7de44da020 | ||||
|   Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b | ||||
|   | ||||
| @@ -50,6 +50,7 @@ | ||||
|     "expo-crypto": "^12.1.0", | ||||
|     "expo-file-system": "^15.1.1", | ||||
|     "expo-haptics": "^12.1.0", | ||||
|     "expo-image": "^1.0.0-beta.6", | ||||
|     "expo-linking": "^3.3.0", | ||||
|     "expo-localization": "^14.0.0", | ||||
|     "expo-notifications": "^0.17.0", | ||||
| @@ -70,8 +71,6 @@ | ||||
|     "react-i18next": "^12.1.4", | ||||
|     "react-intl": "^6.2.7", | ||||
|     "react-native": "^0.70.7", | ||||
|     "react-native-blurhash": "^1.1.10", | ||||
|     "react-native-fast-image": "^8.6.3", | ||||
|     "react-native-flash-message": "^0.4.0", | ||||
|     "react-native-gesture-handler": "~2.9.0", | ||||
|     "react-native-image-picker": "^5.0.1", | ||||
| @@ -116,7 +115,6 @@ | ||||
|   }, | ||||
|   "packageManager": "yarn@3.3.1", | ||||
|   "resolutions": { | ||||
|     "react-native-fast-image@^8.6.3": "patch:react-native-fast-image@npm%3A8.6.3#./.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch", | ||||
|     "expo-av@^13.0.2": "patch:expo-av@npm%3A13.0.2#./.yarn/patches/expo-av-npm-13.0.2-7a651776f1.patch", | ||||
|     "react-native-share-menu@^6.0.0": "patch:react-native-share-menu@npm%3A6.0.0#./.yarn/patches/react-native-share-menu-npm-6.0.0-f1094c3204.patch", | ||||
|     "@types/react-native-share-menu@^5.0.2": "patch:@types/react-native-share-menu@npm%3A5.0.2#./.yarn/patches/@types-react-native-share-menu-npm-5.0.2-373df17ecc.patch", | ||||
|   | ||||
| @@ -38,7 +38,7 @@ const ComponentAccount: React.FC<PropsWithChildren & Props> = ({ account, props, | ||||
|         <> | ||||
|           <View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }}> | ||||
|             <GracefullyImage | ||||
|               uri={{ original: account.avatar, static: account.avatar_static }} | ||||
|               sources={{ default: { uri: account.avatar }, static: { uri: account.avatar_static } }} | ||||
|               style={{ | ||||
|                 width: StyleConstants.Avatar.S, | ||||
|                 height: StyleConstants.Avatar.S, | ||||
|   | ||||
| @@ -40,7 +40,7 @@ const AccountButton: React.FC<Props> = ({ account, additionalActions }) => { | ||||
|       }} | ||||
|     > | ||||
|       <GracefullyImage | ||||
|         uri={{ original: account.avatar_static }} | ||||
|         sources={{ default: { uri: account.avatar_static } }} | ||||
|         dimension={{ | ||||
|           width: StyleConstants.Font.Size.L, | ||||
|           height: StyleConstants.Font.Size.L | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import { getAccountStorage, setAccountStorage } from '@utils/storage/actions' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import layoutAnimation from '@utils/styles/layoutAnimation' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import { Image } from 'expo-image' | ||||
| import { chunk } from 'lodash' | ||||
| import React, { useContext, useEffect, useRef, useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| @@ -19,7 +20,6 @@ import { | ||||
|   TextInput, | ||||
|   View | ||||
| } from 'react-native' | ||||
| import FastImage from 'react-native-fast-image' | ||||
| import EmojisContext from './Context' | ||||
|  | ||||
| const EmojisList = () => { | ||||
| @@ -129,9 +129,7 @@ const EmojisList = () => { | ||||
|               }} | ||||
|               style={{ padding: StyleConstants.Spacing.S }} | ||||
|             > | ||||
|               <FastImage | ||||
|                 enterTransition='fadeIn' | ||||
|                 transitionDuration={60} | ||||
|               <Image | ||||
|                 accessibilityLabel={t('common:customEmoji.accessibilityLabel', { | ||||
|                   emoji: emoji.shortcode | ||||
|                 })} | ||||
|   | ||||
| @@ -1,36 +1,26 @@ | ||||
| import { useAccessibility } from '@utils/accessibility/AccessibilityManager' | ||||
| import { connectMedia } from '@utils/api/helpers/connect' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import React, { useEffect, useState } from 'react' | ||||
| import { | ||||
|   AccessibilityProps, | ||||
|   Image, | ||||
|   Pressable, | ||||
|   StyleProp, | ||||
|   StyleSheet, | ||||
|   View, | ||||
|   ViewStyle | ||||
| } from 'react-native' | ||||
| import { Blurhash } from 'react-native-blurhash' | ||||
| import FastImage, { ImageStyle } from 'react-native-fast-image' | ||||
|  | ||||
| // blurhas -> if blurhash, show before any loading succeed | ||||
| // original -> load original | ||||
| // original, remote -> if original failed, then remote | ||||
| // preview, original -> first show preview, then original | ||||
| // preview, original, remote -> first show preview, then original, if original failed, then remote | ||||
| import { Image, ImageSource, ImageStyle } from 'expo-image' | ||||
| import React, { useState } from 'react' | ||||
| import { AccessibilityProps, Pressable, StyleProp, View, ViewStyle } from 'react-native' | ||||
|  | ||||
| export interface Props { | ||||
|   accessibilityLabel?: AccessibilityProps['accessibilityLabel'] | ||||
|   accessibilityHint?: AccessibilityProps['accessibilityHint'] | ||||
|  | ||||
|   hidden?: boolean | ||||
|   uri: { preview?: string; original?: string; remote?: string; static?: string } | ||||
|   blurhash?: string | ||||
|   sources: { | ||||
|     preview?: ImageSource | ||||
|     default?: ImageSource | ||||
|     remote?: ImageSource | ||||
|     static?: ImageSource | ||||
|     blurhash?: string | ||||
|   } | ||||
|   dimension?: { width: number; height: number } | ||||
|   onPress?: () => void | ||||
|   style?: StyleProp<ViewStyle> | ||||
|   imageStyle?: StyleProp<ImageStyle> | ||||
|   imageStyle?: ImageStyle | ||||
|   // For image viewer when there is no image size available | ||||
|   setImageDimensions?: React.Dispatch< | ||||
|     React.SetStateAction<{ | ||||
| @@ -39,49 +29,30 @@ export interface Props { | ||||
|     }> | ||||
|   > | ||||
|   dim?: boolean | ||||
|   enableLiveTextInteraction?: boolean | ||||
| } | ||||
|  | ||||
| const GracefullyImage = ({ | ||||
|   accessibilityLabel, | ||||
|   accessibilityHint, | ||||
|   hidden = false, | ||||
|   uri, | ||||
|   blurhash, | ||||
|   sources, | ||||
|   dimension, | ||||
|   onPress, | ||||
|   style, | ||||
|   imageStyle, | ||||
|   setImageDimensions, | ||||
|   dim | ||||
|   dim, | ||||
|   enableLiveTextInteraction = false | ||||
| }: Props) => { | ||||
|   const { reduceMotionEnabled } = useAccessibility() | ||||
|   const { colors, theme } = useTheme() | ||||
|   const [imageLoaded, setImageLoaded] = useState(false) | ||||
|   const { theme } = useTheme() | ||||
|  | ||||
|   const [currentUri, setCurrentUri] = useState<string | undefined>(uri.original || uri.remote) | ||||
|   const source: { uri?: string } = { | ||||
|     uri: reduceMotionEnabled && uri.static ? uri.static : currentUri | ||||
|   } | ||||
|   useEffect(() => { | ||||
|     if ( | ||||
|       (uri.original ? currentUri !== uri.original : true) && | ||||
|       (uri.remote ? currentUri !== uri.remote : true) | ||||
|     ) { | ||||
|       setCurrentUri(uri.original || uri.remote) | ||||
|     } | ||||
|   }, [currentUri, uri.original, uri.remote]) | ||||
|  | ||||
|   const blurhashView = () => { | ||||
|     if (hidden || !imageLoaded) { | ||||
|       if (blurhash) { | ||||
|         return <Blurhash decodeAsync blurhash={blurhash} style={styles.placeholder} /> | ||||
|       } else { | ||||
|         return <View style={[styles.placeholder, { backgroundColor: colors.shimmerDefault }]} /> | ||||
|       } | ||||
|     } else { | ||||
|       return null | ||||
|     } | ||||
|   } | ||||
|   const [currentSource, setCurrentSource] = useState<ImageSource | undefined>( | ||||
|     sources.default || sources.remote | ||||
|   ) | ||||
|   const source: ImageSource | undefined = | ||||
|     reduceMotionEnabled && sources.static ? sources.static : currentSource | ||||
|  | ||||
|   return ( | ||||
|     <Pressable | ||||
| @@ -91,50 +62,40 @@ const GracefullyImage = ({ | ||||
|       style={[style, dimension]} | ||||
|       {...(onPress ? (hidden ? { disabled: true } : { onPress }) : { disabled: true })} | ||||
|     > | ||||
|       {uri.preview && !imageLoaded ? ( | ||||
|         <FastImage | ||||
|           source={connectMedia({ uri: uri.preview })} | ||||
|           enterTransition='fadeIn' | ||||
|           transitionDuration={60} | ||||
|           style={[styles.placeholder]} | ||||
|         /> | ||||
|       ) : null} | ||||
|       <FastImage | ||||
|         source={connectMedia(source)} | ||||
|         enterTransition={!blurhash && !uri.preview ? 'fadeIn' : 'none'} | ||||
|         transitionDuration={60} | ||||
|         style={[{ flex: 1 }, imageStyle]} | ||||
|         onLoad={() => { | ||||
|           setImageLoaded(true) | ||||
|           if (setImageDimensions && source.uri) { | ||||
|             Image.getSize(source.uri, (width, height) => setImageDimensions({ width, height })) | ||||
|       <Image | ||||
|         placeholder={sources.blurhash || connectMedia(sources.preview)} | ||||
|         source={hidden ? undefined : connectMedia(source)} | ||||
|         transition={{ duration: 100 }} | ||||
|         style={{ flex: 1, ...imageStyle }} | ||||
|         onLoad={event => { | ||||
|           if (setImageDimensions && event.source) { | ||||
|             setImageDimensions(event.source) | ||||
|           } | ||||
|         }} | ||||
|         onError={() => { | ||||
|           if (uri.original && uri.original === currentUri && uri.remote) { | ||||
|             setCurrentUri(uri.remote) | ||||
|           if ( | ||||
|             sources.default?.uri && | ||||
|             sources.default?.uri === currentSource?.uri && | ||||
|             sources.remote | ||||
|           ) { | ||||
|             setCurrentSource(sources.remote) | ||||
|           } | ||||
|         }} | ||||
|         enableLiveTextInteraction={enableLiveTextInteraction} | ||||
|       /> | ||||
|       {blurhashView()} | ||||
|       {dim && theme !== 'light' ? ( | ||||
|         <View | ||||
|           style={[ | ||||
|             styles.placeholder, | ||||
|             { backgroundColor: 'black', opacity: theme === 'dark_lighter' ? 0.18 : 0.36 } | ||||
|           ]} | ||||
|           style={{ | ||||
|             width: '100%', | ||||
|             height: '100%', | ||||
|             position: 'absolute', | ||||
|             backgroundColor: 'black', | ||||
|             opacity: theme === 'dark_lighter' ? 0.18 : 0.36 | ||||
|           }} | ||||
|         /> | ||||
|       ) : null} | ||||
|     </Pressable> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| const styles = StyleSheet.create({ | ||||
|   placeholder: { | ||||
|     width: '100%', | ||||
|     height: '100%', | ||||
|     position: 'absolute' | ||||
|   } | ||||
| }) | ||||
|  | ||||
| export default GracefullyImage | ||||
|   | ||||
| @@ -19,12 +19,13 @@ import { | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import * as AuthSession from 'expo-auth-session' | ||||
| import { Image } from 'expo-image' | ||||
| import * as Random from 'expo-random' | ||||
| import * as WebBrowser from 'expo-web-browser' | ||||
| import { debounce } from 'lodash' | ||||
| import React, { RefObject, useCallback, useState } from 'react' | ||||
| import { Trans, useTranslation } from 'react-i18next' | ||||
| import { Alert, Image, KeyboardAvoidingView, Platform, TextInput, View } from 'react-native' | ||||
| import { Alert, KeyboardAvoidingView, Platform, TextInput, View } from 'react-native' | ||||
| import { ScrollView } from 'react-native-gesture-handler' | ||||
| import { fromByteArray } from 'react-native-quick-base64' | ||||
| import parse from 'url-parse' | ||||
|   | ||||
| @@ -5,9 +5,9 @@ import { useGlobalStorage } from '@utils/storage/actions' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import { adaptiveScale } from '@utils/styles/scaling' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import { Image } from 'expo-image' | ||||
| import React from 'react' | ||||
| import { ColorValue, Platform, TextStyle } from 'react-native' | ||||
| import FastImage from 'react-native-fast-image' | ||||
|  | ||||
| const regexEmoji = new RegExp(/(:[A-Za-z0-9_]+:)/) | ||||
|  | ||||
| @@ -77,8 +77,8 @@ const ParseEmojis: React.FC<Props> = ({ | ||||
|                 return ( | ||||
|                   <CustomText key={emojiShortcode + i}> | ||||
|                     {i === 0 ? ' ' : undefined} | ||||
|                     <FastImage | ||||
|                       source={connectMedia({ uri: uri.trim() })} | ||||
|                     <Image | ||||
|                       source={connectMedia({ uri })} | ||||
|                       style={{ | ||||
|                         width: adaptedFontsize, | ||||
|                         height: adaptedFontsize, | ||||
|   | ||||
| @@ -79,7 +79,10 @@ const TimelineConversation: React.FC<Props> = ({ conversation, queryKey, highlig | ||||
|             {conversation.accounts.slice(0, 4).map(account => ( | ||||
|               <GracefullyImage | ||||
|                 key={account.id} | ||||
|                 uri={{ original: account.avatar, static: account.avatar_static }} | ||||
|                 sources={{ | ||||
|                   default: { uri: account.avatar }, | ||||
|                   static: { uri: account.avatar_static } | ||||
|                 }} | ||||
|                 dimension={{ | ||||
|                   width: StyleConstants.Avatar.M, | ||||
|                   height: | ||||
|   | ||||
| @@ -9,7 +9,6 @@ import { StackNavigationProp } from '@react-navigation/stack' | ||||
| import { RootStackParamList } from '@utils/navigation/navigators' | ||||
| import { usePreferencesQuery } from '@utils/queryHooks/preferences' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import layoutAnimation from '@utils/styles/layoutAnimation' | ||||
| import React, { useContext, useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { Pressable, View } from 'react-native' | ||||
| @@ -207,7 +206,6 @@ const TimelineAttachment = () => { | ||||
|               content={t('shared.attachment.sensitive.button')} | ||||
|               overlay | ||||
|               onPress={() => { | ||||
|                 layoutAnimation() | ||||
|                 setSensitiveShown(false) | ||||
|                 haptics('Light') | ||||
|               }} | ||||
|   | ||||
| @@ -7,7 +7,6 @@ import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import { Audio } from 'expo-av' | ||||
| import React, { useCallback, useEffect, useRef, useState } from 'react' | ||||
| import { AppState, AppStateStatus, StyleSheet, View } from 'react-native' | ||||
| import { Blurhash } from 'react-native-blurhash' | ||||
| import AttachmentAltText from './AltText' | ||||
| import { aspectRatio } from './dimensions' | ||||
|  | ||||
| @@ -72,19 +71,23 @@ const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio | ||||
|       <View style={styles.overlay}> | ||||
|         {sensitiveShown ? ( | ||||
|           audio.blurhash ? ( | ||||
|             <Blurhash | ||||
|               blurhash={audio.blurhash} | ||||
|             <GracefullyImage | ||||
|               sources={{ blurhash: audio.blurhash }} | ||||
|               style={{ | ||||
|                 width: '100%', | ||||
|                 height: '100%' | ||||
|               }} | ||||
|               dim | ||||
|             /> | ||||
|           ) : null | ||||
|         ) : ( | ||||
|           <> | ||||
|             {audio.preview_url ? ( | ||||
|               <GracefullyImage | ||||
|                 uri={{ original: audio.preview_url, remote: audio.preview_remote_url }} | ||||
|                 sources={{ | ||||
|                   default: { uri: audio.preview_url }, | ||||
|                   remote: { uri: audio.preview_remote_url } | ||||
|                 }} | ||||
|                 style={styles.background} | ||||
|                 dim | ||||
|               /> | ||||
|   | ||||
| @@ -35,8 +35,11 @@ const AttachmentImage = ({ | ||||
|         <GracefullyImage | ||||
|           accessibilityLabel={image.description} | ||||
|           hidden={sensitiveShown} | ||||
|           uri={{ original: image.preview_url, remote: image.remote_url }} | ||||
|           blurhash={image.blurhash} | ||||
|           sources={{ | ||||
|             default: { uri: image.preview_url }, | ||||
|             remote: { uri: image.remote_url }, | ||||
|             blurhash: image.blurhash | ||||
|           }} | ||||
|           onPress={() => navigateToImagesViewer(image.id)} | ||||
|           style={{ aspectRatio: aspectRatio({ total, index, ...image.meta?.original }) }} | ||||
|           dim | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import Button from '@components/Button' | ||||
| import GracefullyImage from '@components/GracefullyImage' | ||||
| import openLink from '@components/openLink' | ||||
| import CustomText from '@components/Text' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| @@ -6,7 +7,6 @@ import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { View } from 'react-native' | ||||
| import { Blurhash } from 'react-native-blurhash' | ||||
| import AttachmentAltText from './AltText' | ||||
| import { aspectRatio } from './dimensions' | ||||
|  | ||||
| @@ -33,8 +33,8 @@ const AttachmentUnsupported: React.FC<Props> = ({ total, index, sensitiveShown, | ||||
|       }} | ||||
|     > | ||||
|       {attachment.blurhash ? ( | ||||
|         <Blurhash | ||||
|           blurhash={attachment.blurhash} | ||||
|         <GracefullyImage | ||||
|           sources={{ blurhash: attachment.blurhash }} | ||||
|           style={{ | ||||
|             position: 'absolute', | ||||
|             width: '100%', | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import Button from '@components/Button' | ||||
| import GracefullyImage from '@components/GracefullyImage' | ||||
| import { useAccessibility } from '@utils/accessibility/AccessibilityManager' | ||||
| import { connectMedia } from '@utils/api/helpers/connect' | ||||
| import { useAccountStorage, useGlobalStorage } from '@utils/storage/actions' | ||||
| @@ -8,7 +9,6 @@ import { Platform } from 'expo-modules-core' | ||||
| import * as ScreenOrientation from 'expo-screen-orientation' | ||||
| import React, { useRef, useState } from 'react' | ||||
| import { Pressable, View } from 'react-native' | ||||
| import { Blurhash } from 'react-native-blurhash' | ||||
| import AttachmentAltText from './AltText' | ||||
| import { aspectRatio } from './dimensions' | ||||
|  | ||||
| @@ -120,7 +120,10 @@ const AttachmentVideo: React.FC<Props> = ({ | ||||
|       > | ||||
|         {sensitiveShown ? ( | ||||
|           video.blurhash ? ( | ||||
|             <Blurhash blurhash={video.blurhash} style={{ width: '100%', height: '100%' }} /> | ||||
|             <GracefullyImage | ||||
|               sources={{ blurhash: video.blurhash }} | ||||
|               style={{ width: '100%', height: '100%' }} | ||||
|             /> | ||||
|           ) : null | ||||
|         ) : !gifv || (gifv && (reduceMotionEnabled || !shouldAutoplayGifv)) ? ( | ||||
|           <Button | ||||
|   | ||||
| @@ -33,7 +33,10 @@ const TimelineAvatar: React.FC<Props> = ({ account }) => { | ||||
|       onPress={() => | ||||
|         !disableOnPress && navigation.push('Tab-Shared-Account', { account: actualAccount }) | ||||
|       } | ||||
|       uri={{ original: actualAccount.avatar, static: actualAccount.avatar_static }} | ||||
|       sources={{ | ||||
|         default: { uri: actualAccount.avatar }, | ||||
|         static: { uri: actualAccount.avatar_static } | ||||
|       }} | ||||
|       dimension={ | ||||
|         disableDetails || isConversation | ||||
|           ? { | ||||
|   | ||||
| @@ -82,8 +82,7 @@ const TimelineCard: React.FC = () => { | ||||
|       <> | ||||
|         {status.card?.image ? ( | ||||
|           <GracefullyImage | ||||
|             uri={{ original: status.card.image }} | ||||
|             blurhash={status.card.blurhash} | ||||
|             sources={{ default: { uri: status.card.image }, blurhash: status.card.blurhash }} | ||||
|             style={{ flexBasis: StyleConstants.Font.LineHeight.M * 5 }} | ||||
|             imageStyle={{ borderTopLeftRadius: 6, borderBottomLeftRadius: 6 }} | ||||
|             dim | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import Button from '@components/Button' | ||||
| import GracefullyImage from '@components/GracefullyImage' | ||||
| import haptics from '@components/haptics' | ||||
| import { Loading } from '@components/Loading' | ||||
| import { ParseHTML } from '@components/Parse' | ||||
| @@ -6,7 +7,6 @@ import RelativeTime from '@components/RelativeTime' | ||||
| import CustomText from '@components/Text' | ||||
| import { BlurView } from '@react-native-community/blur' | ||||
| import { useAccessibility } from '@utils/accessibility/AccessibilityManager' | ||||
| import { connectMedia } from '@utils/api/helpers/connect' | ||||
| import { RootStackScreenProps } from '@utils/navigation/navigators' | ||||
| import { useAnnouncementMutation, useAnnouncementQuery } from '@utils/queryHooks/announcement' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| @@ -22,7 +22,6 @@ import { | ||||
|   StyleSheet, | ||||
|   View | ||||
| } from 'react-native' | ||||
| import FastImage from 'react-native-fast-image' | ||||
| import { FlatList, ScrollView } from 'react-native-gesture-handler' | ||||
| import { SafeAreaView } from 'react-native-safe-area-context' | ||||
|  | ||||
| @@ -139,12 +138,13 @@ const ScreenAnnouncements: React.FC<RootStackScreenProps<'Screen-Announcements'> | ||||
|                 } | ||||
|               > | ||||
|                 {reaction.url ? ( | ||||
|                   <FastImage | ||||
|                     source={connectMedia({ | ||||
|                       uri: reduceMotionEnabled ? reaction.static_url : reaction.url | ||||
|                     })} | ||||
|                     style={{ | ||||
|                       width: StyleConstants.Font.LineHeight.M + 3, | ||||
|                   <GracefullyImage | ||||
|                     sources={{ | ||||
|                       default: { uri: reaction.url }, | ||||
|                       static: { uri: reaction.static_url } | ||||
|                     }} | ||||
|                     dimension={{ | ||||
|                       width: StyleConstants.Font.LineHeight.M, | ||||
|                       height: StyleConstants.Font.LineHeight.M | ||||
|                     }} | ||||
|                   /> | ||||
|   | ||||
| @@ -9,10 +9,10 @@ import { ScreenComposeStackScreenProps } from '@utils/navigation/navigators' | ||||
| import { getAccountStorage, setAccountStorage, useAccountStorage } from '@utils/storage/actions' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import { Image } from 'expo-image' | ||||
| import React, { useContext, useEffect, useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { Dimensions, Modal, Pressable, View } from 'react-native' | ||||
| import FastImage from 'react-native-fast-image' | ||||
| import ComposeContext from './utils/createContext' | ||||
| import { formatText } from './utils/processText' | ||||
| import { ComposeStateDraft, ExtendedAttachment } from './utils/types' | ||||
| @@ -140,7 +140,7 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose- | ||||
|                     }} | ||||
|                   > | ||||
|                     {item.attachments.uploads.map((attachment, index) => ( | ||||
|                       <FastImage | ||||
|                       <Image | ||||
|                         key={index} | ||||
|                         style={{ | ||||
|                           width: | ||||
|   | ||||
| @@ -11,10 +11,10 @@ import { featureCheck } from '@utils/helpers/featureCheck' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import layoutAnimation from '@utils/styles/layoutAnimation' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import { Image } from 'expo-image' | ||||
| import React, { RefObject, useContext, useEffect, useRef } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { FlatList, Pressable, StyleSheet, View } from 'react-native' | ||||
| import FastImage from 'react-native-fast-image' | ||||
| import ComposeContext from '../../utils/createContext' | ||||
| import { ExtendedAttachment } from '../../utils/types' | ||||
| import chooseAndUploadAttachment from './addAttachment' | ||||
| @@ -104,9 +104,7 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => { | ||||
|           width: calculateWidth(item) | ||||
|         }} | ||||
|       > | ||||
|         <FastImage | ||||
|           enterTransition='fadeIn' | ||||
|           transitionDuration={60} | ||||
|         <Image | ||||
|           style={{ width: '100%', height: '100%' }} | ||||
|           source={ | ||||
|             item.local?.thumbnail | ||||
|   | ||||
| @@ -193,10 +193,10 @@ const ScreenImagesViewer = ({ | ||||
|                     }} | ||||
|                   > | ||||
|                     <GracefullyImage | ||||
|                       uri={{ | ||||
|                         preview: item.preview_url, | ||||
|                         remote: item.remote_url, | ||||
|                         original: item.url | ||||
|                       sources={{ | ||||
|                         preview: { uri: item.preview_url, width: item.width, height: item.height }, | ||||
|                         default: { uri: item.url, width: item.width, height: item.height }, | ||||
|                         remote: { uri: item.remote_url, width: item.width, height: item.height } | ||||
|                       }} | ||||
|                       dimension={{ | ||||
|                         width: | ||||
| @@ -208,6 +208,7 @@ const ScreenImagesViewer = ({ | ||||
|                             ? WINDOW_HEIGHT | ||||
|                             : (WINDOW_WIDTH / imageWidth) * imageHeight | ||||
|                       }} | ||||
|                       enableLiveTextInteraction | ||||
|                     /> | ||||
|                   </View> | ||||
|                 } | ||||
|   | ||||
| @@ -82,15 +82,25 @@ const AccountAttachments: React.FC = () => { | ||||
|           } else { | ||||
|             return ( | ||||
|               <GracefullyImage | ||||
|                 uri={{ | ||||
|                   original: | ||||
|                     item.media_attachments[0]?.preview_url || item.media_attachments[0]?.url, | ||||
|                   remote: item.media_attachments[0]?.remote_url | ||||
|                 sources={{ | ||||
|                   preview: { | ||||
|                     uri: item.media_attachments[0]?.preview_url, | ||||
|                     width: item.media_attachments[0]?.meta?.small?.width, | ||||
|                     height: item.media_attachments[0]?.meta?.small?.height | ||||
|                   }, | ||||
|                   default: { | ||||
|                     uri: item.media_attachments[0]?.url, | ||||
|                     width: item.media_attachments[0]?.meta?.original?.width, | ||||
|                     height: item.media_attachments[0]?.meta?.original?.height | ||||
|                   }, | ||||
|                   remote: { | ||||
|                     uri: item.media_attachments[0]?.remote_url, | ||||
|                     width: item.media_attachments[0]?.meta?.original?.width, | ||||
|                     height: item.media_attachments[0]?.meta?.original?.height | ||||
|                   }, | ||||
|                   blurhash: item.media_attachments[0]?.blurhash | ||||
|                 }} | ||||
|                 blurhash={ | ||||
|                   item.media_attachments[0] && (item.media_attachments[0].blurhash || undefined) | ||||
|                 } | ||||
|                 dimension={{ width: width, height: width }} | ||||
|                 dimension={{ width, height: width }} | ||||
|                 style={{ marginLeft: StyleConstants.Spacing.Global.PagePadding }} | ||||
|                 onPress={() => navigation.push('Tab-Shared-Toot', { toot: item })} | ||||
|                 dim | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| import GracefullyImage from '@components/GracefullyImage' | ||||
| import navigationRef from '@utils/navigation/navigationRef' | ||||
| import { useGlobalStorage } from '@utils/storage/actions' | ||||
| import React, { useContext } from 'react' | ||||
| import { Dimensions, Image } from 'react-native' | ||||
| import { useSafeAreaInsets } from 'react-native-safe-area-context' | ||||
| @@ -11,11 +10,9 @@ const AccountHeader: React.FC = () => { | ||||
|  | ||||
|   const topInset = useSafeAreaInsets().top | ||||
|  | ||||
|   useGlobalStorage.string('account.active') | ||||
|  | ||||
|   return ( | ||||
|     <GracefullyImage | ||||
|       uri={{ original: account?.header, static: account?.header_static }} | ||||
|       sources={{ default: { uri: account?.header }, static: { uri: account?.header_static } }} | ||||
|       style={{ height: Dimensions.get('window').width / 3 + topInset }} | ||||
|       onPress={() => { | ||||
|         if (account) { | ||||
|   | ||||
| @@ -3,7 +3,6 @@ import { useNavigation } from '@react-navigation/native' | ||||
| import { StackNavigationProp } from '@react-navigation/stack' | ||||
| import navigationRef from '@utils/navigation/navigationRef' | ||||
| import { TabLocalStackParamList } from '@utils/navigation/navigators' | ||||
| import { useAccountStorage } from '@utils/storage/actions' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import React, { useContext } from 'react' | ||||
| import AccountContext from '../Context' | ||||
| @@ -13,20 +12,13 @@ const AccountInformationAvatar: React.FC = () => { | ||||
|  | ||||
|   const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>() | ||||
|  | ||||
|   const [accountAvatarStatic] = useAccountStorage.string('auth.account.avatar_static') | ||||
|  | ||||
|   return ( | ||||
|     <GracefullyImage | ||||
|       key={account?.avatar} | ||||
|       style={{ | ||||
|         borderRadius: 8, | ||||
|         overflow: 'hidden', | ||||
|         width: StyleConstants.Avatar.L, | ||||
|         height: StyleConstants.Avatar.L | ||||
|       }} | ||||
|       uri={{ | ||||
|         original: account?.avatar || (pageMe ? accountAvatarStatic : undefined), | ||||
|         static: account?.avatar_static || (pageMe ? accountAvatarStatic : undefined) | ||||
|       style={{ borderRadius: 8, overflow: 'hidden' }} | ||||
|       dimension={{ width: StyleConstants.Avatar.L, height: StyleConstants.Avatar.L }} | ||||
|       sources={{ | ||||
|         default: { uri: account?.avatar }, | ||||
|         static: { uri: account?.avatar_static } | ||||
|       }} | ||||
|       onPress={() => { | ||||
|         if (account) { | ||||
|   | ||||
| @@ -52,7 +52,7 @@ const ScreenTabs = () => { | ||||
|               return ( | ||||
|                 <View style={{ flexDirection: 'row', alignItems: 'center' }}> | ||||
|                   <GracefullyImage | ||||
|                     uri={{ original: avatarStatic }} | ||||
|                     sources={{ default: { uri: avatarStatic } }} | ||||
|                     dimension={{ width: size, height: size }} | ||||
|                     style={{ | ||||
|                       borderRadius: size, | ||||
|   | ||||
| @@ -81,19 +81,18 @@ export const CONNECT_DOMAIN = (index?: number) => | ||||
|     development: 'connect-development.tooot.app' | ||||
|   }) | ||||
|  | ||||
| export const connectMedia = ({ | ||||
|   uri | ||||
| }: { | ||||
| export const connectMedia = (args?: { | ||||
|   uri?: string | ||||
| }): { uri?: string; headers?: { 'x-tooot-domain': string } } => { | ||||
|   if (GLOBAL.connect) { | ||||
|     if (uri) { | ||||
|       const host = parse(uri).host | ||||
|     if (args?.uri) { | ||||
|       const host = parse(args.uri).host | ||||
|       return { | ||||
|         uri: uri.replace( | ||||
|         ...args, | ||||
|         uri: args.uri.replace( | ||||
|           host, | ||||
|           CONNECT_DOMAIN( | ||||
|             uri | ||||
|             args.uri | ||||
|               .split('') | ||||
|               .map(i => i.charCodeAt(0)) | ||||
|               .reduce((a, b) => a + b, 0) % | ||||
| @@ -103,10 +102,10 @@ export const connectMedia = ({ | ||||
|         headers: { 'x-tooot-domain': host } | ||||
|       } | ||||
|     } else { | ||||
|       return { uri } | ||||
|       return { ...args } | ||||
|     } | ||||
|   } else { | ||||
|     return { uri } | ||||
|     return { ...args } | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										31
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								yarn.lock
									
									
									
									
									
								
							| @@ -5706,6 +5706,15 @@ __metadata: | ||||
|   languageName: node | ||||
|   linkType: hard | ||||
|  | ||||
| "expo-image@npm:^1.0.0-beta.6": | ||||
|   version: 1.0.0-beta.6 | ||||
|   resolution: "expo-image@npm:1.0.0-beta.6" | ||||
|   peerDependencies: | ||||
|     expo: "*" | ||||
|   checksum: d874d6779db813166a682be6f4c4ee3e101be90121376963946db85bcbef71f50bc027b18d5e07b4ca6a03337597a60df2cc2cfed66661149ec7cf53d6b6bae9 | ||||
|   languageName: node | ||||
|   linkType: hard | ||||
|  | ||||
| "expo-keep-awake@npm:~11.0.1": | ||||
|   version: 11.0.1 | ||||
|   resolution: "expo-keep-awake@npm:11.0.1" | ||||
| @@ -9639,26 +9648,6 @@ __metadata: | ||||
|   languageName: node | ||||
|   linkType: hard | ||||
|  | ||||
| "react-native-fast-image@npm:8.6.3": | ||||
|   version: 8.6.3 | ||||
|   resolution: "react-native-fast-image@npm:8.6.3" | ||||
|   peerDependencies: | ||||
|     react: ^17 || ^18 | ||||
|     react-native: ">=0.60.0" | ||||
|   checksum: 29289cb6b2eae0983c8922b22e2d9de3be07322bb7991c5def19f95eadefaedb0e308ff0b38cc1d0444e8bd4fe94a7621a99a2d3d9298100bcb60b3144677234 | ||||
|   languageName: node | ||||
|   linkType: hard | ||||
|  | ||||
| "react-native-fast-image@patch:react-native-fast-image@npm%3A8.6.3#./.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch::locator=tooot%40workspace%3A.": | ||||
|   version: 8.6.3 | ||||
|   resolution: "react-native-fast-image@patch:react-native-fast-image@npm%3A8.6.3#./.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch::version=8.6.3&hash=1a9a6d&locator=tooot%40workspace%3A." | ||||
|   peerDependencies: | ||||
|     react: ^17 || ^18 | ||||
|     react-native: ">=0.60.0" | ||||
|   checksum: 4b2c6b2d6fc461f26936ff5033acccf7aef15f9d176ea835d09c87bee83accbb6c2b98a2435ad019a305c0751aa43040c153a6d5735664ace31e64aad0b2bc61 | ||||
|   languageName: node | ||||
|   linkType: hard | ||||
|  | ||||
| "react-native-flash-message@npm:^0.4.0": | ||||
|   version: 0.4.0 | ||||
|   resolution: "react-native-flash-message@npm:0.4.0" | ||||
| @@ -11432,6 +11421,7 @@ __metadata: | ||||
|     expo-crypto: ^12.1.0 | ||||
|     expo-file-system: ^15.1.1 | ||||
|     expo-haptics: ^12.1.0 | ||||
|     expo-image: ^1.0.0-beta.6 | ||||
|     expo-linking: ^3.3.0 | ||||
|     expo-localization: ^14.0.0 | ||||
|     expo-notifications: ^0.17.0 | ||||
| @@ -11454,7 +11444,6 @@ __metadata: | ||||
|     react-native: ^0.70.7 | ||||
|     react-native-blurhash: ^1.1.10 | ||||
|     react-native-clean-project: ^4.0.1 | ||||
|     react-native-fast-image: ^8.6.3 | ||||
|     react-native-flash-message: ^0.4.0 | ||||
|     react-native-gesture-handler: ~2.9.0 | ||||
|     react-native-image-picker: ^5.0.1 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user