diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..39fb081 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..96cc43e --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..0e23f8e --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..fbb6828 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..f5e9010 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index fe059e5..0f5f892 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ +<<<<<<< HEAD # sp17proj4android Repository for Spring 2017 MDB Android Training Program Mini-Project 4 Submissions +======= +# sp17proj3android + +Repository for Spring 2017 MDB Android Training Program Mini-Project 3 Submissions +>>>>>>> 5e6c17b66b707dd814343d3596acc8495d0ef957 Finalized mini-projects should be stored in personal portfolios, but this repository will be used for providing feedback on code quality using the GitHub code review features. diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..bddc4d4 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,42 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 25 + buildToolsVersion "25.0.2" + defaultConfig { + applicationId "com.example.sarahtang.mdbsocials" + minSdkVersion 15 + targetSdkVersion 25 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + compile 'com.android.support:appcompat-v7:25.1.1' + compile 'com.android.support:design:25.1.1' + compile 'com.google.firebase:firebase-auth:10.0.1' + compile 'com.android.support.constraint:constraint-layout:1.0.0-beta5' + compile 'com.android.support:recyclerview-v7:25.1.1' + compile 'com.google.firebase:firebase-database:10.0.1' + compile 'com.android.support:cardview-v7:25.1.1' + compile 'com.google.firebase:firebase-storage:10.0.1' + compile 'com.github.bumptech.glide:glide:3.5.2' + //have to import card view for it to work + testCompile 'junit:junit:4.12' +} + + + +apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000..c501625 --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,55 @@ +{ + "project_info": { + "project_number": "799608942291", + "firebase_url": "https://mdbsocials-fdfae.firebaseio.com", + "project_id": "mdbsocials-fdfae", + "storage_bucket": "mdbsocials-fdfae.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:799608942291:android:1f285eb783f2efbf", + "android_client_info": { + "package_name": "com.example.sarahtang.mdbsocials" + } + }, + "oauth_client": [ + { + "client_id": "799608942291-7854bdum2v4kgrds1tr1q900fnrgpkei.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.example.sarahtang.mdbsocials", + "certificate_hash": "5B82A4C2F4E221AA580043A88F835C0D1000768D" + } + }, + { + "client_id": "799608942291-gc1482dps39lji62m7hu90kk4is82j5f.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyBnnXhGkvbbFDwwWGvUtBEFMVKYebNI348" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 2, + "other_platform_oauth_client": [ + { + "client_id": "799608942291-gc1482dps39lji62m7hu90kk4is82j5f.apps.googleusercontent.com", + "client_type": 3 + } + ] + }, + "ads_service": { + "status": 2 + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..643146f --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/sarahtang/Library/Android/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/app/src/androidTest/java/com/example/sarahtang/mdbsocials/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/example/sarahtang/mdbsocials/ExampleInstrumentedTest.java new file mode 100644 index 0000000..6f7104d --- /dev/null +++ b/app/src/androidTest/java/com/example/sarahtang/mdbsocials/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.example.sarahtang.mdbsocials; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumentation test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.example.sarahtang.mdbsocials", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ae4ce01 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/sarahtang/mdbsocials/DetailsActivity.java b/app/src/main/java/com/example/sarahtang/mdbsocials/DetailsActivity.java new file mode 100644 index 0000000..ffef189 --- /dev/null +++ b/app/src/main/java/com/example/sarahtang/mdbsocials/DetailsActivity.java @@ -0,0 +1,220 @@ +package com.example.sarahtang.mdbsocials; + +import android.content.Intent; +import android.content.res.ColorStateList; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.net.Uri; +import android.os.AsyncTask; +import android.support.annotation.NonNull; +import android.support.design.widget.FloatingActionButton; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.bumptech.glide.Glide; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.MutableData; +import com.google.firebase.database.Transaction; +import com.google.firebase.storage.FirebaseStorage; + +import java.util.ArrayList; + +/** + * Details Activity: Detailed information about each social + */ + +public class DetailsActivity extends AppCompatActivity implements View.OnClickListener { + + ImageView imageDetail; + TextView nameDetail; //title + TextView interestedDetail;//number of people interested + TextView hostDetail; + TextView descriptionDetail; + String firebaseKey; + ArrayList peopleInterested; + String currEmail = FirebaseAuth.getInstance().getCurrentUser().getEmail(); + boolean buttonPressed = false; + boolean numberChanged = false; + FloatingActionButton fabInterested; + FloatingActionButton fabStar; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_details); + + /** + * On Click Listener implementation in activity + */ + + + fabInterested = (FloatingActionButton) findViewById(R.id.fabInterested); + fabInterested.setOnClickListener(this); + fabStar = (FloatingActionButton) findViewById(R.id.fabStar); + fabStar.setOnClickListener(this); + + imageDetail = (ImageView) findViewById(R.id.imageDetail); + nameDetail = (TextView) findViewById(R.id.nameDetail); + interestedDetail = (TextView) findViewById(R.id.interestedDetail); + hostDetail = (TextView) findViewById(R.id.hostDetail); + descriptionDetail = (TextView) findViewById(R.id.descriptionDetail); + + //Getting information from intent from socials adapter + Intent intent = getIntent(); + String name = intent.getStringExtra(SocialsAdapter.NAME_KEY); + String host = intent.getStringExtra(SocialsAdapter.HOST_KEY); + String description = intent.getStringExtra(SocialsAdapter.DESCRIPTION_KEY); + String image = intent.getStringExtra(SocialsAdapter.FIREBASE_URL); + final int numberInterested = intent.getIntExtra(SocialsAdapter.NUMBER_INTERESTED, -1); + ArrayList resultArray = intent.getStringArrayListExtra(SocialsAdapter.PEOPLE_INTERESTED); + if (resultArray == null) { + resultArray = new ArrayList<>(); + } + peopleInterested = resultArray; + firebaseKey = intent.getStringExtra(SocialsAdapter.FIREBASE_KEY); + + //Download image asynchronously + class DownloadFilesTask extends AsyncTask { + protected Bitmap doInBackground(String... strings) { + try {return Glide. + with(getApplicationContext()). + load(strings[0]). + asBitmap(). + into(100, 100). // Width and height + get();} + catch (Exception e) {return null;} + } + + protected void onProgressUpdate(Void... progress) {} + + protected void onPostExecute(Bitmap result) { + imageDetail.setImageBitmap(result); + } + } + + + //Retrieving image from firebase storage + FirebaseStorage.getInstance().getReferenceFromUrl("gs://mdbsocials-fdfae.appspot.com").child(image + ".png").getDownloadUrl().addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(Uri uri) { + (new DownloadFilesTask()).execute(uri.toString()); + Log.d("GotImageFromStorage", uri.toString()); + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception exception) { + Log.d("NoImageFromStorage", exception.toString()); + } + }); + + //Setting text for each Text view in layout + nameDetail.setText(name); + hostDetail.setText(getString(R.string.hostedBy) + host); + descriptionDetail.setText(getString(R.string.descriptionIntro) + description); + + switch(numberInterested) { + case 1: + interestedDetail.setText(numberInterested + getString(R.string.personInterested)); + break; + default: + interestedDetail.setText(numberInterested + getString(R.string.peopleInterested)); + } + } + + /** + * Transaction to increase number of people interested by one and to add person to + * interested list (if not already added); + * Modularized ish + */ + public void addInterested() { + Log.d("TRANSACTION", "Success"); + + final DatabaseReference ref = FirebaseDatabase.getInstance().getReference("/socials"); + ref.child(firebaseKey).runTransaction(new Transaction.Handler() { + @Override + public Transaction.Result doTransaction(MutableData mutableData) { + //String currEmail = FirebaseAuth.getInstance().getCurrentUser().getEmail(); + + if (!buttonPressed) { + buttonPressed = true; + int numInterested = mutableData.child("numberInterested").getValue(Integer.class); + numInterested++; + Log.d("Details", "transaction"); + DetailsActivity.addInterestedToDatabase(numInterested,firebaseKey); + + + + ArrayList a = (ArrayList) mutableData.child("peopleInterested").getValue(); + if (a == null) { + a = new ArrayList(); + } + + if (!a.contains(currEmail)) { + a.add(currEmail); + ref.child(firebaseKey).child("peopleInterested").setValue(a); + } + + } + else { + Toast.makeText(getApplicationContext(), R.string.toastAlreadyInterested, Toast.LENGTH_SHORT).show(); + } + + return Transaction.success(mutableData); + } + @Override + public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) { + + } + }); + } + + public static void addInterestedToDatabase(int interested, String firekey) { + DatabaseReference ref = FirebaseDatabase.getInstance().getReference("/socials"); + ref.child(firekey).child("numberInterested").setValue(interested); + } + + /** + * All of the on click listeners + * @param view + */ + + public void onClick(View view) { + + if (view.getId() == R.id.fabInterested) { + Log.d("Details", "listInterested"); + Intent intentInterested = new Intent(getApplicationContext(), InterestedActivity.class); + intentInterested.putStringArrayListExtra("peopleList", peopleInterested); + startActivity(intentInterested); + } + if (view.getId() == R.id.fabStar) { + /** + * Interested button + */ + Log.d("Details", "interested"); + fabStar.setRippleColor(Color.parseColor("#ffcf32")); + fabStar.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ffcf32"))); + if (!peopleInterested.contains(currEmail)) { + Toast.makeText(getApplicationContext(), "Interested In Event!", Toast.LENGTH_SHORT).show(); + + addInterested(); + //TODO FIX + //interestedDetail.setText(numberInterested); + } + else { + Toast.makeText(getApplicationContext(), R.string.toastAlreadyInterested, Toast.LENGTH_SHORT).show(); + } + } + + } +} diff --git a/app/src/main/java/com/example/sarahtang/mdbsocials/Firebase_Utils.java b/app/src/main/java/com/example/sarahtang/mdbsocials/Firebase_Utils.java new file mode 100644 index 0000000..49f715e --- /dev/null +++ b/app/src/main/java/com/example/sarahtang/mdbsocials/Firebase_Utils.java @@ -0,0 +1,85 @@ +package com.example.sarahtang.mdbsocials; + +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.widget.AutoCompleteTextView; +import android.widget.EditText; +import android.widget.Toast; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; + +/** + * Created by sarahtang on 2/28/17. + * Static class to hold general methods for code. + */ + +public class Firebase_Utils extends AppCompatActivity{ + + /** + * Attempt to sign up/create user in Firebase + */ + + public static void attemptSignUp (AutoCompleteTextView mEmailView, EditText mPasswordView, FirebaseAuth mAuth, final LoginActivity loginActivity) { + String email = mEmailView.getText().toString(); + String password = mPasswordView.getText().toString(); + + if (!email.equals("") && !password.equals("")) { + mAuth.createUserWithEmailAndPassword(email, password) + .addOnCompleteListener(loginActivity, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + Log.d("status", "createUserWithEmail:onComplete:" + task.isSuccessful()); + if (!task.isSuccessful()) { + Log.w("status", "signInWithEmail", task.getException()); + Toast.makeText(loginActivity, R.string.toastFailSignUp, + Toast.LENGTH_SHORT).show(); + } + else { + Log.d("status", "signInSuccessful"); + final DatabaseReference ref = FirebaseDatabase.getInstance().getReference(); + FirebaseUser currUser = FirebaseAuth.getInstance().getCurrentUser(); + final String key = currUser.getUid(); + ref.child("users").child(key).child("email").setValue(currUser.getEmail()); + } + } + }); + } + else { + Toast.makeText(loginActivity, R.string.missingInfo, Toast.LENGTH_SHORT).show(); + } + } + + /** + * Attempt to log in user through Firebase + */ + + public static void attemptLogin(EditText emailU, EditText passwordU, FirebaseAuth mAuth, final LoginActivity loginActivity) { + final String email = emailU.getText().toString(); + String password = passwordU.getText().toString(); + + if (!email.equals("") && !password.equals("")) { + mAuth.signInWithEmailAndPassword(email, password) + .addOnCompleteListener(loginActivity, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + Log.d("status", "signInWithEmail:onComplete:" + task.isSuccessful()); + if (!task.isSuccessful()) { + Log.w("status", "signInWithEmail:failed", task.getException()); + Toast.makeText(loginActivity, R.string.failLogIn, + Toast.LENGTH_SHORT).show(); + } + } + }); + } + else { + Toast.makeText(loginActivity, R.string.missingInfo, Toast.LENGTH_SHORT).show(); + } + } +} diff --git a/app/src/main/java/com/example/sarahtang/mdbsocials/InterestedActivity.java b/app/src/main/java/com/example/sarahtang/mdbsocials/InterestedActivity.java new file mode 100644 index 0000000..f05ecef --- /dev/null +++ b/app/src/main/java/com/example/sarahtang/mdbsocials/InterestedActivity.java @@ -0,0 +1,32 @@ +package com.example.sarahtang.mdbsocials; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; + +import java.util.ArrayList; + +/** + * Interested activity sets the layout view and connects with Interested Adapter + * to display the people that are interested. + * List of emails of people interested in a social. + */ + +public class InterestedActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_interested); + + //Connect people interested in social with recycler view layout + Log.d("InterestedActivity", "Int"); + RecyclerView recyclerViewInterested = (RecyclerView) findViewById(R.id.recyclerInterested); + recyclerViewInterested.setLayoutManager(new LinearLayoutManager(getApplicationContext())); + ArrayList peopleInterested = getIntent().getStringArrayListExtra("peopleList"); + InterestedAdapter interestedAdapter = new InterestedAdapter(getApplicationContext(), peopleInterested); + recyclerViewInterested.setAdapter(interestedAdapter); + } + } + diff --git a/app/src/main/java/com/example/sarahtang/mdbsocials/InterestedAdapter.java b/app/src/main/java/com/example/sarahtang/mdbsocials/InterestedAdapter.java new file mode 100644 index 0000000..da2181a --- /dev/null +++ b/app/src/main/java/com/example/sarahtang/mdbsocials/InterestedAdapter.java @@ -0,0 +1,53 @@ +package com.example.sarahtang.mdbsocials; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.ArrayList; + +/** + * Created by sarahtang on 2/21/17. + * + * Interested adapter connects with list of people (email) + * that are interested in the social. + */ + + +public class InterestedAdapter extends RecyclerView.Adapter { + private Context context; + private ArrayList names; + + public InterestedAdapter(Context context, ArrayList names){ + this.context = context; + this.names = names; + } + + @Override + public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.interested_row_view, parent, false); + return new CustomViewHolder(view); + } + + @Override + public void onBindViewHolder(InterestedAdapter.CustomViewHolder holder, int position) { + holder.textView.setText(names.get(position).toString()); + } + + @Override + public int getItemCount() { + return names.size(); + } + + public class CustomViewHolder extends RecyclerView.ViewHolder { + TextView textView; + + public CustomViewHolder(View view) { + super(view); + textView = (TextView) (view.findViewById(R.id.textView_interested)); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/sarahtang/mdbsocials/ListActivity.java b/app/src/main/java/com/example/sarahtang/mdbsocials/ListActivity.java new file mode 100644 index 0000000..1dbec0b --- /dev/null +++ b/app/src/main/java/com/example/sarahtang/mdbsocials/ListActivity.java @@ -0,0 +1,107 @@ +package com.example.sarahtang.mdbsocials; + +import android.content.Intent; +import android.os.Bundle; +import android.support.design.widget.FloatingActionButton; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.View; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; + +import java.util.ArrayList; +import java.util.List; + + +/** + * List Activity: Main list for social events + */ + +public class ListActivity extends AppCompatActivity implements View.OnClickListener { + //List view = recycler activity and main list showing the list of socials + protected SocialsAdapter socialsAdapter; + ArrayList socials; + static public ArrayList keyList; + + FloatingActionButton fab; + FloatingActionButton signOut; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_list); + + socials = new ArrayList<>(); + keyList = new ArrayList<>(); + final ArrayList listSocials = socials; + + //Connect with adapter + socialsAdapter = new SocialsAdapter(getApplicationContext(), socials); + final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerSocial); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); //change this to getApplicationContext() + recyclerView.setAdapter(socialsAdapter); + final DatabaseReference ref = FirebaseDatabase.getInstance().getReference("/socials"); + + /** + * On Click listener + */ + + fab = (FloatingActionButton) findViewById(R.id.fab); + signOut = (FloatingActionButton) findViewById(R.id.signOut); + fab.setOnClickListener(this); + signOut.setOnClickListener(this); + + //This line orders the socials by time (recent to least recent) in the beginning + ref.orderByChild("time").addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + listSocials.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + Social newSocial = snapshot.getValue(Social.class); + keyList.add(snapshot.getKey()); + List peopleInterested = (List) snapshot.child("peopleInterested").getValue(); + listSocials.add(newSocial); + } + if (socialsAdapter != null) { + socialsAdapter.notifyDataSetChanged(); + } + recyclerView.setAdapter(socialsAdapter); + } + + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + + /** + * On Click listener implementation + * @param view + */ + + public void onClick(View view) { + if (view.getId() == R.id.fab) { + //Go to new social activity + Log.d("ListAct", "NewSocial"); + Intent intent = new Intent(getApplicationContext(), NewSocialActivity.class); + startActivity(intent); + } + if (view.getId() == R.id.signOut) { + //Sign out user and go back to login activity + Log.d("ListAct", "logout"); + FirebaseAuth.getInstance().signOut(); + Intent intent = new Intent(getApplicationContext(), LoginActivity.class); + startActivity(intent); + + } + } + +} diff --git a/app/src/main/java/com/example/sarahtang/mdbsocials/LoginActivity.java b/app/src/main/java/com/example/sarahtang/mdbsocials/LoginActivity.java new file mode 100644 index 0000000..3eee066 --- /dev/null +++ b/app/src/main/java/com/example/sarahtang/mdbsocials/LoginActivity.java @@ -0,0 +1,105 @@ +package com.example.sarahtang.mdbsocials; + +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.AutoCompleteTextView; +import android.widget.Button; +import android.widget.EditText; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +/** + * Login Activity: Activity for initial screen that calls users to + * login or sign up accordingly. + */ + +public class LoginActivity extends AppCompatActivity implements OnClickListener { + + private AutoCompleteTextView mEmailView; + private EditText mPasswordView; + private EditText email; + private EditText password; + FirebaseAuth mAuth; + FirebaseAuth.AuthStateListener mAuthListener; + Button signInButton; + Button registerButton; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + mEmailView = (AutoCompleteTextView) findViewById(R.id.email); + mAuth = FirebaseAuth.getInstance(); + mPasswordView = (EditText) findViewById(R.id.password); + email = (EditText) findViewById(R.id.email); + password = (EditText) findViewById(R.id.password); + + signInButton = (Button) findViewById(R.id.email_sign_in_button); + signInButton.setOnClickListener(this); + registerButton = (Button) findViewById(R.id.register_button); + registerButton.setOnClickListener(this); + + /** + * Initialize FirebaseAuth instance and AuthStateListener method to + * track when user signs in and signs out + */ + + mAuthListener = new FirebaseAuth.AuthStateListener() { + @Override + public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { + FirebaseUser user = firebaseAuth.getCurrentUser(); + if (user != null) { + // User is signed in + Intent intent = new Intent(getApplicationContext(), ListActivity.class); + startActivity(intent); + Log.d("status", "onAuthStateChanged:signed_in:" + user.getUid()); + } else { + // User is signed out + Log.d("status", "onAuthStateChanged:signed_out"); + } + } + }; + } + + + public void onClick(View view) { + if (view.getId() == R.id.email_sign_in_button) { + Firebase_Utils.attemptLogin(email, password, mAuth, LoginActivity.this); + } + if (view.getId() == R.id.register_button) { + Firebase_Utils.attemptSignUp(mEmailView, mPasswordView, mAuth, LoginActivity.this); + } + } + + /** + * Allows for automatic go to list activity if already signed in + */ + @Override + public void onStart() { + super.onStart(); + mAuth.addAuthStateListener(mAuthListener); + } + + @Override + public void onStop() { + super.onStop(); + if (mAuthListener != null) { + mAuth.removeAuthStateListener(mAuthListener); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mAuthListener != null) { + mAuth.removeAuthStateListener(mAuthListener); + } + } + +} diff --git a/app/src/main/java/com/example/sarahtang/mdbsocials/NewSocialActivity.java b/app/src/main/java/com/example/sarahtang/mdbsocials/NewSocialActivity.java new file mode 100644 index 0000000..c424dbf --- /dev/null +++ b/app/src/main/java/com/example/sarahtang/mdbsocials/NewSocialActivity.java @@ -0,0 +1,184 @@ +package com.example.sarahtang.mdbsocials; + +import android.animation.ObjectAnimator; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.os.Handler; +import android.provider.MediaStore; +import android.support.annotation.NonNull; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.view.animation.DecelerateInterpolator; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ProgressBar; +import android.widget.Toast; + +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.storage.FirebaseStorage; +import com.google.firebase.storage.StorageReference; +import com.google.firebase.storage.UploadTask; + +import java.util.ArrayList; + +/** + * New Social Activity = Place to put in required information to create a new social + */ + +public class NewSocialActivity extends AppCompatActivity { + public static DatabaseReference ref = FirebaseDatabase.getInstance().getReference("/social"); + Intent data; + private static final int PROGRESS = 0x1; + ProgressBar progressBar; + private int progressStatus = 0; + private Handler handler = new Handler(); + ObjectAnimator animation; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_new_social); + + final EditText editName = (EditText) findViewById(R.id.editName); + final EditText editDate = (EditText) findViewById(R.id.editDate); + final EditText editDescription = (EditText) findViewById(R.id.editDescription); + Button addImageButton = (Button) findViewById(R.id.addImageButton); + Button buttonSubmit = (Button) findViewById(R.id.buttonSubmit); + progressBar = (ProgressBar)findViewById(R.id.progressBar); + progressBar.setVisibility(View.INVISIBLE); + + /** + * Get photo from gallery or camera + */ + addImageButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AlertDialog.Builder builder = new AlertDialog.Builder(NewSocialActivity.this); + builder.setMessage(R.string.galleryOrCamera) + .setPositiveButton("Camera", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + startActivityForResult(cameraIntent, 1); + } + }) + .setNegativeButton("Gallery", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); + startActivityForResult(galleryIntent, 2); + } + }); + builder.show(); + } + }); + + //Create all the aspects of connection to storage - so that when make new social it gets stored (submit) + buttonSubmit.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + progressBar.setVisibility(View.VISIBLE); + +// //p.setProgress(50); +// if(arg0%2==1){ +// item.setBackgroundColor(Color.rgb(252, 234, 238)); +// } +// return view; + + + new Thread(new Runnable() { + @Override + public void run() { + while (progressStatus < 100) { + // Update the progress status + progressStatus += 1; + + // Try to sleep the thread for 20 milliseconds + try { + Thread.sleep(20); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // Update the progress bar + handler.post(new Runnable() { + @Override + public void run() { + progressBar.setProgress(progressStatus); + // Show the progress on TextView + //tv.setText(progressStatus + ""); + progressBar.getProgressDrawable().setColorFilter(Color.rgb(220, 41, 82), PorterDuff.Mode.SRC_IN); + animation = ObjectAnimator.ofInt(progressBar, "progress", 16); + animation.setDuration(500); // 0.5 second + animation.setInterpolator(new DecelerateInterpolator()); + animation.start(); + } + }); + } + } + }); + + + if (data == null) { + Toast.makeText(NewSocialActivity.this, R.string.missingInfo, Toast.LENGTH_SHORT).show(); + } else { + + Log.d("Got to here", "and here"); + + + + final DatabaseReference ref = FirebaseDatabase.getInstance().getReference(); + final String key = ref.child("socials").push().getKey(); + StorageReference storageRef = FirebaseStorage.getInstance().getReferenceFromUrl(getString(R.string.storageURL)); + StorageReference riversRef = storageRef.child(key + ".png"); + riversRef.putFile(data.getData()).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception exception) { + Log.d("NewSocialActivity", "Failure"); + Toast.makeText(NewSocialActivity.this, "Need an image!", Toast.LENGTH_SHORT).show(); + } + }).addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { + progressBar.setVisibility(View.VISIBLE); + + Log.d("NewSocialActivity", "CreationSuccess"); + String name = editName.getText().toString(); + String date = editDate.getText().toString(); + String description = editDescription.getText().toString(); + ArrayList peopleInterested = new ArrayList<>(); + String host = FirebaseAuth.getInstance().getCurrentUser().getEmail(); + + Social social = new Social(name, date, description, host, 0, peopleInterested, key); + ref.child("socials").child(key).setValue(social); + + + //New Intent to go back to List Activity + Intent intent = new Intent(NewSocialActivity.this, ListActivity.class); + startActivity(intent); + } + }); + } + } + //TODO make visible PROGRESS BAR(spinning bar), when finishes ==> goes to next view + }); + + } + + + + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + this.data = data; + } +} + diff --git a/app/src/main/java/com/example/sarahtang/mdbsocials/Social.java b/app/src/main/java/com/example/sarahtang/mdbsocials/Social.java new file mode 100644 index 0000000..f52ac26 --- /dev/null +++ b/app/src/main/java/com/example/sarahtang/mdbsocials/Social.java @@ -0,0 +1,35 @@ +package com.example.sarahtang.mdbsocials; + +import android.util.Log; + +import java.util.ArrayList; + +/** + * Created by sarahtang on 2/23/17. + * A model class that contains all properties of a social + */ + +public class Social { + String name; + String date; + String description; + String host; //email + int numberInterested; + String firebaseimageURL; + ArrayList peopleInterested; + + public Social() { + Log.e("SocialClass", "noInfo"); + } + + public Social (String name, String date, String description, String creator, int numberInterested, ArrayList peopleInterested, String firebaseimageURL) { + this.name = name; + this.date = date; + this.description = description; + this.host = creator; + this.numberInterested = numberInterested; + this.peopleInterested = peopleInterested; + this.firebaseimageURL = firebaseimageURL; + + } +} diff --git a/app/src/main/java/com/example/sarahtang/mdbsocials/SocialsAdapter.java b/app/src/main/java/com/example/sarahtang/mdbsocials/SocialsAdapter.java new file mode 100644 index 0000000..285db46 --- /dev/null +++ b/app/src/main/java/com/example/sarahtang/mdbsocials/SocialsAdapter.java @@ -0,0 +1,161 @@ +package com.example.sarahtang.mdbsocials; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.AsyncTask; +import android.support.annotation.NonNull; +import android.support.v7.widget.CardView; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.firebase.FirebaseApp; +import com.google.firebase.FirebaseOptions; +import com.google.firebase.storage.FirebaseStorage; + +import java.util.ArrayList; + +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; + +/** + * Created by sarahtang on 2/21/17. + * Connects social layout with social information. + */ + +public class SocialsAdapter extends RecyclerView.Adapter { + private Context context; + public View view; + ArrayList listSocials; + + public static final String NAME_KEY = "name"; + public static final String HOST_KEY = "host"; + public static final String DESCRIPTION_KEY = "description"; + public static final String PEOPLE_INTERESTED = "peopleInterested"; + public static final String NUMBER_INTERESTED = "numberInterested"; + public static final String FIREBASE_URL = "firebaseURL"; + public static final String FIREBASE_KEY = "firebaseKey"; + + public SocialsAdapter(Context context, ArrayList listSocials) { + this.context = context; + this.listSocials = listSocials; + } + + @Override + public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.socials_row_view, parent, false); + return new CustomViewHolder(view); + } + + @Override + public void onBindViewHolder(final CustomViewHolder holder, int position) { + final Social social = listSocials.get(listSocials.size()-position-1); + holder.nameEvent.setText(social.name); + holder.creatorEvent.setText(social.host); + + if (social.numberInterested == 1) { + holder.numberInterestedEvent.setText("" + social.numberInterested + context.getString(R.string.personInterested)); + } + else { + holder.numberInterestedEvent.setText("" + social.numberInterested + context.getString(R.string.peopleInterested)); + } + + class DownloadFilesTask extends AsyncTask { + protected Bitmap doInBackground(String... strings) { + try {return Glide. + with(context). + load(strings[0]). + asBitmap(). + into(100, 100). // Width and height + get();} + catch (Exception e) {return null;} + } + + protected void onProgressUpdate(Void... progress) {} + + protected void onPostExecute(Bitmap result) { + holder.imageEvent.setImageBitmap(result); + } + } + + FirebaseOptions opts = FirebaseApp.getInstance().getOptions(); + Log.i("SocialsAdapter", "Bucket = " + opts.getStorageBucket()); + + FirebaseStorage.getInstance().getReferenceFromUrl("gs://mdbsocials-fdfae.appspot.com").child(social.firebaseimageURL + ".png").getDownloadUrl().addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(Uri uri) { + (new DownloadFilesTask()).execute(uri.toString()); + Log.d("Getting image", uri.toString()); + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception exception) { + Log.d("No image :(", exception.toString()); + } + }); + + } + + @Override + public int getItemCount() { + if (listSocials != null) { + return listSocials.size(); + } + else {return 0;} + } + + //CARD View for custom view holder in List activity recycler view + public class CustomViewHolder extends RecyclerView.ViewHolder { + TextView nameEvent; + TextView creatorEvent; + TextView numberInterestedEvent; + ImageView imageEvent; + + public CustomViewHolder(View view) { + super(view); + this.nameEvent = (TextView) (view.findViewById(R.id.nameEvent)); + this.creatorEvent = (TextView) (view.findViewById(R.id.creatorEvent)); + this.numberInterestedEvent = (TextView) (view.findViewById(R.id.numberInterestedEvent)); + this.imageEvent = (ImageView) (view.findViewById(R.id.imageEvent)); + CardView cardView = (CardView) (view.findViewById(R.id.viewSocial)); + + cardView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(context, DetailsActivity.class); + context.startActivity(intent); + } + }); + + //Get adapter position gets the position of row that was clicked on --> allows for information of correct social + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Log.d("SocialsAdapter", "detailsIntent?"); + Social social = listSocials.get((listSocials.size()) - getAdapterPosition() - 1); + Intent intent = new Intent(context, DetailsActivity.class); + intent.putExtra(NAME_KEY, social.name); + intent.putExtra(HOST_KEY, social.host); + intent.putExtra(DESCRIPTION_KEY, social.description); + intent.putExtra(PEOPLE_INTERESTED, social.peopleInterested); + intent.putExtra(NUMBER_INTERESTED, social.numberInterested); + intent.putExtra(FIREBASE_URL, social.firebaseimageURL); + intent.putExtra(FIREBASE_KEY, ListActivity.keyList.get((listSocials.size()) - getAdapterPosition() - 1)); + intent.addFlags(FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + } + + } + +} diff --git a/app/src/main/res/drawable/circular_progress_bar.xml b/app/src/main/res/drawable/circular_progress_bar.xml new file mode 100644 index 0000000..9ebe2c0 --- /dev/null +++ b/app/src/main/res/drawable/circular_progress_bar.xml @@ -0,0 +1,23 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_add_black_24dp.xml b/app/src/main/res/drawable/ic_add_black_24dp.xml new file mode 100644 index 0000000..b9b8eca --- /dev/null +++ b/app/src/main/res/drawable/ic_add_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_add_circle_outline_black_24dp.xml b/app/src/main/res/drawable/ic_add_circle_outline_black_24dp.xml new file mode 100644 index 0000000..cc39b56 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_circle_outline_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_group_black_24dp.xml b/app/src/main/res/drawable/ic_group_black_24dp.xml new file mode 100644 index 0000000..6877df0 --- /dev/null +++ b/app/src/main/res/drawable/ic_group_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_navigate_before_black_24dp.xml b/app/src/main/res/drawable/ic_navigate_before_black_24dp.xml new file mode 100644 index 0000000..7428907 --- /dev/null +++ b/app/src/main/res/drawable/ic_navigate_before_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_photo_camera_black_24dp.xml b/app/src/main/res/drawable/ic_photo_camera_black_24dp.xml new file mode 100644 index 0000000..4fa7158 --- /dev/null +++ b/app/src/main/res/drawable/ic_photo_camera_black_24dp.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_star_black_24dp.xml b/app/src/main/res/drawable/ic_star_black_24dp.xml new file mode 100644 index 0000000..fa1c999 --- /dev/null +++ b/app/src/main/res/drawable/ic_star_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/logo.png b/app/src/main/res/drawable/logo.png new file mode 100644 index 0000000..95b42ee Binary files /dev/null and b/app/src/main/res/drawable/logo.png differ diff --git a/app/src/main/res/drawable/mdblogo.jpg b/app/src/main/res/drawable/mdblogo.jpg new file mode 100644 index 0000000..bd67d5b Binary files /dev/null and b/app/src/main/res/drawable/mdblogo.jpg differ diff --git a/app/src/main/res/drawable/mdblogo2.jpg b/app/src/main/res/drawable/mdblogo2.jpg new file mode 100644 index 0000000..bd67d5b Binary files /dev/null and b/app/src/main/res/drawable/mdblogo2.jpg differ diff --git a/app/src/main/res/layout/activity_details.xml b/app/src/main/res/layout/activity_details.xml new file mode 100644 index 0000000..6bec9cd --- /dev/null +++ b/app/src/main/res/layout/activity_details.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_interested.xml b/app/src/main/res/layout/activity_interested.xml new file mode 100644 index 0000000..02c6bf4 --- /dev/null +++ b/app/src/main/res/layout/activity_interested.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/app/src/main/res/layout/activity_list.xml b/app/src/main/res/layout/activity_list.xml new file mode 100644 index 0000000..8a9e120 --- /dev/null +++ b/app/src/main/res/layout/activity_list.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..e8eba9a --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + +