Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP|Implement for react-native-web #112

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
dde7d52
Move BlurhashModule to its own file
jacob-israel-turner Mar 7, 2021
dbb5e91
TEMP|Trying web with webpack
jacob-israel-turner Mar 7, 2021
133aae7
Revert "TEMP|Trying web with webpack"
jacob-israel-turner Mar 7, 2021
22bacde
Add prepare:dev script
jacob-israel-turner Mar 7, 2021
5dbb7af
Add react-native-web/expo-web in examples
jacob-israel-turner Mar 7, 2021
d167339
Enhance prepare:dev
jacob-israel-turner Mar 7, 2021
67c70b1
Get web example running
jacob-israel-turner Mar 7, 2021
56d8196
Initial implementation of web working
jacob-israel-turner Mar 7, 2021
adf71c5
Tidy up
jacob-israel-turner Mar 7, 2021
318d43c
Note
jacob-israel-turner Mar 7, 2021
e9d4d2c
Get iOS example to build
jacob-israel-turner Mar 7, 2021
c27164d
Fix native platforms
jacob-israel-turner Mar 7, 2021
f81736f
Apply styles to container
jacob-israel-turner Mar 7, 2021
bada2a4
Fix linting
jacob-israel-turner Mar 7, 2021
ce59868
Create .web files
jacob-israel-turner Mar 29, 2021
ea7c389
Cleanup
jacob-israel-turner Mar 29, 2021
6617368
Build web BlurhashModule
jacob-israel-turner Mar 29, 2021
9ac4819
Run prettier
jacob-israel-turner Mar 29, 2021
af2a8f9
Update package-lock.json
jacob-israel-turner Mar 29, 2021
7140010
Run Prettier on /example
jacob-israel-turner Mar 29, 2021
9d93f26
Cleanup
jacob-israel-turner Mar 29, 2021
cd22852
Move blurhash to peer dependencies
jacob-israel-turner Apr 9, 2021
3720989
Add blurhash to dev dependencies
jacob-israel-turner Apr 10, 2021
777befb
Remove expo-web
jacob-israel-turner Apr 10, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ buck-out/

# CocoaPods
/ios/Pods/

# Expo
.expo/
8 changes: 7 additions & 1 deletion example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@
* @format
*/

import { AppRegistry } from 'react-native';
import { AppRegistry, Platform } from 'react-native';
import App from './App';
import { name as appName } from './app.json';

AppRegistry.registerComponent(appName, () => App);

if (Platform.OS === 'web') {
AppRegistry.runApplication(appName, {
rootTag: document.getElementById('root'),
});
}
5 changes: 5 additions & 0 deletions example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

use_modular_headers!
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not get the current iOS example to run without these changes.


platform :ios, '10.0'
target 'example' do
# Pods for example
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec', :modular_headers => false
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec', :modular_headers => false
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec', :modular_headers => false
target 'exampleTests' do
inherit! :complete
# Pods for testing
Expand Down
8 changes: 4 additions & 4 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ PODS:
- React-cxxreact (= 0.63.1)
- React-jsi (= 0.63.1)
- React-jsinspector (0.63.1)
- react-native-blurhash (1.0.29):
- React
- react-native-blurhash (1.1.4):
- React-Core
- React-RCTActionSheet (0.63.1):
- React-Core/RCTActionSheetHeaders (= 0.63.1)
- React-RCTAnimation (0.63.1):
Expand Down Expand Up @@ -450,7 +450,7 @@ SPEC CHECKSUMS:
React-jsi: b32a31da32e030f30bbf9a8d3a9c8325df9e793f
React-jsiexecutor: 7ab9cdcdd18d57652fb041f8a147fe9658d4e00a
React-jsinspector: 2e28bb487e42dda6c94dbfa0c648d1343767a0fb
react-native-blurhash: 90886ae897cafbbdf2773cb3654656bcb34e8f43
react-native-blurhash: ec98d751a9cb9075cef0b9e3188244c517d6ab22
React-RCTActionSheet: 1702a1a85e550b5c36e2e03cb2bd3adea053de95
React-RCTAnimation: ddda576010a878865a4eab83a78acd92176ef6a1
React-RCTBlob: 34334384284c81577409d5205bd2b9ff594d8ab6
Expand All @@ -464,6 +464,6 @@ SPEC CHECKSUMS:
Yoga: d5bd05a2b6b94c52323745c2c2b64557c8c66f64
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a

PODFILE CHECKSUM: 6a759bd1b10fa49b7d7ab5dfa9a81d1d8edc3516
PODFILE CHECKSUM: 8506680dfcf32aa1a80406d612d0d0de42e135c5

COCOAPODS: 1.10.1
7 changes: 6 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@
"scripts": {
"postinstall": "rm -rf node_modules/react-native-blurhash/node_modules",
"android": "react-native run-android",
"web": "expo web",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint --ext .js,.jsx,.ts,.tsx ."
},
"dependencies": {
"babel-preset-expo": "^8.2.1",
"expo": "^37.0.12",
"react": "16.13.1",
"react-dom": "^17.0.1",
"react-native": "0.63.1",
"react-native-blurhash": "link:.."
"react-native-blurhash": "link:..",
"react-native-web": "^0.15.0"
},
"devDependencies": {
"@babel/core": "^7.10.2",
Expand Down
1,600 changes: 1,588 additions & 12 deletions example/yarn.lock

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"scripts": {
"lint": "eslint --ext .js,.jsx,.ts,.tsx .",
"prepare": "bob build",
"prepare:dev": "nodemon --watch src/ --watch web/ --ext js,ts,tsx --exec \"yarn prepare\"",
"release": "release-it"
},
"repository": {
Expand Down Expand Up @@ -65,6 +66,7 @@
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react-native": "^3.10.0",
"nodemon": "^2.0.7",
"prettier": "^2.2.0",
"react-native-builder-bob": "^0.17.1",
"release-it": "^14.4.1",
Expand Down Expand Up @@ -104,5 +106,8 @@
"eslintIgnore": [
"node_modules/",
"lib/"
]
],
"dependencies": {
"blurhash": "^1.1.3"
}
}
12 changes: 12 additions & 0 deletions src/blurhashModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { NativeModules, Platform } from 'react-native';
const BlurhashModule: BlurhashModule = Platform.select({
web: null,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

native: NativeModules.BlurhashModule,
});

type BlurhashModule = {
createBlurhashFromImage: (imageUri: string, componentsX: number, componentsY: number) => Promise<string>,
clearCosineCache: () => void
};

export default BlurhashModule;
22 changes: 11 additions & 11 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import * as React from 'react';
import { requireNativeComponent, NativeModules, Platform, ViewProps, NativeSyntheticEvent } from 'react-native';
import { requireNativeComponent, Platform, ViewProps, NativeSyntheticEvent } from 'react-native';
import { decode83, decodeDC, isBlurhashValid, RGB } from './utils';

// NativeModules automatically resolves 'BlurhashView' to 'BlurhashViewModule'
const BlurhashModule = NativeModules.BlurhashView;
import BlurhashModule from './blurhashModule';

export interface BlurhashProps extends Omit<ViewProps, 'children'> {
/**
Expand Down Expand Up @@ -123,7 +122,10 @@ export class Blurhash extends React.PureComponent<BlurhashProps> {
if (this.props.onLoadEnd != null) this.props.onLoadEnd();
}
_onLoadError(event?: NativeSyntheticEvent<{ message?: string }>) {
if (this.props.onLoadError != null) this.props.onLoadError(event?.nativeEvent?.message);
if (this.props.onLoadError != null) {
const message = event?.nativeEvent?.message; // TODO: Not sure how to get proper value here on web
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

this.props.onLoadError(message);
}
}

render() {
Expand All @@ -132,16 +134,14 @@ export class Blurhash extends React.PureComponent<BlurhashProps> {
{...this.props}
onLoadStart={this._onLoadStart}
onLoadEnd={this._onLoadEnd}
// @ts-expect-error
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was giving me a build error

onLoadError={this._onLoadError}
/>
);
}
}

// requireNativeComponent automatically resolves 'BlurhashView' to 'BlurhashViewManager'
const NativeBlurhashView = requireNativeComponent<BlurhashProps>(
'BlurhashView',
// @ts-expect-error this second argument is still not public, but probably required for TurboModules.
Blurhash,
);
const NativeBlurhashView = Platform.OS === 'web' ? require('./web/blurhashView').default : requireNativeComponent<BlurhashProps>(
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried a couple iterations of this.

Setting NativeBlurhashView as a let then assigning within an if statement, caused issues with Typescript. Didn't like that it was unset for a short period.

Using Platform.select still caused reuireNativeComponent to be called on web. In react-native, irrelevant Platform.select branches are removed at build time - doesn't look like that happens with react-native-web, unfortunately.

'BlurhashView',
// @ts-expect-error this second argument is still not public, but probably required for TurboModules.
Blurhash,
);
41 changes: 41 additions & 0 deletions src/web/blurhashView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React, { useEffect, useState } from 'react';
import { View } from 'react-native';
import BlurhashCanvas from './canvas';
import type { BlurhashProps } from '../index';
import { decode } from 'blurhash';

interface BlurhashViewProps extends BlurhashProps {
}

export default function BlurhashView ({
blurhash,
decodeHeight = 128,
decodePunch,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to test and ensure punch is implemented properly.

decodeWidth = 128,
onLoadStart = () => null,
onLoadEnd = () => null,
onLoadError = () => null,
style,
...rest
}: BlurhashViewProps) {
const [decodedBlurhash, setDecodedBlurhash] = useState<null | Uint8ClampedArray>(null);
useEffect(() => {
try {
onLoadStart();
setDecodedBlurhash(decode(blurhash, decodeWidth, decodeHeight, decodePunch));
} catch (e) {
onLoadError(e);
}
}, [blurhash]);

return (
<View style={style}>
{decodedBlurhash ? <BlurhashCanvas
decodedBlurhash={decodedBlurhash}
height={decodeHeight}
onLoadEnd={onLoadEnd}
width={decodeWidth}
/> : null}
</View>
);
};
30 changes: 30 additions & 0 deletions src/web/canvas.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { useCallback } from 'react';

export type Props = React.CanvasHTMLAttributes<HTMLCanvasElement> & {
getContext?: Function;
decodedBlurhash: Uint8ClampedArray;
height?: number;
onLoadEnd: Function;
punch?: number;
width?: number;
};

export default function BlurhashCanvas ({
// TODO: See how canvas handles unset width/height
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// TODO: See how canvas handles unset width/height

decodedBlurhash,
height = 128,
onLoadEnd,
width = 128,
...rest
}: Props) {
const canvasRef = useCallback((canvas: Props) => {
if (!canvas) return;
const ctx = canvas.getContext && canvas.getContext('2d');
const imageData = ctx.createImageData(width, height);
imageData.data.set(decodedBlurhash);
ctx.putImageData(imageData, 0, 0);
onLoadEnd();
}, [decodedBlurhash]);

return <canvas {...rest} height={height} width={width} ref={canvasRef} />
};