+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/final/css/.DS_Store b/final/css/.DS_Store
new file mode 100644
index 0000000..78273c7
Binary files /dev/null and b/final/css/.DS_Store differ
diff --git a/final/css/edit-profile.css b/final/css/edit-profile.css
new file mode 100644
index 0000000..b7f495b
--- /dev/null
+++ b/final/css/edit-profile.css
@@ -0,0 +1,63 @@
+.change-profile{
+ width: 100px;
+ height: 100px;
+ margin: 0 auto;
+ /* background-color:#3e2fae; */
+ background-image: url("../imgs/change-profile.png");
+ background-size: cover;
+ border-radius: 15px;
+}
+
+body{
+ background-color: #eeeeee;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+header{
+ display: none;
+}
+#profilePicInput{
+ display: none;
+}
+
+.edit{
+ padding-top: 50px;
+ width: 80vw;
+ margin: 0 auto;
+ text-align: left;
+}
+
+.edit p{
+ margin-bottom: 10px;
+ font-size: 1.2em;
+ text-align: left;
+
+}
+
+#usernameInput{
+ font-size: 1em;
+ text-indent: 10px;
+ border-radius: 10px;
+ border: 2px solid #f9d861;
+ width: 100%;
+ height: 32px;
+
+}
+#statusInput{
+ font-size: 1em;
+ text-indent: 10px;
+ border-radius: 10px;
+ border: 2px solid #f9d861;
+ width: 100%;
+ height: 32px;
+}
+
+
+#profileSaveInput{
+ font-size: 1em;
+ background-color: #f9d861;
+ width: 100%;
+ margin-top: 20px;
+ border-radius: 10px;
+ height: 36px;
+}
\ No newline at end of file
diff --git a/final/css/groupchat.css b/final/css/groupchat.css
new file mode 100644
index 0000000..305ab3b
--- /dev/null
+++ b/final/css/groupchat.css
@@ -0,0 +1,44 @@
+body{
+ background-color: #3e2fae;
+ width: 90vw;
+ height: 100vh;
+ margin: 0 auto;
+}
+
+#searchMsg{
+ width:100%;
+ text-indent: 10px;
+ height: 30px;
+ background-color: #ffffff;
+ border-radius: 10px;
+ border:2px solid #f9d861;
+ font-family: 'Josefin Sans', sans-serif;
+ margin-left: 20px;
+}
+
+.flex-box{
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+ margin-top: 5vh;
+}
+
+h2{
+ color: white;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+h4{
+ font-family: 'Josefin Sans', sans-serif;
+ color: black;
+ background-color: #f9d861;
+ border-radius: 10px;
+ padding: 10px 10px;
+}
+
+a{
+ text-decoration: none;
+}
+a:visited{
+ color: black;
+}
\ No newline at end of file
diff --git a/final/css/login.css b/final/css/login.css
new file mode 100644
index 0000000..f56fb5b
--- /dev/null
+++ b/final/css/login.css
@@ -0,0 +1,76 @@
+.logo{
+ margin: 0 auto;
+ text-align: center;
+ margin-top: 80px;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+body{
+ font-family: 'Josefin Sans', sans-serif;
+ background-color: #eee;
+}
+
+h1{
+ color: #3e2fae;
+}
+
+
+
+.edit{
+ padding-top: 50px;
+ width: 80vw;
+ margin: 0 auto;
+ text-align: left;
+}
+
+.edit p{
+ margin-bottom: 10px;
+ font-size: 1.2em;
+ text-align: left;
+
+}
+#usernameInput{
+ font-size: 1em;
+ text-indent: 10px;
+ border-radius: 10px;
+ border: 2px solid #f9d861;
+ width: 100%;
+ height: 32px;
+ font-family: 'Josefin Sans', sans-serif;
+
+}
+#emailInput{
+ font-size: 1em;
+ text-indent: 10px;
+ border-radius: 10px;
+ border: 2px solid #f9d861;
+ width: 100%;
+ height: 32px;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+#passwordInput{
+ font-size: 1em;
+ text-indent: 10px;
+ border-radius: 10px;
+ border: 2px solid #f9d861;
+ width: 100%;
+ height: 32px;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+#profileSaveInput{
+ font-size: 1em;
+ background-color: #f9d861;
+ width: 100%;
+ margin-top: 20px;
+ border-radius: 10px;
+ height: 36px;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+div .login{
+ font-size: 0.8em;
+ text-align: center;
+}
+
diff --git a/final/css/main.css b/final/css/main.css
new file mode 100755
index 0000000..b164ede
--- /dev/null
+++ b/final/css/main.css
@@ -0,0 +1,246 @@
+* {
+ box-sizing: border-box;
+}
+body {
+
+ background-color: #c4c4c4;
+ color:black;
+ width: 100vw;
+ margin: 0px;
+ padding: 0px;
+ max-height: 100vh;
+ overflow: hidden;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+a{
+ text-decoration: none;
+ color: black;
+}
+
+
+ #burger ~ nav {
+ background-color: #3e2fae;
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100px;
+ z-index: 3;
+ transition: .5s;
+ transition-delay: .01s;
+ overflow: hidden;
+ }
+
+
+nav{
+ background-color: #3e2fae;
+ display: flex;
+ justify-content: space-around;
+}
+nav a{
+ align-self: center;
+}
+nav h2{
+ margin: 0px;
+ align-self: center;
+ color: white;
+ font-size: 1.4em
+
+}
+
+
+#profilePic {
+ width: 200px;
+ height: 200px;
+ border-radius: 50%;
+ background-color: darkgray;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.pfp{
+ padding-bottom: 50px;
+}
+
+
+.Me {
+
+ color: black;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ justify-content: space-between;
+ text-align: right;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+.Me > .people{
+
+ color:black;
+ padding-right: 20px;
+ font-size: 1em;
+ margin: 0;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+
+#chatbox{
+
+ width: 100%;
+ height: 90vh;
+ overflow: auto;
+ background: #fff;
+ padding: 5vw;
+ padding-top: 110px;
+
+
+}
+
+
+
+div{
+
+ display: flex;
+ justify-content: space-between;
+ text-align: left;
+ font-family: 'Josefin Sans', sans-serif;;
+
+}
+
+div > span > h4{
+ font-size: 10px;
+ opacity: 50%;
+ margin:0;
+
+}
+
+div > span > h2{
+
+ font-family: 'Josefin Sans', sans-serif;
+ font-size: 1em;
+ margin-bottom: 4px;
+}
+div:not(.Me) > span > p{
+
+ margin-top: 5px;
+ background-color: #f9d861;
+ -webkit-border-radius: 8px;
+ -webkit-border-top-left-radius: 0;
+ -moz-border-radius: 8px;
+ -moz-border-radius-topleft: 0;
+ border-radius: 8px;
+ border-top-left-radius: 0;
+ padding-left: 15px;
+ padding-right: 15px;
+ font-size: 15px;
+ padding-top: 8px;
+ padding-bottom: 8px;
+
+}
+
+.Me > span > p{
+ margin-top: 5px;
+ text-align: left;
+ background-color:#3e2fae;
+ -webkit-border-radius: 8x;
+ -webkit-border-top-right-radius: 0;
+ -moz-border-radius: 8px;
+ -moz-border-radius-topright: 0;
+ border-radius: 8px;
+ border-top-right-radius: 0;
+ padding-left: 15px;
+ padding-right: 15px;
+ font-size: 15px;
+ padding-top: 8px;
+ padding-bottom: 8px;
+ color: #fff;
+
+}
+
+.Me > span > h2{
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+#chatinbox{
+ position: absolute;
+ width:100%;
+ height: 10%;
+ background-color: #eee;
+ padding: 20px;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+
+ }
+
+#chatinbox > #newmsg {
+ width: 88%;
+ font-size: 1em;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border:2px solid #3e2fae;
+ font-family: 'Josefin Sans', sans-serif;
+ margin-right: 10px;
+
+ }
+#newmsg {
+ background-color: white;
+ border-radius: 10px;
+ padding-right: 10px;
+
+
+}
+
+/* #sendBtn {
+ color:#3e2fae;
+ border-radius: 50%;
+ outline: none;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding-right: 2px;
+} */
+header{
+ width: 50px;
+ padding: 10px;
+ margin: 10px;
+}
+.center{
+ display: flex;
+
+ flex-direction: column;
+ padding: 0;
+
+ justify-content: center;
+ align-items: center;
+
+}
+
+.center > p{
+ background-color: #fff;
+ padding: 15px;
+ -webkit-border-radius: 20px;
+-moz-border-radius: 20px;
+border-radius: 20px;
+width: 200px;
+}
+input{
+ display: flex;
+ justify-content: center;
+ border: none;
+ width: 100%;
+ padding: 10px;
+}
+#profileSaveInput{
+ margin-top: 10px;
+ padding: 10px;
+ -webkit-border-radius: 20px;
+-moz-border-radius: 20px;
+border-radius: 20px;
+background-color: rgb(112, 112, 175);
+color: white;
+}
\ No newline at end of file
diff --git a/final/css/profile.css b/final/css/profile.css
new file mode 100755
index 0000000..6bdee79
--- /dev/null
+++ b/final/css/profile.css
@@ -0,0 +1,95 @@
+body{
+ font-family: 'Josefin Sans', sans-serif;
+ background-color: #eee;
+ width: 100vw;
+ margin: 0;
+ padding: 0;
+}
+
+header{
+ background-color: #3e2fae;
+ min-height: 45vh;
+ width: 100vw;
+ margin:0;
+ padding: 0;
+}
+header a img{
+ display: block;
+ padding-top: 5vh;
+ padding-bottom: 10px;
+ padding-left: 20px;
+ padding-right: 20px
+
+
+}
+header .profile{
+ display: block;
+ margin: 0 auto;
+ text-align: center;
+ padding-top: 20px;
+}
+header p{
+ text-align: center;
+ color: white;
+ font-family: 'Josefin Sans', sans-serif;
+ font-size: 20px;
+}
+
+.input{
+ text-align: center;
+ display: none;
+}
+
+#usernameDisplay{
+ text-align: center;
+ color: white;
+ font-size: 2em;
+ font-weight: bold;
+}
+
+#userStatusDisplay{
+ text-align: center;
+ color: white;
+ font-size: 1em;
+
+}
+
+.profile{
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+#userProfilePicDisplay{
+ width: 100px;
+ height: 100px;
+ border-radius: 15px;
+}
+
+a{
+ display: block;
+ text-decoration: none;
+ text-align: center;
+ font-size: 1.5em;
+}
+a:visited{
+ color:black;
+}
+
+.button{
+ width: 80vw;
+ margin: 0 auto;
+ text-align: left;
+}
+
+button{
+ font-size: 0.8em;
+ background-color: #f9d861;
+ margin-top: 20px;
+ border-radius: 10px;
+ font-family: 'Josefin Sans', sans-serif;
+ border: 2px solid #f9d861;
+ width: 100%;
+ padding: 0;
+ height: 32px;
+}
\ No newline at end of file
diff --git a/final/css/signup.css b/final/css/signup.css
new file mode 100644
index 0000000..6e8966a
--- /dev/null
+++ b/final/css/signup.css
@@ -0,0 +1,87 @@
+.logo{
+ margin: 0 auto;
+ text-align: center;
+ margin-top: 80px;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+body{
+ font-family: 'Josefin Sans', sans-serif;
+ background-color: #eee;
+}
+
+h1{
+ color: #3e2fae;
+}
+
+
+
+.edit{
+ padding-top: 50px;
+ width: 80vw;
+ margin: 0 auto;
+ text-align: left;
+}
+
+.edit p{
+ margin-bottom: 10px;
+ font-size: 1.2em;
+ text-align: left;
+
+}
+#usernameInput{
+ font-size: 1em;
+ text-indent: 10px;
+ border-radius: 10px;
+ border: 2px solid #f9d861;
+ width: 100%;
+ height: 32px;
+ font-family: 'Josefin Sans', sans-serif;
+
+}
+#emailInput{
+ font-size: 1em;
+ text-indent: 10px;
+ border-radius: 10px;
+ border: 2px solid #f9d861;
+ width: 100%;
+ height: 32px;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+#passwordInput{
+ font-size: 1em;
+ text-indent: 10px;
+ border-radius: 10px;
+ border: 2px solid #f9d861;
+ width: 100%;
+ height: 32px;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+#profileSaveInput{
+ font-size: 1em;
+ background-color: #f9d861;
+ width: 100%;
+ margin-top: 20px;
+ border-radius: 10px;
+ height: 36px;
+ font-family: 'Josefin Sans', sans-serif;
+}
+
+div .login{
+ font-size: 0.8em;
+ text-align: center;
+}
+
+.login > a{
+ font-size: 1.2em;
+ color: #3e2fae;
+}
+
+.profile{
+ display: none;
+}
+a{
+ text-decoration: none;
+}
\ No newline at end of file
diff --git a/final/icon192.png b/final/icon192.png
new file mode 100644
index 0000000..cd035a3
Binary files /dev/null and b/final/icon192.png differ
diff --git a/final/icon512.png b/final/icon512.png
new file mode 100644
index 0000000..8f79164
Binary files /dev/null and b/final/icon512.png differ
diff --git a/final/imgs/.DS_Store b/final/imgs/.DS_Store
new file mode 100644
index 0000000..5cd5f19
Binary files /dev/null and b/final/imgs/.DS_Store differ
diff --git a/final/imgs/backbutton.png b/final/imgs/backbutton.png
new file mode 100644
index 0000000..4e627ae
Binary files /dev/null and b/final/imgs/backbutton.png differ
diff --git a/final/imgs/camera.png b/final/imgs/camera.png
new file mode 100644
index 0000000..4e355ec
Binary files /dev/null and b/final/imgs/camera.png differ
diff --git a/final/imgs/change-profile.png b/final/imgs/change-profile.png
new file mode 100644
index 0000000..668a6ed
Binary files /dev/null and b/final/imgs/change-profile.png differ
diff --git a/final/imgs/hamburger.png b/final/imgs/hamburger.png
new file mode 100644
index 0000000..ecd61d1
Binary files /dev/null and b/final/imgs/hamburger.png differ
diff --git a/final/imgs/icon-transparent.png b/final/imgs/icon-transparent.png
new file mode 100644
index 0000000..40f2f99
Binary files /dev/null and b/final/imgs/icon-transparent.png differ
diff --git a/final/imgs/profile.png b/final/imgs/profile.png
new file mode 100644
index 0000000..b298494
Binary files /dev/null and b/final/imgs/profile.png differ
diff --git a/final/imgs/sendbutton.png b/final/imgs/sendbutton.png
new file mode 100644
index 0000000..437dc54
Binary files /dev/null and b/final/imgs/sendbutton.png differ
diff --git a/final/index.html b/final/index.html
new file mode 100755
index 0000000..7e5c57d
--- /dev/null
+++ b/final/index.html
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+ Chatmate
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/final/js/.DS_Store b/final/js/.DS_Store
new file mode 100644
index 0000000..cd13533
Binary files /dev/null and b/final/js/.DS_Store differ
diff --git a/final/js/edit-profile.js b/final/js/edit-profile.js
new file mode 100644
index 0000000..5be80ef
--- /dev/null
+++ b/final/js/edit-profile.js
@@ -0,0 +1,52 @@
+
+let userName = localStorage.getItem('userName') || "Yucheng";
+let userStatus = localStorage.getItem('userStatus') || "update your profile to display a status";
+let userProfilePic = localStorage.getItem('userProfilePic') || "profile.png" ;
+let usernameInput = document.querySelector("#usernameInput");
+let statusInput = document.querySelector("#statusInput");
+let profilePicInput = document.querySelector("#profilePicInput");
+let profileSaveInput = document.querySelector("#profileSaveInput");
+let userProfilePicDisplay = document.querySelector("#userProfilePicDisplay");
+
+// setting the input values default
+usernameInput.value = localStorage.getItem('userName');
+statusInput.value = localStorage.getItem('userStatus');
+userProfilePicDisplay.value = localStorage.getItem('profilePicInput')
+
+function saveProfileImageLocally() {
+ if (profilePicInput.files && profilePicInput.files[0]) {
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ localStorage.setItem("userProfilePic", reader.result);
+ }
+ reader.readAsDataURL(profilePicInput.files[0]);
+ }
+}
+
+//set button colors when click
+/* var count = 1;
+ function setColor(btn, color) {
+ var property = document.getElementById("profileSaveInput");
+ if (count == 0) {
+ property.style.backgroundColor = "#f9d861"
+ count = 1;
+ }
+ else {
+ property.style.backgroundColor = "#3e2fae"
+ count = 0;
+ }
+ } */
+
+
+
+profileSaveInput.addEventListener( 'click', function(e) {
+ e.preventDefault();
+ localStorage.setItem("userName", usernameInput.value);
+ localStorage.setItem("userStatus", statusInput.value);
+
+ saveProfileImageLocally();
+});
+
+usernameDisplay.innerHTML = userName;
+userStatusDisplay.innerHTML = userStatus;
+userProfilePicDisplay.src = userProfilePic;
\ No newline at end of file
diff --git a/final/js/firebase-chat-functions.js b/final/js/firebase-chat-functions.js
new file mode 100755
index 0000000..fd56646
--- /dev/null
+++ b/final/js/firebase-chat-functions.js
@@ -0,0 +1,28 @@
+function saveMessageToFirebase(msg) {
+ db.collection("messages").add(msg)
+}
+
+function getAllMessagesFromFirebase() {
+ let allMsgs = [];
+ db.collection("messages").orderBy('dateStamp', 'asc').limit(200).get().then(function(querySnapshot) {
+ querySnapshot.forEach(function(doc) {
+ // doc.data() is never undefined for query doc snapshots
+ allMsgs.push(doc.data())
+ });
+ });
+
+ return allMsgs;
+}
+
+function watchFirebaseForChanges(callBack) {
+ db.collection("messages").orderBy('dateStamp','asc').onSnapshot(function(querySnapshot) {
+ querySnapshot.docChanges().forEach(function(change) {
+ if (change.type === "added") {
+ callBack(change.doc);
+ }
+ });
+ });
+}
+
+
+//getAllMessagesFromFirebase();
diff --git a/final/js/firebase-config.js b/final/js/firebase-config.js
new file mode 100755
index 0000000..166ed82
--- /dev/null
+++ b/final/js/firebase-config.js
@@ -0,0 +1,12 @@
+var firebaseConfig = {
+ apiKey: "AIzaSyAbh39Rb-F9_PO8lpAoob_qA1dYUVNYAkg",
+ authDomain: "dmd-3440-pwa-demo.firebaseapp.com",
+ databaseURL: "https://dmd-3440-pwa-demo.firebaseio.com",
+ projectId: "dmd-3440-pwa-demo",
+ storageBucket: "dmd-3440-pwa-demo.appspot.com",
+ messagingSenderId: "239477441112",
+ appId: "1:239477441112:web:0dcd3f94fe067b09ac402d"
+ };
+ // Initialize Firebase
+ firebase.initializeApp(firebaseConfig);
+ var db = firebase.firestore();
\ No newline at end of file
diff --git a/final/js/main.js b/final/js/main.js
new file mode 100755
index 0000000..173f7dc
--- /dev/null
+++ b/final/js/main.js
@@ -0,0 +1,117 @@
+
+
+// Register a service worker, this one located in serviceworker.js
+// A service worker is a piece of code the browser runs behind the scenes.
+if ('serviceWorker' in navigator) {
+ console.log('CLIENT: service worker registration in progress.');
+ navigator.serviceWorker.register('sw.js').then(function() {
+ console.log('CLIENT: service worker registration complete.');
+ }, function() {
+ console.log('CLIENT: service worker registration failure.');
+ });
+ } else {
+ console.log('CLIENT: service workers are not supported.');
+ }
+
+
+
+let allMessages = [];
+let chatBox = document.querySelector("#chatbox");
+let inputBox = document.querySelector("#newmsg");
+
+// var pictureEndpoint= document.querySelector("#profilePic");
+
+// pictureEndpoint.setAttribute("src",localStorage.userProfilePic)
+
+
+let curr_date = new Date();
+let month = curr_date.getMonth() + 1;
+let dateStr = month.toString() + "/" + curr_date.getDate().toString() + "/" + curr_date.getFullYear().toString();
+
+let curr_time = new Date();
+let timeStr = curr_time.getHours().toString() + ":" + curr_time.getMinutes().toString();
+// document.getElementById("time").innerHTML = timeStr;
+
+function makeMessage(msg) {
+
+ var stagedMessage = document.createElement("div");
+ var inLineContainer = document.createElement("span");
+ var name = document.createElement("h2");
+
+ var message = document.createElement("p");
+ var timeStamp = document.createElement("h4");
+
+ if(msg.sentBy == localStorage.userName){
+ stagedMessage.setAttribute("class", "Me");
+ }
+
+ inLineContainer.setAttribute("class", "people");
+
+
+ name.innerHTML=msg.sentBy;
+ timeStamp.innerHTML=msg.timeStr + " " + msg.dateStr;
+ message.innerHTML=msg.message;
+
+
+ inLineContainer.appendChild(name);
+ inLineContainer.appendChild(timeStamp);
+
+ stagedMessage.appendChild(inLineContainer);
+ inLineContainer.appendChild(message);
+ chatBox.appendChild(stagedMessage);
+ stagedMessage.scrollIntoView();
+ //allMessages.push(newMessage);
+
+
+ console.log(allMessages);
+}
+
+
+
+
+
+
+document.querySelector("#sendBtn").addEventListener('click', () => {
+ let msg = document.querySelector("#newmsg").value;
+ let src = "notification.mp3"
+ let audio = new Audio(src);
+ audio.play();
+
+ document.querySelector("#newmsg").value = "";
+ document.querySelector("#newmsg").focus();
+
+
+
+
+ let userMsg = {
+ sentBy: localStorage.userName,
+ //dateStamp: date_str,
+ dateStr: month.toString() + "/" + curr_date.getDate().toString() + "/" + curr_date.getFullYear().toString(),
+ message: msg
+
+ }
+ if (localStorage.userName != undefined) {
+ saveMessageToFirebase(userMsg);
+ } else {
+ alert("Set a Username");
+ }
+
+
+ inputBox.value = "";
+ inputBox.focus();
+
+ console.log(new_message);
+ window.navigator.vibrate(200);
+
+
+ //makeMessage("Me", date_str, msg,localStorage.userName);
+
+});
+
+
+
+watchFirebaseForChanges(
+ function(msg){
+ makeMessage(msg.data())
+ }
+);
\ No newline at end of file
diff --git a/final/js/profile.js b/final/js/profile.js
new file mode 100755
index 0000000..4ec22f3
--- /dev/null
+++ b/final/js/profile.js
@@ -0,0 +1,55 @@
+
+let userName = localStorage.getItem('userName') || "Yucheng";
+let userStatus = localStorage.getItem('userStatus') || "update your profile to display a status";
+let userProfilePic = localStorage.getItem('userProfilePic') || "profile.png" ;
+let usernameInput = document.querySelector("#usernameInput");
+let statusInput = document.querySelector("#statusInput");
+// let emailInput = document.querySelector("#emailInput");
+let profilePicInput = document.querySelector("#profilePicInput");
+let profileSaveInput = document.querySelector("#profileSaveInput");
+let userProfilePicDisplay = document.querySelector("#userProfilePicDisplay");
+
+// setting the input values default
+usernameInput.value = localStorage.getItem('userName');
+statusInput.value = localStorage.getItem('userStatus');
+userProfilePicDisplay.value = localStorage.getItem('profilePicInput')
+// emailInput.value = localStorage.getItem('userEmail');
+
+function saveProfileImageLocally() {
+ if (profilePicInput.files && profilePicInput.files[0]) {
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ localStorage.setItem("userProfilePic", reader.result);
+ }
+ reader.readAsDataURL(profilePicInput.files[0]);
+ }
+}
+
+//set button colors when click
+/* var count = 1;
+ function setColor(btn, color) {
+ var property = document.getElementById("profileSaveInput");
+ if (count == 0) {
+ property.style.backgroundColor = "#f9d861"
+ count = 1;
+ }
+ else {
+ property.style.backgroundColor = "#3e2fae"
+ count = 0;
+ }
+ } */
+
+
+
+profileSaveInput.addEventListener( 'click', function(e) {
+ e.preventDefault();
+ localStorage.setItem("userName", usernameInput.value);
+ localStorage.setItem("userStatus", statusInput.value);
+ // localStorage.setItem("userEmail", emailInput.value);
+
+ saveProfileImageLocally();
+});
+usernameDisplay.innerHTML = userName;
+userStatusDisplay.innerHTML = userStatus;
+// userEmailDisplay.innerHTML = userEmail;
+userProfilePicDisplay.src = userProfilePic;
\ No newline at end of file
diff --git a/final/js/register-sw.js b/final/js/register-sw.js
new file mode 100755
index 0000000..2b40a14
--- /dev/null
+++ b/final/js/register-sw.js
@@ -0,0 +1,12 @@
+// Register a service worker, this one located in serviceworker.js
+// A service worker is a piece of code the browser runs behind the scenes.
+if ('serviceWorker' in navigator) {
+ console.log('CLIENT: service worker registration in progress.');
+ navigator.serviceWorker.register('sw.js').then(function() {
+ console.log('CLIENT: service worker registration complete.');
+ }, function() {
+ console.log('CLIENT: service worker registration failure.');
+ });
+ } else {
+ console.log('CLIENT: service workers are not supported.');
+ }
\ No newline at end of file
diff --git a/final/js/signup.js b/final/js/signup.js
new file mode 100644
index 0000000..922a56a
--- /dev/null
+++ b/final/js/signup.js
@@ -0,0 +1,51 @@
+
+let userName = localStorage.getItem('userName') || "Yucheng";
+let userStatus = localStorage.getItem('userStatus') || "update your profile to display a status";
+let userProfilePic = localStorage.getItem('userProfilePic') || "profile.png" ;
+let usernameInput = document.querySelector("#usernameInput");
+let emailInput = document.querySelector("#emailInput");
+let profilePicInput = document.querySelector("#profilePicInput");
+let profileSaveInput = document.querySelector("#profileSaveInput");
+let userProfilePicDisplay = document.querySelector("#userProfilePicDisplay");
+
+// setting the input values default
+usernameInput.value = localStorage.getItem('userName');
+emailInput.value = localStorage.getItem('userEmail');
+userProfilePicDisplay.value = localStorage.getItem('profilePicInput')
+
+function saveProfileImageLocally() {
+ if (profilePicInput.files && profilePicInput.files[0]) {
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ localStorage.setItem("userProfilePic", reader.result);
+ }
+ reader.readAsDataURL(profilePicInput.files[0]);
+ }
+}
+
+//set button colors when click
+/* var count = 1;
+ function setColor(btn, color) {
+ var property = document.getElementById("profileSaveInput");
+ if (count == 0) {
+ property.style.backgroundColor = "#f9d861"
+ count = 1;
+ }
+ else {
+ property.style.backgroundColor = "#3e2fae"
+ count = 0;
+ }
+ } */
+
+
+
+profileSaveInput.addEventListener( 'click', function(e) {
+ e.preventDefault();
+ localStorage.setItem("userName", usernameInput.value);
+ localStorage.setItem("userEmail", emailInput.value);
+
+ saveProfileImageLocally();
+});
+usernameDisplay.innerHTML = userName;
+userEmailDisplay.innerHTML = userEmail;
+userProfilePicDisplay.src = userProfilePic;
\ No newline at end of file
diff --git a/final/js/sw.js b/final/js/sw.js
new file mode 100755
index 0000000..971588f
--- /dev/null
+++ b/final/js/sw.js
@@ -0,0 +1,200 @@
+console.log('SERVICE WORKER: executing.');
+
+/* A version number is useful when updating the worker logic,
+ allowing you to remove outdated cache entries during the update.
+*/
+var version = 'v6::';
+
+/* These resources will be downloaded and cached by the service worker
+ during the installation process. If any resource fails to be downloaded,
+ then the service worker won't be installed either.
+*/
+var offlineFiles = [
+ '',
+ 'whatsapp-icon.png',
+ 'icon2.png',
+ 'index.html',
+ 'main.css',
+ 'main.js'
+];
+
+/* The install event fires when the service worker is first installed.
+ You can use this event to prepare the service worker to be able to serve
+ files while visitors are offline.
+*/
+self.addEventListener("install", function(event) {
+ console.log('WORKER: install event in progress.');
+ /* Using event.waitUntil(p) blocks the installation process on the provided
+ promise. If the promise is rejected, the service worker won't be installed.
+ */
+ event.waitUntil(
+ /* The caches built-in is a promise-based API that helps you cache responses,
+ as well as finding and deleting them.
+ */
+ caches
+ /* You can open a cache by name, and this method returns a promise. We use
+ a versioned cache name here so that we can remove old cache entries in
+ one fell swoop later, when phasing out an older service worker.
+ */
+ .open(version + 'fundamentals')
+ .then(function(cache) {
+ /* After the cache is opened, we can fill it with the offline fundamentals.
+ The method below will add all resources in `offlineFiles` to the
+ cache, after making requests for them.
+ */
+ return cache.addAll(offlineFiles);
+ })
+ .then(function() {
+ console.log('WORKER: install completed');
+ })
+ );
+});
+
+/* The fetch event fires whenever a page controlled by this service worker requests
+ a resource. This isn't limited to `fetch` or even XMLHttpRequest. Instead, it
+ comprehends even the request for the HTML page on first load, as well as JS and
+ CSS resources, fonts, any images, etc.
+*/
+self.addEventListener("fetch", function(event) {
+ console.log('WORKER: fetch event in progress.');
+
+ /* We should only cache GET requests, and deal with the rest of method in the
+ client-side, by handling failed POST,PUT,PATCH,etc. requests.
+ */
+ if (event.request.method !== 'GET') {
+ /* If we don't block the event as shown below, then the request will go to
+ the network as usual.
+ */
+ console.log('WORKER: fetch event ignored.', event.request.method, event.request.url);
+ return;
+ }
+ /* Similar to event.waitUntil in that it blocks the fetch event on a promise.
+ Fulfillment result will be used as the response, and rejection will end in a
+ HTTP response indicating failure.
+ */
+ event.respondWith(
+ caches
+ /* This method returns a promise that resolves to a cache entry matching
+ the request. Once the promise is settled, we can then provide a response
+ to the fetch request.
+ */
+ .match(event.request)
+ .then(function(cached) {
+ /* Even if the response is in our cache, we go to the network as well.
+ This pattern is known for producing "eventually fresh" responses,
+ where we return cached responses immediately, and meanwhile pull
+ a network response and store that in the cache.
+
+ Read more:
+ https://ponyfoo.com/articles/progressive-networking-serviceworker
+ */
+ var networked = fetch(event.request)
+ // We handle the network request with success and failure scenarios.
+ .then(fetchedFromNetwork, unableToResolve)
+ // We should catch errors on the fetchedFromNetwork handler as well.
+ .catch(unableToResolve);
+
+ /* We return the cached response immediately if there is one, and fall
+ back to waiting on the network as usual.
+ */
+ console.log('WORKER: fetch event', cached ? '(cached)' : '(network)', event.request.url);
+ return cached || networked;
+
+ function fetchedFromNetwork(response) {
+ /* We copy the response before replying to the network request.
+ This is the response that will be stored on the ServiceWorker cache.
+ */
+ var cacheCopy = response.clone();
+
+ console.log('WORKER: fetch response from network.', event.request.url);
+
+ caches
+ // We open a cache to store the response for this request.
+ .open(version + 'pages')
+ .then(function add(cache) {
+ /* We store the response for this request. It'll later become
+ available to caches.match(event.request) calls, when looking
+ for cached responses.
+ */
+ return cache.put(event.request, cacheCopy);
+ })
+ .then(function() {
+ console.log('WORKER: fetch response stored in cache.', event.request.url);
+ });
+
+ // Return the response so that the promise is settled in fulfillment.
+ return response;
+ }
+
+ /* When this method is called, it means we were unable to produce a response
+ from either the cache or the network. This is our opportunity to produce
+ a meaningful response even when all else fails. It's the last chance, so
+ you probably want to display a "Service Unavailable" view or a generic
+ error response.
+ */
+ function unableToResolve () {
+ /* There's a couple of things we can do here.
+ - Test the Accept header and then return one of the `offlineFiles`
+ e.g: `return caches.match('/some/cached/image.png')`
+ - You should also consider the origin. It's easier to decide what
+ "unavailable" means for requests against your origins than for requests
+ against a third party, such as an ad provider.
+ - Generate a Response programmaticaly, as shown below, and return that.
+ */
+
+ console.log('WORKER: fetch request failed in both cache and network.');
+
+ /* Here we're creating a response programmatically. The first parameter is the
+ response body, and the second one defines the options for the response.
+ */
+ return new Response('
Service Unavailable
', {
+ status: 503,
+ statusText: 'Service Unavailable',
+ headers: new Headers({
+ 'Content-Type': 'text/html'
+ })
+ });
+ }
+ })
+ );
+});
+
+/* The activate event fires after a service worker has been successfully installed.
+ It is most useful when phasing out an older version of a service worker, as at
+ this point you know that the new worker was installed correctly. In this example,
+ we delete old caches that don't match the version in the worker we just finished
+ installing.
+*/
+self.addEventListener("activate", function(event) {
+ /* Just like with the install event, event.waitUntil blocks activate on a promise.
+ Activation will fail unless the promise is fulfilled.
+ */
+ console.log('WORKER: activate event in progress.');
+
+ event.waitUntil(
+ caches
+ /* This method returns a promise which will resolve to an array of available
+ cache keys.
+ */
+ .keys()
+ .then(function (keys) {
+ // We return a promise that settles when all outdated caches are deleted.
+ return Promise.all(
+ keys
+ .filter(function (key) {
+ // Filter by keys that don't start with the latest version prefix.
+ return !key.startsWith(version);
+ })
+ .map(function (key) {
+ /* Return a promise that's fulfilled
+ when each outdated cache is deleted.
+ */
+ return caches.delete(key);
+ })
+ );
+ })
+ .then(function() {
+ console.log('WORKER: activate completed.');
+ })
+ );
+});
\ No newline at end of file
diff --git a/final/login.html b/final/login.html
new file mode 100644
index 0000000..b51ccc3
--- /dev/null
+++ b/final/login.html
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Login
+
+
+
+
+
+
Chatmate
+
+
+
+
Username
+
+
Password
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/final/mainfest.json b/final/mainfest.json
new file mode 100755
index 0000000..4513a31
--- /dev/null
+++ b/final/mainfest.json
@@ -0,0 +1,20 @@
+{
+ "short_name": "Chatmate",
+ "name": "Chatmate",
+ "icons": [
+ {
+ "src":"icon192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icon512.png",
+ "type": "image/png",
+ "sizes": "512x512"
+ }
+ ],
+ "start_url": "index.html",
+ "background_color": "#3e2fa",
+ "theme_color": "#3e2fa",
+ "display": "fullscreen"
+ }
\ No newline at end of file
diff --git a/final/notification.mp3 b/final/notification.mp3
new file mode 100644
index 0000000..d8f9071
Binary files /dev/null and b/final/notification.mp3 differ
diff --git a/imgs/.DS_Store b/imgs/.DS_Store
index 203c0e1..0ce7aea 100644
Binary files a/imgs/.DS_Store and b/imgs/.DS_Store differ
diff --git a/manifest.json b/manifest.json
index 8a3c5f5..0f76670 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,6 +1,6 @@
{
- "short_name": "Room of Chat",
- "name": "Room of Chat",
+ "short_name": "Chatmate",
+ "name": "Chatmate",
"icons": [
{
"src":"icon192.png",