๋๋ฐ์ด์ค์ ๋ฐ๋ผ ํฐํธ ์ฌ์ด์ฆ๊ฐ ๋ณ๋๋์ง ์๋๋ก ์ค์
Text.defaultProps = Text.defaultProps || {};
Text.defaultProps.allowFontScaling = false;
ํฐํธ ๋ก๋ & ํธ์ ์๋์ ๋ค ๋น๋๊ธฐ๋ก ๋์
async function registerForPushNotification() {
let token;
if (Constants.isDevice) {
const { status: existingStatus } =
await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== "granted") {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== "granted") {
alert("Failed to get push token for push notification!");
return;
}
token = (await Notifications.getExpoPushTokenAsync()).data;
console.log(token);
} else {
alert("Must use physical device for Push Notifications");
}
์ค์ ๋๋ฐ์ด์ค์ธ์ง ํ์ธ -> ํ์ฌ ๊ถํ์ด ์๋์ง ํ์ธ -> ์์ผ๋ฉด ๊ถํ ์์ฒญ -> ์ต์ข ๊ถํ ํ์ธ
์คํ ๋ก์ง
ํฐํธ๊ฐ ๋ค ๋ก๋๋์๊ณ , ์ ์ ์ ๋ณด ๋ก๋ฉ์ด ๋๋๋ฉด ์ ์ ์ ๋ณด ์ฒดํฌ
-> ์ ์ ๊ฐ ์์ผ๋ฉด MainScreenF.js๋ก ๋ฐ๋ก ๋์ด๊ฐ / ์ ์ ๊ฐ ์์ผ๋ฉด Registration.js๋ก ๋์ด๊ฐ
์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ๋ก ๊ฐ์
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then((response) => {
const uid = response.user.uid;
const data = {
email,
fullName,
picture,
url,
myCourses,
};
์ ์ ๋ฐ์ดํฐ ์์ฑ
์ด๋ฉ์ผ, ์ฑ๋ช , ํ๋กํ ์ด๋ฏธ์ง ์ฌ๋ถ, ํ๋กํ ์ด๋ฏธ์ง ์ฃผ์, ๋์ ์๊ฐ๋ชฉ๋ก
const usersRef = firebase.firestore().collection("users");
usersRef
.doc(email)
.set(data)
.then(() => {
setReRendering(isReRendering + 1);
})
.catch((error) => {
console.error("Error: ", error);
});
์ปค๋ฎค๋ํฐ ์ฆ๊ฒจ์ฐพ๊ธฐ
const favoritesRef = firebase.firestore().collection("favorites");
favoritesRef.doc(email).set(
{
selectedItemsArray: [],
},
{ merge: true }
);
allCommunities.forEach((element) => {
favoritesRef
.doc(email)
.collection("all")
.doc(element)
.set({}, { merge: true });
});
favoritesRef.doc(email).collection("selectedItems").add({});
Bottom Tab Navigator
์ ์ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
const curUserEmail = firebase.auth().currentUser.providerData[0].email;
const unsubscribe = firebase
.firestore()
.collection("users")
.doc(curUserEmail)
.onSnapshot((snapshot) => {
const getUser = snapshot.data();
setUser(getUser);
if (!getUser.myCourses.length) {
return () => {
unsubscribe();
};
}
์๊ฐ๋ชฉ๋ก ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
getUser.myCourses.forEach((course) => {
let background = randomHex();
const courseRef = firebase.firestore().collection("courses").doc(course);
courseRef.get().then((doc) => {
const getMyCourse = doc.data();
let array_of_schedules = splitSchedule(getMyCourse.schedule);
for (var i = 0; i < array_of_schedules.length; i++) {
let day = array_of_schedules[i].substr(0, 3);
let time = array_of_schedules[i].substr(4, 1);
let row = matchTime(time);
let column = matchDays(day);
if (isSelected[row][column] == "#FFFFFF") {
isSelected[row][column] = background;
courseName[row][column] = getMyCourse.name;
}
}
});
});
๋์ ์๊ฐ๋ชฉ๋ก์ ํด๋นํ๋ ๊ณผ๋ชฉ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ -> ๊ณผ๋ชฉ ์ค์ผ์ฅด ํ์ธ -> ํด๋นํ๋ ์๊ฐํ ๋ฐฐ์ด์ ๋ฐฐ๊ฒฝ์ & ๊ณผ๋ชฉ๋ช ์ง์
Stack Navigator
Stack Navigator
์ฆ๊ฒจ์ฐพ๊ธฐ์ ์ถ๊ฐ๋ ์ปค๋ฎค๋ํฐ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
const getSelectedItems = firebase
.firestore()
.collection("favorites")
.doc(curUserEmail)
.collection("selectedItems")
.orderBy("createdAt", "desc")
.onSnapshot((querySnapshot) => {
const selectedItems = querySnapshot.docs.map((docSnapshot) => {
const selectedItem = {
_id: docSnapshot.id,
...docSnapshot.data(),
};
return selectedItem;
});
setSelectedItems(selectedItems);
});
์ฆ๊ฒจ์ฐพ๊ธฐ์ ๊ด๋ จ๋ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
์ฆ๊ฒจ์ฐพ๊ธฐ์ ์ถ๊ฐํ ์ปค๋ฎค๋ํฐ ์ ํ
const pick = (community) => {
let tempSelectedItems = selectedItemsArray;
const index = tempSelectedItems.indexOf(community._id);
if (index > -1) {
tempSelectedItems.splice(index, 1);
} else {
tempSelectedItems.push(community._id);
}
setSelectedItemsArray(tempSelectedItems);
setReRendering(isReRendering + 1);
};
์ด๋ฏธ ์ฒดํฌ๋์ด ์๋ค๋ฉด ํด์ / ์ฒดํฌํ์ง ์์๋ค๋ฉด ์ฒดํฌ
{
selectedItemsArray.includes(item._id) ? (
<MaterialIcons
name="check-box"
size={24}
color="black"
style={style.communityIcon}
/>
) : (
<MaterialIcons
name="check-box-outline-blank"
size={24}
color="black"
style={style.communityIcon}
/>
);
}
์ฆ๊ฒจ์ฐพ๊ธฐ์ ์ถ๊ฐ
selectedItemsArray.forEach((item) => {
selectedItemsRef
.doc(item)
.set(
{
createdAt: new Date().getTime(),
},
{ merge: true }
)
.catch(function (error) {
console.error("Error: ", error);
});
});
์ถ๊ฐํ ์๊ฐ๊ณผ ํจ๊ป DB์ ์ ๋ก๋
firebase
.firestore()
.collection("favorites")
.doc(user.email)
.set(
{
selectedItemsArray: selectedItemsArray,
},
{ merge: true }
)
.catch(function (error) {
console.error("Error: ", error);
});
Stack Navigator
์ปค๋ฎค๋ํฐ ๋ค๋น๊ฒ์ด์ ํค๋ ์ด๋ฆ ์ค์
function getHeaderTitle(route) {
const routeName = getFocusedRouteNameFromRoute(route) ?? "All";
switch (routeName) {
case "All":
return "All";
case "Info":
return "Info";
case "Campus":
return "Campus";
case "Friends":
return "Friends";
}
}
getFocusedRouteNameFromRoute(route)
๋ ํ์ฌ ํ์ฑํ๋์ด ์๋ route์ ์ด๋ฆ์ ๋ฐํ
-> ๋ง์ฝ ์ด ๊ฐ์ด null์ด๊ฑฐ๋ undefined์ด๋ฉด ์ค๋ฅธ์ชฝ ๊ฐ ๋ฐํ
๊ธ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ
const getData = db.onSnapshot((querySnapshot) => {
const writings = querySnapshot.docs.map((docSnapshot) => {
const data = {
_id: docSnapshot.id,
...docSnapshot.data(),
};
return data;
});
setWriting(writings);
});
์ค์๊ฐ์ผ๋ก ๊ฐ์ ธ์ค๊ธฐ ์ํด onSnapshot
์ฌ์ฉ
๊ธ ๋ชฉ๋ก ๋ณด์ฌ์ฃผ๊ธฐ
<ScrollView style={style.container}>
{writing.map((writing) => (
<TouchableOpacity
onPress={() => {
navigation.push("See", {
extraData: user,
data: writing,
listName: listName,
});
}}
key={writing._id}
>
<Card style={style.box}>
๋ฐ์ดํฐ๋ฅผ mapping ํด์ ์คํฌ๋กค๋ทฐ์์ ๋ณด์ฌ์ค
ํค๋ ์ค์
useLayoutEffect
: ๋ ๋๋ง ํ ํ๋ฉด์ด ์
๋ฐ์ดํธ ๋๊ธฐ ์ ์ ๋๊ธฐ์ ์ผ๋ก ์คํ(cf. useEffect
๋ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ)
๊ธ ์์ฑ
const onSubmit = async (event) => {
firebase
.firestore()
.collection(listName)
.doc(title)
.set({
_id: Math.random().toString(36).slice(2),
title: title,
content: content,
creator: user,
createdAt: Date.now(),
like: [],
comments: [],
})
.then(() => {
navigation.goBack();
});
setTitle("");
setContent("");
};
๊ฒ์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
const fetchWriting = () => {
if (writing) {
setWriting([]);
}
listRf
.where("title", "<=", search)
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
const data = doc.data();
setWriting((prev) => [data, ...prev]);
});
});
setisSearch(false);
};
๊ฒ์ ๋ฒํผ ์ด๋ฒคํธ
<Right>
<TouchableOpacity
onPress={() => {
fetchWriting();
setisSearch(true);
}}
>
<Feather name="search" size={30} />
</TouchableOpacity>
</Right>
};
isSearch
๊ฐ์ด true ์ด๋ฉด ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ๋ณด์ฌ์ง๋ค.
์ข์์ ํด๋ฆญ
๋๊ธ ์์ฑ
๊ธ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ
function getData() {
const dbCom = firebase.firestore().collection(listName).doc(writing.title);
dbCom.onSnapshot((doc) => {
if (doc.data() !== undefined) {
const data = doc.data().comments;
setAllComment(data);
const likeList = doc.data().like;
setCurrentLike(likeList);
}
});
}
๊ธ์ ์ญ์ ํ๊ณ ๋ ํ์๋ doc.data()
๊ฐ undefined๊ฐ ๋๋ฏ๋ก if๋ฌธ์ ์ถ๊ฐํ์๋ค.
๊ธ ์์
const reWritingUpdate = () => {
firebase
.firestore()
.collection(listName)
.doc(writing.title)
.get()
.then((doc) => {
firebase.firestore().collection(listName).doc(reTitle).set(
{
title: reTitle,
content: reContent,
comments: doc.data().comments,
createdAt: doc.data().createdAt,
creator: doc.data().creator,
like: doc.data().like,
},
{ merge: true }
);
});
firebase.firestore().collection(listName).doc(writing.title).delete();
setReModal(false);
setModalVisible(false);
navigation.goBack();
};
๊ธ ์ ๋ชฉ์ด ๋ฐ๋๋ฏ๋ก ์๋ ์กด์ฌํ๋ doc์ ์ง์์ฃผ๊ณ ์๋ก์ด doc์ ์์ฑํ์ฌ์ผ ํ๋ค.
<Modal>
์์ <Modal>
์ ๋ ๋ฃ์ด์ค์ ๊ธ์ ์์ ํ ๋๋ง ํ์
์ฐฝ์ด ๋ณด์ด๋๋ก ํ์๋ค.
๊ธ/๋๊ธ ์ญ์
onPress: () => {
firebase
.firestore()
.collection(listName)
.doc(writing.title)
.update({
comments: firebase.firestore.FieldValue.arrayRemove(comment),
});
},
๋๊ธ ์ญ์ ์, Firebase ๋ฐฐ์ด ์์ ์ ๋ฐ์ดํธ ์ฐธ๊ณ
๊ธ ์์ฑ์์ ์ฑํ ์์
๋ง์ฝ ๊ธฐ์กด ์ฑํ ๋ฐฉ์ด ์กด์ฌํ์ง ์๋๋ค๋ฉด ์๋ก์ด ์ฑํ ๋ฐฉ ์์ฑ
if (
Object.keys(thread).length === 0 &&
thread.constructor === Object
) {
thread = {
latestMessage: {
text: "",
createdAt: new Date().getTime(),
},
name: commentAuthor.fullName,
target: {
email: commentAuthor.email,
},
user: user,
};
firebase
.firestore()
.collection("chat")
.doc(commentAuthor.email)
.set(thread, { merge: true });
firebase
.firestore()
.collection("chat")
.doc(commentAuthor.email)
.collection("messages")
.add({
text: "Your chat room has been created.",
createdAt: new Date().getTime(),
system: true,
});
Stack Navigator
์ ์ฒด ๊ฐ์ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ
setCourses(array)
๋ด๊ฐ ์๊ฐํ๋ ๊ฐ์ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ
setMyCourses(getUser.myCourses)
๊ฐ์ ์ญ์
const handleClickCourse = (courseName, row, col) => {
Alert.alert("Do you want to remove this course?", courseName, [
{
text: "No",
onPress: () => console.log("No"),
},
{
text: "Yes",
onPress: () => {
console.log("Yes");
removeBackground(isSelected[row][col]);
let selected_code = getCourseCode(courseName);
update_array = myCourses.filter(
(element) => element !== selected_code
);
userRef
.set(
{
myCourses: update_array,
},
{ merge: true }
)
.catch(function (error) {
console.error("Error: ", error);
});
},
style: "destructive",
},
]);
};
filter()
๋ฉ์๋๋ ์ฃผ์ด์ง ํจ์์ ํ
์คํธ๋ฅผ ํต๊ณผํ๋ ๋ชจ๋ ์์๋ฅผ ๋ชจ์ ์๋ก์ด ๋ฐฐ์ด๋ก ๋ฐํํ๋ค.
์๊ฐํ ํ ์์ฑ
<View>
ํ๊ทธ๋ก ํ
์ด๋ธ์ ๋ง๋ค์๋ค.
์ ์ฒด ๊ฐ์ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ
setCourses(array)
๋ด๊ฐ ์๊ฐํ๋ ๊ฐ์ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ
setMyCourses(getUser.myCourses)
๊ฐ์ ์ถ๊ฐ
const handlePickCourse = (schedule, code, name) => {
console.log("handling");
let array_of_schedules = splitSchedule(schedule);
setBackground(randomHex());
for (var i = 0; i < array_of_schedules.length; i++) {
let day = array_of_schedules[i].substr(0, 3);
let time = array_of_schedules[i].substr(4, 1);
if (isSelected[matchTime(time)][matchDays(day)] != "#FFFFFF") {
Alert.alert("Duplicate Entry");
return;
}
isSelected[matchTime(time)][matchDays(day)] = background;
courseName[matchTime(time)][matchDays(day)] = name;
}
let update_array = myCourses;
update_array.push(code);
userRef
.set(
{
myCourses: update_array,
},
{ merge: true }
)
.catch(function (error) {
console.error("Error: ", error);
});
};
๊ฐ์ ๋ชฉ๋ก ๋ณด์ฌ์ฃผ๊ธฐ
<ScrollView>
{courses.map((course) => (
<TouchableOpacity
onPress={() =>
handlePickCourse(course.schedule, course.code, course.name)
}
key={course.code}
>
<CourseItem
name={course.name}
prof={course.prof}
schedule={course.schedule}
credits={course.credits}
code={course.code}
/>
</TouchableOpacity>
))}
</ScrollView>
courses.map()
์ ์ฌ์ฉํด์ CourseItem.js์ function์ ๋ณด์ฌ์ค๋ค.
Material Top Tab Navigator
๊ณต์ง์ฌํญ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
const unsubscribe = firebase
.firestore()
.collection("notification")
.orderBy("createdAt", "desc")
.onSnapshot((querySnapshot) => {
if (querySnapshot.size) {
const notices = querySnapshot.docs.map((docSnapshot) => {
return {
...docSnapshot.data(),
};
});
setData(notices);
} else {
console.log("No such document!");
}
});
๊ณต์ง์ฌํญ ๋งํฌ ์ฐ๊ฒฐ
const noticeClick = async (item) => {
Linking.canOpenURL(item.url).then((supported) => {
if (supported) {
Linking.openURL(item.url);
} else {
Linking.openURL(
"https://www.ajou.ac.kr/oia/notice/notice.do?mode=list&srCategoryId=108&srSearchKey=&srSearchVal="
);
}
});
๊ณต์ง์ฌํญ ๋ชฉ๋ก ๋ณด์ฌ์ฃผ๊ธฐ
return (
<View style={style.container}>
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id.toString()}
contentContainerStyle={style.list}
/>
</View>
);
const renderItem = ({ item }) => {
const isRead = item.isRead;
return (
<TouchableOpacity
style={[style.box, isRead ? style.boxRead : style.boxUnRead]}
onPress={() => noticeClick(item)}
>
<View style=>
<Text style={style.title}>{item.title}</Text>
<Text style={style.time}>{calculateTime(item.createdAt)}</Text>
</View>
<Text style={style.content}>{item.content}</Text>
</TouchableOpacity>
);
};
<FlatList>
ํ๊ทธ์ renderItem()
function์ ์ด์ฉํ๋ค.Stack Navigator
์ฑํ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ
const unsubscribe = firebase
.firestore()
.collection("chat")
.orderBy("latestMessage.createdAt", "desc")
.onSnapshot((snapshot) => {
const threads = [];
snapshot.docs.map((docSnapshot) => {
if (
docSnapshot.data().user.email == user.email ||
docSnapshot.data().target.email == user.email
) {
let thread = {
_id: docSnapshot.data().target.email,
...docSnapshot.data(),
};
threads.push(thread);
}
});
setThreads(threads);
setReRendering(isReRendering + 1);
});
setReRendering(isReRendering + 1)
์ ์คํํ๋ค.์ฑํ ๋ฐฉ์ผ๋ก ์ด๋
const moveToChat = (item) => {
navigation.navigate("Chat", { thread: item, user: user });
};
<FlatList>
๋ฅผ ์ฌ์ฉํด์ ์ฑํ
๋ชฉ๋ก์ ๋ณด์ฌ์ฃผ๊ธฐ ๋๋ฌธ์ renderItem()
์ item์ thread์ ๋ด์ ํ๋ฉด์ ์ด๋ํ๋ค.์ฑํ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
const unsubscribe = firebase
.firestore()
.collection("chat")
.doc(thread._id)
.collection("messages")
.orderBy("createdAt", "desc")
.onSnapshot((snapshot) => {
const messages = snapshot.docs.map((docSnapshot) => {
const data = {
_id: docSnapshot.id,
text: "",
createdAt: new Date().getTime(),
...docSnapshot.data(),
};
if (!docSnapshot.data().system) {
data.user = {
...docSnapshot.data().user,
name: docSnapshot.data().user.fullName,
};
}
return data;
});
setMessages(messages);
});
GiftedChat ์ด์ฉ
return (
<GiftedChat
messages={messages}
onSend={onSend}
user=
renderAvatar={null}
showAvatarForEveryMessage={true}
alwaysShowSend={true}
renderBubble={renderBubble}
/>
);
๋ฉ์์ง ๋ณด๋ด๊ธฐ
async function onSend(messages) {
const text = messages[0].text;
firebase
.firestore()
.collection("chat")
.doc(thread._id)
.collection("messages")
.add({
text,
createdAt: new Date().getTime(),
user: {
_id: user.email,
name: user.fullName,
},
});
await firebase
.firestore()
.collection("chat")
.doc(thread._id)
.set(
{
latestMessage: {
text,
createdAt: new Date().getTime(),
},
},
{ merge: true }
);
}
๋งค๊ฐ๋ณ์๋ก ๋ฐ๋ messages[0]์ text๊ฐ ๋ณด๋ด๋ ๋ฉ์์ง์ด๋ค.
Storage์์ ํ๋กํ ์ด๋ฏธ์ง ๊ฐ์ ธ์ค๊ธฐ
usersRef.get().then((doc) => {
const getuser = doc.data();
if (getuser.picture) {
setPicture(true);
const storageRef = firebase.storage().ref(`${user.email}`);
storageRef
.getDownloadURL()
.then((url) => {
setUrl(url);
})
.catch((error) => {
console.error("Error updating document: ", error);
});
}
});
Storage์ ํ๋กํ ์ด๋ฏธ์ง ์ฌ๋ฆฌ๊ธฐ
const uploadImageToStorage = async (path, imageName) => {
const response = await fetch(path);
const blob = await response.blob();
const ref = firebase.storage().ref().child(imageName);
return ref.put(blob);
};
์ด๋ฆ์ ์ต๋ช ์ผ๋ก ๋ฐ๊พธ๊ธฐ
์ด๋ฆ ๋ฐ๊พธ๊ธฐ
ํ๋กํ ์ด๋ฏธ์ง ์ด๊ธฐํ
onPress: () => {
console.log("Yes");
setPicture(false);
setUrl("");
const storageRef = firebase.storage().ref(`${user.email}`);
storageRef
.delete()
.then(() => {
console.log("Your profile has been reset");
})
.catch((error) => {
console.error("Error updating document: ", error);
});
usersRef
.set({ picture: false, url: "" }, { merge: true })
.then(() => {
console.log("Document successfully updated!");
setReRendering(isReRendering + 1);
})
.catch((error) => {
console.error("Error updating document: ", error);
});
},
profile
, url
์ด๊ธฐํ๋ก๊ทธ์์
firebase
.auth()
.signOut()
.then(() => {
console.log("Sign-out successful");
Update.reloadAsync();
})
.catch((error) => {
console.log("Error: ", error);
});
์ฑ ์ฌ์คํ