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 |     - ExpoModulesCore | ||||||
|   - ExpoHaptics (12.1.0): |   - ExpoHaptics (12.1.0): | ||||||
|     - ExpoModulesCore |     - 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): |   - ExpoKeepAwake (11.0.1): | ||||||
|     - ExpoModulesCore |     - ExpoModulesCore | ||||||
|   - ExpoLocalization (14.0.0): |   - ExpoLocalization (14.0.0): | ||||||
| @@ -58,7 +64,16 @@ PODS: | |||||||
|   - fmt (6.2.1) |   - fmt (6.2.1) | ||||||
|   - glog (0.3.5) |   - glog (0.3.5) | ||||||
|   - hermes-engine (0.70.7) |   - 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) |   - libevent (2.1.12) | ||||||
|  |   - libvmaf (2.2.0) | ||||||
|   - libwebp (1.2.4): |   - libwebp (1.2.4): | ||||||
|     - libwebp/demux (= 1.2.4) |     - libwebp/demux (= 1.2.4) | ||||||
|     - libwebp/mux (= 1.2.4) |     - libwebp/mux (= 1.2.4) | ||||||
| @@ -299,8 +314,6 @@ PODS: | |||||||
|     - glog |     - glog | ||||||
|   - react-native-blur (4.3.0): |   - react-native-blur (4.3.0): | ||||||
|     - React-Core |     - React-Core | ||||||
|   - react-native-blurhash (1.1.10): |  | ||||||
|     - React-Core |  | ||||||
|   - react-native-cameraroll (5.2.3): |   - react-native-cameraroll (5.2.3): | ||||||
|     - React-Core |     - React-Core | ||||||
|   - react-native-image-picker (5.0.1): |   - react-native-image-picker (5.0.1): | ||||||
| @@ -401,10 +414,6 @@ PODS: | |||||||
|     - React-Core |     - React-Core | ||||||
|   - RNCClipboard (1.11.1): |   - RNCClipboard (1.11.1): | ||||||
|     - React-Core |     - React-Core | ||||||
|   - RNFastImage (8.6.3): |  | ||||||
|     - React-Core |  | ||||||
|     - SDWebImage (~> 5.15.0) |  | ||||||
|     - SDWebImageWebPCoder (~> 0.9.1) |  | ||||||
|   - RNGestureHandler (2.9.0): |   - RNGestureHandler (2.9.0): | ||||||
|     - React-Core |     - React-Core | ||||||
|   - RNReanimated (2.14.4): |   - RNReanimated (2.14.4): | ||||||
| @@ -447,6 +456,11 @@ PODS: | |||||||
|   - SDWebImage (5.15.0): |   - SDWebImage (5.15.0): | ||||||
|     - SDWebImage/Core (= 5.15.0) |     - SDWebImage/Core (= 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): |   - SDWebImageWebPCoder (0.9.1): | ||||||
|     - libwebp (~> 1.0) |     - libwebp (~> 1.0) | ||||||
|     - SDWebImage/Core (~> 5.13) |     - SDWebImage/Core (~> 5.13) | ||||||
| @@ -467,6 +481,7 @@ DEPENDENCIES: | |||||||
|   - Expo (from `../node_modules/expo`) |   - Expo (from `../node_modules/expo`) | ||||||
|   - ExpoCrypto (from `../node_modules/expo-crypto/ios`) |   - ExpoCrypto (from `../node_modules/expo-crypto/ios`) | ||||||
|   - ExpoHaptics (from `../node_modules/expo-haptics/ios`) |   - ExpoHaptics (from `../node_modules/expo-haptics/ios`) | ||||||
|  |   - ExpoImage (from `../node_modules/expo-image/ios`) | ||||||
|   - ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`) |   - ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`) | ||||||
|   - ExpoLocalization (from `../node_modules/expo-localization/ios`) |   - ExpoLocalization (from `../node_modules/expo-localization/ios`) | ||||||
|   - ExpoModulesCore (from `../node_modules/expo-modules-core`) |   - ExpoModulesCore (from `../node_modules/expo-modules-core`) | ||||||
| @@ -500,7 +515,6 @@ DEPENDENCIES: | |||||||
|   - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) |   - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) | ||||||
|   - React-logger (from `../node_modules/react-native/ReactCommon/logger`) |   - React-logger (from `../node_modules/react-native/ReactCommon/logger`) | ||||||
|   - "react-native-blur (from `../node_modules/@react-native-community/blur`)" |   - "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-cameraroll (from `../node_modules/@react-native-camera-roll/camera-roll`)" | ||||||
|   - react-native-image-picker (from `../node_modules/react-native-image-picker`) |   - react-native-image-picker (from `../node_modules/react-native-image-picker`) | ||||||
|   - react-native-ios-context-menu (from `../node_modules/react-native-ios-context-menu`) |   - 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`) |   - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) | ||||||
|   - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" |   - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" | ||||||
|   - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" |   - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" | ||||||
|   - RNFastImage (from `../node_modules/react-native-fast-image`) |  | ||||||
|   - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) |   - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) | ||||||
|   - RNReanimated (from `../node_modules/react-native-reanimated`) |   - RNReanimated (from `../node_modules/react-native-reanimated`) | ||||||
|   - RNScreens (from `../node_modules/react-native-screens`) |   - RNScreens (from `../node_modules/react-native-screens`) | ||||||
| @@ -539,11 +552,16 @@ DEPENDENCIES: | |||||||
| SPEC REPOS: | SPEC REPOS: | ||||||
|   trunk: |   trunk: | ||||||
|     - fmt |     - fmt | ||||||
|  |     - libaom | ||||||
|  |     - libavif | ||||||
|     - libevent |     - libevent | ||||||
|  |     - libvmaf | ||||||
|     - libwebp |     - libwebp | ||||||
|     - MMKV |     - MMKV | ||||||
|     - MMKVCore |     - MMKVCore | ||||||
|     - SDWebImage |     - SDWebImage | ||||||
|  |     - SDWebImageAVIFCoder | ||||||
|  |     - SDWebImageSVGCoder | ||||||
|     - SDWebImageWebPCoder |     - SDWebImageWebPCoder | ||||||
|     - Sentry |     - Sentry | ||||||
|     - Swime |     - Swime | ||||||
| @@ -573,6 +591,8 @@ EXTERNAL SOURCES: | |||||||
|     :path: "../node_modules/expo-crypto/ios" |     :path: "../node_modules/expo-crypto/ios" | ||||||
|   ExpoHaptics: |   ExpoHaptics: | ||||||
|     :path: "../node_modules/expo-haptics/ios" |     :path: "../node_modules/expo-haptics/ios" | ||||||
|  |   ExpoImage: | ||||||
|  |     :path: "../node_modules/expo-image/ios" | ||||||
|   ExpoKeepAwake: |   ExpoKeepAwake: | ||||||
|     :path: "../node_modules/expo-keep-awake/ios" |     :path: "../node_modules/expo-keep-awake/ios" | ||||||
|   ExpoLocalization: |   ExpoLocalization: | ||||||
| @@ -635,8 +655,6 @@ EXTERNAL SOURCES: | |||||||
|     :path: "../node_modules/react-native/ReactCommon/logger" |     :path: "../node_modules/react-native/ReactCommon/logger" | ||||||
|   react-native-blur: |   react-native-blur: | ||||||
|     :path: "../node_modules/@react-native-community/blur" |     :path: "../node_modules/@react-native-community/blur" | ||||||
|   react-native-blurhash: |  | ||||||
|     :path: "../node_modules/react-native-blurhash" |  | ||||||
|   react-native-cameraroll: |   react-native-cameraroll: | ||||||
|     :path: "../node_modules/@react-native-camera-roll/camera-roll" |     :path: "../node_modules/@react-native-camera-roll/camera-roll" | ||||||
|   react-native-image-picker: |   react-native-image-picker: | ||||||
| @@ -689,8 +707,6 @@ EXTERNAL SOURCES: | |||||||
|     :path: "../node_modules/@react-native-async-storage/async-storage" |     :path: "../node_modules/@react-native-async-storage/async-storage" | ||||||
|   RNCClipboard: |   RNCClipboard: | ||||||
|     :path: "../node_modules/@react-native-clipboard/clipboard" |     :path: "../node_modules/@react-native-clipboard/clipboard" | ||||||
|   RNFastImage: |  | ||||||
|     :path: "../node_modules/react-native-fast-image" |  | ||||||
|   RNGestureHandler: |   RNGestureHandler: | ||||||
|     :path: "../node_modules/react-native-gesture-handler" |     :path: "../node_modules/react-native-gesture-handler" | ||||||
|   RNReanimated: |   RNReanimated: | ||||||
| @@ -719,6 +735,7 @@ SPEC CHECKSUMS: | |||||||
|   Expo: b9fa98bf260992312ee3c424400819fb9beadafe |   Expo: b9fa98bf260992312ee3c424400819fb9beadafe | ||||||
|   ExpoCrypto: 6eb2a5ede7d95b7359a5f0391ee0c5d2ecd144b3 |   ExpoCrypto: 6eb2a5ede7d95b7359a5f0391ee0c5d2ecd144b3 | ||||||
|   ExpoHaptics: 129d3f8d44c2205adcdf8db760602818463d5437 |   ExpoHaptics: 129d3f8d44c2205adcdf8db760602818463d5437 | ||||||
|  |   ExpoImage: 748f2b8d3974f1d51c7706fd61057b93241738aa | ||||||
|   ExpoKeepAwake: 69b59d0a8d2b24de9f82759c39b3821fec030318 |   ExpoKeepAwake: 69b59d0a8d2b24de9f82759c39b3821fec030318 | ||||||
|   ExpoLocalization: e202d1e2a4950df17ac8d0889d65a1ffd7532d7e |   ExpoLocalization: e202d1e2a4950df17ac8d0889d65a1ffd7532d7e | ||||||
|   ExpoModulesCore: 485dff3a59b036a33b6050c0a5aea3cf1037fdd1 |   ExpoModulesCore: 485dff3a59b036a33b6050c0a5aea3cf1037fdd1 | ||||||
| @@ -735,7 +752,10 @@ SPEC CHECKSUMS: | |||||||
|   fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 |   fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 | ||||||
|   glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b |   glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b | ||||||
|   hermes-engine: 566e656aa95456a3f3f739fd76ea9a9656f2633f |   hermes-engine: 566e656aa95456a3f3f739fd76ea9a9656f2633f | ||||||
|  |   libaom: 9bb51e0f8f9192245e3ca2a1c9e4375d9cbccc52 | ||||||
|  |   libavif: e242998ccec1c83bcba0bbdc256f460ad5077348 | ||||||
|   libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 |   libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 | ||||||
|  |   libvmaf: 8d61aabc2f4ed3e6591cf7406fa00a223ec11289 | ||||||
|   libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef |   libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef | ||||||
|   MMKV: 7f34558bbb5a33b0eaefae2de4b6a20a2ffdad6f |   MMKV: 7f34558bbb5a33b0eaefae2de4b6a20a2ffdad6f | ||||||
|   MMKVCore: ddf41b9d9262f058419f9ba7598719af56c02cd3 |   MMKVCore: ddf41b9d9262f058419f9ba7598719af56c02cd3 | ||||||
| @@ -755,7 +775,6 @@ SPEC CHECKSUMS: | |||||||
|   React-jsinspector: 1c34fea1868136ecde647bc11fae9266d4143693 |   React-jsinspector: 1c34fea1868136ecde647bc11fae9266d4143693 | ||||||
|   React-logger: e9f407f9fdf3f3ce7749ae6f88affe63e8446019 |   React-logger: e9f407f9fdf3f3ce7749ae6f88affe63e8446019 | ||||||
|   react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3 |   react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3 | ||||||
|   react-native-blurhash: add4df9a937b4e021a24bc67a0714f13e0bd40b7 |  | ||||||
|   react-native-cameraroll: 5b25d0be40185d02e522bf2abf8a1ba4e8faa107 |   react-native-cameraroll: 5b25d0be40185d02e522bf2abf8a1ba4e8faa107 | ||||||
|   react-native-image-picker: 8cb4280e2c1efc3daeb2d9d597f9429a60472e40 |   react-native-image-picker: 8cb4280e2c1efc3daeb2d9d597f9429a60472e40 | ||||||
|   react-native-ios-context-menu: e529171ba760a1af7f2ef0729f5a7f4d226171c5 |   react-native-ios-context-menu: e529171ba760a1af7f2ef0729f5a7f4d226171c5 | ||||||
| @@ -782,7 +801,6 @@ SPEC CHECKSUMS: | |||||||
|   ReactCommon: 0253d197eaa7f6689dcd3e7d5360449ab93e10df |   ReactCommon: 0253d197eaa7f6689dcd3e7d5360449ab93e10df | ||||||
|   RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60 |   RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60 | ||||||
|   RNCClipboard: 2834e1c4af68697089cdd455ee4a4cdd198fa7dd |   RNCClipboard: 2834e1c4af68697089cdd455ee4a4cdd198fa7dd | ||||||
|   RNFastImage: bd611b5635f1e0f43c8ccf597b1ef6ee0d0f966d |  | ||||||
|   RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39 |   RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39 | ||||||
|   RNReanimated: 6668b0587bebd4b15dd849b99e5a9c70fc12ed95 |   RNReanimated: 6668b0587bebd4b15dd849b99e5a9c70fc12ed95 | ||||||
|   RNScreens: ea4cd3a853063cda19a4e3c28d2e52180c80f4eb |   RNScreens: ea4cd3a853063cda19a4e3c28d2e52180c80f4eb | ||||||
| @@ -790,6 +808,8 @@ SPEC CHECKSUMS: | |||||||
|   RNShareMenu: cb9dac548c8bf147d06f0bf07296ad51ea9f5fc3 |   RNShareMenu: cb9dac548c8bf147d06f0bf07296ad51ea9f5fc3 | ||||||
|   RNSVG: c1e76b81c76cdcd34b4e1188852892dc280eb902 |   RNSVG: c1e76b81c76cdcd34b4e1188852892dc280eb902 | ||||||
|   SDWebImage: 9bec4c5cdd9579e1f57104735ee0c37df274d593 |   SDWebImage: 9bec4c5cdd9579e1f57104735ee0c37df274d593 | ||||||
|  |   SDWebImageAVIFCoder: d759e21cf4efb640cc97250566aa556ad8bb877c | ||||||
|  |   SDWebImageSVGCoder: 6fc109f9c2a82ab44510fff410b88b1a6c271ee8 | ||||||
|   SDWebImageWebPCoder: 18503de6621dd2c420d680e33d46bf8e1d5169b0 |   SDWebImageWebPCoder: 18503de6621dd2c420d680e33d46bf8e1d5169b0 | ||||||
|   Sentry: 4c9babff9034785067c896fd580b1f7de44da020 |   Sentry: 4c9babff9034785067c896fd580b1f7de44da020 | ||||||
|   Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b |   Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b | ||||||
|   | |||||||
| @@ -50,6 +50,7 @@ | |||||||
|     "expo-crypto": "^12.1.0", |     "expo-crypto": "^12.1.0", | ||||||
|     "expo-file-system": "^15.1.1", |     "expo-file-system": "^15.1.1", | ||||||
|     "expo-haptics": "^12.1.0", |     "expo-haptics": "^12.1.0", | ||||||
|  |     "expo-image": "^1.0.0-beta.6", | ||||||
|     "expo-linking": "^3.3.0", |     "expo-linking": "^3.3.0", | ||||||
|     "expo-localization": "^14.0.0", |     "expo-localization": "^14.0.0", | ||||||
|     "expo-notifications": "^0.17.0", |     "expo-notifications": "^0.17.0", | ||||||
| @@ -70,8 +71,6 @@ | |||||||
|     "react-i18next": "^12.1.4", |     "react-i18next": "^12.1.4", | ||||||
|     "react-intl": "^6.2.7", |     "react-intl": "^6.2.7", | ||||||
|     "react-native": "^0.70.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-flash-message": "^0.4.0", | ||||||
|     "react-native-gesture-handler": "~2.9.0", |     "react-native-gesture-handler": "~2.9.0", | ||||||
|     "react-native-image-picker": "^5.0.1", |     "react-native-image-picker": "^5.0.1", | ||||||
| @@ -116,7 +115,6 @@ | |||||||
|   }, |   }, | ||||||
|   "packageManager": "yarn@3.3.1", |   "packageManager": "yarn@3.3.1", | ||||||
|   "resolutions": { |   "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", |     "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", |     "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", |     "@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' }}> |           <View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }}> | ||||||
|             <GracefullyImage |             <GracefullyImage | ||||||
|               uri={{ original: account.avatar, static: account.avatar_static }} |               sources={{ default: { uri: account.avatar }, static: { uri: account.avatar_static } }} | ||||||
|               style={{ |               style={{ | ||||||
|                 width: StyleConstants.Avatar.S, |                 width: StyleConstants.Avatar.S, | ||||||
|                 height: StyleConstants.Avatar.S, |                 height: StyleConstants.Avatar.S, | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ const AccountButton: React.FC<Props> = ({ account, additionalActions }) => { | |||||||
|       }} |       }} | ||||||
|     > |     > | ||||||
|       <GracefullyImage |       <GracefullyImage | ||||||
|         uri={{ original: account.avatar_static }} |         sources={{ default: { uri: account.avatar_static } }} | ||||||
|         dimension={{ |         dimension={{ | ||||||
|           width: StyleConstants.Font.Size.L, |           width: StyleConstants.Font.Size.L, | ||||||
|           height: 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 { StyleConstants } from '@utils/styles/constants' | ||||||
| import layoutAnimation from '@utils/styles/layoutAnimation' | import layoutAnimation from '@utils/styles/layoutAnimation' | ||||||
| import { useTheme } from '@utils/styles/ThemeManager' | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
|  | import { Image } from 'expo-image' | ||||||
| import { chunk } from 'lodash' | import { chunk } from 'lodash' | ||||||
| import React, { useContext, useEffect, useRef, useState } from 'react' | import React, { useContext, useEffect, useRef, useState } from 'react' | ||||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||||
| @@ -19,7 +20,6 @@ import { | |||||||
|   TextInput, |   TextInput, | ||||||
|   View |   View | ||||||
| } from 'react-native' | } from 'react-native' | ||||||
| import FastImage from 'react-native-fast-image' |  | ||||||
| import EmojisContext from './Context' | import EmojisContext from './Context' | ||||||
|  |  | ||||||
| const EmojisList = () => { | const EmojisList = () => { | ||||||
| @@ -129,9 +129,7 @@ const EmojisList = () => { | |||||||
|               }} |               }} | ||||||
|               style={{ padding: StyleConstants.Spacing.S }} |               style={{ padding: StyleConstants.Spacing.S }} | ||||||
|             > |             > | ||||||
|               <FastImage |               <Image | ||||||
|                 enterTransition='fadeIn' |  | ||||||
|                 transitionDuration={60} |  | ||||||
|                 accessibilityLabel={t('common:customEmoji.accessibilityLabel', { |                 accessibilityLabel={t('common:customEmoji.accessibilityLabel', { | ||||||
|                   emoji: emoji.shortcode |                   emoji: emoji.shortcode | ||||||
|                 })} |                 })} | ||||||
|   | |||||||
| @@ -1,36 +1,26 @@ | |||||||
| import { useAccessibility } from '@utils/accessibility/AccessibilityManager' | import { useAccessibility } from '@utils/accessibility/AccessibilityManager' | ||||||
| import { connectMedia } from '@utils/api/helpers/connect' | import { connectMedia } from '@utils/api/helpers/connect' | ||||||
| import { useTheme } from '@utils/styles/ThemeManager' | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
| import React, { useEffect, useState } from 'react' | import { Image, ImageSource, ImageStyle } from 'expo-image' | ||||||
| import { | import React, { useState } from 'react' | ||||||
|   AccessibilityProps, | import { AccessibilityProps, Pressable, StyleProp, View, ViewStyle } from 'react-native' | ||||||
|   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 |  | ||||||
|  |  | ||||||
| export interface Props { | export interface Props { | ||||||
|   accessibilityLabel?: AccessibilityProps['accessibilityLabel'] |   accessibilityLabel?: AccessibilityProps['accessibilityLabel'] | ||||||
|   accessibilityHint?: AccessibilityProps['accessibilityHint'] |   accessibilityHint?: AccessibilityProps['accessibilityHint'] | ||||||
|  |  | ||||||
|   hidden?: boolean |   hidden?: boolean | ||||||
|   uri: { preview?: string; original?: string; remote?: string; static?: string } |   sources: { | ||||||
|   blurhash?: string |     preview?: ImageSource | ||||||
|  |     default?: ImageSource | ||||||
|  |     remote?: ImageSource | ||||||
|  |     static?: ImageSource | ||||||
|  |     blurhash?: string | ||||||
|  |   } | ||||||
|   dimension?: { width: number; height: number } |   dimension?: { width: number; height: number } | ||||||
|   onPress?: () => void |   onPress?: () => void | ||||||
|   style?: StyleProp<ViewStyle> |   style?: StyleProp<ViewStyle> | ||||||
|   imageStyle?: StyleProp<ImageStyle> |   imageStyle?: ImageStyle | ||||||
|   // For image viewer when there is no image size available |   // For image viewer when there is no image size available | ||||||
|   setImageDimensions?: React.Dispatch< |   setImageDimensions?: React.Dispatch< | ||||||
|     React.SetStateAction<{ |     React.SetStateAction<{ | ||||||
| @@ -39,49 +29,30 @@ export interface Props { | |||||||
|     }> |     }> | ||||||
|   > |   > | ||||||
|   dim?: boolean |   dim?: boolean | ||||||
|  |   enableLiveTextInteraction?: boolean | ||||||
| } | } | ||||||
|  |  | ||||||
| const GracefullyImage = ({ | const GracefullyImage = ({ | ||||||
|   accessibilityLabel, |   accessibilityLabel, | ||||||
|   accessibilityHint, |   accessibilityHint, | ||||||
|   hidden = false, |   hidden = false, | ||||||
|   uri, |   sources, | ||||||
|   blurhash, |  | ||||||
|   dimension, |   dimension, | ||||||
|   onPress, |   onPress, | ||||||
|   style, |   style, | ||||||
|   imageStyle, |   imageStyle, | ||||||
|   setImageDimensions, |   setImageDimensions, | ||||||
|   dim |   dim, | ||||||
|  |   enableLiveTextInteraction = false | ||||||
| }: Props) => { | }: Props) => { | ||||||
|   const { reduceMotionEnabled } = useAccessibility() |   const { reduceMotionEnabled } = useAccessibility() | ||||||
|   const { colors, theme } = useTheme() |   const { theme } = useTheme() | ||||||
|   const [imageLoaded, setImageLoaded] = useState(false) |  | ||||||
|  |  | ||||||
|   const [currentUri, setCurrentUri] = useState<string | undefined>(uri.original || uri.remote) |   const [currentSource, setCurrentSource] = useState<ImageSource | undefined>( | ||||||
|   const source: { uri?: string } = { |     sources.default || sources.remote | ||||||
|     uri: reduceMotionEnabled && uri.static ? uri.static : currentUri |   ) | ||||||
|   } |   const source: ImageSource | undefined = | ||||||
|   useEffect(() => { |     reduceMotionEnabled && sources.static ? sources.static : currentSource | ||||||
|     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 |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <Pressable |     <Pressable | ||||||
| @@ -91,50 +62,40 @@ const GracefullyImage = ({ | |||||||
|       style={[style, dimension]} |       style={[style, dimension]} | ||||||
|       {...(onPress ? (hidden ? { disabled: true } : { onPress }) : { disabled: true })} |       {...(onPress ? (hidden ? { disabled: true } : { onPress }) : { disabled: true })} | ||||||
|     > |     > | ||||||
|       {uri.preview && !imageLoaded ? ( |       <Image | ||||||
|         <FastImage |         placeholder={sources.blurhash || connectMedia(sources.preview)} | ||||||
|           source={connectMedia({ uri: uri.preview })} |         source={hidden ? undefined : connectMedia(source)} | ||||||
|           enterTransition='fadeIn' |         transition={{ duration: 100 }} | ||||||
|           transitionDuration={60} |         style={{ flex: 1, ...imageStyle }} | ||||||
|           style={[styles.placeholder]} |         onLoad={event => { | ||||||
|         /> |           if (setImageDimensions && event.source) { | ||||||
|       ) : null} |             setImageDimensions(event.source) | ||||||
|       <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 })) |  | ||||||
|           } |           } | ||||||
|         }} |         }} | ||||||
|         onError={() => { |         onError={() => { | ||||||
|           if (uri.original && uri.original === currentUri && uri.remote) { |           if ( | ||||||
|             setCurrentUri(uri.remote) |             sources.default?.uri && | ||||||
|  |             sources.default?.uri === currentSource?.uri && | ||||||
|  |             sources.remote | ||||||
|  |           ) { | ||||||
|  |             setCurrentSource(sources.remote) | ||||||
|           } |           } | ||||||
|         }} |         }} | ||||||
|  |         enableLiveTextInteraction={enableLiveTextInteraction} | ||||||
|       /> |       /> | ||||||
|       {blurhashView()} |  | ||||||
|       {dim && theme !== 'light' ? ( |       {dim && theme !== 'light' ? ( | ||||||
|         <View |         <View | ||||||
|           style={[ |           style={{ | ||||||
|             styles.placeholder, |             width: '100%', | ||||||
|             { backgroundColor: 'black', opacity: theme === 'dark_lighter' ? 0.18 : 0.36 } |             height: '100%', | ||||||
|           ]} |             position: 'absolute', | ||||||
|  |             backgroundColor: 'black', | ||||||
|  |             opacity: theme === 'dark_lighter' ? 0.18 : 0.36 | ||||||
|  |           }} | ||||||
|         /> |         /> | ||||||
|       ) : null} |       ) : null} | ||||||
|     </Pressable> |     </Pressable> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
| const styles = StyleSheet.create({ |  | ||||||
|   placeholder: { |  | ||||||
|     width: '100%', |  | ||||||
|     height: '100%', |  | ||||||
|     position: 'absolute' |  | ||||||
|   } |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| export default GracefullyImage | export default GracefullyImage | ||||||
|   | |||||||
| @@ -19,12 +19,13 @@ import { | |||||||
| import { StyleConstants } from '@utils/styles/constants' | import { StyleConstants } from '@utils/styles/constants' | ||||||
| import { useTheme } from '@utils/styles/ThemeManager' | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
| import * as AuthSession from 'expo-auth-session' | import * as AuthSession from 'expo-auth-session' | ||||||
|  | import { Image } from 'expo-image' | ||||||
| import * as Random from 'expo-random' | import * as Random from 'expo-random' | ||||||
| import * as WebBrowser from 'expo-web-browser' | import * as WebBrowser from 'expo-web-browser' | ||||||
| import { debounce } from 'lodash' | import { debounce } from 'lodash' | ||||||
| import React, { RefObject, useCallback, useState } from 'react' | import React, { RefObject, useCallback, useState } from 'react' | ||||||
| import { Trans, useTranslation } from 'react-i18next' | 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 { ScrollView } from 'react-native-gesture-handler' | ||||||
| import { fromByteArray } from 'react-native-quick-base64' | import { fromByteArray } from 'react-native-quick-base64' | ||||||
| import parse from 'url-parse' | import parse from 'url-parse' | ||||||
|   | |||||||
| @@ -5,9 +5,9 @@ import { useGlobalStorage } from '@utils/storage/actions' | |||||||
| import { StyleConstants } from '@utils/styles/constants' | import { StyleConstants } from '@utils/styles/constants' | ||||||
| import { adaptiveScale } from '@utils/styles/scaling' | import { adaptiveScale } from '@utils/styles/scaling' | ||||||
| import { useTheme } from '@utils/styles/ThemeManager' | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
|  | import { Image } from 'expo-image' | ||||||
| import React from 'react' | import React from 'react' | ||||||
| import { ColorValue, Platform, TextStyle } from 'react-native' | import { ColorValue, Platform, TextStyle } from 'react-native' | ||||||
| import FastImage from 'react-native-fast-image' |  | ||||||
|  |  | ||||||
| const regexEmoji = new RegExp(/(:[A-Za-z0-9_]+:)/) | const regexEmoji = new RegExp(/(:[A-Za-z0-9_]+:)/) | ||||||
|  |  | ||||||
| @@ -77,8 +77,8 @@ const ParseEmojis: React.FC<Props> = ({ | |||||||
|                 return ( |                 return ( | ||||||
|                   <CustomText key={emojiShortcode + i}> |                   <CustomText key={emojiShortcode + i}> | ||||||
|                     {i === 0 ? ' ' : undefined} |                     {i === 0 ? ' ' : undefined} | ||||||
|                     <FastImage |                     <Image | ||||||
|                       source={connectMedia({ uri: uri.trim() })} |                       source={connectMedia({ uri })} | ||||||
|                       style={{ |                       style={{ | ||||||
|                         width: adaptedFontsize, |                         width: adaptedFontsize, | ||||||
|                         height: adaptedFontsize, |                         height: adaptedFontsize, | ||||||
|   | |||||||
| @@ -79,7 +79,10 @@ const TimelineConversation: React.FC<Props> = ({ conversation, queryKey, highlig | |||||||
|             {conversation.accounts.slice(0, 4).map(account => ( |             {conversation.accounts.slice(0, 4).map(account => ( | ||||||
|               <GracefullyImage |               <GracefullyImage | ||||||
|                 key={account.id} |                 key={account.id} | ||||||
|                 uri={{ original: account.avatar, static: account.avatar_static }} |                 sources={{ | ||||||
|  |                   default: { uri: account.avatar }, | ||||||
|  |                   static: { uri: account.avatar_static } | ||||||
|  |                 }} | ||||||
|                 dimension={{ |                 dimension={{ | ||||||
|                   width: StyleConstants.Avatar.M, |                   width: StyleConstants.Avatar.M, | ||||||
|                   height: |                   height: | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ import { StackNavigationProp } from '@react-navigation/stack' | |||||||
| import { RootStackParamList } from '@utils/navigation/navigators' | import { RootStackParamList } from '@utils/navigation/navigators' | ||||||
| import { usePreferencesQuery } from '@utils/queryHooks/preferences' | import { usePreferencesQuery } from '@utils/queryHooks/preferences' | ||||||
| import { StyleConstants } from '@utils/styles/constants' | import { StyleConstants } from '@utils/styles/constants' | ||||||
| import layoutAnimation from '@utils/styles/layoutAnimation' |  | ||||||
| import React, { useContext, useState } from 'react' | import React, { useContext, useState } from 'react' | ||||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||||
| import { Pressable, View } from 'react-native' | import { Pressable, View } from 'react-native' | ||||||
| @@ -207,7 +206,6 @@ const TimelineAttachment = () => { | |||||||
|               content={t('shared.attachment.sensitive.button')} |               content={t('shared.attachment.sensitive.button')} | ||||||
|               overlay |               overlay | ||||||
|               onPress={() => { |               onPress={() => { | ||||||
|                 layoutAnimation() |  | ||||||
|                 setSensitiveShown(false) |                 setSensitiveShown(false) | ||||||
|                 haptics('Light') |                 haptics('Light') | ||||||
|               }} |               }} | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ import { useTheme } from '@utils/styles/ThemeManager' | |||||||
| import { Audio } from 'expo-av' | import { Audio } from 'expo-av' | ||||||
| import React, { useCallback, useEffect, useRef, useState } from 'react' | import React, { useCallback, useEffect, useRef, useState } from 'react' | ||||||
| import { AppState, AppStateStatus, StyleSheet, View } from 'react-native' | import { AppState, AppStateStatus, StyleSheet, View } from 'react-native' | ||||||
| import { Blurhash } from 'react-native-blurhash' |  | ||||||
| import AttachmentAltText from './AltText' | import AttachmentAltText from './AltText' | ||||||
| import { aspectRatio } from './dimensions' | import { aspectRatio } from './dimensions' | ||||||
|  |  | ||||||
| @@ -72,19 +71,23 @@ const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio | |||||||
|       <View style={styles.overlay}> |       <View style={styles.overlay}> | ||||||
|         {sensitiveShown ? ( |         {sensitiveShown ? ( | ||||||
|           audio.blurhash ? ( |           audio.blurhash ? ( | ||||||
|             <Blurhash |             <GracefullyImage | ||||||
|               blurhash={audio.blurhash} |               sources={{ blurhash: audio.blurhash }} | ||||||
|               style={{ |               style={{ | ||||||
|                 width: '100%', |                 width: '100%', | ||||||
|                 height: '100%' |                 height: '100%' | ||||||
|               }} |               }} | ||||||
|  |               dim | ||||||
|             /> |             /> | ||||||
|           ) : null |           ) : null | ||||||
|         ) : ( |         ) : ( | ||||||
|           <> |           <> | ||||||
|             {audio.preview_url ? ( |             {audio.preview_url ? ( | ||||||
|               <GracefullyImage |               <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} |                 style={styles.background} | ||||||
|                 dim |                 dim | ||||||
|               /> |               /> | ||||||
|   | |||||||
| @@ -35,8 +35,11 @@ const AttachmentImage = ({ | |||||||
|         <GracefullyImage |         <GracefullyImage | ||||||
|           accessibilityLabel={image.description} |           accessibilityLabel={image.description} | ||||||
|           hidden={sensitiveShown} |           hidden={sensitiveShown} | ||||||
|           uri={{ original: image.preview_url, remote: image.remote_url }} |           sources={{ | ||||||
|           blurhash={image.blurhash} |             default: { uri: image.preview_url }, | ||||||
|  |             remote: { uri: image.remote_url }, | ||||||
|  |             blurhash: image.blurhash | ||||||
|  |           }} | ||||||
|           onPress={() => navigateToImagesViewer(image.id)} |           onPress={() => navigateToImagesViewer(image.id)} | ||||||
|           style={{ aspectRatio: aspectRatio({ total, index, ...image.meta?.original }) }} |           style={{ aspectRatio: aspectRatio({ total, index, ...image.meta?.original }) }} | ||||||
|           dim |           dim | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import Button from '@components/Button' | import Button from '@components/Button' | ||||||
|  | import GracefullyImage from '@components/GracefullyImage' | ||||||
| import openLink from '@components/openLink' | import openLink from '@components/openLink' | ||||||
| import CustomText from '@components/Text' | import CustomText from '@components/Text' | ||||||
| import { StyleConstants } from '@utils/styles/constants' | import { StyleConstants } from '@utils/styles/constants' | ||||||
| @@ -6,7 +7,6 @@ import { useTheme } from '@utils/styles/ThemeManager' | |||||||
| import React from 'react' | import React from 'react' | ||||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||||
| import { View } from 'react-native' | import { View } from 'react-native' | ||||||
| import { Blurhash } from 'react-native-blurhash' |  | ||||||
| import AttachmentAltText from './AltText' | import AttachmentAltText from './AltText' | ||||||
| import { aspectRatio } from './dimensions' | import { aspectRatio } from './dimensions' | ||||||
|  |  | ||||||
| @@ -33,8 +33,8 @@ const AttachmentUnsupported: React.FC<Props> = ({ total, index, sensitiveShown, | |||||||
|       }} |       }} | ||||||
|     > |     > | ||||||
|       {attachment.blurhash ? ( |       {attachment.blurhash ? ( | ||||||
|         <Blurhash |         <GracefullyImage | ||||||
|           blurhash={attachment.blurhash} |           sources={{ blurhash: attachment.blurhash }} | ||||||
|           style={{ |           style={{ | ||||||
|             position: 'absolute', |             position: 'absolute', | ||||||
|             width: '100%', |             width: '100%', | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import Button from '@components/Button' | import Button from '@components/Button' | ||||||
|  | import GracefullyImage from '@components/GracefullyImage' | ||||||
| import { useAccessibility } from '@utils/accessibility/AccessibilityManager' | import { useAccessibility } from '@utils/accessibility/AccessibilityManager' | ||||||
| import { connectMedia } from '@utils/api/helpers/connect' | import { connectMedia } from '@utils/api/helpers/connect' | ||||||
| import { useAccountStorage, useGlobalStorage } from '@utils/storage/actions' | 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 * as ScreenOrientation from 'expo-screen-orientation' | ||||||
| import React, { useRef, useState } from 'react' | import React, { useRef, useState } from 'react' | ||||||
| import { Pressable, View } from 'react-native' | import { Pressable, View } from 'react-native' | ||||||
| import { Blurhash } from 'react-native-blurhash' |  | ||||||
| import AttachmentAltText from './AltText' | import AttachmentAltText from './AltText' | ||||||
| import { aspectRatio } from './dimensions' | import { aspectRatio } from './dimensions' | ||||||
|  |  | ||||||
| @@ -120,7 +120,10 @@ const AttachmentVideo: React.FC<Props> = ({ | |||||||
|       > |       > | ||||||
|         {sensitiveShown ? ( |         {sensitiveShown ? ( | ||||||
|           video.blurhash ? ( |           video.blurhash ? ( | ||||||
|             <Blurhash blurhash={video.blurhash} style={{ width: '100%', height: '100%' }} /> |             <GracefullyImage | ||||||
|  |               sources={{ blurhash: video.blurhash }} | ||||||
|  |               style={{ width: '100%', height: '100%' }} | ||||||
|  |             /> | ||||||
|           ) : null |           ) : null | ||||||
|         ) : !gifv || (gifv && (reduceMotionEnabled || !shouldAutoplayGifv)) ? ( |         ) : !gifv || (gifv && (reduceMotionEnabled || !shouldAutoplayGifv)) ? ( | ||||||
|           <Button |           <Button | ||||||
|   | |||||||
| @@ -33,7 +33,10 @@ const TimelineAvatar: React.FC<Props> = ({ account }) => { | |||||||
|       onPress={() => |       onPress={() => | ||||||
|         !disableOnPress && navigation.push('Tab-Shared-Account', { account: actualAccount }) |         !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={ |       dimension={ | ||||||
|         disableDetails || isConversation |         disableDetails || isConversation | ||||||
|           ? { |           ? { | ||||||
|   | |||||||
| @@ -82,8 +82,7 @@ const TimelineCard: React.FC = () => { | |||||||
|       <> |       <> | ||||||
|         {status.card?.image ? ( |         {status.card?.image ? ( | ||||||
|           <GracefullyImage |           <GracefullyImage | ||||||
|             uri={{ original: status.card.image }} |             sources={{ default: { uri: status.card.image }, blurhash: status.card.blurhash }} | ||||||
|             blurhash={status.card.blurhash} |  | ||||||
|             style={{ flexBasis: StyleConstants.Font.LineHeight.M * 5 }} |             style={{ flexBasis: StyleConstants.Font.LineHeight.M * 5 }} | ||||||
|             imageStyle={{ borderTopLeftRadius: 6, borderBottomLeftRadius: 6 }} |             imageStyle={{ borderTopLeftRadius: 6, borderBottomLeftRadius: 6 }} | ||||||
|             dim |             dim | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import Button from '@components/Button' | import Button from '@components/Button' | ||||||
|  | import GracefullyImage from '@components/GracefullyImage' | ||||||
| import haptics from '@components/haptics' | import haptics from '@components/haptics' | ||||||
| import { Loading } from '@components/Loading' | import { Loading } from '@components/Loading' | ||||||
| import { ParseHTML } from '@components/Parse' | import { ParseHTML } from '@components/Parse' | ||||||
| @@ -6,7 +7,6 @@ import RelativeTime from '@components/RelativeTime' | |||||||
| import CustomText from '@components/Text' | import CustomText from '@components/Text' | ||||||
| import { BlurView } from '@react-native-community/blur' | import { BlurView } from '@react-native-community/blur' | ||||||
| import { useAccessibility } from '@utils/accessibility/AccessibilityManager' | import { useAccessibility } from '@utils/accessibility/AccessibilityManager' | ||||||
| import { connectMedia } from '@utils/api/helpers/connect' |  | ||||||
| import { RootStackScreenProps } from '@utils/navigation/navigators' | import { RootStackScreenProps } from '@utils/navigation/navigators' | ||||||
| import { useAnnouncementMutation, useAnnouncementQuery } from '@utils/queryHooks/announcement' | import { useAnnouncementMutation, useAnnouncementQuery } from '@utils/queryHooks/announcement' | ||||||
| import { StyleConstants } from '@utils/styles/constants' | import { StyleConstants } from '@utils/styles/constants' | ||||||
| @@ -22,7 +22,6 @@ import { | |||||||
|   StyleSheet, |   StyleSheet, | ||||||
|   View |   View | ||||||
| } from 'react-native' | } from 'react-native' | ||||||
| import FastImage from 'react-native-fast-image' |  | ||||||
| import { FlatList, ScrollView } from 'react-native-gesture-handler' | import { FlatList, ScrollView } from 'react-native-gesture-handler' | ||||||
| import { SafeAreaView } from 'react-native-safe-area-context' | import { SafeAreaView } from 'react-native-safe-area-context' | ||||||
|  |  | ||||||
| @@ -139,12 +138,13 @@ const ScreenAnnouncements: React.FC<RootStackScreenProps<'Screen-Announcements'> | |||||||
|                 } |                 } | ||||||
|               > |               > | ||||||
|                 {reaction.url ? ( |                 {reaction.url ? ( | ||||||
|                   <FastImage |                   <GracefullyImage | ||||||
|                     source={connectMedia({ |                     sources={{ | ||||||
|                       uri: reduceMotionEnabled ? reaction.static_url : reaction.url |                       default: { uri: reaction.url }, | ||||||
|                     })} |                       static: { uri: reaction.static_url } | ||||||
|                     style={{ |                     }} | ||||||
|                       width: StyleConstants.Font.LineHeight.M + 3, |                     dimension={{ | ||||||
|  |                       width: StyleConstants.Font.LineHeight.M, | ||||||
|                       height: 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 { getAccountStorage, setAccountStorage, useAccountStorage } from '@utils/storage/actions' | ||||||
| import { StyleConstants } from '@utils/styles/constants' | import { StyleConstants } from '@utils/styles/constants' | ||||||
| import { useTheme } from '@utils/styles/ThemeManager' | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
|  | import { Image } from 'expo-image' | ||||||
| import React, { useContext, useEffect, useState } from 'react' | import React, { useContext, useEffect, useState } from 'react' | ||||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||||
| import { Dimensions, Modal, Pressable, View } from 'react-native' | import { Dimensions, Modal, Pressable, View } from 'react-native' | ||||||
| import FastImage from 'react-native-fast-image' |  | ||||||
| import ComposeContext from './utils/createContext' | import ComposeContext from './utils/createContext' | ||||||
| import { formatText } from './utils/processText' | import { formatText } from './utils/processText' | ||||||
| import { ComposeStateDraft, ExtendedAttachment } from './utils/types' | import { ComposeStateDraft, ExtendedAttachment } from './utils/types' | ||||||
| @@ -140,7 +140,7 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose- | |||||||
|                     }} |                     }} | ||||||
|                   > |                   > | ||||||
|                     {item.attachments.uploads.map((attachment, index) => ( |                     {item.attachments.uploads.map((attachment, index) => ( | ||||||
|                       <FastImage |                       <Image | ||||||
|                         key={index} |                         key={index} | ||||||
|                         style={{ |                         style={{ | ||||||
|                           width: |                           width: | ||||||
|   | |||||||
| @@ -11,10 +11,10 @@ import { featureCheck } from '@utils/helpers/featureCheck' | |||||||
| import { StyleConstants } from '@utils/styles/constants' | import { StyleConstants } from '@utils/styles/constants' | ||||||
| import layoutAnimation from '@utils/styles/layoutAnimation' | import layoutAnimation from '@utils/styles/layoutAnimation' | ||||||
| import { useTheme } from '@utils/styles/ThemeManager' | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
|  | import { Image } from 'expo-image' | ||||||
| import React, { RefObject, useContext, useEffect, useRef } from 'react' | import React, { RefObject, useContext, useEffect, useRef } from 'react' | ||||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||||
| import { FlatList, Pressable, StyleSheet, View } from 'react-native' | import { FlatList, Pressable, StyleSheet, View } from 'react-native' | ||||||
| import FastImage from 'react-native-fast-image' |  | ||||||
| import ComposeContext from '../../utils/createContext' | import ComposeContext from '../../utils/createContext' | ||||||
| import { ExtendedAttachment } from '../../utils/types' | import { ExtendedAttachment } from '../../utils/types' | ||||||
| import chooseAndUploadAttachment from './addAttachment' | import chooseAndUploadAttachment from './addAttachment' | ||||||
| @@ -104,9 +104,7 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => { | |||||||
|           width: calculateWidth(item) |           width: calculateWidth(item) | ||||||
|         }} |         }} | ||||||
|       > |       > | ||||||
|         <FastImage |         <Image | ||||||
|           enterTransition='fadeIn' |  | ||||||
|           transitionDuration={60} |  | ||||||
|           style={{ width: '100%', height: '100%' }} |           style={{ width: '100%', height: '100%' }} | ||||||
|           source={ |           source={ | ||||||
|             item.local?.thumbnail |             item.local?.thumbnail | ||||||
|   | |||||||
| @@ -193,10 +193,10 @@ const ScreenImagesViewer = ({ | |||||||
|                     }} |                     }} | ||||||
|                   > |                   > | ||||||
|                     <GracefullyImage |                     <GracefullyImage | ||||||
|                       uri={{ |                       sources={{ | ||||||
|                         preview: item.preview_url, |                         preview: { uri: item.preview_url, width: item.width, height: item.height }, | ||||||
|                         remote: item.remote_url, |                         default: { uri: item.url, width: item.width, height: item.height }, | ||||||
|                         original: item.url |                         remote: { uri: item.remote_url, width: item.width, height: item.height } | ||||||
|                       }} |                       }} | ||||||
|                       dimension={{ |                       dimension={{ | ||||||
|                         width: |                         width: | ||||||
| @@ -208,6 +208,7 @@ const ScreenImagesViewer = ({ | |||||||
|                             ? WINDOW_HEIGHT |                             ? WINDOW_HEIGHT | ||||||
|                             : (WINDOW_WIDTH / imageWidth) * imageHeight |                             : (WINDOW_WIDTH / imageWidth) * imageHeight | ||||||
|                       }} |                       }} | ||||||
|  |                       enableLiveTextInteraction | ||||||
|                     /> |                     /> | ||||||
|                   </View> |                   </View> | ||||||
|                 } |                 } | ||||||
|   | |||||||
| @@ -82,15 +82,25 @@ const AccountAttachments: React.FC = () => { | |||||||
|           } else { |           } else { | ||||||
|             return ( |             return ( | ||||||
|               <GracefullyImage |               <GracefullyImage | ||||||
|                 uri={{ |                 sources={{ | ||||||
|                   original: |                   preview: { | ||||||
|                     item.media_attachments[0]?.preview_url || item.media_attachments[0]?.url, |                     uri: item.media_attachments[0]?.preview_url, | ||||||
|                   remote: item.media_attachments[0]?.remote_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={ |                 dimension={{ width, height: width }} | ||||||
|                   item.media_attachments[0] && (item.media_attachments[0].blurhash || undefined) |  | ||||||
|                 } |  | ||||||
|                 dimension={{ width: width, height: width }} |  | ||||||
|                 style={{ marginLeft: StyleConstants.Spacing.Global.PagePadding }} |                 style={{ marginLeft: StyleConstants.Spacing.Global.PagePadding }} | ||||||
|                 onPress={() => navigation.push('Tab-Shared-Toot', { toot: item })} |                 onPress={() => navigation.push('Tab-Shared-Toot', { toot: item })} | ||||||
|                 dim |                 dim | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| import GracefullyImage from '@components/GracefullyImage' | import GracefullyImage from '@components/GracefullyImage' | ||||||
| import navigationRef from '@utils/navigation/navigationRef' | import navigationRef from '@utils/navigation/navigationRef' | ||||||
| import { useGlobalStorage } from '@utils/storage/actions' |  | ||||||
| import React, { useContext } from 'react' | import React, { useContext } from 'react' | ||||||
| import { Dimensions, Image } from 'react-native' | import { Dimensions, Image } from 'react-native' | ||||||
| import { useSafeAreaInsets } from 'react-native-safe-area-context' | import { useSafeAreaInsets } from 'react-native-safe-area-context' | ||||||
| @@ -11,11 +10,9 @@ const AccountHeader: React.FC = () => { | |||||||
|  |  | ||||||
|   const topInset = useSafeAreaInsets().top |   const topInset = useSafeAreaInsets().top | ||||||
|  |  | ||||||
|   useGlobalStorage.string('account.active') |  | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <GracefullyImage |     <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 }} |       style={{ height: Dimensions.get('window').width / 3 + topInset }} | ||||||
|       onPress={() => { |       onPress={() => { | ||||||
|         if (account) { |         if (account) { | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ import { useNavigation } from '@react-navigation/native' | |||||||
| import { StackNavigationProp } from '@react-navigation/stack' | import { StackNavigationProp } from '@react-navigation/stack' | ||||||
| import navigationRef from '@utils/navigation/navigationRef' | import navigationRef from '@utils/navigation/navigationRef' | ||||||
| import { TabLocalStackParamList } from '@utils/navigation/navigators' | import { TabLocalStackParamList } from '@utils/navigation/navigators' | ||||||
| import { useAccountStorage } from '@utils/storage/actions' |  | ||||||
| import { StyleConstants } from '@utils/styles/constants' | import { StyleConstants } from '@utils/styles/constants' | ||||||
| import React, { useContext } from 'react' | import React, { useContext } from 'react' | ||||||
| import AccountContext from '../Context' | import AccountContext from '../Context' | ||||||
| @@ -13,20 +12,13 @@ const AccountInformationAvatar: React.FC = () => { | |||||||
|  |  | ||||||
|   const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>() |   const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>() | ||||||
|  |  | ||||||
|   const [accountAvatarStatic] = useAccountStorage.string('auth.account.avatar_static') |  | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <GracefullyImage |     <GracefullyImage | ||||||
|       key={account?.avatar} |       style={{ borderRadius: 8, overflow: 'hidden' }} | ||||||
|       style={{ |       dimension={{ width: StyleConstants.Avatar.L, height: StyleConstants.Avatar.L }} | ||||||
|         borderRadius: 8, |       sources={{ | ||||||
|         overflow: 'hidden', |         default: { uri: account?.avatar }, | ||||||
|         width: StyleConstants.Avatar.L, |         static: { uri: account?.avatar_static } | ||||||
|         height: StyleConstants.Avatar.L |  | ||||||
|       }} |  | ||||||
|       uri={{ |  | ||||||
|         original: account?.avatar || (pageMe ? accountAvatarStatic : undefined), |  | ||||||
|         static: account?.avatar_static || (pageMe ? accountAvatarStatic : undefined) |  | ||||||
|       }} |       }} | ||||||
|       onPress={() => { |       onPress={() => { | ||||||
|         if (account) { |         if (account) { | ||||||
|   | |||||||
| @@ -52,7 +52,7 @@ const ScreenTabs = () => { | |||||||
|               return ( |               return ( | ||||||
|                 <View style={{ flexDirection: 'row', alignItems: 'center' }}> |                 <View style={{ flexDirection: 'row', alignItems: 'center' }}> | ||||||
|                   <GracefullyImage |                   <GracefullyImage | ||||||
|                     uri={{ original: avatarStatic }} |                     sources={{ default: { uri: avatarStatic } }} | ||||||
|                     dimension={{ width: size, height: size }} |                     dimension={{ width: size, height: size }} | ||||||
|                     style={{ |                     style={{ | ||||||
|                       borderRadius: size, |                       borderRadius: size, | ||||||
|   | |||||||
| @@ -81,19 +81,18 @@ export const CONNECT_DOMAIN = (index?: number) => | |||||||
|     development: 'connect-development.tooot.app' |     development: 'connect-development.tooot.app' | ||||||
|   }) |   }) | ||||||
|  |  | ||||||
| export const connectMedia = ({ | export const connectMedia = (args?: { | ||||||
|   uri |  | ||||||
| }: { |  | ||||||
|   uri?: string |   uri?: string | ||||||
| }): { uri?: string; headers?: { 'x-tooot-domain': string } } => { | }): { uri?: string; headers?: { 'x-tooot-domain': string } } => { | ||||||
|   if (GLOBAL.connect) { |   if (GLOBAL.connect) { | ||||||
|     if (uri) { |     if (args?.uri) { | ||||||
|       const host = parse(uri).host |       const host = parse(args.uri).host | ||||||
|       return { |       return { | ||||||
|         uri: uri.replace( |         ...args, | ||||||
|  |         uri: args.uri.replace( | ||||||
|           host, |           host, | ||||||
|           CONNECT_DOMAIN( |           CONNECT_DOMAIN( | ||||||
|             uri |             args.uri | ||||||
|               .split('') |               .split('') | ||||||
|               .map(i => i.charCodeAt(0)) |               .map(i => i.charCodeAt(0)) | ||||||
|               .reduce((a, b) => a + b, 0) % |               .reduce((a, b) => a + b, 0) % | ||||||
| @@ -103,10 +102,10 @@ export const connectMedia = ({ | |||||||
|         headers: { 'x-tooot-domain': host } |         headers: { 'x-tooot-domain': host } | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       return { uri } |       return { ...args } | ||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
|     return { uri } |     return { ...args } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								yarn.lock
									
									
									
									
									
								
							| @@ -5706,6 +5706,15 @@ __metadata: | |||||||
|   languageName: node |   languageName: node | ||||||
|   linkType: hard |   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": | "expo-keep-awake@npm:~11.0.1": | ||||||
|   version: 11.0.1 |   version: 11.0.1 | ||||||
|   resolution: "expo-keep-awake@npm:11.0.1" |   resolution: "expo-keep-awake@npm:11.0.1" | ||||||
| @@ -9639,26 +9648,6 @@ __metadata: | |||||||
|   languageName: node |   languageName: node | ||||||
|   linkType: hard |   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": | "react-native-flash-message@npm:^0.4.0": | ||||||
|   version: 0.4.0 |   version: 0.4.0 | ||||||
|   resolution: "react-native-flash-message@npm:0.4.0" |   resolution: "react-native-flash-message@npm:0.4.0" | ||||||
| @@ -11432,6 +11421,7 @@ __metadata: | |||||||
|     expo-crypto: ^12.1.0 |     expo-crypto: ^12.1.0 | ||||||
|     expo-file-system: ^15.1.1 |     expo-file-system: ^15.1.1 | ||||||
|     expo-haptics: ^12.1.0 |     expo-haptics: ^12.1.0 | ||||||
|  |     expo-image: ^1.0.0-beta.6 | ||||||
|     expo-linking: ^3.3.0 |     expo-linking: ^3.3.0 | ||||||
|     expo-localization: ^14.0.0 |     expo-localization: ^14.0.0 | ||||||
|     expo-notifications: ^0.17.0 |     expo-notifications: ^0.17.0 | ||||||
| @@ -11454,7 +11444,6 @@ __metadata: | |||||||
|     react-native: ^0.70.7 |     react-native: ^0.70.7 | ||||||
|     react-native-blurhash: ^1.1.10 |     react-native-blurhash: ^1.1.10 | ||||||
|     react-native-clean-project: ^4.0.1 |     react-native-clean-project: ^4.0.1 | ||||||
|     react-native-fast-image: ^8.6.3 |  | ||||||
|     react-native-flash-message: ^0.4.0 |     react-native-flash-message: ^0.4.0 | ||||||
|     react-native-gesture-handler: ~2.9.0 |     react-native-gesture-handler: ~2.9.0 | ||||||
|     react-native-image-picker: ^5.0.1 |     react-native-image-picker: ^5.0.1 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user