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

feat: 글 신고 && 사용자 차단 팝업 UI 구현 #100

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import AppLoading from 'expo-app-loading';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { NavigationContainer } from '@react-navigation/native';
import { MenuProvider } from 'react-native-popup-menu';
import useWhaledoneFonts from './infrastructures/hooks/useWhaledoneFonts';
import Screens from './presentation/screens';

Expand All @@ -15,7 +16,9 @@ export default function App() {
return (
<SafeAreaProvider>
<NavigationContainer>
<Screens />
<MenuProvider>
<Screens />
</MenuProvider>
</NavigationContainer>
</SafeAreaProvider>
);
Expand Down
Binary file added assets/ic-more.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/ic-moreBtn-line.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10,134 changes: 10,134 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,15 @@
"react-native-elements": "^3.4.2",
"react-native-gesture-handler": "~2.1.0",
"react-native-maps": "^0.30.1",
"react-native-modal": "^13.0.1",
"react-native-pages": "0.9.0",
"react-native-popup-menu": "^0.15.12",
"react-native-reanimated": "~2.1.0",
"react-native-safe-area-context": "3.2.0",
"react-native-screens": "~3.0.0",
"react-native-snap-carousel": "^3.9.1",
"react-native-svg": "12.3.0",
"react-native-walkthrough-tooltip": "^1.4.0",
"react-native-web": "0.17.1",
"react-native-webview": "11.17.2",
"styled-components": "5.3.3"
Expand Down
229 changes: 201 additions & 28 deletions presentation/components/FeedItem.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,38 @@
import React, { useRef, useState } from 'react';
import { Image, Pressable, StyleSheet, Text, View } from 'react-native';
import {
Image,
Pressable,
StyleSheet,
Text,
View,
TouchableOpacity,
Alert
} from 'react-native';
import {
Menu,
MenuOptions,
MenuOption,
MenuTrigger,
} from 'react-native-popup-menu';
import Modal from 'react-native-modal';
import Tooltip from 'react-native-walkthrough-tooltip';
import { api } from '../../infrastructures/api';
import { Feed, reactionToIcon } from '../../infrastructures/types/feed';
import COLORS from '../styles/colors';

const ImageEmptyProfile = require('../../assets/image-profile-empty.png');
const IcEditBlack = require('../../assets/ic-edit-black.png');
const IcDeleteRed = require('../../assets/ic-delete-red.png');
const IcMore = require('../../assets/ic-more.png');
const IcLine = require('../../assets/ic-moreBtn-line.png');

const modalButtonStyle = {
width: 139,
height: 50,
borderRadius: 5,
justifyContent: 'center',
alignItems: 'center',
};

const styles = StyleSheet.create({
profileImage: {
Expand Down Expand Up @@ -65,11 +91,23 @@ const styles = StyleSheet.create({
borderWidth: 1,
borderColor: COLORS.GREY_030,
},
feedReactions: {
iconsWrap: {
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: 10,
paddingHorizontal: 20,
},
feedReactions: {
flexDirection: 'row',
},
feedMoreButton: {
flexDirection: 'row',
},
moreIcon: {
width: 16,
height: 16,
marginVertical: 8,
},
reactionBox: {
flexDirection: 'row',
marginRight: 10,
Expand All @@ -95,6 +133,43 @@ const styles = StyleSheet.create({
color: 'black',
paddingHorizontal: 20,
},
modalContainer: {
width: 327,
height: 194,
backgroundColor: '#ffffff',
borderRadius: 10,
padding: 20,
justifyContent: 'space-between',
position: 'absolute',
},
modalTitleText: {
fontFamily: 'Pretendard-Bold',
fontSize: 20,
},
modalContentText: {
fontFamily: 'Pretendard',
fontSize: 14,
color: COLORS.TEXT_SECONDARY,
lineHeight: 25,
},
modalButtonWrap: {
flexDirection: 'row',
},
modalWithdrawButton: {
...modalButtonStyle,
// backgroundColor: 'yellow',
marginRight: 9,
borderWidth: 1,
borderColor: COLORS.TEXT_DISABLED_GREY,
},
modalActiveButton: {
...modalButtonStyle,
backgroundColor: COLORS.THEME_NEGATIVE,
},
modalButtonText: {
fontFamily: 'Pretendard',
fontSize: 16,
},
});

function FeedItem({
Expand Down Expand Up @@ -123,6 +198,11 @@ function FeedItem({
const [positionY, setPositionY] = useState<number | undefined>(undefined);
const [height, setHeight] = useState<number | undefined>(undefined);
const [editVisible, setEditVisible] = useState(false);
const [modalVisible, setModalVisible] = useState<boolean>(false);
const [modalValue, setModalValue] = useState<string>('');
const [modalContent, setModalContent] = useState('');
const [isReported, setIsReported] = useState<boolean>(false);

const feedViewRef = useRef<View>(null);
const onBubbleClicked = () => {
setSelectedFeedID();
Expand All @@ -148,6 +228,37 @@ function FeedItem({
});
};

const onMorePressed = (value: string) => {
setModalVisible(true);
setModalValue(value);
if (value === '신고하기') {
setModalContent(
'상대방이 업로드한 모든 게시글이 삭제돼요. 신고 후에는 취소할 수 없으니 신중히 사용해 주세요.',
);
} else {
setModalContent(
'이제 상대방과 더 이상 소통하지 않아요. 차단 후에는 취소할 수 없으니 신중히 사용해 주세요.',
);
}
};

const onActivePressed = () => {
setIsReported(!isReported);
setModalVisible(false);
Alert.alert(
'⚠ 신고 접수 안내',
'서비스 운영정책 위반으로 소통이 임시 제한되었어요. 임시조치 기간동안 다른 서비스는 이용 가능하나 소통 공유는 불가하며 탈퇴에 제한이 있어요.',
[
{
text: '확인',
// onPress: () => console.log("글이 안보임"),
style: 'cancel',
},
],
{ cancelable: false },
);
};

return (
<View
style={[styles.feed, isMine ? styles.myFeed : styles.familyFeed]}
Expand Down Expand Up @@ -180,35 +291,97 @@ function FeedItem({
onPress={onBubbleClicked}
onLongPress={onBubbleLongPressed}
>
<Text style={styles.titleText}>{feed.title}</Text>
{feed.type === 'TEXT' && (
<Text style={styles.bodyText}>{feed.body}</Text>
{isReported && (
<Text
style={{ color: COLORS.TEXT_DISABLED_GREY, textAlign: 'center' }}
>
신고 접수로 잠시 제한된 글입니다.
</Text>
)}
{feed.type === 'IMAGE' && (
<View style={{ paddingHorizontal: 24 }}>
<Image
source={{ uri: feed.body }}
style={{
width: '100%',
height: 332,
marginTop: 16,
borderRadius: 5,
alignSelf: 'center',
}}
/>
{!isReported && (
<View>
<Text style={styles.titleText}>{feed.title}</Text>
{feed.type === 'TEXT' && (
<Text style={styles.bodyText}>{feed.body}</Text>
)}
{feed.type === 'IMAGE' && (
<View style={{ paddingHorizontal: 24 }}>
<Image
source={{ uri: feed.body }}
style={{
width: '100%',
height: 332,
marginTop: 16,
borderRadius: 5,
alignSelf: 'center',
}}
/>
</View>
)}
<View style={styles.iconsWrap}>
<View style={styles.feedReactions}>
{feed.reactions.map((reaction) => (
<Pressable key={reaction.type} style={styles.reactionBox}>
<Image
source={reactionToIcon[reaction.type]}
style={styles.reactionIcon}
/>
<Text style={styles.reactionCount}>{reaction.count}</Text>
</Pressable>
))}
</View>
<Modal
// isVisible Props에 State 값을 물려주어 On/off control
isVisible={modalVisible}
// 아이폰에서 모달창 동작시 깜박임 해결
useNativeDriver
hideModalContentWhileAnimating
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}
>
<View style={styles.modalContainer}>
<Text style={styles.modalTitleText}>{modalValue}</Text>
<Text style={styles.modalContentText}>{modalContent}</Text>
<View style={styles.modalButtonWrap}>
<Pressable onPress={() => setModalVisible(false)}>
<View style={styles.modalWithdrawButton}>
<Text style={styles.modalButtonText}>취소하기</Text>
</View>
</Pressable>
<Pressable onPress={onActivePressed}>
<View style={styles.modalActiveButton}>
<Text
style={[styles.modalButtonText, { color: 'white' }]}
>
{modalValue}
</Text>
</View>
</Pressable>
</View>
</View>
</Modal>
<Menu onSelect={onMorePressed}>
<MenuTrigger>
<Image source={IcMore} style={styles.moreIcon} />
</MenuTrigger>
<MenuOptions style={{ padding: 10 }}>
<MenuOption value="신고하기" text="글 신고하기" />
<MenuOption value={2} disableTouchable>
<Image
source={IcLine}
style={{ width: 168, height: 1, alignItems: 'center' }}
/>
</MenuOption>
<MenuOption value="차단하기" text="사용자 차단하기" />
</MenuOptions>
</Menu>
</View>
</View>
)}
<View style={styles.feedReactions}>
{feed.reactions.map((reaction) => (
<Pressable key={reaction.type} style={styles.reactionBox}>
<Image
source={reactionToIcon[reaction.type]}
style={styles.reactionIcon}
/>
<Text style={styles.reactionCount}>{reaction.count}</Text>
</Pressable>
))}
</View>

{isMine && editVisible && (
<View
style={{
Expand Down
35 changes: 34 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5772,7 +5772,7 @@ prompts@^2.4.0:
kleur "^3.0.3"
sisteransi "^1.0.5"

prop-types@^15.5.10, prop-types@^15.5.9, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.7.2:
prop-types@^15.5.10, prop-types@^15.5.9, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
Expand Down Expand Up @@ -5844,6 +5844,11 @@ [email protected]:
object-assign "^4.1.1"
scheduler "^0.20.1"

react-fast-compare@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==

react-is@^16.13.0, react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
Expand All @@ -5854,6 +5859,13 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==

[email protected]:
version "1.3.3"
resolved "https://registry.yarnpkg.com/react-native-animatable/-/react-native-animatable-1.3.3.tgz#a13a4af8258e3bb14d0a9d839917e9bb9274ec8a"
integrity sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==
dependencies:
prop-types "^15.7.2"

react-native-codegen@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.0.6.tgz#b3173faa879cf71bfade8d030f9c4698388f6909"
Expand Down Expand Up @@ -5902,13 +5914,26 @@ react-native-maps@^0.30.1:
dependencies:
"@types/geojson" "^7946.0.7"

react-native-modal@^13.0.1:
version "13.0.1"
resolved "https://registry.yarnpkg.com/react-native-modal/-/react-native-modal-13.0.1.tgz#691f1e646abb96fa82c1788bf18a16d585da37cd"
integrity sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw==
dependencies:
prop-types "^15.6.2"
react-native-animatable "1.3.3"

[email protected]:
version "0.9.0"
resolved "https://registry.yarnpkg.com/react-native-pages/-/react-native-pages-0.9.0.tgz#1e673eda2e8b64419e69a3dd6688ba4ca3255689"
integrity sha512-ea1VNr3KMO4BS2Rpu8T710QbIq16g1sM+ET9IGt559AIHFhqCKB7TeKwyagCA8v5swSpQLWNpTJxp/JB+4mDFQ==
dependencies:
prop-types "^15.5.9"

react-native-popup-menu@^0.15.12:
version "0.15.12"
resolved "https://registry.yarnpkg.com/react-native-popup-menu/-/react-native-popup-menu-0.15.12.tgz#386852f4245f8d661a5003776989b9b55c9ce381"
integrity sha512-33zMqHW+7rt5m2Bgg7xM8jy1guIdUCE8qJfznYYNRlIt4+fJX/rDcwmJIrkSGrvfhlhhEaG3otW6h25uFZLFfg==

[email protected]:
version "8.0.4"
resolved "https://registry.yarnpkg.com/react-native-ratings/-/react-native-ratings-8.0.4.tgz#efd5ebad8acc08bf98d34d39b18fb7a6813ef991"
Expand Down Expand Up @@ -5957,6 +5982,14 @@ [email protected]:
css-select "^4.2.1"
css-tree "^1.0.0-alpha.39"

react-native-walkthrough-tooltip@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/react-native-walkthrough-tooltip/-/react-native-walkthrough-tooltip-1.4.0.tgz#5b6f5c3255cb4415dd40e37073c5c231dfb772b6"
integrity sha512-nyBuynmCuzPKJN9NRGhSzCutGOk7/WqszGtX01gjDtlRfoJ25cSM0h+TEi/lsLbSCTEdB+e65qOTvoVhIq2gzA==
dependencies:
prop-types "^15.6.1"
react-fast-compare "^2.0.4"

[email protected]:
version "0.17.1"
resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.17.1.tgz#90d473c89dd99b88bc9830b2a9fcdd2fc5f04902"
Expand Down