diff --git a/.gitignore b/.gitignore index b44359f..4014e95 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,6 @@ output.json #Since Android Studio 3.0 #NDK obj/ -.externalNativeBuild \ No newline at end of file +.externalNativeBuild + +/DEPRECATED \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 037d78a..f0e21a1 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,7 +3,6 @@ - diff --git a/app/build.gradle b/app/build.gradle index 9ae3f37..8c13a6a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,15 +1,19 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 + compileSdkVersion 27 buildToolsVersion "26.0.2" defaultConfig { applicationId "com.groupproject" - minSdkVersion 15 - targetSdkVersion 25 + minSdkVersion 24 + targetSdkVersion 27 + multiDexEnabled true versionCode 1 versionName "1.0" + +// resConfigs "auto" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + vectorDrawables.useSupportLibrary = true } buildTypes { release { @@ -17,25 +21,60 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + + compileOptions { + targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_1_8 + } } dependencies { - implementation 'com.google.firebase:firebase-auth:11.0.4' + implementation 'com.google.firebase:firebase-storage:11.6.2' 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.firebaseui:firebase-ui-storage:0.6.0' + compile 'com.google.firebase:firebase-database:11.6.2' + compile 'com.google.firebase:firebase-core:11.6.2' + compile 'com.google.firebase:firebase-auth:11.6.2' + + compile 'com.firebaseui:firebase-ui-database:3.1.0' + + compile 'com.google.android.gms:play-services-location:11.6.2' + compile 'com.google.android.gms:play-services-auth:11.6.2' + compile 'com.google.android.gms:play-services-maps:11.6.2' + + compile 'net.jodah:expiringmap:0.5.8' - compile 'com.android.support:appcompat-v7:25.3.1' + compile 'com.facebook.android:facebook-android-sdk:4.28.0' + + compile 'com.android.support:recyclerview-v7:27.0.2' compile 'com.android.support.constraint:constraint-layout:1.0.2' - compile 'com.facebook.android:facebook-android-sdk:[4,5)' - compile 'com.android.support:support-v4:25.3.1' - compile 'com.google.android.gms:play-services-maps:11.0.4' - compile 'com.google.android.gms:play-services:11.0.4' - compile 'com.android.support:design:25.3.1' + compile 'com.android.support:support-v4:27.0.2' + compile "com.android.support:design:27.0.2" + compile 'com.android.support:appcompat-v7:27.0.2' + compile "com.android.support:customtabs:27.0.2" + compile "com.android.support:cardview-v7:27.0.2" + + testCompile 'junit:junit:4.12' } + + apply plugin: 'com.google.gms.google-services' + + + + + + + + + + + + diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000..9447ce1 --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,71 @@ +{ + "project_info": { + "project_number": "942324893888", + "firebase_url": "https://cmps121groupproject.firebaseio.com", + "project_id": "cmps121groupproject", + "storage_bucket": "cmps121groupproject.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:942324893888:android:7eae2e78f97fb57c", + "android_client_info": { + "package_name": "com.groupproject" + } + }, + "oauth_client": [ + { + "client_id": "942324893888-b48nk1potcm57l3qluondiori5ep7kli.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.groupproject", + "certificate_hash": "258e567c165a7a69d3a877e5e9d32188891e7ff5" + } + }, + { + "client_id": "942324893888-0i1o3vb81ocql43i7ij50o6ns5i6f37b.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.groupproject", + "certificate_hash": "786cc879e8f2496637368ccd182d31376276bba8" + } + }, + { + "client_id": "942324893888-eqh6lrn11gniur1e2g1oglbnqjflsuj7.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.groupproject", + "certificate_hash": "ede084a57df325def457472f38c36a5b0251d13a" + } + }, + { + "client_id": "942324893888-ib2l5s9342h42ro4fi94p5mbede9ad3u.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDHwJBHBG6IXKGF3htdR01x3YS32JG-w88" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 2, + "other_platform_oauth_client": [ + { + "client_id": "942324893888-ib2l5s9342h42ro4fi94p5mbede9ad3u.apps.googleusercontent.com", + "client_type": 3 + } + ] + }, + "ads_service": { + "status": 2 + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/src/debug/res/values/strings.xml b/app/src/debug/res/values/strings.xml new file mode 100644 index 0000000..78717b8 --- /dev/null +++ b/app/src/debug/res/values/strings.xml @@ -0,0 +1,5 @@ + + + save + end date + \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ac3cef6..9254fa3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ @@ -13,14 +14,18 @@ - + + + android:theme="@style/Theme.AppCompat.Light.NoActionBar"> @@ -38,15 +43,6 @@ - - - - @@ -67,19 +63,37 @@ - - - + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/groupproject/Controller/AddEventScreen.java b/app/src/main/java/com/groupproject/Controller/AddEventScreen.java deleted file mode 100644 index 5b17872..0000000 --- a/app/src/main/java/com/groupproject/Controller/AddEventScreen.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.groupproject.Controller; - -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.widget.ArrayAdapter; -import android.widget.Spinner; - -import com.groupproject.R; - -import java.util.ArrayList; -import java.util.Calendar; - -/** - * Created by haileypun on 31/10/2017. - */ - -public class AddEventScreen extends AppCompatActivity { - - ArrayList years = new ArrayList<>(); - ArrayList days = new ArrayList<>(); - ArrayList months = new ArrayList<>(); - ArrayList hours = new ArrayList<>(); - ArrayList minutes = new ArrayList<>(); - - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.create_event); - - dropdownYear(); - dropdownDay(); - dropdownMonth(); - dropdownHour(); - dropdownMinute(); - } - - public void dropdownYear(){ - - int currentYear = Calendar.getInstance().get(Calendar.YEAR); - - for(int i = 1900; i <= currentYear; i++ ){ - - years.add(Integer.toString(i)); - - } - - ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, years); - - Spinner selectYear = (Spinner)findViewById(R.id.Year); - - selectYear.setAdapter(adapter); - - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - - } - - public void dropdownDay(){ - - int currentDays = Calendar.getInstance().get(Calendar.DAY_OF_MONTH); - - for(int i = 1; i <= currentDays; i++ ){ - - days.add(Integer.toString(i)); - - } - - days.add("29"); - days.add("30"); - days.add("31"); - - ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, days); - - Spinner selectDay = (Spinner)findViewById(R.id.Day); - - selectDay.setAdapter(adapter); - - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - - } - - public void dropdownMonth(){ - - months.add("JAN"); - months.add("FEB"); - months.add("MAR"); - months.add("APR"); - months.add("MAY"); - months.add("JUN"); - months.add("JUL"); - months.add("AUG"); - months.add("SEP"); - months.add("OCT"); - months.add("NOV"); - months.add("DEC"); - - ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, months); - - Spinner selectMonth = (Spinner)findViewById(R.id.Month); - - selectMonth.setAdapter(adapter); - - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - - } - - public void dropdownHour(){ - - for(int i = 0; i <= 9; i++){ - - hours.add("0"+Integer.toString(i)); - - } - - for(int i = 10; i <= 23; i++ ){ - - hours.add(Integer.toString(i)); - - } - - ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, hours); - - Spinner selectHour = (Spinner)findViewById(R.id.Hours); - - selectHour.setAdapter(adapter); - - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - - } - - public void dropdownMinute(){ - - for(int i = 0; i <= 9; i++){ - - minutes.add("0"+Integer.toString(i)); - - } - - for (int j = 10; j <= 59; j++){ - - minutes.add(Integer.toString(j)); - - } - - ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, minutes); - - Spinner selectMinute = (Spinner)findViewById(R.id.Minutes); - - selectMinute.setAdapter(adapter); - - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - - } -} \ No newline at end of file diff --git a/app/src/main/java/com/groupproject/Controller/BaseActivity.java b/app/src/main/java/com/groupproject/Controller/BaseActivity.java new file mode 100644 index 0000000..ab3a562 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/BaseActivity.java @@ -0,0 +1,302 @@ +package com.groupproject.Controller; + +import android.app.Activity; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.SystemClock; +import android.support.annotation.NonNull; +import android.support.design.widget.NavigationView; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.SearchView; +import android.support.v7.widget.Toolbar; +import android.view.ContextMenu; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.ImageView; +import android.widget.TextView; + +import com.groupproject.Controller.MapActivites.MapsFragment; +import com.groupproject.Controller.SearchActivities.SearchFragment; +import com.groupproject.Controller.SearchActivities.SearchType; +import com.groupproject.Controller.SideBarActivities.SidebarFragment; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.DataBaseAPI.DataBaseCallBacks; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.User; +import com.groupproject.R; + +import java.util.List; + + +public class BaseActivity extends AppCompatActivity + implements NavigationView.OnNavigationItemSelectedListener, NavigationView.OnCreateContextMenuListener, + DataBaseCallBacks { + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + private InputMethodManager imm; + + FragmentManager fragmentManager = getSupportFragmentManager(); + SearchFragment searchFrag = new SearchFragment(); + SidebarFragment sidebarFragment = new SidebarFragment(); + Fragment mapsFrag = MapsFragment.newInstance(); + private SearchView searchView; + private Fragment currentFragment; + private ActionBarDrawerToggle actionBarDrawerToggle; + TextView userProfileName; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + DataBaseAPI.removeExpiredEvents(); + + setContentView(R.layout.navigation_base); + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + imm = (InputMethodManager) getApplication().getSystemService(BaseActivity.INPUT_METHOD_SERVICE); + + DrawerLayout drawer = findViewById(R.id.drawer_layout); + actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, + R.string.navigation_drawer_open, R.string.navigation_drawer_close) { + @Override + public void onDrawerClosed(View drawerView) { + super.onDrawerClosed(drawerView); + } + + @Override + public void onDrawerOpened(View drawerView) { + super.onDrawerOpened(drawerView); + InputMethodManager inputMethodManager = (InputMethodManager) + getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); + } + + @Override + public void onDrawerSlide(View drawerView, float slideOffset) { + super.onDrawerSlide(drawerView, slideOffset); + InputMethodManager inputMethodManager = (InputMethodManager) + getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); + } + }; + drawer.addDrawerListener(actionBarDrawerToggle); + actionBarDrawerToggle.syncState(); + + NavigationView navigationView = findViewById(R.id.nav_view); + navigationView.setNavigationItemSelectedListener(this); + + getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); + getSupportActionBar().setCustomView(R.layout.abs_layout); + + + FragmentTransaction ft = fragmentManager.beginTransaction(); + ft.replace(R.id.dashboard_content, mapsFrag, "maps"); + currentFragment = mapsFrag; + ft.commit(); + + if (getIntent().getStringExtra("openNotifications") != null) { + openNotifications(); + } + } + + + @Override + public void onConfigurationChanged(Configuration configuration){ + super.onConfigurationChanged(configuration); + actionBarDrawerToggle.onConfigurationChanged(configuration); + } + + + @Override + public void onBackPressed() { + DrawerLayout drawer = findViewById(R.id.drawer_layout); + if (drawer.isDrawerOpen(GravityCompat.START)) { + drawer.closeDrawer(GravityCompat.START); + } else if (currentFragment != mapsFrag) { + fragmentManager.beginTransaction().replace(R.id.dashboard_content, mapsFrag, + "maps").remove(searchFrag).commitAllowingStateLoss(); + currentFragment = mapsFrag; + if (searchView != null) { + searchView.setQuery("", true); + searchView.clearFocus(); + } + } else { + super.onBackPressed(); + } + } + + + public void onResume() { + super.onResume(); + AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); + Intent intent = new Intent(this, NotificationService.class); + PendingIntent pi = PendingIntent.getService(this, 0, intent, 0); + if (am != null) { + am.cancel(pi); + am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + 60*1000, + 60*1000, pi); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + String currentUserID = dataBaseAPI.getCurrentUserID(); + dataBaseAPI.getUser(currentUserID, this, null); + getMenuInflater().inflate(R.menu.navigation_bar, menu); + final MenuItem myActionMenuItem = menu.findItem( R.id.action_search); + searchView = (SearchView) myActionMenuItem.getActionView(); + searchView.clearFocus(); + searchView.setIconifiedByDefault(false); + searchView.setIconified(false); + + myActionMenuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { + @Override + public boolean onMenuItemActionExpand(MenuItem menuItem) { + if(currentFragment == mapsFrag) { + fragmentManager.beginTransaction().replace(R.id.dashboard_content, searchFrag, + "search").commit(); + currentFragment = searchFrag; + } + searchView.findFocus(); + return true; + } + + @Override + public boolean onMenuItemActionCollapse(MenuItem menuItem) { + fragmentManager.beginTransaction().replace(R.id.dashboard_content, mapsFrag, + "maps").remove(searchFrag).commitAllowingStateLoss(); + currentFragment = mapsFrag; + searchView.setIconified(true); + searchView.clearFocus(); + currentFragment = mapsFrag; + return true; + } + }); + + + ImageView closeButton = searchView.findViewById(R.id.search_close_btn); + closeButton.setOnClickListener(v -> { + searchView.setQuery("", true); + imm.hideSoftInputFromWindow(searchView.getWindowToken(), 0); + fragmentManager.beginTransaction().replace(R.id.dashboard_content, mapsFrag, + "maps").remove(searchFrag).commitAllowingStateLoss(); + currentFragment = mapsFrag; + searchView.clearFocus(); + }); + + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + imm.hideSoftInputFromWindow(searchView.getWindowToken(), 0); + return false; + } + + @Override + public boolean onQueryTextChange(String s) { + //TODO Download list if filtering + if(currentFragment == searchFrag) + searchFrag.setQ(s.toLowerCase()); + else if(currentFragment == sidebarFragment){ + sidebarFragment.filterResults(s.toLowerCase()); + } + return false; + } + }); + return true; + } + + @SuppressWarnings("StatementWithEmptyBody") + @Override + public boolean onNavigationItemSelected(@NonNull MenuItem item) { + // Handle navigation view item clicks here. + int id = item.getItemId(); + Bundle bundle = new Bundle(); + sidebarFragment = new SidebarFragment(); + if (id == R.id.friends) { + bundle.putString("type", "friend"); + }else if (id == R.id.events) { + bundle.putString("type", "events"); + } else if (id == R.id.groups) { + bundle.putString("type", "groups"); + }else if (id == R.id.notifications) { + bundle.putString("type", "notifications"); + } else if (id == R.id.sign_out) { + dataBaseAPI.signOut(this); + return true; + } + sidebarFragment.setArguments(bundle); + fragmentManager.beginTransaction().replace(currentFragment.getId(), sidebarFragment, + "sidebar").remove(searchFrag).commitAllowingStateLoss(); + currentFragment = sidebarFragment; + DrawerLayout drawer = findViewById(R.id.drawer_layout); + drawer.closeDrawer(GravityCompat.START); + return true; + } + + public Fragment getActiveFragment() { + if (getSupportFragmentManager().getBackStackEntryCount() == 0) { + return null; + } + String tag = getSupportFragmentManager() + .getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1) + .getName(); + return getSupportFragmentManager().findFragmentByTag(tag); + } + + private void openNotifications() { + sidebarFragment = new SidebarFragment(); + Bundle bundle = new Bundle(); + bundle.putString("type", "notifications"); + sidebarFragment.setArguments(bundle); + fragmentManager.beginTransaction().replace(currentFragment.getId(), sidebarFragment, + "sidebar").remove(searchFrag).commitAllowingStateLoss(); + currentFragment = sidebarFragment; + DrawerLayout drawer = findViewById(R.id.drawer_layout); + drawer.closeDrawer(GravityCompat.START); + } + + @Override + public void onCreateContextMenu(ContextMenu var1, View var2, ContextMenu.ContextMenuInfo var3){ + InputMethodManager inputMethodManager = + (InputMethodManager) this.getSystemService(Activity.INPUT_METHOD_SERVICE); + inputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0); + } + + @Override + public void getUser(User user, ViewHolder holder) { + userProfileName = findViewById(R.id.userProfile); + userProfileName.setText(user.getName()); + } + + @Override + public void getEvent(Event event, ViewHolder holder) { + + } + + @Override + public void getGroup(Group group, ViewHolder holder) { + + } + + @Override + public void executeQuery(List result, SearchType.Type type) { + + } +} diff --git a/app/src/main/java/com/groupproject/Controller/BootReceiver.java b/app/src/main/java/com/groupproject/Controller/BootReceiver.java new file mode 100644 index 0000000..1d61361 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/BootReceiver.java @@ -0,0 +1,22 @@ +package com.groupproject.Controller; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.SystemClock; + +public class BootReceiver extends BroadcastReceiver { + public void onReceive(Context context, Intent intent) { + AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + Intent i = new Intent(context, NotificationService.class); + PendingIntent pi = PendingIntent.getService(context, 0, i, 0); + if (am != null) { + am.cancel(pi); + am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + 60*1000, + 60*1000, pi); + } + } +} diff --git a/app/src/main/java/com/groupproject/Controller/EventActivities/CreateEventActivity.java b/app/src/main/java/com/groupproject/Controller/EventActivities/CreateEventActivity.java new file mode 100644 index 0000000..86bb777 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/EventActivities/CreateEventActivity.java @@ -0,0 +1,351 @@ +package com.groupproject.Controller.EventActivities; + +import android.app.Activity; +import android.app.DatePickerDialog; +import android.app.TimePickerDialog; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.Spinner; +import android.widget.Switch; +import android.widget.Toast; + +import com.google.android.gms.maps.model.LatLng; +import com.google.firebase.database.Query; +import com.groupproject.Controller.SearchActivities.SearchType; +import com.google.firebase.storage.FirebaseStorage; +import com.google.firebase.storage.StorageReference; +import com.google.firebase.storage.UploadTask; +import com.groupproject.Controller.ViewHolder; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.DataBaseAPI.DataBaseCallBacks; +import com.groupproject.Model.CustomLocation; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.User; +import com.groupproject.Model.Visibility; +import com.groupproject.R; + +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Objects; + +public class CreateEventActivity extends AppCompatActivity implements DataBaseCallBacks { + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + + private EditText name; + private EditText description; + private EditText startDate; + private EditText endDate; + private Calendar startDateCalendar; + private Calendar endDateCalendar; + private DatePickerDialog.OnDateSetListener start_date_picker; + private DatePickerDialog.OnDateSetListener end_date_picker; + private Spinner visibility, groupSelector; + private ImageButton upload; + private StorageReference mStorageRef; + private InputStream image; + private static final int PICK_PHOTO_FOR_AVATAR = 0; + + private boolean asGroup; + + ArrayList options = new ArrayList<>(); + ArrayList groups = new ArrayList<>(); + ArrayList groupNames = new ArrayList<>(); + private ArrayAdapter groupAdapter; + private Switch aSwitch; + private Event event; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final LatLng eventLocation; + + setContentView(R.layout.event_create); + + mStorageRef = FirebaseStorage.getInstance().getReference(); + + if (getIntent().hasExtra("event_location")) { + eventLocation = getIntent().getExtras().getParcelable("event_location"); + } else { + throw new IllegalArgumentException("Activity cannot find extras event_location"); + } + setContentView(R.layout.event_create); + startDateCalendar = Calendar.getInstance(); + endDateCalendar = Calendar.getInstance(); + name =findViewById(R.id.name); + description =findViewById(R.id.desc); + startDate =findViewById(R.id.start_date); + endDate =findViewById(R.id.end_date); + groupSelector =findViewById(R.id.groupSelectorSpinner); + + groupAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, groups); + groupSelector.setAdapter(groupAdapter); + groupSelector.setVisibility(View.INVISIBLE); + + Query query = dataBaseAPI.getmUserRef().child(dataBaseAPI.getCurrentUserID()).child("joinedGroupIDs"); + dataBaseAPI.executeQuery(query, this, SearchType.Type.GROUPS); + + aSwitch = findViewById(R.id.createAsGroup); + aSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { + asGroup = isChecked; + if(isChecked) + groupSelector.setVisibility(View.VISIBLE); + else + groupSelector.setVisibility(View.INVISIBLE); + }); + + upload = findViewById(R.id.uploadEvent); + upload.setOnClickListener(view -> { + pickImage(); + }); + + start_date_picker = (view, year, monthOfYear, dayOfMonth) -> { + updateCalendar(startDateCalendar, year, monthOfYear, dayOfMonth); + endDate.setText(""); + int hour = startDateCalendar.get(Calendar.HOUR_OF_DAY); + int minute = startDateCalendar.get(Calendar.MINUTE); + createTimePicker(startDateCalendar, startDate, hour, minute, null); + }; + + startDate.setOnClickListener(v -> { + DatePickerDialog datePickerDialog = new DatePickerDialog( + this, + start_date_picker, + startDateCalendar.get(Calendar.YEAR), + startDateCalendar.get(Calendar.MONTH), + startDateCalendar.get(Calendar.DAY_OF_MONTH)); + datePickerDialog.getDatePicker().setMinDate(System.currentTimeMillis() - 1000); + datePickerDialog.show(); + }); + + end_date_picker = (view, year, monthOfYear, dayOfMonth) -> { + updateCalendar(endDateCalendar, year, monthOfYear, dayOfMonth); + updateCalendarTime(endDateCalendar, startDateCalendar.get(Calendar.HOUR_OF_DAY), + startDateCalendar.get(Calendar.MINUTE)); + endDateCalendar.add(Calendar.HOUR, 2); + int hour = endDateCalendar.get(Calendar.HOUR_OF_DAY); + int minute = endDateCalendar.get(Calendar.MINUTE); + createTimePicker(endDateCalendar, endDate, hour, minute, startDateCalendar); + }; + + endDate.setOnClickListener(v -> { + if (!startDate.getText().toString().trim().isEmpty()) { + //Get start date's date and assign in to the end date calendar + DateFormat format = new SimpleDateFormat("MM/dd/yy", Locale.US); + Date date = null; + try { + date = format.parse(startDate.getText().toString()); + } catch (ParseException e) { + e.printStackTrace(); + } + if (date != null) + endDateCalendar.setTime(date); + long minDate = endDateCalendar.getTimeInMillis(); + DatePickerDialog datePickerDialog = new DatePickerDialog( + this, + end_date_picker, + endDateCalendar.get(Calendar.YEAR), + endDateCalendar.get(Calendar.MONTH), + endDateCalendar.get(Calendar.DAY_OF_MONTH)); + datePickerDialog.getDatePicker().setMinDate(minDate); + datePickerDialog.show(); + } + }); + + Button saveButton = findViewById(R.id.savebutton); + saveButton.setOnClickListener(v -> { + if (allDataEntered()) { + String myFormat = "MM/dd/yy hh:mm"; + SimpleDateFormat sdf = new SimpleDateFormat(myFormat, Locale.US); + try { + Date sDate = sdf.parse(startDate.getText().toString()); + Date fDate = sdf.parse(endDate.getText().toString()); + Visibility.VISIBILITY eventVis = (visibility.getSelectedItem().toString().equals("Public")) ? + Visibility.VISIBILITY.PUBLIC : Visibility.VISIBILITY.INVITE_ONLY; + + if (eventLocation != null) { + event = new Event(sDate, fDate, + new CustomLocation(eventLocation.latitude, eventLocation.longitude), eventVis, + name.getText().toString(), description.getText().toString(), dataBaseAPI.getCurrentUserID()); + dataBaseAPI.addEventToUser(event); + + if (asGroup) { + Group group = (Group) groupSelector.getSelectedItem(); + Query inviteGroup = dataBaseAPI.getmGroupRef().child(group.getId()).child("membersIDs"); + dataBaseAPI.executeQuery(inviteGroup, this, SearchType.Type.USERS); + dataBaseAPI.getmGroupRef().child(group.getId()).child("eventsIDs").child(event.getId()).setValue(true); + event.setGroupName(group.getName()); + } + + dataBaseAPI.addEventToUser(event); + if (image != null) { + StorageReference groupRef = mStorageRef.child(event.getId() + ".jpg"); + UploadTask uploadTask = groupRef.putStream(image); + uploadTask.addOnFailureListener(exception -> { + // Handle unsuccessful uploads + }).addOnSuccessListener(taskSnapshot -> { + // taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL. + Uri downloadUrl = taskSnapshot.getDownloadUrl(); + }); + } + } + Intent intent = new Intent(this, EventInfoActivity.class); + intent.putExtra("key", event.getId()); + startActivity(intent); + StorageReference groupRef = mStorageRef.child(event.getId()+".jpg"); + if (image != null) { + UploadTask uploadTask = groupRef.putStream(image); + uploadTask.addOnFailureListener(exception -> { + // Handle unsuccessful uploads + }).addOnSuccessListener(taskSnapshot -> { + // taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL. + Uri downloadUrl = taskSnapshot.getDownloadUrl(); + }); + } + finish(); + } catch (ParseException ignored) { + + } + } else { + Toast.makeText(this, "Please fill in all the data", + Toast.LENGTH_LONG).show(); + } + }); + + options.add("Public"); + options.add("Private"); + ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, options); + visibility = findViewById(R.id.visibility); + visibility.setAdapter(adapter); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + } + + private void createTimePicker(final Calendar calendar, final EditText label, int hour, int min, + final Calendar calendarMin) { + TimePickerDialog timePickerDialog; + timePickerDialog = new TimePickerDialog(this, + (timePicker, selectedHour, selectedMinute) -> { + if (calendarMin != null) { + updateCalendarTime(calendar, selectedHour, selectedMinute); + if (calendar.getTime().compareTo(calendarMin.getTime()) > 0) { + updateLabel(label, calendar, selectedHour, + selectedMinute); + updateCalendarTime(calendar, selectedHour, selectedMinute); + } else { + Toast.makeText(this, + "End time cannot be before start time", + Toast.LENGTH_LONG).show(); + } + } else { + updateLabel(label, calendar, selectedHour, + selectedMinute); + updateCalendarTime(calendar, selectedHour, selectedMinute); + } + }, hour, min, true); + timePickerDialog.setTitle("Select Time"); + timePickerDialog.show(); + } + + private void updateCalendarTime(Calendar calendar, int hour, int min) { + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, min); + } + + private void updateCalendar(Calendar calendar, int year, int month, int day) { + calendar.set(Calendar.YEAR, year); + calendar.set(Calendar.MONTH, month); + calendar.set(Calendar.DAY_OF_MONTH, day); + } + + private void updateLabel(EditText label, Calendar calendar, int hour, int min) { + String myFormat = "MM/dd/yy"; + SimpleDateFormat sdf = new SimpleDateFormat(myFormat, Locale.US); + String hourString = hour + "", minString = min + ""; + if (hour == 0) + hourString = "00"; + if (min == 0) + minString = "00"; + String text = sdf.format(calendar.getTime()) + " " + hourString + ":" + minString; + label.setText(text); + } + + private boolean allDataEntered() { + return isEditTextEmpty(name) && isEditTextEmpty(description) && + isEditTextEmpty(startDate) && isEditTextEmpty(endDate); + } + + private boolean isEditTextEmpty(EditText editText) { + return !editText.getText().toString().trim().isEmpty(); + } + + + public void pickImage() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("image/*"); + startActivityForResult(intent, PICK_PHOTO_FOR_AVATAR); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == PICK_PHOTO_FOR_AVATAR && resultCode == Activity.RESULT_OK) { + if (data == null) { + return; + } + try { + InputStream inputStream = getApplicationContext().getContentResolver().openInputStream(data.getData()); + image = inputStream; + Toast.makeText(getApplicationContext(), "Image uploaded.", Toast.LENGTH_LONG).show(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + } + + @Override + public void getUser(User user, ViewHolder holder) { + if(!Objects.equals(user.getId(), dataBaseAPI.getCurrentUserID())) + dataBaseAPI.sendEventInvite(user.getId(), event.getId()); + } + + @Override + public void getEvent(Event event, ViewHolder holder) { + + } + + @Override + public void getGroup(Group group, ViewHolder holder) { + groups.add(group); + groupNames.add(group.getName()); + groupAdapter.notifyDataSetChanged(); + } + + @Override + public void executeQuery(List result, SearchType.Type type) { + if(type == SearchType.Type.GROUPS) { + for (String id : result) { + dataBaseAPI.getGroup(id, this, null); + } + }else if(type == SearchType.Type.USERS){ + for (String id : result) { + dataBaseAPI.getUser(id, this, null); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/groupproject/Controller/EventActivities/EventInfoActivity.java b/app/src/main/java/com/groupproject/Controller/EventActivities/EventInfoActivity.java new file mode 100644 index 0000000..a9a36f5 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/EventActivities/EventInfoActivity.java @@ -0,0 +1,208 @@ +package com.groupproject.Controller.EventActivities; + +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.text.Html; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.firebase.ui.storage.images.FirebaseImageLoader; +import com.google.firebase.storage.FirebaseStorage; +import com.google.firebase.storage.StorageReference; +import com.google.firebase.database.Query; +import com.groupproject.Controller.InviteActivity; +import com.groupproject.Controller.SearchActivities.SearchType; +import com.groupproject.Controller.ViewHolder; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.DataBaseAPI.DataBaseCallBacks; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.User; +import com.groupproject.R; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public class EventInfoActivity extends AppCompatActivity implements DataBaseCallBacks { + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + private TextView eventText; + private TextView startDateText; + private TextView endDateText; + private TextView startTimeText; + private TextView endTimeText; + private TextView numOfPeopleText; + private TextView eventDescription; + private Button button; + private Button inviteButton; + private String userID; + private StorageReference mStorageRef; + private ImageView eventPic; + List goingEventsLists = new ArrayList<>(); + private ArrayAdapter adapter; + + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.event_info); + eventText = findViewById(R.id.eventName); + startDateText = findViewById(R.id.startDateText); + endDateText = findViewById(R.id.endDateText); + startTimeText = findViewById(R.id.startTimeText); + endTimeText = findViewById(R.id.endTimeText); + numOfPeopleText = findViewById(R.id.numOfPeopleText); + eventDescription = findViewById(R.id.eventDescription); + button = findViewById(R.id.btn_join_leave_del); + userID = dataBaseAPI.getCurrentUserID(); + resetEvent(); + mStorageRef = FirebaseStorage.getInstance().getReference(); + eventPic = findViewById(R.id.eventPic); + inviteButton = findViewById(R.id.invite_friends); + Button doneButton = findViewById(R.id.btn_done); + doneButton.setOnClickListener(view -> finish()); + } + + private void resetEvent() { + if (getIntent().hasExtra("key")) { + String event_id = getIntent().getStringExtra("key"); + dataBaseAPI.getEvent(event_id, this, null); + } + } + + private String changeStringDisplay(String string) { + return "" + string.charAt(0) + "" + + string.substring(1, string.length()) + ""; + } + + private boolean userGoingToEvent(Event event) { + return event.goingIDs != null && userID != null && event.goingIDs.contains(userID); + } + + private boolean userIsHost(Event event) { + return event != null && userID != null && event.getHostID().equals(userID); + } + + + private void assignButtons(Event event) { + if (event != null && userID != null && !userIsHost(event)) { + if (userGoingToEvent(event)) { + button.setBackgroundColor(getResources().getColor(R.color.red)); + button.setText(R.string.leave); + inviteButton.setVisibility(View.VISIBLE); + } else { + button.setBackgroundColor(getResources().getColor(R.color.green)); + button.setText(R.string.join); + inviteButton.setVisibility(View.GONE); + } + } + + if (event != null) { + button.setOnClickListener(v -> { + if (userID != null) { + if (userIsHost(event)) { + DialogInterface.OnClickListener dialogClickListener = (dialog, which) -> { + if (which == DialogInterface.BUTTON_POSITIVE) { + dataBaseAPI.deleteEvent(event); + finish(); + } + }; + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage("Are you sure you want to delete the event?") + .setPositiveButton("Yes", dialogClickListener) + .setNegativeButton("No", dialogClickListener).show(); + } else { + if (userGoingToEvent(event)) { + dataBaseAPI.leaveEvent(event); + resetEvent(); + } else { + dataBaseAPI.acceptEventInvite(event); + resetEvent(); + } + } + } + }); + + inviteButton.setOnClickListener(view -> { + Intent intent = new Intent(this, InviteActivity.class); + intent.putExtra("type", "event"); + intent.putExtra("id", event.getId()); + startActivity(intent); + }); + } + } + + public void display(Event event) { + eventText.setText(Html.fromHtml(changeStringDisplay(event.getName()))); + SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yy", Locale.US); + SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm", Locale.US); + startDateText.setText(dateFormat.format(event.getStartDate())); + endDateText.setText(dateFormat.format(event.getEndDate())); + startTimeText.setText(timeFormat.format(event.getStartDate())); + endTimeText.setText(timeFormat.format(event.getEndDate())); + String numOfPeople; + if (event.goingIDs == null) + numOfPeople = "0"; + else + numOfPeople = "" + event.goingIDs.size(); + numOfPeopleText.setText(numOfPeople); + if (userIsHost(event)) { + button.setText(R.string.Delete); + button.setBackgroundColor(getResources().getColor(R.color.red)); + } + } + + private void populateGoingUserList(Event event) { + ListView goingUsers = findViewById(R.id.goingUsers); + goingUsers.setAdapter(null); + adapter = new ArrayAdapter<> + (this, android.R.layout.simple_spinner_item, goingEventsLists); + goingUsers.setAdapter(adapter); + Query query = dataBaseAPI.getmEventRef().child(event.getId()).child("goingIDs"); + dataBaseAPI.executeQuery(query, this, SearchType.Type.EVENTS); + } + + @Override + public void getUser(User user, ViewHolder holder) { + if (!goingEventsLists.contains(user.getName())) { + goingEventsLists.add(user.getName()); + adapter.notifyDataSetChanged(); + } + } + + @Override + public void getEvent(Event event, ViewHolder holder) { + eventDescription.setText(event.getDescription()); + goingEventsLists.clear(); + StorageReference storageReference = mStorageRef.child(event.getId()+".jpg"); + Glide.with(this) + .using(new FirebaseImageLoader()) + .load(storageReference) + .into(eventPic); + display(event); + assignButtons(event); + populateGoingUserList(event); + } + + @Override + public void getGroup(Group group, ViewHolder holder) { + + } + + @Override + public void executeQuery(List result, SearchType.Type type) { + for (String id : result) { + dataBaseAPI.getUser(id, this, null); + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/groupproject/Controller/GroupActivities/NewGroup.java b/app/src/main/java/com/groupproject/Controller/GroupActivities/NewGroup.java new file mode 100644 index 0000000..3d2b40e --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/GroupActivities/NewGroup.java @@ -0,0 +1,119 @@ +package com.groupproject.Controller.GroupActivities; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.Spinner; +import android.widget.Toast; + +import com.google.firebase.storage.FirebaseStorage; +import com.google.firebase.storage.StorageReference; +import com.google.firebase.storage.UploadTask; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.Group; +import com.groupproject.Model.Visibility; +import com.groupproject.R; + +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.ArrayList; + +public class NewGroup extends AppCompatActivity { + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + private StorageReference mStorageRef; + private static final int PICK_PHOTO_FOR_AVATAR = 0; + private InputStream image; + EditText name; + ImageButton upload; + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.new_group); + + Button createGroup = findViewById(R.id.createGroup); + upload = findViewById(R.id.upload); + + name = findViewById(R.id.GroupNameEdit); + EditText description = findViewById(R.id.GroupDescriptionEdit); + EditText tags = findViewById(R.id.GroupTagsEdit); + ArrayList options = new ArrayList<>(); + options.add("Public"); + options.add("Private"); + ArrayAdapter adapter = new ArrayAdapter(this, + android.R.layout.simple_spinner_item, options); + Spinner visibility = findViewById(R.id.GroupVisibilitySpinner); + visibility.setAdapter(adapter); + + //TODO add tags + + mStorageRef = FirebaseStorage.getInstance().getReference(); + + createGroup.setOnClickListener(view -> { + Group g; + Visibility.VISIBILITY groupVis = + (visibility.getSelectedItem().toString().equals("Public")) ? + Visibility.VISIBILITY.PUBLIC : Visibility.VISIBILITY.INVITE_ONLY; + if (name.getText() != null && description.getText() != null) { + g = new Group(name.getText().toString(), description.getText().toString(), groupVis, + dataBaseAPI.getCurrentUserID()); + dataBaseAPI.addGroupToUser(g);//TODO fix this and use a callback + if(image != null) { + StorageReference groupRef = mStorageRef.child(g.getId() + ".jpg"); + UploadTask uploadTask = groupRef.putStream(image); + uploadTask.addOnFailureListener(exception -> { + // Handle unsuccessful uploads + }).addOnSuccessListener(taskSnapshot -> { + // taskSnapshot.getMetadata() contains file metadata such as size, + // content-type, and download URL. + Uri downloadUrl = taskSnapshot.getDownloadUrl(); + }); + } + finish(); + } else { + Toast.makeText(getApplicationContext(), "Please fill in all the data", + Toast.LENGTH_LONG).show(); + } + }); + + upload.setOnClickListener(view -> { + pickImage(); + }); + + + } + + public void pickImage() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("image/*"); + startActivityForResult(intent, PICK_PHOTO_FOR_AVATAR); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == PICK_PHOTO_FOR_AVATAR && resultCode == Activity.RESULT_OK) { + if (data != null) { + try { + //e.g. create user, then change "images" to where i was called from + InputStream inputStream = getApplicationContext().getContentResolver() + .openInputStream(data.getData()); + image = inputStream; + Toast.makeText(getApplicationContext(), "Image uploaded.", + Toast.LENGTH_LONG).show(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + } + } + + +} + diff --git a/app/src/main/java/com/groupproject/Controller/GroupActivities/ViewGroupActivity.java b/app/src/main/java/com/groupproject/Controller/GroupActivities/ViewGroupActivity.java new file mode 100644 index 0000000..165b386 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/GroupActivities/ViewGroupActivity.java @@ -0,0 +1,186 @@ +package com.groupproject.Controller.GroupActivities; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.firebase.ui.storage.images.FirebaseImageLoader; +import com.google.firebase.database.Query; +import com.google.firebase.storage.FirebaseStorage; +import com.google.firebase.storage.StorageReference; +import com.groupproject.Controller.InviteActivity; +import com.groupproject.Controller.SearchActivities.SearchType; +import com.groupproject.Controller.ViewHolder; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.DataBaseAPI.DataBaseCallBacks; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.User; +import com.groupproject.R; + +import java.util.ArrayList; +import java.util.List; + + +public class ViewGroupActivity extends AppCompatActivity implements DataBaseCallBacks { + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + private ArrayAdapter eventAdapter; + private ArrayAdapter memberAdapter; + + TextView groupName; + TextView groupDescription; + + Button groupInteract; + Button inviteButton; + ImageView groupPic; + List eventList = new ArrayList<>(); + List memberList = new ArrayList<>(); + + private StorageReference mStorageRef; + + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + setContentView(R.layout.view_group); + + Bundle b = getIntent().getExtras(); + String id = b.getString("key"); + dataBaseAPI.getGroup(id, this, null); + groupName = findViewById(R.id.groupName); + groupDescription = findViewById(R.id.groupDescription); + groupPic = findViewById(R.id.groupPic); + groupInteract = findViewById(R.id.groupInteract); + mStorageRef = FirebaseStorage.getInstance().getReference(); + + ListView eventListView = findViewById( R.id.eventListView); + ListView membersListView = findViewById( R.id.memberListView); + eventAdapter = new ArrayAdapter<> + (this, android.R.layout.simple_spinner_item, eventList); + memberAdapter = new ArrayAdapter<> + (this, android.R.layout.simple_spinner_item, memberList); + eventListView.setAdapter(eventAdapter); + membersListView.setAdapter(memberAdapter); + + inviteButton = findViewById(R.id.groupInvite); + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void getUser(User user, ViewHolder holder) { + memberList.add(user.getName()); + memberAdapter.notifyDataSetChanged(); + } + + @Override + public void getEvent(Event event, ViewHolder holder) { + eventList.add(event.getName()); + eventAdapter.notifyDataSetChanged(); + } + + + @Override + public void getGroup(Group group, ViewHolder holder) { + groupName.setText(group.getName()); + groupDescription.setText(group.getDescription()); + Query query1 = dataBaseAPI.getmGroupRef().child(group.getId()).child("membersIDs"); + dataBaseAPI.executeQuery(query1, this, SearchType.Type.USERS); + Query query2 = dataBaseAPI.getmGroupRef().child(group.getId()).child("eventsIDs"); + dataBaseAPI.executeQuery(query2, this, SearchType.Type.EVENTS); + StorageReference storageReference = mStorageRef.child(group.getId()+".jpg"); + Glide.with(this) + .using(new FirebaseImageLoader()) + .load(storageReference) + .into(groupPic); + + DataBaseAPI.STATUS status = dataBaseAPI.getGroupRelationShip(group); + switch (status) { + case HOST: + groupInteract.setText("Delete Group"); + break; + case HIDDEN: + finish(); + break; + case JOINED: + groupInteract.setText("Leave Group"); + break; + case INVITED: + groupInteract.setText("Accept Invite"); + break; + case PUBLIC: + groupInteract.setText("Join Group"); + break; + } + + groupInteract.setOnClickListener(view -> { + switch (status) { + case HOST: + dataBaseAPI.deleteGroup(group); + finish(); + break; + case HIDDEN: + finish(); + break; + case JOINED: + resetGroup(); + dataBaseAPI.leaveGroup(group); + break; + case INVITED: + resetGroup(); + inviteButton.setVisibility(View.VISIBLE); + dataBaseAPI.acceptGroupInvite(group); + break; + case PUBLIC: + resetGroup(); + dataBaseAPI.acceptGroupInvite(group); + break; + } + }); + + + DataBaseAPI.STATUS userStatus = dataBaseAPI.getGroupRelationShip(group); + if(userStatus == DataBaseAPI.STATUS.JOINED || userStatus == DataBaseAPI.STATUS.HOST) { + inviteButton.setVisibility(View.VISIBLE); + inviteButton.setOnClickListener(view -> { + Intent intent = new Intent(this, InviteActivity.class); + intent.putExtra("type", "group"); + intent.putExtra("id", group.getId()); + startActivity(intent); + }); + }else{ + inviteButton.setVisibility(View.GONE); + } + + } + + private void resetGroup() { + if (getIntent().hasExtra("key")) { + String id = getIntent().getStringExtra("key"); + dataBaseAPI.getGroup(id, this, null); + } + } + + @Override + public void executeQuery(List result, SearchType.Type type) { + if(type == SearchType.Type.USERS){ + for (String id : result) { + dataBaseAPI.getUser(id, this, null); + } + }else if(type == SearchType.Type.EVENTS){ + for (String id : result) { + dataBaseAPI.getEvent(id, this, null); + } + } + } +} diff --git a/app/src/main/java/com/groupproject/Controller/GroupsFragment.java b/app/src/main/java/com/groupproject/Controller/GroupsFragment.java deleted file mode 100644 index d59d9d3..0000000 --- a/app/src/main/java/com/groupproject/Controller/GroupsFragment.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.groupproject.Controller; - -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.groupproject.R; - -public class GroupsFragment extends Fragment { - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_groups, container, false); - } -} diff --git a/app/src/main/java/com/groupproject/Controller/InviteActivity.java b/app/src/main/java/com/groupproject/Controller/InviteActivity.java new file mode 100644 index 0000000..cc22ae2 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/InviteActivity.java @@ -0,0 +1,139 @@ +package com.groupproject.Controller; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.SearchView; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuItem; +import android.view.inputmethod.InputMethodManager; +import android.widget.Toast; + +import com.google.firebase.database.Query; +import com.groupproject.Controller.SearchActivities.SearchType; +import com.groupproject.Controller.SideBarActivities.SidebarAdapter; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.DataBaseAPI.DataBaseCallBacks; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.User; +import com.groupproject.R; + +import java.util.List; +import java.util.Set; + +public class InviteActivity extends AppCompatActivity implements SearchType, DataBaseCallBacks { + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + private SidebarAdapter mSearchAdapter; + private InputMethodManager imm; + private String id; + private String type; + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle b = getIntent().getExtras(); + + type = b.getString("type"); + id = b.getString("id"); + + setContentView(R.layout.activity_invite); + Toolbar myToolbar = findViewById(R.id.my_toolbar); + setSupportActionBar(myToolbar); + getSupportActionBar().setDisplayShowTitleEnabled(false); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + + final LinearLayoutManager mLayoutManager = new LinearLayoutManager(this); + imm = (InputMethodManager) getApplication().getSystemService(BaseActivity.INPUT_METHOD_SERVICE); + + Query query = dataBaseAPI.getmUserRef().child(dataBaseAPI.getCurrentUserID()).child("friendsIDs"); + dataBaseAPI.executeQuery(query, this, Type.USERS); + mSearchAdapter = new SidebarAdapter(null, Type.INVITE, id); + mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + RecyclerView mRecyclerView = findViewById(R.id.friends_invite); + mRecyclerView.setLayoutManager(mLayoutManager); + mRecyclerView.swapAdapter(mSearchAdapter, true); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.invite_bar, menu); + MenuItem searchItem = menu.findItem(R.id.action_search); + SearchView searchView = (SearchView) searchItem.getActionView(); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + imm.hideSoftInputFromWindow(searchView.getWindowToken(), 0); + return false; + } + + @Override + public boolean onQueryTextChange(String s) { + mSearchAdapter.getFilter().filter(s); + return false; + } + }); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_menu_done: + Set invited = mSearchAdapter.getInvited(); + Set uninvited = mSearchAdapter.getUninvited(); + for (String userID : invited) { + if(type.equals("group")){ + dataBaseAPI.sendGroupInvite(userID, id); + }else if(type.equals("event")){ + dataBaseAPI.sendEventInvite(userID, id); + } + } + for (String userID : uninvited) { + if(type.equals("event")){ + dataBaseAPI.cancelEventInvite(userID, id); + }else if(type.equals("group")){ + dataBaseAPI.cancelGroupInvite(userID, id); + } + } + + Toast.makeText(this, "Invites sent", Toast.LENGTH_LONG).show(); + super.onBackPressed(); + return true; + case android.R.id.home: + super.onBackPressed(); + default: + return super.onOptionsItemSelected(item); + } + } + + @Override + public void getUser(User user, ViewHolder holder) { + mSearchAdapter.getItems().add(user); + mSearchAdapter.notifyDataSetChanged(); + } + + @Override + public void getEvent(Event event, ViewHolder holder) { + + } + + @Override + public void getGroup(Group group, ViewHolder holder) { + } + + @Override + public void executeQuery(List result, Type type) { + for (String s : result) { + if(type == Type.USERS) + dataBaseAPI.getUser(s, this, null); + else if(type == Type.EVENTS) + dataBaseAPI.getEvent(s, this, null); + else if(type == Type.GROUPS) + dataBaseAPI.getGroup(s, this, null); + } + } +} diff --git a/app/src/main/java/com/groupproject/Controller/LoginActivities/EmailSignUpActivity.java b/app/src/main/java/com/groupproject/Controller/LoginActivities/EmailSignUpActivity.java new file mode 100644 index 0000000..e899b44 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/LoginActivities/EmailSignUpActivity.java @@ -0,0 +1,126 @@ +package com.groupproject.Controller.LoginActivities; + +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +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.groupproject.Controller.BaseActivity; +import com.groupproject.Model.User; +import com.groupproject.R; + +public class EmailSignUpActivity extends AppCompatActivity { + + private FirebaseAuth mAuth; + private EditText mName; + private EditText mEmailField; + private EditText mPasswordField; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_email_sign_up); + mEmailField = (EditText) findViewById(R.id.InputEmail); + mPasswordField = (EditText) findViewById(R.id.InputPassword); + mName = (EditText) findViewById(R.id.InputName); + mAuth = FirebaseAuth.getInstance(); + + Button createAccount = (Button) findViewById(R.id.SignUp); + createAccount.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + createAccount(mEmailField.getText().toString(), mPasswordField.getText().toString(), mName.getText().toString()); + } + }); + } + + private void createAccount(final String email, String password, final String name) { + if (!validateForm()) { + return; + } + mAuth.createUserWithEmailAndPassword(email, password) + .addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + FirebaseUser user = mAuth.getCurrentUser(); + if (user != null) { + new User(user.getUid(), name, email); + } + sendEmailVerification(); + // Sign in success, update UI with the signed-in user's information + + } else { + Toast.makeText(EmailSignUpActivity.this, + "Authentication failed. " + task.getException().getMessage(), + Toast.LENGTH_SHORT).show(); + } + } + }); + } + + private void sendEmailVerification() { + final FirebaseUser user = mAuth.getCurrentUser(); + if (user != null) { + user.sendEmailVerification() + .addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + + Toast.makeText(EmailSignUpActivity.this, + "Verification email sent to " + user.getEmail(), + Toast.LENGTH_SHORT).show(); + Intent intent = new Intent(getApplication(), BaseActivity + .class); + startActivity(intent); + } else { + Toast.makeText(EmailSignUpActivity.this, + "Failed to send verification email.", + Toast.LENGTH_SHORT).show(); + } + } + }); + } + } + + + private boolean validateForm() { + boolean valid = true; + + String email = mEmailField.getText().toString(); + if (TextUtils.isEmpty(email)) { + mEmailField.setError("Required."); + valid = false; + } else { + mEmailField.setError(null); + } + + String name = mName.getText().toString(); + if (TextUtils.isEmpty(name)) { + mEmailField.setError("Required."); + valid = false; + } else { + mEmailField.setError(null); + } + + String password = mPasswordField.getText().toString(); + if (TextUtils.isEmpty(password)) { + mPasswordField.setError("Required."); + valid = false; + } else { + mPasswordField.setError(null); + } + return valid; + } +} diff --git a/app/src/main/java/com/groupproject/Controller/LoginActivities/LoginActivity.java b/app/src/main/java/com/groupproject/Controller/LoginActivities/LoginActivity.java new file mode 100644 index 0000000..c1491db --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/LoginActivities/LoginActivity.java @@ -0,0 +1,239 @@ +package com.groupproject.Controller.LoginActivities; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.FloatingActionButton; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import com.facebook.AccessToken; +import com.facebook.CallbackManager; +import com.facebook.FacebookCallback; +import com.facebook.FacebookException; +import com.facebook.appevents.AppEventsLogger; +import com.facebook.login.LoginManager; +import com.facebook.login.LoginResult; +import com.google.android.gms.auth.api.signin.GoogleSignIn; +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.auth.api.signin.GoogleSignInClient; +import com.google.android.gms.auth.api.signin.GoogleSignInOptions; +import com.google.android.gms.common.api.ApiException; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthCredential; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FacebookAuthProvider; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.auth.GoogleAuthProvider; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.ValueEventListener; +import com.groupproject.Controller.BaseActivity; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.User; +import com.groupproject.R; + +import java.util.Arrays; +import java.util.Collection; + + +public class LoginActivity extends AppCompatActivity { + + private static final int RC_SIGN_IN = 9001; + + private FirebaseAuth mAuth; + private static final DataBaseAPI databaseAPI = DataBaseAPI.getDataBase(); + private GoogleSignInClient mGoogleSignInClient; + private CallbackManager mCallbackManager; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + + mAuth = FirebaseAuth.getInstance(); + + /////////FACEBOOK LOGIN///////// + final Activity activity = this; + setUpFaceBook(); + + /////////GOOGLE LOGIN///////// + setUpGoogle(); + + /////////BUTTON LISTENERS///////// + FloatingActionButton facebookLogin = findViewById(R.id.FacebookFloatingButton); + facebookLogin.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Collection permission = Arrays.asList("public_profile", "user_friends"); + LoginManager.getInstance().logInWithReadPermissions(activity, permission); + } + }); + + FloatingActionButton googleLogin = findViewById(R.id.GoogleFloatingButton); + googleLogin.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent signInIntent = mGoogleSignInClient.getSignInIntent(); + startActivityForResult(signInIntent, RC_SIGN_IN); + } + }); + + Button emailLogin = findViewById(R.id.loginButton); + emailLogin.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + EditText email = findViewById(R.id.emailInput); + EditText password = findViewById(R.id.passwordIn); + signInEmail(email.getText().toString(), password.getText().toString()); + } + }); + + Button createAccount = findViewById(R.id.createAccount); + createAccount.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent createNewUser = new Intent(getApplication(), EmailSignUpActivity.class); + startActivity(createNewUser); + + } + }); + } + + private void setUpFaceBook(){ + AppEventsLogger.activateApp(getApplication()); + mCallbackManager = CallbackManager.Factory.create(); + LoginManager.getInstance().registerCallback(mCallbackManager, + new FacebookCallback() { + @Override + public void onSuccess(LoginResult loginResult) { + signInFacebook(loginResult.getAccessToken()); + } + @Override + public void onCancel() { + //TODO Deal with this + } + @Override + public void onError(FacebookException exception) { + exception.printStackTrace(); + } + }); + } + + private void setUpGoogle(){ + GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestIdToken(getString(R.string.default_web_client_id)) + .requestEmail() + .build(); + mGoogleSignInClient = GoogleSignIn.getClient(this, gso); + } + + + public void signInEmail(String email, String password) { + mAuth.signInWithEmailAndPassword(email, password) + .addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + // Sign in success, update UI with the signed-in user's information + onSuccessfulSignUp(); + } else { + // If sign in fails, display a message to the user. + Toast.makeText(LoginActivity.this, + "Authentication failed. " + task.getException().getMessage(), + Toast.LENGTH_SHORT).show(); + } + } + }); + } + + private void signInFacebook(AccessToken token) { + + AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken()); + mAuth.signInWithCredential(credential) + .addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + // Sign in success, update UI with the signed-in user's information + onSuccessfulSignUp(); + } else { + Toast.makeText(LoginActivity.this, + "Authentication failed.. " + task.getException().getMessage(), + Toast.LENGTH_SHORT).show(); + } + } + }); + } + + + private void singInGoogle(GoogleSignInAccount acct) { + AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null); + mAuth.signInWithCredential(credential) + .addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + // Sign in success, update UI with the signed-in user's information + onSuccessfulSignUp(); + } else { + // If sign in fails, display a message to the user. + Toast.makeText(LoginActivity.this, + "Authentication failed. . " + task.getException().getMessage(), + Toast.LENGTH_SHORT).show(); + } + } + }); + } + + public void onSuccessfulSignUp(){ + FirebaseUser user = mAuth.getCurrentUser(); + if (user != null) { + databaseAPI.getmUserRef().child(user.getUid()).addListenerForSingleValueEvent( + new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot snapshot) { + Intent intent = new Intent(getApplication(), BaseActivity.class); + if (!snapshot.child(user.getUid()).exists()) { + new User(user.getUid(), user.getDisplayName(), user.getEmail()); + } + startActivity(intent); + } + + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if(requestCode == 64206) + mCallbackManager.onActivityResult(requestCode, resultCode, data); + if (requestCode == RC_SIGN_IN) { + Task task = GoogleSignIn.getSignedInAccountFromIntent(data); + try { + GoogleSignInAccount account = task.getResult(ApiException.class); + singInGoogle(account); + } catch (ApiException ignored) { + + } + } + } +} + + + + + + diff --git a/app/src/main/java/com/groupproject/Controller/LoginActivity.java b/app/src/main/java/com/groupproject/Controller/LoginActivity.java deleted file mode 100644 index 6f0c04f..0000000 --- a/app/src/main/java/com/groupproject/Controller/LoginActivity.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.groupproject.Controller; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; - -import com.facebook.CallbackManager; -import com.facebook.FacebookCallback; -import com.facebook.FacebookException; -import com.facebook.FacebookSdk; -import com.facebook.GraphRequest; -import com.facebook.GraphResponse; -import com.facebook.appevents.AppEventsLogger; -import com.facebook.login.LoginManager; -import com.facebook.login.LoginResult; -import com.groupproject.R; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.Arrays; - -public class LoginActivity extends Activity { - - CallbackManager callbackManager; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - AppEventsLogger.activateApp(getApplication()); - setContentView(R.layout.activity_login); - callbackManager = CallbackManager.Factory.create(); - LoginManager.getInstance().registerCallback(callbackManager, - new FacebookCallback() { - @Override - public void onSuccess(LoginResult loginResult) { - // App code - GraphRequest request = GraphRequest.newMeRequest( - loginResult.getAccessToken(), - new GraphRequest.GraphJSONObjectCallback() { - @Override //TODO MATTHEO refactor - public void onCompleted(JSONObject object, GraphResponse response) { - Log.v("LoginActivityRe", response.toString()); - String[] dataToRetrieve = - new String[]{"id", "email", "first_name", - "last_name"}; - String[] data = new String[dataToRetrieve.length]; - try { - for (int i = 0; i < dataToRetrieve.length; i++) { - data[i] = object.getString(dataToRetrieve[i]); - } - //TODO: HENRY create user on db based on above data - } catch (JSONException e) { - e.printStackTrace(); - } - } - }); - Bundle parameters = new Bundle(); - parameters.putString("fields", "id, first_name, last_name, email, birthday"); - request.setParameters(parameters); - request.executeAsync(); - Intent intent = new Intent(getApplicationContext(), MainActivity.class); - startActivity(intent); - finish(); - } - - @Override - public void onCancel() { - } - - @Override - public void onError(FacebookException error) { - } - }); - - LoginManager.getInstance().logInWithReadPermissions(this, - Arrays.asList("public_profile", "email", "user_birthday", "user_friends")); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - callbackManager.onActivityResult(requestCode, resultCode, data); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/groupproject/Controller/MainActivity.java b/app/src/main/java/com/groupproject/Controller/MainActivity.java deleted file mode 100644 index 0e87674..0000000 --- a/app/src/main/java/com/groupproject/Controller/MainActivity.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.groupproject.Controller; - -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentTabHost; -import android.os.Bundle; - -import com.groupproject.R; - -public class MainActivity extends FragmentActivity { - - // Fragment TabHost as mTabHost - private FragmentTabHost mTabHost; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost); - mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent); - - mTabHost.addTab(mTabHost.newTabSpec("groups").setIndicator("groups"), - GroupsFragment.class, null); - mTabHost.addTab(mTabHost.newTabSpec("maps").setIndicator("maps"), - MapsFragment.class, null); - } - - @Override - public void onBackPressed() { - super.onBackPressed(); - } - -} diff --git a/app/src/main/java/com/groupproject/Controller/MapActivites/MapsFragment.java b/app/src/main/java/com/groupproject/Controller/MapActivites/MapsFragment.java new file mode 100644 index 0000000..7ecc552 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/MapActivites/MapsFragment.java @@ -0,0 +1,350 @@ +package com.groupproject.Controller.MapActivites; + +import android.Manifest; +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.location.Location; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.FloatingActionButton; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ProgressBar; +import android.widget.Toast; +import com.google.android.gms.maps.model.BitmapDescriptor; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; +import com.google.android.gms.location.FusedLocationProviderClient; +import com.google.android.gms.location.LocationServices; +import com.google.android.gms.maps.CameraUpdate; +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.MapView; +import com.google.android.gms.maps.MapsInitializer; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.MarkerOptions; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.database.ChildEventListener; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.groupproject.Controller.EventActivities.CreateEventActivity; +import com.groupproject.Controller.EventActivities.EventInfoActivity; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.Event; +import com.groupproject.Model.Visibility; +import com.groupproject.R; + +import java.util.Calendar; + + +public class MapsFragment extends Fragment implements GoogleMap.OnMarkerClickListener { + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + private static final int DEFAULT_ZOOM = 15; + private boolean foundLocation; + MapView mMapView; + private GoogleMap googleMap; + private LocationControl locationControlTask; + View rootView; + + public static Fragment newInstance(){ + Fragment fragment = new MapsFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + rootView = inflater.inflate(R.layout.maps_fragment, container, false); + mMapView = rootView.findViewById(R.id.mapView); + mMapView.onCreate(savedInstanceState); + + mMapView.onResume(); // needed to get the map to display immediately + + DataBaseAPI.loadActiveEvents(); + + try { + MapsInitializer.initialize(getActivity().getApplicationContext()); + } catch (Exception e) { + e.printStackTrace(); + } + + FloatingActionButton createEvent = rootView.findViewById(R.id.create_event_fab); + createEvent.setOnClickListener(v -> { + Toast.makeText(getActivity(), "Tap to add a pin!", Toast.LENGTH_LONG).show(); + googleMap.setOnMapClickListener(point -> { + googleMap.setOnMapClickListener(null); + Intent intent = new Intent(getActivity(), CreateEventActivity.class); + intent.putExtra("event_location", + new LatLng(point.latitude, point.longitude)); + startActivity(intent); + }); + }); + setUpListener(); + return rootView; + } + + private void setUpListener() { + ChildEventListener childEventListener = new ChildEventListener() { + @Override + public void onChildAdded(DataSnapshot dataSnapshot, String s) { + Event event = dataSnapshot.getValue(com.groupproject.Model.Event.class); + if (event != null) { + addPinsToMap(); + } + } + + @Override + public void onChildChanged(DataSnapshot dataSnapshot, String s) { + Event event = dataSnapshot.getValue(com.groupproject.Model.Event.class); + if (event != null) { + addPinsToMap(); + } + } + + @Override + public void onChildRemoved(DataSnapshot dataSnapshot) { + Event event = dataSnapshot.getValue(com.groupproject.Model.Event.class); + if (event != null) { + DataBaseAPI.getEventMap().remove(event.getId()); + addPinsToMap(); + } + } + + @Override + public void onChildMoved(DataSnapshot dataSnapshot, String s) { + + } + + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }; + dataBaseAPI.addChildListener("events", childEventListener); + } + + @Override + public void onStop() { + super.onStop(); + if (locationControlTask != null) + locationControlTask.cancel(true); + } + + public void addPinsToMap() { + if(googleMap != null) { + googleMap.clear(); + for (Event event : DataBaseAPI.getEventMap().values()) { + DataBaseAPI.STATUS status = dataBaseAPI.getEventRelationShip(event); + if(status != DataBaseAPI.STATUS.HIDDEN) { + BitmapDescriptor descriptor = null; + if(status == DataBaseAPI.STATUS.HOST){ + descriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW); + } else if(status == DataBaseAPI.STATUS.PUBLIC){ + descriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE); + }else if(event.getVisibility() == Visibility.VISIBILITY.INVITE_ONLY && + event.invitedIDs.contains(dataBaseAPI.getCurrentUserID()) ){ + descriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN); + }else if(event.getVisibility() == Visibility.VISIBILITY.INVITE_ONLY && + event.goingIDs.contains(dataBaseAPI.getCurrentUserID()) ){ + descriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED); + } + Marker marker = googleMap.addMarker(new MarkerOptions() + .position(new LatLng(event.getCustomLocation().getLatitude(), + event.getCustomLocation().getLongitude())) + .title(event.getName()) + .snippet(event.getEndDate().toString()) + .icon(descriptor)); + marker.setTag(event.getId()); + } + } + } + } + + @Override + public void onResume() { + super.onResume(); + rootView.requestFocus(); + mMapView.onResume(); + mMapView.getMapAsync(mMap -> { + googleMap = mMap; + + googleMap.setOnMapLoadedCallback(() -> { + addPinsToMap(); + }); + + askForLocationPermissions(); + googleMap.setOnMarkerClickListener(MapsFragment.this); + }); + } + + @Override + public void onPause() { + super.onPause(); + mMapView.onPause(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mMapView.onDestroy(); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mMapView.onLowMemory(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], + @NonNull int[] grantResults) { + if (requestCode == 1) { + if ((grantResults.length > 0) && + (grantResults[0] + grantResults[1]) == PackageManager.PERMISSION_GRANTED) { + setCurrentLocation(); + } else { + AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create(); + alertDialog.setTitle("Alert"); + alertDialog.setMessage("Please enable location settings. " + + "If no request is appearing, go to Settings > Apps > Pinned > Permissions "); + alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", + (dialog, which) -> { + dialog.dismiss(); + askForLocationPermissions(); + }); + alertDialog.show(); + } + } + } + + @Override + public boolean onMarkerClick(Marker marker) { + Intent intent = new Intent(getActivity(), EventInfoActivity.class); + intent.putExtra("key", (String) marker.getTag()); + startActivity(intent); + return true; + } + + private void askForLocationPermissions() { + if (ActivityCompat.checkSelfPermission( + getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != + PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( + getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != + PackageManager.PERMISSION_GRANTED) { + + MapsFragment.this.requestPermissions( + new String[]{Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION}, 1); + } else { + setCurrentLocation(); + } + } + + private class LocationControl extends AsyncTask { + ProgressBar progressBar = (ProgressBar) getView().findViewById(R.id.progressBar); + + protected void onPreExecute() { + progressBar.setVisibility(View.VISIBLE); + } + + protected Void doInBackground(Context... params) { + //Wait 15 seconds to see if we can get a location from either network or GPSp + Long t = Calendar.getInstance().getTimeInMillis(); + while (!foundLocation) { + searchForLocation(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return null; + } + + protected void onPostExecute(final Void unused) { + progressBar.setVisibility(View.GONE); + setCurrentLocation(); + } + } + + /** + * Search for location without creating an async task + */ + private void searchForLocation() { + foundLocation = false; + FusedLocationProviderClient mFusedLocationProviderClient = LocationServices + .getFusedLocationProviderClient(getActivity()); + //Ignore the red line - we check for permissions before this function is called + if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + + return; + } + Task lastLocation = mFusedLocationProviderClient.getLastLocation(); + lastLocation.addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + // Set the map's camera position to the current location of the device. + Location location = task.getResult(); + if (location != null) { + LatLng currentLatLng = new LatLng(location.getLatitude(), + location.getLongitude()); + CameraUpdate update = CameraUpdateFactory.newLatLngZoom(currentLatLng, + DEFAULT_ZOOM); + googleMap.moveCamera(update); + foundLocation = true; + } + } + } + }); + } + + /** + * Set current location, creating an async task if the location can't be found at that moment + */ + private void setCurrentLocation() { + foundLocation = false; + //Ignore the red line - we check for permissions before this function is called + if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + return; + } + googleMap.setMyLocationEnabled(true); + FusedLocationProviderClient mFusedLocationProviderClient = LocationServices + .getFusedLocationProviderClient(getActivity()); + //Ignore the red line - we check for permissions before this function is called + Task lastLocation = mFusedLocationProviderClient.getLastLocation(); + lastLocation.addOnCompleteListener(task -> { + if (task.isSuccessful()) { + // Set the map's camera position to the current location of the device. + Location location = task.getResult(); + if (location == null) { + locationControlTask = new LocationControl(); + locationControlTask.execute(getActivity()); + } else { + LatLng currentLatLng = new LatLng(location.getLatitude(), + location.getLongitude()); + CameraUpdate update = CameraUpdateFactory.newLatLngZoom(currentLatLng, + DEFAULT_ZOOM); + googleMap.moveCamera(update); + foundLocation = true; + } + } + }); + } +} + + diff --git a/app/src/main/java/com/groupproject/Controller/MapsFragment.java b/app/src/main/java/com/groupproject/Controller/MapsFragment.java deleted file mode 100644 index ff88210..0000000 --- a/app/src/main/java/com/groupproject/Controller/MapsFragment.java +++ /dev/null @@ -1,217 +0,0 @@ -package com.groupproject.Controller; - -import android.Manifest; -import android.content.Context; -import android.content.pm.PackageManager; -import android.location.Criteria; -import android.location.Location; -import android.location.LocationManager; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.app.ActivityCompat; -import android.support.v4.app.Fragment; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.location.FusedLocationProviderClient; -import com.google.android.gms.location.LocationRequest; -import com.google.android.gms.location.LocationServices; -import com.google.android.gms.location.LocationListener; -import com.google.android.gms.location.LocationSettingsRequest; -import com.google.android.gms.location.SettingsClient; -import com.google.android.gms.maps.CameraUpdate; -import com.google.android.gms.maps.CameraUpdateFactory; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.MapFragment; -import com.google.android.gms.maps.MapView; -import com.google.android.gms.maps.MapsInitializer; -import com.google.android.gms.maps.OnMapReadyCallback; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.MarkerOptions; -import com.google.android.gms.tasks.OnCompleteListener; -import com.google.android.gms.tasks.OnSuccessListener; -import com.google.android.gms.tasks.Task; -import com.groupproject.R; - -import static android.content.ContentValues.TAG; - - -public class MapsFragment extends Fragment { - - MapView mMapView; - private GoogleMap googleMap; - GoogleApiClient googleApiClient; - private Location mLastKnownLocation; - private LocationRequest mLocationRequest; - private FusedLocationProviderClient mFusedLocationClient; - private LatLng coordinates; - Context mContext; - - private final LatLng mDefaultLocation = new LatLng(36.9980751, -122.0575037); - private static final int DEFAULT_ZOOM = 15; - private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1; - private boolean mLocationPermissionGranted = true; - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getContext()); - View rootView = inflater.inflate(R.layout.maps_fragment, container, false); - mMapView = (MapView) rootView.findViewById(R.id.mapView); - mMapView.onCreate(savedInstanceState); - - mMapView.onResume(); // needed to get the map to display immediately - - try { - MapsInitializer.initialize(getActivity().getApplicationContext()); - } catch (Exception e) { - e.printStackTrace(); - } - - mMapView.getMapAsync(new OnMapReadyCallback() { - @Override - public void onMapReady(GoogleMap mMap) { - googleMap = mMap; - - // For showing a move to my location button - if (ActivityCompat.checkSelfPermission( - getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != - PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( - getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != - PackageManager.PERMISSION_GRANTED) { - - ActivityCompat.requestPermissions(getActivity(), - new String[]{Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.ACCESS_COARSE_LOCATION}, 1); - return; - } - getDeviceLocation(); - //createMap(googleMap); - } - }); - - return rootView; - } - - private void getDeviceLocation() { - try { - if (mLocationPermissionGranted) { - googleMap.setMyLocationEnabled(true); - Task locationResult = mFusedLocationClient.getLastLocation(); - locationResult.addOnCompleteListener(new OnCompleteListener() { - @Override - public void onComplete(@NonNull Task task) { - if (task.isSuccessful()) { - // Set the map's camera position to the current location of the device. - mLastKnownLocation = task.getResult(); - googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom( - new LatLng(mLastKnownLocation.getLatitude(), - mLastKnownLocation.getLongitude()), DEFAULT_ZOOM)); - } else { - Log.d(TAG, "Current location is null. Using defaults."); - Log.e(TAG, "Exception: %s", task.getException()); - googleMap.moveCamera(CameraUpdateFactory - .newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM)); - googleMap.getUiSettings().setMyLocationButtonEnabled(false); - } - } - }); - } - } catch (SecurityException e) { - Log.e("Exception: %s", e.getMessage()); - } - } - - @Override - public void onResume() { - super.onResume(); - mMapView.onResume(); - } - - @Override - public void onPause() { - super.onPause(); - mMapView.onPause(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - mMapView.onDestroy(); - } - - @Override - public void onLowMemory() { - super.onLowMemory(); - mMapView.onLowMemory(); - } - - @Override - public void onRequestPermissionsResult(int requestCode, - @NonNull String permissions[], - @NonNull int[] grantResults) { - //TODO: Error message if location denied? - switch (requestCode) { - case 1: { - if ((grantResults.length > 0) && (grantResults[0] + - grantResults[1]) == PackageManager.PERMISSION_GRANTED) { - createMap(googleMap); - } else { - ActivityCompat.requestPermissions(getActivity(), - new String[]{Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.ACCESS_COARSE_LOCATION}, 1); - } - } - } - } - - private void createMap(GoogleMap mMap) { - mMap.setMyLocationEnabled(true); - //TODO: Get user's location and zoom in on it using the code below - - // For zooming automatically to the location of the marker -// CameraPosition cameraPosition = new CameraPosition.Builder() -// .target(new LatLng(location.getLatitude(), -// location.getLongitude())).zoom(12).build(); -// googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); - //Location currLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient); - //LatLng newLatLng = new LatLng(currLocation.getLatitude(), currLocation.getLongitude()); -/* - mLocationRequest = new LocationRequest(); - mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); - - // Create LocationSettingsRequest object using location request - LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); - builder.addLocationRequest(mLocationRequest); - LocationSettingsRequest locationSettingsRequest = builder.build(); - - // Check whether location settings are satisfied - // https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient - SettingsClient settingsClient = LocationServices.getSettingsClient(this); - settingsClient.checkLocationSettings(locationSettingsRequest);*/ - - - Location location = new Location("dummyprovider"); - location.setLatitude(36.9980751); - location.setLongitude(-122.0575037); - - double currentLatitude = location.getLatitude(); - double currentLongitude = location.getLongitude(); - - LatLng latLng = new LatLng(currentLatitude, currentLongitude); - - CameraUpdate center = CameraUpdateFactory.newLatLng(latLng); - googleMap.addMarker(new MarkerOptions().position(latLng) - .title("Marker")); - CameraUpdate zoom=CameraUpdateFactory.zoomTo(DEFAULT_ZOOM); - - mMap.moveCamera(center); - mMap.animateCamera(zoom); - } -} diff --git a/app/src/main/java/com/groupproject/Controller/NotificationCallBack.java b/app/src/main/java/com/groupproject/Controller/NotificationCallBack.java new file mode 100644 index 0000000..34e97f2 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/NotificationCallBack.java @@ -0,0 +1,9 @@ +package com.groupproject.Controller; + +import com.groupproject.Model.PinnedNotification; + +import java.util.List; + +public interface NotificationCallBack { + void getNotifications(List notifications); +} diff --git a/app/src/main/java/com/groupproject/Controller/NotificationService.java b/app/src/main/java/com/groupproject/Controller/NotificationService.java new file mode 100644 index 0000000..ef2661c --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/NotificationService.java @@ -0,0 +1,161 @@ +package com.groupproject.Controller; + +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.os.AsyncTask; +import android.os.IBinder; +import android.os.PowerManager; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.TaskStackBuilder; + +import com.groupproject.Controller.SearchActivities.SearchType; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.DataBaseAPI.DataBaseCallBacks; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.PinnedNotification; +import com.groupproject.Model.User; +import com.groupproject.R; + +import java.util.List; + +public class NotificationService extends Service implements DataBaseCallBacks, NotificationCallBack { + + private PowerManager.WakeLock mWakeLock; + private DataBaseAPI dataBaseAPI; + private int notificationCounter; + + @Override public IBinder onBind(Intent intent) { + return null; + } + + private void handleIntent(Intent intent) { + // obtain the wake lock + PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "wakelock"); + mWakeLock.acquire(10*60*1000L /*10 minutes*/); + dataBaseAPI = DataBaseAPI.getDataBase(); + notificationCounter = 1; + // check the global background data setting + ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); + if (cm == null || cm.getActiveNetworkInfo() == null) { + stopSelf(); + return; + } + // do the actual work, in a separate thread + new PollTask().execute(); + } + + @Override + public void getUser(User user, ViewHolder holder) { + buildNotification("Friend Request!", user.getName(), notificationCounter); + notificationCounter++; + } + + @Override + public void getEvent(Event event, ViewHolder holder) { + buildNotification("Event Invite!", event.getName(), notificationCounter); + notificationCounter++; + } + + @Override + public void getGroup(Group group, ViewHolder holder) { + buildNotification("Group Invite!", group.getName(), notificationCounter); + notificationCounter++; + } + + @Override + public void executeQuery(List result, SearchType.Type type) { + if(type == SearchType.Type.USERS) { + for (String id : result) { + dataBaseAPI.getUser(id, this, null); + } + } else if(type == SearchType.Type.EVENTS) { + for (String id : result) { + dataBaseAPI.getEvent(id, this, null); + } + } else if(type == SearchType.Type.GROUPS) { + for (String id : result) { + dataBaseAPI.getGroup(id, this, null); + } + } + } + + @Override + public void getNotifications(List notifications) { + for (PinnedNotification notification: notifications) { + switch (notification.type) { + case "user": + dataBaseAPI.getUser(notification.id, this, null); + dataBaseAPI.setNotificationAsSeen(notification.id, SearchType.Type.USERS); + break; + case "event": + dataBaseAPI.getEvent(notification.id, this, null); + dataBaseAPI.setNotificationAsSeen(notification.id, SearchType.Type.EVENTS); + break; + case "group": + dataBaseAPI.getGroup(notification.id, this, null); + dataBaseAPI.setNotificationAsSeen(notification.id, SearchType.Type.GROUPS); + break; + } + } + } + + private class PollTask extends AsyncTask { + + @Override + protected Void doInBackground(Void... params) { + return null; + } + + @Override protected void onPostExecute(Void result) { + sendNotification(); + stopSelf(); + } + } + + @Override public int onStartCommand(Intent intent, int flags, int startId) { + handleIntent(intent); + return START_NOT_STICKY; + } + + public void onDestroy() { + super.onDestroy(); + mWakeLock.release(); + } + + private void sendNotification() { + dataBaseAPI.getNotifications(this); + } + + private void buildNotification(String type, String name, int id) { + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(this) + .setSmallIcon(R.drawable.eventpic) + .setContentTitle(type) + .setContentText(name); + + // Creates an explicit intent for an Activity in your app + Intent resultIntent = new Intent(this, BaseActivity.class); + resultIntent.putExtra("openNotifications", "yes"); + + // The stack builder object will contain an artificial back stack for the started Activity. + TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); + // Adds the back stack for the Intent (but not the Intent itself) + stackBuilder.addParentStack(BaseActivity.class); + // Adds the Intent that starts the Activity to the top of the stack + stackBuilder.addNextIntent(resultIntent); + PendingIntent resultPendingIntent = + stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); + mBuilder.setContentIntent(resultPendingIntent); + mBuilder.setAutoCancel(true); + // Gets an instance of the NotificationManager service + NotificationManager mNotifyMgr = + (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + // Builds the notification and issues it. + mNotifyMgr.notify(id, mBuilder.build()); + } +} diff --git a/app/src/main/java/com/groupproject/Controller/SearchActivities/SearchAdapter.java b/app/src/main/java/com/groupproject/Controller/SearchActivities/SearchAdapter.java new file mode 100644 index 0000000..a09d3b2 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/SearchActivities/SearchAdapter.java @@ -0,0 +1,158 @@ +package com.groupproject.Controller.SearchActivities; + +import android.content.Intent; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.firebase.ui.database.FirebaseRecyclerAdapter; +import com.firebase.ui.database.FirebaseRecyclerOptions; +import com.google.firebase.database.Query; +import com.groupproject.Controller.EventActivities.EventInfoActivity; +import com.groupproject.Controller.GroupActivities.ViewGroupActivity; +import com.groupproject.Controller.ViewHolder; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.DataBaseAPI.DataBaseCallBacks; +import com.groupproject.Model.DataBaseItem; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.User; +import com.groupproject.R; +import com.groupproject.Controller.ViewProfileActivity; + +import java.util.List; + +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.STATUS.HIDDEN; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.STATUS.HOST; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.STATUS.INVITED; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.STATUS.JOINED; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.STATUS.PUBLIC; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.UserRelationship.FRIENDS; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.UserRelationship.ME; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.UserRelationship.NONE; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.UserRelationship.REQUESTED; + + +public class SearchAdapter extends FirebaseRecyclerAdapter implements DataBaseCallBacks { + + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + private final Fragment fragment; + + SearchAdapter(Query query, Fragment fragment) { + super(new FirebaseRecyclerOptions.Builder().setQuery(query, DataBaseItem.class).build()); + this.fragment = fragment; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.search_result, viewGroup, false); + return new ViewHolder(itemView); + } + + @Override + protected void onBindViewHolder(ViewHolder holder, int position, DataBaseItem model) { + holder.selected.setVisibility(View.GONE); + if (((SearchFragment) fragment).getSearchType() == SearchType.Type.USERS) { + dataBaseAPI.getUser(model.getId(), this, holder); + holder.cardView.setOnClickListener(v -> { + Intent intent = new Intent(fragment.getActivity(), ViewProfileActivity.class); + intent.putExtra("key", model.getId()); + fragment.getActivity().startActivity(intent); + }); + }else if (((SearchFragment) fragment).getSearchType() == SearchType.Type.EVENTS) { + dataBaseAPI.getEvent(model.getId(), this, holder); + holder.cardView.setOnClickListener(v -> { + Intent intent = new Intent(fragment.getActivity(), EventInfoActivity.class); + intent.putExtra("key", model.getId()); + fragment.getActivity().startActivity(intent); + }); + }else if (((SearchFragment) fragment).getSearchType() == SearchType.Type.GROUPS) { + dataBaseAPI.getGroup(model.getId(), this, holder); + holder.cardView.setOnClickListener(v -> { + Intent intent = new Intent(fragment.getActivity(), ViewGroupActivity.class); + intent.putExtra("key", model.getId()); + fragment.getActivity().startActivity(intent); + }); + } + } + + @Override + public void getUser(User user, ViewHolder holder) { + DataBaseAPI.UserRelationship userRelationship = dataBaseAPI.getRelationShip(user); + + if(userRelationship == ME) { + holder.interact.setImageDrawable(null); + } else if(userRelationship == FRIENDS) { + holder.interact.setImageDrawable(null); //TODO go to profile to remove + } else if(userRelationship == REQUESTED) { + holder.interact.setImageDrawable(ContextCompat.getDrawable(fragment.getActivity(), + R.drawable.cancel_button)); + }else if(userRelationship == NONE) { + holder.interact.setImageDrawable(ContextCompat.getDrawable(fragment.getActivity(), + R.drawable.add_button)); + } + holder.interact.setOnClickListener(view -> { + if(userRelationship == FRIENDS) { + dataBaseAPI.removeFriend(user); //TODO go to profile to remove + } else if(userRelationship == REQUESTED) { + dataBaseAPI.cancelFriendRequest(user); + }else if(userRelationship == NONE) { + dataBaseAPI.sendFriendRequest(user); + } + }); + holder.vName.setText(user.getName()); + } + + @Override + public void getEvent(Event event, ViewHolder holder) { + DataBaseAPI.STATUS status = dataBaseAPI.getEventRelationShip(event); + if(status == HOST){ + holder.interact.setImageDrawable(null); + } else if(status == HIDDEN) { + holder.cardView.setVisibility(View.GONE); + } else if(status == JOINED) { + holder.interact.setImageDrawable(null); + } else if(status == INVITED) { + holder.interact.setImageDrawable(ContextCompat.getDrawable(fragment.getActivity(), R.drawable.add_button)); + }else if(status == PUBLIC) { + holder.interact.setImageDrawable(null); + } + holder.interact.setOnClickListener(view -> { + if(status == INVITED) { + dataBaseAPI.acceptEventInvite(event); + } + }); + holder.vName.setText(event.getName()); + } + + @Override + public void getGroup(Group group, ViewHolder holder) { + DataBaseAPI.STATUS status = dataBaseAPI.getGroupRelationShip(group); + if(status == HOST){ + holder.interact.setImageDrawable(null); + } else if(status == HIDDEN) { + holder.cardView.setVisibility(View.GONE); + } else if(status == JOINED) { + holder.interact.setImageDrawable(null); + } else if(status == INVITED) { + holder.interact.setImageDrawable(ContextCompat.getDrawable(fragment.getActivity(), + R.drawable.add_button)); + }else if(status == PUBLIC) { + holder.interact.setImageDrawable(null); + } + holder.interact.setOnClickListener(view -> { + if(status == INVITED) { + dataBaseAPI.acceptGroupInvite(group); + } + }); + holder.vName.setText(group.getName()); + } + + @Override + public void executeQuery(List result, SearchType.Type type) { + + } +} diff --git a/app/src/main/java/com/groupproject/Controller/SearchActivities/SearchFragment.java b/app/src/main/java/com/groupproject/Controller/SearchActivities/SearchFragment.java new file mode 100644 index 0000000..7e8ee5e --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/SearchActivities/SearchFragment.java @@ -0,0 +1,125 @@ +package com.groupproject.Controller.SearchActivities; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.FloatingActionButton; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RadioButton; +import android.widget.RadioGroup; + + +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.Query; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.R; + + +public class SearchFragment extends Fragment implements SearchType{ + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + private RecyclerView mRecyclerView; + private DatabaseReference reference; + private SearchAdapter mSearchAdapter; + + private Type searchType; + private String q; + + public interface SwitchFragment{ + void switchFragment(Fragment frag, Bundle args); + } + + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + this.q = ""; + View rootView = inflater.inflate(R.layout.search_results, container, false); + final LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity()); + mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + + FloatingActionButton floatingActionButton = rootView.findViewById(R.id.new_group); + floatingActionButton.setVisibility(View.GONE); + + mRecyclerView = rootView.findViewById(R.id.search_fragment); + mRecyclerView.setLayoutManager(mLayoutManager); + + RadioGroup radioGroup = rootView.findViewById(R.id.rGroup); + RadioButton radioButton = rootView.findViewById(R.id.friendsRadio); + radioButton.setChecked(true); + reference = dataBaseAPI.getmUserRef(); + searchType = SearchType.Type.USERS; + + radioGroup.setOnCheckedChangeListener((group, checkedId) -> { + if (checkedId == R.id.friendsRadio) { + reference = dataBaseAPI.getmUserRef(); + searchType = SearchType.Type.USERS; + } else if (checkedId == R.id.eventsRadio) { + reference = dataBaseAPI.getmEventRef(); + searchType = SearchType.Type.EVENTS; + } else if (checkedId == R.id.groupsRadio) { + reference = dataBaseAPI.getmGroupRef(); + searchType = SearchType.Type.GROUPS; + } + setQ(""); + }); + return rootView; + } + + @Override + public void onResume() { + super.onResume(); + setQ(q); + } + + + public void setData(SearchAdapter mSearchAdapter) { + this.mSearchAdapter = mSearchAdapter; + } + + public SearchAdapter getData() { + return mSearchAdapter; + } + + @Override + public void onStop() { + super.onStop(); + if(mSearchAdapter != null) + mSearchAdapter.stopListening(); + } + + @Override + public void onStart() { + super.onStart(); + } + + public void setQ(String q) { + this.q = q; + if(reference != null) { + Query query = reference.orderByChild("nameLower").startAt(q).endAt(q + "\uf8ff"); + if (searchType.equals(Type.EVENTS)) + query = reference.orderByChild("expired_vis_nameLower").startAt("false_PUBLIC_"+q).endAt("false_PUBLIC_"+q + "\uf8ff"); + else if (searchType.equals(Type.GROUPS)) + query = reference.orderByChild("vis_nameLower").startAt("PUBLIC_"+q).endAt("PUBLIC_"+q + "\uf8ff"); + + + mSearchAdapter = new SearchAdapter(query, this); + mRecyclerView.swapAdapter(mSearchAdapter, true); + mSearchAdapter.startListening(); + } + } + + public void switchFrag(Fragment fragment, Bundle args) { + SwitchFragment callback = (SwitchFragment) this.getActivity(); + if (callback != null) { + callback.switchFragment(fragment, args); + } + } + + public Type getSearchType() { + return searchType; + } +} diff --git a/app/src/main/java/com/groupproject/Controller/SearchActivities/SearchType.java b/app/src/main/java/com/groupproject/Controller/SearchActivities/SearchType.java new file mode 100644 index 0000000..10db33b --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/SearchActivities/SearchType.java @@ -0,0 +1,14 @@ +package com.groupproject.Controller.SearchActivities; + + + +public interface SearchType { + + enum Type{ + USERS, + EVENTS, + GROUPS, + NOTIFICATIONS, + INVITE + } +} diff --git a/app/src/main/java/com/groupproject/Controller/SideBarActivities/SidebarAdapter.java b/app/src/main/java/com/groupproject/Controller/SideBarActivities/SidebarAdapter.java new file mode 100644 index 0000000..68d8d90 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/SideBarActivities/SidebarAdapter.java @@ -0,0 +1,231 @@ +package com.groupproject.Controller.SideBarActivities; + +import android.app.Activity; +import android.content.Intent; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Filter; +import android.widget.Filterable; + +import com.groupproject.Controller.EventActivities.EventInfoActivity; +import com.groupproject.Controller.GroupActivities.ViewGroupActivity; +import com.groupproject.Controller.SearchActivities.SearchType; +import com.groupproject.Controller.ViewHolder; +import com.groupproject.Controller.ViewProfileActivity; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.DataBaseAPI.DataBaseCallBacks; +import com.groupproject.Model.DataBaseItem; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.User; +import com.groupproject.R; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +public class SidebarAdapter extends RecyclerView.Adapter implements Filterable, DataBaseCallBacks{ + + private static final DataBaseAPI databaseAPI = DataBaseAPI.getDataBase(); + private final SearchType.Type type; + private Set invited = new HashSet<>(); + private Set uninvited = new HashSet<>(); + private List items; + private final List filteredItemsList; + private String dataBaseItemID; + + private final Activity activity; + private UserFilter filter; + + public SidebarAdapter(Activity activity, SearchType.Type type, @Nullable String dataBaseItemID) { + super(); + items = new ArrayList<>(); + filteredItemsList = new ArrayList<>(); + this.activity = activity; + this.type = type; + this.dataBaseItemID = dataBaseItemID; + } + + public List getItems() { + return items; + } + + void setItems(List items) { + this.items = items; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.search_result, + viewGroup, false); + return new ViewHolder(itemView); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + DataBaseItem dataBaseItem = items.get(position); + holder.vName.setText(dataBaseItem.getName()); + String id = items.get(position).getId(); + switch (type){ + case USERS: + databaseAPI.getUser(id, this, holder); + holder.cardView.setOnClickListener(v -> { + Intent intent = new Intent(activity, ViewProfileActivity.class); + intent.putExtra("key", id); + activity.startActivity(intent); + }); + holder.interact.setImageDrawable(null); + holder.selected.setVisibility(View.GONE); + break; + case EVENTS: + holder.cardView.setOnClickListener(v -> { + Intent intent = new Intent(activity, EventInfoActivity.class); + intent.putExtra("key", id); + activity.startActivity(intent); + }); + holder.interact.setImageDrawable(null); + holder.selected.setVisibility(View.GONE); + break; + case GROUPS: + holder.cardView.setOnClickListener(v -> { + Intent intent = new Intent(activity, ViewGroupActivity.class); + intent.putExtra("key", id); + activity.startActivity(intent); + }); + holder.interact.setImageDrawable(null); + holder.selected.setVisibility(View.GONE); + break; + case NOTIFICATIONS: + holder.selected.setVisibility(View.GONE); + holder.interact.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.accept_button)); + holder.interact.setOnClickListener(view -> { + if(dataBaseItem instanceof User) { + databaseAPI.acceptRequestUser((User) dataBaseItem); + }else if(dataBaseItem instanceof Event){ + databaseAPI.acceptEventInvite((Event) dataBaseItem); + }else if(dataBaseItem instanceof Group){ + databaseAPI.acceptGroupInvite((Group) dataBaseItem); + } + this.getItems().remove(dataBaseItem); + this.notifyDataSetChanged(); + }); + break; + case INVITE: + User user = (User) dataBaseItem; + if(user.invitedEventsIDs.contains(dataBaseItemID) || + user.invitedGroupIDs.contains(dataBaseItemID)){ + holder.selected.setChecked(true); + }else { + holder.selected.setChecked(false); + } + holder.interact.setImageDrawable(null); + holder.selected.setOnCheckedChangeListener((compoundButton, b) -> { + boolean userInvited =user.invitedEventsIDs.contains(dataBaseItemID) || + user.invitedGroupIDs.contains(dataBaseItemID); + if (b && !userInvited) { + invited.add(dataBaseItem.getId()); + if(uninvited.contains(dataBaseItem.getId())) + uninvited.remove(dataBaseItem.getId()); + }else if(!b && userInvited){ + holder.selected.setChecked(false); + uninvited.add(dataBaseItem.getId()); + if(invited.contains(dataBaseItem.getId())) + invited.remove(dataBaseItem.getId()); + } else { +// invited.remove(dataBaseItem.getId()); + } + }); + } + } + + public Set getInvited() { + return invited; + } + + public Set getUninvited() { + return uninvited; + } + + @Override + public int getItemCount() { + return items.size(); + } + + @Override + public Filter getFilter() { + if(filter == null) { + filter = new UserFilter(this, items); + + } + return filter; + } + + @Override + public void getUser(User user, ViewHolder holder) { + + } + + @Override + public void getEvent(Event event, ViewHolder holder) { + + } + + @Override + public void getGroup(Group group, ViewHolder holder) { + + } + + @Override + public void executeQuery(List result, SearchType.Type type) { + + } + + private static class UserFilter extends Filter { + + private final SidebarAdapter adapter; + private final List originalList; + private final List filteredList; + + private UserFilter(SidebarAdapter adapter, List originalList) { + super(); + this.adapter = adapter; + this.originalList = new LinkedList<>(originalList); + this.filteredList = new ArrayList<>(); + } + + @Override + protected FilterResults performFiltering(CharSequence constraint) { + filteredList.clear(); + final FilterResults results = new FilterResults(); + + if (constraint.length() == 0) { + filteredList.addAll(originalList); + } else { + final String filterPattern = constraint.toString().toLowerCase().trim(); + + for (final DataBaseItem item : originalList) { + if (item.getNameLower().contains(filterPattern)) { + filteredList.add(item); + } + } + } + results.values = filteredList; + results.count = filteredList.size(); + return results; + } + + @Override + protected void publishResults(CharSequence constraint, FilterResults results) { + adapter.filteredItemsList.clear(); + adapter.filteredItemsList.addAll((ArrayList) results.values); + adapter.setItems((ArrayList) results.values); + adapter.notifyDataSetChanged(); + } + } +} diff --git a/app/src/main/java/com/groupproject/Controller/SideBarActivities/SidebarFragment.java b/app/src/main/java/com/groupproject/Controller/SideBarActivities/SidebarFragment.java new file mode 100644 index 0000000..d0fe080 --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/SideBarActivities/SidebarFragment.java @@ -0,0 +1,143 @@ +package com.groupproject.Controller.SideBarActivities; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.FloatingActionButton; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.google.firebase.database.Query; +import com.groupproject.Controller.GroupActivities.NewGroup; +import com.groupproject.Controller.SearchActivities.SearchType; +import com.groupproject.Controller.ViewHolder; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.DataBaseAPI.DataBaseCallBacks; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.User; +import com.groupproject.R; + +import java.util.List; + +public class SidebarFragment extends Fragment implements SearchType, DataBaseCallBacks{ + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + + private SidebarAdapter mSearchAdapter; + + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + + View rootView = inflater.inflate(R.layout.search_results, container, false); + final LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity()); + + FrameLayout radioGroup = rootView.findViewById(R.id.radio_buttons); + radioGroup.setVisibility(View.GONE); + + Type searchType = null; + Intent intent = null; + + Bundle bundle = getArguments(); + String type = bundle.getString("type"); + FloatingActionButton create = rootView.findViewById(R.id.new_group); + + Query query; + + + + assert type != null; + switch (type) { + case "friend": + create.setVisibility(View.INVISIBLE); + searchType = Type.USERS; + create.setVisibility(View.GONE); + query = dataBaseAPI.getmUserRef().child(dataBaseAPI.getCurrentUserID()).child("friendsIDs"); + dataBaseAPI.executeQuery(query, this, Type.USERS); + break; + case "events": + create.setVisibility(View.INVISIBLE); + searchType = Type.EVENTS; + //intent = new Intent(getActivity(), CreateEventActivity.class); + create.setVisibility(View.GONE); + query = dataBaseAPI.getmUserRef().child(dataBaseAPI.getCurrentUserID()).child("goingEventsIDs"); + dataBaseAPI.executeQuery(query, this, Type.EVENTS); + break; + case "groups": + searchType = Type.GROUPS; + intent = new Intent(getActivity(), NewGroup.class); + query = dataBaseAPI.getmUserRef().child(dataBaseAPI.getCurrentUserID()).child("joinedGroupIDs"); + dataBaseAPI.executeQuery(query, this, Type.GROUPS); + break; + case "notifications": + create.setVisibility(View.INVISIBLE); + searchType = Type.NOTIFICATIONS; + query = dataBaseAPI.getmUserRef().child(dataBaseAPI.getCurrentUserID()).child("requestsID"); + dataBaseAPI.executeQuery(query, this, Type.USERS); + query = dataBaseAPI.getmUserRef().child(dataBaseAPI.getCurrentUserID()).child("invitedEventsIDs"); + dataBaseAPI.executeQuery(query, this, Type.EVENTS); + query = dataBaseAPI.getmUserRef().child(dataBaseAPI.getCurrentUserID()).child("invitedGroupIDs"); + dataBaseAPI.executeQuery(query, this, Type.GROUPS); + break; + } + + mSearchAdapter = new SidebarAdapter(this.getActivity(), searchType, null); + mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + RecyclerView mRecyclerView = rootView.findViewById(R.id.search_fragment); + mRecyclerView.setLayoutManager(mLayoutManager); + mRecyclerView.swapAdapter(mSearchAdapter, true); + + Intent finalIntent = intent; + create.setOnClickListener(view -> { + if(finalIntent != null) + startActivity(finalIntent); + }); + return rootView; + + } + + + @Override + public void getUser(User user, ViewHolder holder) { + mSearchAdapter.getItems().add(user); + mSearchAdapter.notifyDataSetChanged(); + } + + @Override + public void getEvent(Event event, ViewHolder holder) { + mSearchAdapter.getItems().add(event); + mSearchAdapter.notifyDataSetChanged(); + } + + @Override + public void getGroup(Group group, ViewHolder holder) { + mSearchAdapter.getItems().add(group); + mSearchAdapter.notifyDataSetChanged(); + } + + @Override + public void executeQuery(List result, Type type) { + for (String s : result) { + if(type == Type.USERS) + dataBaseAPI.getUser(s, this, null); + else if(type == Type.EVENTS) + dataBaseAPI.getEvent(s, this, null); + else if(type == Type.GROUPS) + dataBaseAPI.getGroup(s, this, null); + } + } + + + public void filterResults(String string){ + mSearchAdapter.getFilter().filter(string); + } + + +} diff --git a/app/src/main/java/com/groupproject/Controller/SplashActivity.java b/app/src/main/java/com/groupproject/Controller/SplashActivity.java index ec894c8..054e181 100644 --- a/app/src/main/java/com/groupproject/Controller/SplashActivity.java +++ b/app/src/main/java/com/groupproject/Controller/SplashActivity.java @@ -2,23 +2,33 @@ import android.content.Intent; import android.os.Bundle; +import android.os.Handler; import android.support.v7.app.AppCompatActivity; -import com.facebook.AccessToken; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.groupproject.Controller.LoginActivities.LoginActivity; public class SplashActivity extends AppCompatActivity { + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - AccessToken accessToken = AccessToken.getCurrentAccessToken(); - Intent intent; - if (accessToken == null) { - intent = new Intent(this, LoginActivity.class); - } else { - intent = new Intent(this, MainActivity.class); - } - startActivity(intent); - finish(); + final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + //Duration of splash screen in milliseconds + int SPLASH_DISPLAY_LENGTH = 1000; + new Handler().postDelayed(() -> { + Intent intent; + if (user != null) { + // User is signed in + intent = new Intent(SplashActivity.this, BaseActivity.class); + } else { + // No user is signed in + intent = new Intent(SplashActivity.this, LoginActivity.class); + } + startActivity(intent); + finish(); + }, SPLASH_DISPLAY_LENGTH); } } diff --git a/app/src/main/java/com/groupproject/Controller/ViewHolder.java b/app/src/main/java/com/groupproject/Controller/ViewHolder.java new file mode 100644 index 0000000..c8bbfed --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/ViewHolder.java @@ -0,0 +1,29 @@ +package com.groupproject.Controller; + +import android.support.v7.widget.CardView; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.CheckBox; +import android.widget.ImageButton; +import android.widget.TextView; + +import com.groupproject.R; + + +public class ViewHolder extends RecyclerView.ViewHolder { + + public TextView vName; + public CardView cardView; + public ImageButton interact; + public CheckBox selected; + + public ViewHolder(View v) { + super(v); + vName = v.findViewById(R.id.txtName); + cardView = v.findViewById(R.id.card_view); + interact = v.findViewById(R.id.interact); + selected = v.findViewById(R.id.selected); + } + +} + diff --git a/app/src/main/java/com/groupproject/Controller/ViewProfileActivity.java b/app/src/main/java/com/groupproject/Controller/ViewProfileActivity.java new file mode 100644 index 0000000..5001cba --- /dev/null +++ b/app/src/main/java/com/groupproject/Controller/ViewProfileActivity.java @@ -0,0 +1,166 @@ +package com.groupproject.Controller; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; + +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageButton; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.firebase.database.Query; +import com.groupproject.Controller.SearchActivities.SearchType; +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; +import com.groupproject.Model.DataBaseAPI.DataBaseCallBacks; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.User; +import com.groupproject.R; + +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +public class ViewProfileActivity extends AppCompatActivity implements DataBaseCallBacks { + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + private ArrayAdapter adapter; + + TextView userName; + TextView emailAddress; + Button profileButton; + ImageButton upload; + List goingEventsLists = new ArrayList<>(); + private static final int PICK_PHOTO_FOR_AVATAR = 0; + + DataBaseAPI.UserRelationship userRelationship; + + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.view_profile); + Bundle b = getIntent().getExtras(); + String id = b.getString("key"); + setContentView(R.layout.view_profile); + dataBaseAPI.getUser(id, this, null); + + profileButton = findViewById(R.id.profileButton); + userName = findViewById(R.id.userName); + emailAddress = findViewById(R.id.emailAdd); + upload = findViewById(R.id.profileUpload); + upload.setOnClickListener(view -> pickImage()); + + ListView goingEvents = findViewById( R.id.goingEventsLists); + adapter = new ArrayAdapter<> + (this, android.R.layout.simple_spinner_item, goingEventsLists); + goingEvents.setAdapter(adapter); + + Query query = dataBaseAPI.getmUserRef().child(id).child("goingEventsIDs"); + dataBaseAPI.executeQuery(query, this, SearchType.Type.EVENTS); + } + + + @Override + public void getUser(User user, ViewHolder holder) { + userRelationship = dataBaseAPI.getRelationShip(user); + switch (userRelationship){ + case ME: + profileButton.setVisibility(View.GONE); + upload.setClickable(true); + break; + case FRIENDS: + profileButton.setText("Remove Friend"); + upload.setClickable(false); + break; + case REQUESTED: + profileButton.setText("Cancel Request"); + upload.setClickable(false); + break; + case NONE: + profileButton.setText("Send Request"); + upload.setClickable(false); + break; + } + userName.setText(user.getName()); + emailAddress.setText(user.getEmail()); + profileButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + switch (userRelationship){ + case FRIENDS: + profileButton.setText("Send Request"); + dataBaseAPI.removeFriend(user); + upload.setClickable(false); + break; + case REQUESTED: + profileButton.setText("Send Request"); + dataBaseAPI.cancelFriendRequest(user); + upload.setClickable(false); + break; + case NONE: + profileButton.setText("Cancel Request"); + dataBaseAPI.sendFriendRequest(user); + upload.setClickable(false); + break; + } + } + }); + } + + @Override + public void getEvent(Event event, ViewHolder holder) { + //TODO IF PUBLIC etc + goingEventsLists.add(event.getName() + " " +event.getDescription()); + adapter.notifyDataSetChanged(); + } + + @Override + public void getGroup(Group group, ViewHolder holder) {} + + @Override + public void executeQuery(List result, SearchType.Type type) { + for (String id : result) { + dataBaseAPI.getEvent(id, this, null); + } + + } + + public void pickImage() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("image/*"); + startActivityForResult(intent, PICK_PHOTO_FOR_AVATAR); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == PICK_PHOTO_FOR_AVATAR && resultCode == Activity.RESULT_OK) { + if (data == null) { + //Display an error + return; + } + try { + //e.g. create user, then change "images" to where i was called from + InputStream inputStream = getApplicationContext().getContentResolver() + .openInputStream(data.getData()); + Drawable buttonBg = Drawable.createFromStream(inputStream, null); + upload.setImageDrawable(buttonBg); + Toast.makeText(getApplicationContext(), "Image uploaded.", Toast.LENGTH_LONG) + .show(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + } + + + + +} diff --git a/app/src/main/java/com/groupproject/DataManager/DataManager.java b/app/src/main/java/com/groupproject/DataManager/DataManager.java deleted file mode 100644 index bbcac0e..0000000 --- a/app/src/main/java/com/groupproject/DataManager/DataManager.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.groupproject.DataManager; - -/** - * Created by henryhargreaves on 10/11/2017. - */ - -public interface DataManager { - - - - -} diff --git a/app/src/main/java/com/groupproject/Model/CustomLocation.java b/app/src/main/java/com/groupproject/Model/CustomLocation.java new file mode 100644 index 0000000..2e4419b --- /dev/null +++ b/app/src/main/java/com/groupproject/Model/CustomLocation.java @@ -0,0 +1,25 @@ +package com.groupproject.Model; + + +public class CustomLocation { + + + private Double latitude; + private Double longitude; + + public CustomLocation() {} + + public CustomLocation(Double latitude, Double longitude) { + this.latitude = latitude; + this.longitude = longitude; + } + + public Double getLatitude() { + return latitude; + } + + public Double getLongitude() { + return longitude; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/groupproject/Model/DataBaseAPI/DataBaseAPI.java b/app/src/main/java/com/groupproject/Model/DataBaseAPI/DataBaseAPI.java new file mode 100644 index 0000000..8538002 --- /dev/null +++ b/app/src/main/java/com/groupproject/Model/DataBaseAPI/DataBaseAPI.java @@ -0,0 +1,508 @@ +package com.groupproject.Model.DataBaseAPI; + +import android.app.Activity; +import android.content.Intent; +import android.support.annotation.Nullable; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.database.ChildEventListener; +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.Query; +import com.google.firebase.database.ValueEventListener; +import com.groupproject.Controller.LoginActivities.LoginActivity; +import com.groupproject.Controller.NotificationCallBack; +import com.groupproject.Controller.SearchActivities.SearchType; +import com.groupproject.Controller.ViewHolder; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.PinnedNotification; +import com.groupproject.Model.User; +import com.groupproject.Model.Visibility; + +import net.jodah.expiringmap.ExpiringMap; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.UserRelationship.ME; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.UserRelationship.FRIENDS; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.UserRelationship.REQUESTED; +import static com.groupproject.Model.DataBaseAPI.DataBaseAPI.UserRelationship.NONE; + +public class DataBaseAPI { + + private static DatabaseReference mEventRef; + private static DatabaseReference mUserRef; + private static DatabaseReference mGroupRef; + private DataBaseCallBacks dataBaseCallBacks; + private static DataBaseAPI single_instance = null; + private static ExpiringMap eventMap; + + public enum UserRelationship { + ME, + FRIENDS, + REQUESTED, + NONE + } + + public enum STATUS { + HOST, + JOINED, + INVITED, + PUBLIC, + HIDDEN + } + + private DataBaseAPI(){ + mUserRef = FirebaseDatabase.getInstance().getReference("users"); + mEventRef = FirebaseDatabase.getInstance().getReference("events"); + mGroupRef = FirebaseDatabase.getInstance().getReference("groups"); + eventMap = ExpiringMap.builder().variableExpiration().build(); + eventMap.addExpirationListener((key, e) -> { + e.setExpired(true); + e.setExpired_vis_nameLower(true+"_"+e.getVisibility()+"_"+e.getNameLower()); + HashMap result = new HashMap<>(); + result.put(e.getId(), e); + mEventRef.updateChildren(result); + eventMap.remove(e.getId()); + }); + } + + public static DataBaseAPI getDataBase() { + if (single_instance == null) { + single_instance = new DataBaseAPI(); + } + return single_instance; + } + + + public void signOut(Activity activity){ + FirebaseAuth.getInstance().signOut(); + Intent intent = new Intent(activity, LoginActivity.class); + activity.startActivity(intent); + } + + + public void addChildListener(String collection, ChildEventListener childEventListener) { + if (collection.equals("events")) { + mEventRef.addChildEventListener(childEventListener); + } + } + + + public void getUser(String id, DataBaseCallBacks callBacks, @Nullable ViewHolder holder){ + Query query = getmUserRef().child(id); + query.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + if (dataSnapshot.exists()) { + User user = dataSnapshot.getValue(com.groupproject.Model.User.class); + dataBaseCallBacks = callBacks; + dataBaseCallBacks.getUser(user, holder); + } + } + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + + public void getEvent(String id, DataBaseCallBacks callBacks, @Nullable ViewHolder holder){ + Query query = getmEventRef().child(id); + query.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + if (dataSnapshot.exists()) { + Event event = dataSnapshot.getValue(com.groupproject.Model.Event.class); + dataBaseCallBacks = callBacks; + dataBaseCallBacks.getEvent(event, holder); + } + } + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + + public void getGroup(String id, DataBaseCallBacks callBacks, @Nullable ViewHolder holder){ + Query query = getmGroupRef().child(id); + query.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + if (dataSnapshot.exists()) { + Group group = dataSnapshot.getValue(com.groupproject.Model.Group.class); + dataBaseCallBacks = callBacks; + dataBaseCallBacks.getGroup(group, holder); + } + } + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + + public void executeQuery(Query query, DataBaseCallBacks callBacks, SearchType.Type type){ + List ids = new ArrayList<>(); + query.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + dataBaseCallBacks = callBacks; + if (dataSnapshot.exists()) { + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + ids.add(snapshot.getKey()); + } + } + dataBaseCallBacks.executeQuery(ids, type); + } + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + + public String getCurrentUserID(){ + return FirebaseAuth.getInstance().getCurrentUser().getUid(); + } + + public DatabaseReference getmUserRef() { + return mUserRef; + } + + public DatabaseReference getmEventRef() { + return mEventRef; + } + + public DatabaseReference getmGroupRef() { + return mGroupRef; + } + + public UserRelationship getRelationShip(User user){ + if(user.getId().equals(getCurrentUserID())) { + return ME; + }else if(user.friendsIDs.contains(getCurrentUserID())){ + return FRIENDS; + }else if(user.requestsID.contains(getCurrentUserID())){ + return REQUESTED; + }else if(false){ //TODO Check if the user requested you + return REQUESTED; + }else{ + return NONE; + } + } + + public STATUS getEventRelationShip(Event event){ + if(Objects.equals(event.getHostID(), getCurrentUserID())) + return STATUS.HOST; + else if (event.goingIDs.contains(getCurrentUserID())) + return STATUS.JOINED; + else if (event.invitedIDs.contains(getCurrentUserID())) + return STATUS.INVITED; + else if (event.getVisibility() == Visibility.VISIBILITY.PUBLIC) + return STATUS.PUBLIC; + else + return STATUS.HIDDEN; + } + + public STATUS getGroupRelationShip(Group group){ + if(Objects.equals(group.getHost(), getCurrentUserID())) + return STATUS.HOST; + else if (group.membersIDs.contains(getCurrentUserID())) + return STATUS.JOINED; + else if (group.invitedIDs.contains(getCurrentUserID())) + return STATUS.INVITED; + else if (group.getVisibility() == Visibility.VISIBILITY.PUBLIC) + return STATUS.PUBLIC; + else + return STATUS.HIDDEN; + } + + + //TODO ON USER PROFILE INVITE TO EVENTS OR GROUPS *** + public void sendFriendRequest(User user){ + getmUserRef().child(user.getId()).child("requestsID").child(getCurrentUserID()).setValue(true); + getmUserRef().child(user.getId()).child("unSeenNotifications").child(getCurrentUserID()).setValue("user"); + } + + public void sendEventInvite(String userID, String eventID){ + getmEventRef().child(eventID).child("invitedIDs").child(userID).setValue(true); + getmUserRef().child(userID).child("invitedEventsIDs").child(eventID).setValue(true); + getmUserRef().child(userID).child("unSeenNotifications").child(eventID).setValue("event"); + } + + public void sendGroupInvite(String userID, String groupID){ + getmGroupRef().child(groupID).child("invitedIDs").child(userID).setValue(true); + getmUserRef().child(userID).child("invitedGroupIDs").child(groupID).setValue(true); + getmUserRef().child(userID).child("unSeenNotifications").child(groupID).setValue("group"); + } + + + public void removeFriend(User user){ + getmUserRef().child(getCurrentUserID()).child("friendsIDs").child(user.getId()).removeValue(); + getmUserRef().child(user.getId()).child("friendsIDs").child(getCurrentUserID()).removeValue(); + } + + public void leaveEvent(Event event){ + getmEventRef().child(event.getId()).child("goingIDs").child(getCurrentUserID()).removeValue(); + getmUserRef().child(getCurrentUserID()).child("goingEventsIDs").child(event.getId()).removeValue(); + } + + public void leaveGroup(Group group){ + getmGroupRef().child(group.getId()).child("membersIDs").child(getCurrentUserID()).removeValue(); + getmUserRef().child(getCurrentUserID()).child("joinedGroupIDs").child(group.getId()).removeValue(); + } + + public void setNotificationAsSeen(String notificationID, SearchType.Type type){ + getmUserRef().child(getCurrentUserID()).child("unSeenNotifications").child(notificationID).removeValue(); + if(type == SearchType.Type.USERS){ + getmUserRef().child(getCurrentUserID()).child("requestsID").child(notificationID).setValue(false); + } else if(type == SearchType.Type.EVENTS){ + getmUserRef().child(getCurrentUserID()).child("invitedEventsIDs").child(notificationID).setValue(false); + }else if(type == SearchType.Type.GROUPS){ + getmUserRef().child(getCurrentUserID()).child("invitedGroupIDs").child(notificationID).setValue(false); + } + } + + public void getNotifications(NotificationCallBack notificationCallBack){ + List notifications = new ArrayList<>(); + Query query = getmUserRef().child(getCurrentUserID()).child("unSeenNotifications"); + query.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + if(dataSnapshot.exists()) { + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + String id = snapshot.getKey(); + String type = snapshot.getValue(String.class); + notifications.add(new PinnedNotification(id, type)); + } + notificationCallBack.getNotifications(notifications); + } + } + + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + + public void deleteEvent(Event event){ + List goingIDs = new ArrayList<>(); + List invitedIDs = new ArrayList<>(); + Query query1 = getmEventRef().child(event.getId()).child("goingIDs"); + query1.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + if(dataSnapshot.exists()){ + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + goingIDs.add(snapshot.getKey()); + } + cascadeDelete(goingIDs, "goingEventsIDs", event.getId()); + } + } + @Override + public void onCancelled(DatabaseError databaseError) {} + }); + + Query query2 = getmEventRef().child(event.getId()).child("invitedIDs"); + query2.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + if(dataSnapshot.exists()){ + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + invitedIDs.add(snapshot.getKey()); + } + cascadeDelete(invitedIDs, "invitedEventsIDs", event.getId()); + } + } + + @Override + public void onCancelled(DatabaseError databaseError) {} + }); + getmEventRef().child(event.getId()).removeValue(); + } + + public void deleteGroup(Group group){ + List goingIDs = new ArrayList<>(); + List invitedIDs = new ArrayList<>(); + Query query1 = getmGroupRef().child(group.getId()).child("membersIDs"); + query1.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + if(dataSnapshot.exists()){ + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + goingIDs.add(snapshot.getKey()); + } + cascadeDelete(goingIDs, "joinedGroupIDs", group.getId()); + } + } + @Override + public void onCancelled(DatabaseError databaseError) {} + }); + + Query query2 = getmGroupRef().child(group.getId()).child("invitedIDs"); + query2.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + if(dataSnapshot.exists()){ + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + invitedIDs.add(snapshot.getKey()); + } + cascadeDelete(invitedIDs, "invitedGroupIDs", group.getId()); + } + } + + @Override + public void onCancelled(DatabaseError databaseError) {} + }); + } + + public void cancelFriendRequest(User user){ + getmUserRef().child(user.getId()).child("requestsID").child(getCurrentUserID()).removeValue(); + getmUserRef().child(user.getId()).child("unSeenNotifications").child(getCurrentUserID()).removeValue(); + + } + + public void cancelEventInvite(String userID, String eventID){ + getmUserRef().child(userID).child("invitedEventsIDs").child(eventID).removeValue(); + getmUserRef().child(eventID).child("invitedIDs").child(userID).removeValue(); + } + + public void cancelGroupInvite(String userID, String groupID){ + getmUserRef().child(userID).child("invitedGroupIDs").child(groupID).removeValue(); + getmUserRef().child(groupID).child("invitedIDs").child(userID).removeValue(); + } + + public void acceptRequestUser (User user){ + getmUserRef().child(getCurrentUserID()).child("friendsIDs").child(user.getId()).setValue(true); + getmUserRef().child(getCurrentUserID()).child("requestsID").child(user.getId()).removeValue();//Remove request + + getmUserRef().child(user.getId()).child("friendsIDs").child(getCurrentUserID()).setValue(true);//Add current user to users friends + } + + public void acceptEventInvite (Event event){ + getmEventRef().child(event.getId()).child("goingIDs").child(getCurrentUserID()).setValue(true); + getmEventRef().child(event.getId()).child("invitedIDs").child(getCurrentUserID()).removeValue(); + + getmUserRef().child(getCurrentUserID()).child("goingEventsIDs").child(event.getId()).setValue(true); + getmUserRef().child(getCurrentUserID()).child("invitedEventsIDs").child(event.getId()).removeValue();//Remove request + } + + public void acceptGroupInvite (Group group){ + getmGroupRef().child(group.getId()).child("membersIDs").child(getCurrentUserID()).setValue(true); + getmEventRef().child(group.getId()).child("invitedIDs").child(getCurrentUserID()).removeValue(); + getmUserRef().child(getCurrentUserID()).child("joinedGroupIDs").child(group.getId()).setValue(true); + getmUserRef().child(getCurrentUserID()).child("invitedGroupIDs").child(group.getId()).removeValue();//Remove request + } + + public void writeNewUser(User user) { + mUserRef.child(user.getId()).setValue(user); + } + + public void writeNewEvent(Event event) { + event.setId(mEventRef.push().getKey()); + mEventRef.child(event.getId()).setValue(event); + } + + public void writeNewGroup(Group group) { + group.setId(mGroupRef.push().getKey()); + mGroupRef.child(group.getId()).setValue(group); + } + + + public void addEventToUser(Event event) { + mUserRef.child(getCurrentUserID()).child("goingEventsIDs").child(event.getId()).setValue(true); + } + + public void addGroupToUser(Group group) { + mUserRef.child(getCurrentUserID()).child("joinedGroupIDs").child(group.getId()).setValue(true); + } + + public static ExpiringMap getEventMap() { + return eventMap; + } + + public static void removeExpiredEvents() { + Query activeEvents = mEventRef.orderByChild("expired").equalTo(false); + activeEvents.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + if (dataSnapshot.exists()) { + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + Event event = snapshot.getValue(com.groupproject.Model.Event.class); + if (event != null) { + if (event.getEndDate().before(new Date())){ + event.setExpired(true); + event.setExpired_vis_nameLower(true+"_"+event.getVisibility()+"_"+event.getNameLower()); + HashMap result = new HashMap<>(); + result.put(event.getId(), event); + mEventRef.updateChildren(result); + } + } + } + } + } + + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + + public static void loadActiveEvents() { + Date date = new Date(); + Query activeEvents = mEventRef.orderByChild("endDate/time").startAt(date.getTime()); + activeEvents.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + if (dataSnapshot.exists()) { + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + Event event = snapshot.getValue(com.groupproject.Model.Event.class); + if (event != null && eventMap.get(event.getId()) == null && !event.isExpired()) { + eventMap.put(event.getId(), event); + eventMap.setExpiration(event.getId(), event.calculateTimeRemaining(), TimeUnit.MILLISECONDS); + } + } + } + } + + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + + private void cascadeDelete(List result, String child, String idToBeRemoved) { + Query query; + if(!result.isEmpty()) { + for (String id : result) { + query = getmUserRef().child(id).child(child).child(idToBeRemoved); + query.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + dataSnapshot.getRef().removeValue(); + } + + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + } + } +} + + diff --git a/app/src/main/java/com/groupproject/Model/DataBaseAPI/DataBaseCallBacks.java b/app/src/main/java/com/groupproject/Model/DataBaseAPI/DataBaseCallBacks.java new file mode 100644 index 0000000..dde6d72 --- /dev/null +++ b/app/src/main/java/com/groupproject/Model/DataBaseAPI/DataBaseCallBacks.java @@ -0,0 +1,21 @@ +package com.groupproject.Model.DataBaseAPI; + +import com.groupproject.Controller.SearchActivities.SearchType; +import com.groupproject.Controller.ViewHolder; +import com.groupproject.Model.Event; +import com.groupproject.Model.Group; +import com.groupproject.Model.User; + +import java.util.List; + +public interface DataBaseCallBacks { + + void getUser(User user, ViewHolder holder); + + void getEvent(Event event, ViewHolder holder); + + void getGroup(Group group, ViewHolder holder); + + void executeQuery(List result, SearchType.Type type); + +} diff --git a/app/src/main/java/com/groupproject/Model/DataBaseItem.java b/app/src/main/java/com/groupproject/Model/DataBaseItem.java new file mode 100644 index 0000000..bffff9c --- /dev/null +++ b/app/src/main/java/com/groupproject/Model/DataBaseItem.java @@ -0,0 +1,26 @@ +package com.groupproject.Model; + + + +public class DataBaseItem { + + private String nameLower; + private String name; + private String id; + + DataBaseItem() { + + } + + public String getId() { + return id; + } + + public String getNameLower() { + return nameLower; + } + + public String getName() { + return name; + } +} diff --git a/app/src/main/java/com/groupproject/Model/Event.java b/app/src/main/java/com/groupproject/Model/Event.java new file mode 100644 index 0000000..90c00c6 --- /dev/null +++ b/app/src/main/java/com/groupproject/Model/Event.java @@ -0,0 +1,208 @@ +package com.groupproject.Model; + +import android.os.Build; +import android.support.annotation.RequiresApi; + +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class Event extends DataBaseItem { + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + + private String groupName; + private String hostID; + private String nameLower; + private String name; + private String description; + private String id; + + private String expired_vis_nameLower; + + private Date startDate; + private Date endDate; + + public List goingIDs; + public List invitedIDs; + public List tags; + + private CustomLocation customLocation; + private Visibility.VISIBILITY visibility; + + private boolean expired; + + + public Event() { + init(); + } + + public Event(Date startDate, Date endDate, CustomLocation customLocation, Visibility.VISIBILITY visibility, String name, String description, String hostID) { + init(); + this.startDate = startDate; + this.endDate = endDate; + this.customLocation = customLocation; + this.visibility = visibility; + this.name = name; + this.nameLower = name.toLowerCase(); + this.description = description; + this.hostID = hostID; + this.expired_vis_nameLower = isExpired()+"_"+visibility+"_"+nameLower; + goingIDs.add(hostID); + dataBaseAPI.writeNewEvent(this); + } + + private void init(){ + if(endDate != null) + expired = checkExpired(); + this.goingIDs = new ArrayList<>(); + this.invitedIDs = new ArrayList<>(); + + } + + + public boolean checkExpired(){ + return (endDate.getTime() - System.currentTimeMillis()) < 0 ; + } + + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setGoingIDs(Map map) { + goingIDs = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getGoingIDs() { + return goingIDs.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setInvitedIDs(Map map) { + invitedIDs = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getInvitedIDs() { + return invitedIDs.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + + public String getExpired_vis_nameLower() { + return this.expired_vis_nameLower = expired_vis_nameLower; + } + + public void setExpired_vis_nameLower(String expired_vis_nameLower) { + this.expired_vis_nameLower = expired_vis_nameLower; + } + + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + public long calculateTimeRemaining(){ + return endDate.getTime() - System.currentTimeMillis(); + } + + public String getHostID() { + return hostID; + } + + public void setHostID(String hostID) { + this.hostID = hostID; + } + + @Override + public String getNameLower() { + return nameLower; + } + + public void setNameLower(String nameLower) { + this.nameLower = nameLower; + } + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public CustomLocation getCustomLocation() { + return customLocation; + } + + public void setCustomLocation(CustomLocation customLocation) { + this.customLocation = customLocation; + } + + public Visibility.VISIBILITY getVisibility() { + return visibility; + } + + public void setVisibility(Visibility.VISIBILITY visibility) { + this.visibility = visibility; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public boolean isExpired() { + return expired; + } + + public void setExpired(boolean expired) { + this.expired = expired; + } +} + + diff --git a/app/src/main/java/com/groupproject/Model/Group.java b/app/src/main/java/com/groupproject/Model/Group.java new file mode 100644 index 0000000..39bc017 --- /dev/null +++ b/app/src/main/java/com/groupproject/Model/Group.java @@ -0,0 +1,164 @@ +package com.groupproject.Model; + +import android.os.Build; +import android.support.annotation.RequiresApi; + +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class Group extends DataBaseItem{ + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + + private String host; + public List membersIDs;// + public List invitedIDs;//TODO this might be tricky + + public List eventsIDs; + + private String name; + private String description; + + private String nameLower; + + private String id; + private String vis_nameLower; + + + private Visibility.VISIBILITY visibility; + + public Group() { + init(); + } + + + public Group(String name, String description, Visibility.VISIBILITY visibility, String host) { + init(); + this.name = name; + this.description = description; + this.nameLower = name.toLowerCase(); + this.visibility = visibility; + membersIDs.add(host); + this.host = host; + this.vis_nameLower = visibility+"_"+nameLower; + dataBaseAPI.writeNewGroup(this); + } + + public Group(String name, String description) { + this.name = name; + this.nameLower = name.toLowerCase(); + this.description = description; + } + + private void init(){ + eventsIDs = new ArrayList<>(); + membersIDs = new ArrayList<>(); + invitedIDs = new ArrayList<>(); + } + + + public String getVis_nameLower() { + return vis_nameLower; + } + + public void setVis_nameLower(String vis_nameLower) { + this.vis_nameLower = vis_nameLower; + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setMembersIDs(Map map) { + membersIDs = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getMembersIDs() { + return membersIDs.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setEventsIDs(Map map) { + eventsIDs = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getEventsIDs() { + return eventsIDs.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setInvitedIDs(Map map) { + invitedIDs = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getInvitedIDs() { + return invitedIDs.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public void setName(String name) { + this.name = name; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String getNameLower() { + return nameLower; + } + + public void setNameLower(String nameLower) { + this.nameLower = nameLower; + } + + public void setVisibility(Visibility.VISIBILITY visibility) { + this.visibility = visibility; + } + + public String getName() { + return name; + } + + public String getLowerCaseName() { + return nameLower; + } + + public String getDescription() { + return description; + } + + public Visibility.VISIBILITY getVisibility() { + return visibility; + } + + @Override + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + + @Override + public String toString() { + return name; + } +} + + diff --git a/app/src/main/java/com/groupproject/Model/PinnedNotification.java b/app/src/main/java/com/groupproject/Model/PinnedNotification.java new file mode 100644 index 0000000..f0059f1 --- /dev/null +++ b/app/src/main/java/com/groupproject/Model/PinnedNotification.java @@ -0,0 +1,29 @@ +package com.groupproject.Model; + + +public class PinnedNotification { + + public String id; + public String type; + + public PinnedNotification(String id, String type) { + this.id = id; + this.type = type; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/app/src/main/java/com/groupproject/Model/User.java b/app/src/main/java/com/groupproject/Model/User.java new file mode 100644 index 0000000..69bbabb --- /dev/null +++ b/app/src/main/java/com/groupproject/Model/User.java @@ -0,0 +1,193 @@ +package com.groupproject.Model; + +import android.os.Build; +import android.support.annotation.RequiresApi; + +import com.groupproject.Model.DataBaseAPI.DataBaseAPI; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class User extends DataBaseItem{ + + private static final DataBaseAPI dataBaseAPI = DataBaseAPI.getDataBase(); + + public List friendsIDs; + public List requestsID; + public List goingEventsIDs; + public List invitedEventsIDs; + public List joinedGroupIDs; + public List invitedGroupIDs; + public List unSeenNotifications; +// private List interestedEventsIDs;//TODO If interested cant be going and vice versa + + private String nameLower; + private CustomLocation location; + private String name; + private String email; + private String id; + + public User() { + init(); + } + + public User(String id, String name, String email) { + init(); + this.id = id; + this.name = name; + this.nameLower = name.toLowerCase(); + this.email = email; + dataBaseAPI.writeNewUser(this); + } + + private void init(){ + goingEventsIDs= new ArrayList<>(); + friendsIDs= new ArrayList<>(); + requestsID= new ArrayList<>(); + invitedGroupIDs = new ArrayList<>(); + invitedEventsIDs = new ArrayList<>(); + joinedGroupIDs = new ArrayList<>(); + unSeenNotifications = new ArrayList<>(); + } + + public Map getUnSeenNotifications() { + return unSeenNotifications.stream().collect(Collectors.toMap(PinnedNotification::getId, PinnedNotification::getType)); + } + + public void setUnSeenNotifications(Map map) { + this.unSeenNotifications = map.entrySet().stream().map(n -> new PinnedNotification(n.getKey(), n.getValue().toString())).collect(Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setGoingEventsIDs(Map map) { + goingEventsIDs = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getGoingEventsIDs() { + return goingEventsIDs.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setFriendsIDs(Map map) { + friendsIDs = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getFriendsIDs() { + return friendsIDs.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setRequestsID(Map map) { + requestsID = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getRequestsID() { + return requestsID.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setJoinedGroupIDs(Map map) { + joinedGroupIDs = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getJoinedGroupIDs() { + return joinedGroupIDs.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setInvitedGroupIDs(Map map) { + invitedGroupIDs = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getInvitedGroupIDs() { + return invitedGroupIDs.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + + @RequiresApi(api = Build.VERSION_CODES.N) + public void setInvitedEventsIDs(Map map) { + invitedEventsIDs = map.keySet().stream().map(Object::toString).collect (Collectors.toList()); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public Map getInvitedEventsIDs() { + return invitedEventsIDs.stream().collect(Collectors.toMap(Function.identity(), id -> true)); + } + + public CustomLocation getLocation() { + return location; + } + + public void setLocation(CustomLocation location) { + this.location = location; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getId() {return id;} + + public void setId(String id) { + this.id = id; + } + + @Override + public String getNameLower() { + return nameLower; + } + + public void setLowerLower(String nameLower) { + this.nameLower = nameLower; + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/groupproject/Model/Visibility.java b/app/src/main/java/com/groupproject/Model/Visibility.java new file mode 100644 index 0000000..483e165 --- /dev/null +++ b/app/src/main/java/com/groupproject/Model/Visibility.java @@ -0,0 +1,9 @@ +package com.groupproject.Model; + +public class Visibility { + + public enum VISIBILITY { + INVITE_ONLY, + PUBLIC + } +} diff --git a/app/src/main/java/com/groupproject/User.java b/app/src/main/java/com/groupproject/User.java deleted file mode 100644 index 3721fe1..0000000 --- a/app/src/main/java/com/groupproject/User.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.groupproject; - - -public class User { - - private String id; - private String first_name; - private String last_name; - private String email; - - public User(String id, String first_name, String last_name, String email) { - this.id = id; - this.first_name = first_name; - this.last_name = last_name; - this.email = email; - } -} diff --git a/app/src/main/res/drawable-hdpi/ic_add_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_add_black_24dp.png new file mode 100644 index 0000000..c04b523 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_add_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_add_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_add_black_24dp.png new file mode 100644 index 0000000..23bf119 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_add_black_24dp.png differ diff --git a/app/src/main/res/drawable-v21/ic_menu_camera.xml b/app/src/main/res/drawable-v21/ic_menu_camera.xml new file mode 100644 index 0000000..0d9ea10 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_menu_camera.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable-v21/ic_menu_gallery.xml b/app/src/main/res/drawable-v21/ic_menu_gallery.xml new file mode 100644 index 0000000..f6872c4 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_menu_gallery.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_menu_manage.xml b/app/src/main/res/drawable-v21/ic_menu_manage.xml new file mode 100644 index 0000000..c1be60b --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_menu_manage.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/ic_menu_send.xml b/app/src/main/res/drawable-v21/ic_menu_send.xml new file mode 100644 index 0000000..00c668c --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_menu_send.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_menu_share.xml b/app/src/main/res/drawable-v21/ic_menu_share.xml new file mode 100644 index 0000000..a28fb9e --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_menu_share.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_menu_slideshow.xml b/app/src/main/res/drawable-v21/ic_menu_slideshow.xml new file mode 100644 index 0000000..209aa64 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_menu_slideshow.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-xhdpi/ic_add_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_add_black_24dp.png new file mode 100644 index 0000000..3191d52 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_add_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_add_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_add_black_24dp.png new file mode 100644 index 0000000..a84106b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_add_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_add_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_add_black_24dp.png new file mode 100644 index 0000000..3cb1092 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_add_black_24dp.png differ diff --git a/app/src/main/res/drawable/accept_button.png b/app/src/main/res/drawable/accept_button.png new file mode 100644 index 0000000..3619b67 Binary files /dev/null and b/app/src/main/res/drawable/accept_button.png differ diff --git a/app/src/main/res/drawable/add_button.png b/app/src/main/res/drawable/add_button.png new file mode 100644 index 0000000..f1439e5 Binary files /dev/null and b/app/src/main/res/drawable/add_button.png differ diff --git a/app/src/main/res/drawable/border.png b/app/src/main/res/drawable/border.png new file mode 100644 index 0000000..ad5cff1 Binary files /dev/null and b/app/src/main/res/drawable/border.png differ diff --git a/app/src/main/res/drawable/button_accept.png b/app/src/main/res/drawable/button_accept.png new file mode 100644 index 0000000..8895dc4 Binary files /dev/null and b/app/src/main/res/drawable/button_accept.png differ diff --git a/app/src/main/res/drawable/button_add.png b/app/src/main/res/drawable/button_add.png new file mode 100644 index 0000000..ad41ce5 Binary files /dev/null and b/app/src/main/res/drawable/button_add.png differ diff --git a/app/src/main/res/drawable/button_cancel.png b/app/src/main/res/drawable/button_cancel.png new file mode 100644 index 0000000..e5245de Binary files /dev/null and b/app/src/main/res/drawable/button_cancel.png differ diff --git a/app/src/main/res/drawable/cancel_button.png b/app/src/main/res/drawable/cancel_button.png new file mode 100644 index 0000000..bbd4fba Binary files /dev/null and b/app/src/main/res/drawable/cancel_button.png differ diff --git a/app/src/main/res/drawable/defaultpic.png b/app/src/main/res/drawable/defaultpic.png new file mode 100644 index 0000000..11af404 Binary files /dev/null and b/app/src/main/res/drawable/defaultpic.png differ diff --git a/app/src/main/res/drawable/deleteaccount.png b/app/src/main/res/drawable/deleteaccount.png new file mode 100644 index 0000000..de09b9e Binary files /dev/null and b/app/src/main/res/drawable/deleteaccount.png differ diff --git a/app/src/main/res/drawable/eventpic.png b/app/src/main/res/drawable/eventpic.png index 4384c33..8d8829d 100644 Binary files a/app/src/main/res/drawable/eventpic.png and b/app/src/main/res/drawable/eventpic.png differ diff --git a/app/src/main/res/drawable/events.png b/app/src/main/res/drawable/events.png new file mode 100644 index 0000000..14bedb3 Binary files /dev/null and b/app/src/main/res/drawable/events.png differ diff --git a/app/src/main/res/drawable/facebook.png b/app/src/main/res/drawable/facebook.png new file mode 100644 index 0000000..4f53365 Binary files /dev/null and b/app/src/main/res/drawable/facebook.png differ diff --git a/app/src/main/res/drawable/friends.png b/app/src/main/res/drawable/friends.png new file mode 100644 index 0000000..8a7c370 Binary files /dev/null and b/app/src/main/res/drawable/friends.png differ diff --git a/app/src/main/res/drawable/google.png b/app/src/main/res/drawable/google.png new file mode 100644 index 0000000..cbbcb39 Binary files /dev/null and b/app/src/main/res/drawable/google.png differ diff --git a/app/src/main/res/drawable/groups.png b/app/src/main/res/drawable/groups.png new file mode 100644 index 0000000..d2a4adf Binary files /dev/null and b/app/src/main/res/drawable/groups.png differ diff --git a/app/src/main/res/drawable/ic_info_black_24dp.xml b/app/src/main/res/drawable/ic_info_black_24dp.xml new file mode 100644 index 0000000..34b8202 --- /dev/null +++ b/app/src/main/res/drawable/ic_info_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_notifications_black_24dp.xml b/app/src/main/res/drawable/ic_notifications_black_24dp.xml new file mode 100644 index 0000000..e3400cf --- /dev/null +++ b/app/src/main/res/drawable/ic_notifications_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_sync_black_24dp.xml b/app/src/main/res/drawable/ic_sync_black_24dp.xml new file mode 100644 index 0000000..5a283aa --- /dev/null +++ b/app/src/main/res/drawable/ic_sync_black_24dp.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/notification.png b/app/src/main/res/drawable/notification.png new file mode 100644 index 0000000..36e20e1 Binary files /dev/null and b/app/src/main/res/drawable/notification.png differ diff --git a/app/src/main/res/drawable/pinnedlogo.png b/app/src/main/res/drawable/pinnedlogo.png new file mode 100644 index 0000000..881ca1f Binary files /dev/null and b/app/src/main/res/drawable/pinnedlogo.png differ diff --git a/app/src/main/res/drawable/progress.xml b/app/src/main/res/drawable/progress.xml new file mode 100644 index 0000000..408367a --- /dev/null +++ b/app/src/main/res/drawable/progress.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/remove_button.9.png b/app/src/main/res/drawable/remove_button.9.png new file mode 100644 index 0000000..e039f8d Binary files /dev/null and b/app/src/main/res/drawable/remove_button.9.png differ diff --git a/app/src/main/res/drawable/requests.png b/app/src/main/res/drawable/requests.png new file mode 100644 index 0000000..a643afc Binary files /dev/null and b/app/src/main/res/drawable/requests.png differ diff --git a/app/src/main/res/drawable/side_nav_bar.xml b/app/src/main/res/drawable/side_nav_bar.xml new file mode 100644 index 0000000..12a53bf --- /dev/null +++ b/app/src/main/res/drawable/side_nav_bar.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/signout.png b/app/src/main/res/drawable/signout.png new file mode 100644 index 0000000..12a877d Binary files /dev/null and b/app/src/main/res/drawable/signout.png differ diff --git a/app/src/main/res/drawable/splash_background.xml b/app/src/main/res/drawable/splash_background.xml index 566006e..e8fd605 100644 --- a/app/src/main/res/drawable/splash_background.xml +++ b/app/src/main/res/drawable/splash_background.xml @@ -1,11 +1,11 @@ + android:drawable="@color/white"/> + android:src="@drawable/pinnedlogo" /> \ No newline at end of file diff --git a/app/src/main/res/font/josefin_sans_semibold.ttf b/app/src/main/res/font/josefin_sans_semibold.ttf new file mode 100644 index 0000000..03bfb70 Binary files /dev/null and b/app/src/main/res/font/josefin_sans_semibold.ttf differ diff --git a/app/src/main/res/font/segoeuil.ttf b/app/src/main/res/font/segoeuil.ttf new file mode 100644 index 0000000..53edf71 Binary files /dev/null and b/app/src/main/res/font/segoeuil.ttf differ diff --git a/app/src/main/res/layout-v21/activity_email_sign_up.xml b/app/src/main/res/layout-v21/activity_email_sign_up.xml new file mode 100644 index 0000000..6f090ff --- /dev/null +++ b/app/src/main/res/layout-v21/activity_email_sign_up.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + +