728x90
반응형

좌우, 상하의 스크롤시에 해당 스와이프 유무를 체크하기 위한 훅

 

import { Dimensions } from 'react-native';
const windowWidth = Dimensions.get('window').width;

export function useSwipe(
onSwipeLeft?: any,
onSwipeRight?: any,
rangeOffset = 4,
) {
let firstTouch = 0;

function onTouchStart(e: any) {
firstTouch = e.nativeEvent.pageX;
}

function onTouchEnd(e: any) {
const positionX = e.nativeEvent.pageX;
const range = windowWidth / rangeOffset;

if (positionX - firstTouch > range) {
onSwipeRight && onSwipeRight();
} else if (firstTouch - positionX > range) {
onSwipeLeft && onSwipeLeft();
}
}

return { onTouchStart, onTouchEnd };
}

사용은

 

export const IntroModal = ({ isVisible, onClose }: IntroModalProps) => {
const { onTouchStart, onTouchEnd } = useSwipe(onSwipeLeft, onSwipeRight, 15);

function onSwipeLeft() {
console.log('IntroModal SWIPE_LEFT');
onClose();
}

function onSwipeRight() {
console.log('IntroModal SWIPE_RIGHT');
}

return (
<Modal
isVisible={isVisible}
animationIn={'slideInLeft'}
animationOut={'slideOutLeft'}
style={styles.modal}
>
<ScrollView
onTouchStart={onTouchStart}
onTouchCancel={onTouchEnd}
onTouchEnd={onTouchEnd}
style={{ flex: 1, backgroundColor: 'blue' }}
pagingEnabled
>
<View
style={{
backgroundColor: 'blue',
flex: 1,
width: deviceWidth,
height: deviceHeight,
}}
></View>
<View
style={{
backgroundColor: 'red',
flex: 1,
width: deviceWidth,
height: deviceHeight,
}}
></View>
<View
style={{
backgroundColor: 'yellow',
flex: 1,
width: deviceWidth,
height: deviceHeight,
}}
></View>
</ScrollView>
</Modal>
);
};

이런식으로하면 된다.

 

ScrollView pagingEabled 에서 상하를 판독하고,

 

hook에서 좌우를 판독함

 

onTouchEnd 에서 가끔 failed 가 뜨기에

 

onTouchCancel에 도 넣어주니 정상 작동한다.

728x90
반응형
728x90
반응형

Flash list 를 사용해보기위해, 

 

yarn add @shopify/flash-list

 

로 설치를 하고, 안드로이드로 빌드해보니

 

A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
   > Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in modules jetified-kotlin-stdlib-1.8.10

 

이런 에러가 떴다.

 

app/build.gradle 에

 

 implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))

 

를 추가해주니 해결되었다.

728x90
반응형
728x90
반응형

Flatlist 

<FlatList
data={data.data}
keyExtractor={keyExtractor}
renderItem={renderItem}
getItemLayout={getItemLayout}
initialNumToRender={3}
onEndReached={paginationLive}
removeClippedSubviews={true}
maxToRenderPerBatch={30}
refreshing={isRefreshing}
onRefresh={onRefresh}
style={{ width: '100%', height: '100%' }}
/>

랜더링을 최소한으로 하고,

import pure from 'recompose/pure';

라이브러리를 통해 renderItem을 pureComponent로 작성해주었다.

728x90
반응형
728x90
반응형

작업을 하다보니, 구형 모델의 안드로이드 기기에서 특정 화면에서 앱이 꺼지는 것을 확인했다.

 

다른 화면을 들렀다가 오면 앱이 내려가지 않는 것을 확인하고

 

안드로이드 메모리 문제라고 생각했다. 

 

안드로이드 스튜디오를 켜서 로그캣을 돌려본 결과

 

renderThread 가 죽는 것을 발견하고, 메모리 문제가 맞다는 결론을 내렸다.

 

해당 에러는 

이것이었고, 

 

manifest 파일에 

 

<application
        android:hardwareAccelerated="false"

 

를 추가해주며 해결했다.

728x90
반응형
728x90
반응형

현재 회사에서 개발하고 있는 앱/컨트롤 패널에서 hdmi 선을 통해 화면을 띄울일이 있었다.

 

화면 미러링을 하면, 조작하고 있는 화면이 모두 나오기 때문에, 

 

react-native-external-display

 

라이브러리를 통해 외부 display에 연결하였다.

 

라이브러리 자체가 사용하기 편하고,

 

screen을 배엷 값으로 받기때문에, 해당 디스플레이의 키값만 넣어주면 된다

 

https://drive.google.com/file/d/1dbxzHbQktO_XZJsdxGfGg-QRBdgdZLm6/view?usp=sharing

728x90
반응형
728x90
반응형

기존 사용하고 있는 라이브러리중에, 포크를 딸만큼은 아니지만, 패키지가 수정되어야 할 부분이 존재했다.

 

android compile 이 deprecated 되고, implementation 으로 변경되었기 때문에, 간단히 patch-package 를 해주기로했다.

 

일단 package.json 에

 

postinstall : patch-package 를 적용해주었다.

 

yarn과 npm 후(post)에 실행해주는 명령어이다.

 

그뒤

 

yarn add patch-package

로 patch-package 를 세팅해준다.

 

후, 원하는 패키지의 코드를 변경해준다.

 

compile "com.facebook.react:react-native:+"

implementation "com.facebook.react:react-native:+"

로 변경

npx patch-package "모듈이름"

을 통해 patch파일을 생성해준다.

 

내가 수정한 모듈이름은 react-native-orientation이었다. 따라서 나는

 

npx patch-package react-native-orientation 을통해 패치파일들을 생성해주었다.

 

패치 파일이 생긴걸 확인

 

rm -rf node_modules

를 통해 node_modules를 제거하고 다시

 

yarn을 통해 깔아보면 patch가 반영되는것으로 확인 된다.

728x90
반응형
728x90
반응형
import {Stomp} from '@stomp/stompjs';
import {useCallback, useEffect} from 'react';
import SockJS from 'sockjs-client';
import {stompClient} from '../../App';
import Config from '../config';
import showSlice from '../reudx/slices/show';
import {useAppDispatch} from '../reudx/store';
import NetInfo, {useNetInfo} from '@react-native-community/netinfo';

export const useSocket = () => {
console.log('::::::: useSocket render ::::::::');

const dispatch = useAppDispatch();

const initSocket = useCallback(() => {
console.log('::::::: init socket ::::::::');
stompClient.current = Stomp.over(function () {
return new SockJS(Config.SOCKET_URL);
});
// stompClient.client.appendMissingNULLonIncoming = true;
// stompClient.client.forceBinaryWSFrames = true;
}, []);

const disconnectHandler = useCallback(() => {
console.log('::::::: disconnectHandler :::::::');
stompClient.current.disconnect();
}, []);

const connectHandler = useCallback(() => {
console.log('::::::: connectHandler :::::::');
stompClient.current.connect(
{},
() => {
//connect
console.log('open');
dispatch(showSlice.actions.setSocketConnected(true));
},
() => {
//error
console.log('error');
dispatch(showSlice.actions.setSocketConnected(false));
},
() => {
//close
console.log('close');
dispatch(showSlice.actions.setSocketConnected(false));
},
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
let beforeState: boolean | null = true;
const unsubscribe = NetInfo.addEventListener(state => {
console.log(' ::::::::::::::::::::::::::::: ');
console.log('Connection type', state.type);
console.log('Is connected?', state.isConnected);
// dispatch(showSlice.actions.setIpAddress(state?.details?.ipAddress));

if (beforeState !== state.isConnected) {
console.log(
'network changed ::::::::::::::::::::: to ' + state.isConnected,
);

// todo 네트워크 재연결 뒤에 소켓 연결할지
// if (state.isConnected) {
// initSocket();
// connectHandler();
// }
}
beforeState = state.isConnected;
});

// Unsubscribe
return () => unsubscribe();
}, []);

useEffect(() => {
let beforeState:
| SockJS.CONNECTING
| SockJS.OPEN
| SockJS.CLOSING
| SockJS.CLOSED;

let timer = setInterval(() => {
// console.log('stompClient.current.state :::' + stompClient.current.state);
if (beforeState !== stompClient.current.state) {
console.log('changed :::::::::' + stompClient.current.state);
if (
stompClient.current.state === SockJS.OPEN ||
stompClient.current.state === SockJS.CONNECTING
) {
console.log('socket Connected::: true');
// dispatch(showSlice.actions.setSocketConnected(true));
} else {
console.log('socket Connected::: false');
// dispatch(showSlice.actions.setSocketConnected(false));
connectHandler();
}
}
beforeState = stompClient.current.state;
}, 1000);

return () => clearInterval(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return {connectHandler, disconnectHandler, initSocket};
};

 

initSocket()

connectHandler()

로 필요한곳에서 사용하면 된다.

728x90
반응형
728x90
반응형

rtmp로 영상을 전송하는 중에, 컨트롤러에서 카메라의 노출값을 조절할 일이 생겼다.

 

기존 사용하고있는 react-native-nodemediaclient

 

에는 카메라관련 세팅이 너무 미흡하기에, 

 

react-native-vision-camera 에 있는

useFrameProcessor

를 사용하여 만들기로 결정했다.

 

frame-processor/unavailable: Frame Processors are not enabled

 

일단 해당 에러는 

 

react-native-worklets-core 를 설치하고

react-native-reanimated 를 사용하면서 해결하였다.

728x90
반응형
728x90
반응형

./gradlew assembleRelase 로 해당 에러가나서 검색해보니

 

./graldew app:assembleRelease 로 해결했다는 글을 찾았다.

 

해당 명령어로 빌드하니 성공.

728x90
반응형
728x90
반응형

앱 아이콘 제네레이터에서 앱아이콘을 png 형태로 받아서 그냥 사용했더니

 

AAPT: error: failed to read PNG signature: file does not start with PNG signature.

 

해당 에러가 나왔다.

 

png 형태를 jpg로 강제변환해주고

 

jpg2png 사이트에서 한번도 저장하니 정상작동했다.

728x90
반응형

+ Recent posts