diff --git a/frontend/Movie_Pigeon/app/build.gradle b/frontend/Movie_Pigeon/app/build.gradle index ef18c65..140b711 100644 --- a/frontend/Movie_Pigeon/app/build.gradle +++ b/frontend/Movie_Pigeon/app/build.gradle @@ -31,19 +31,27 @@ android { dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { - exclude group: 'com.android.support', module: 'support-annotations' - }) + compile files('libs/universal-image-loader-1.9.5.jar') + compile files('libs/gson-2.8.0.jar') + compile files('libs/eventbus-3.0.0.jar') compile 'com.android.support:appcompat-v7:25.1.1' compile 'com.android.support:support-v4:25.1.1' compile 'com.android.support:recyclerview-v7:25.1.1' - testCompile 'junit:junit:4.12' - compile files('libs/universal-image-loader-1.9.5.jar') compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' compile 'com.squareup.okhttp3:okhttp:3.6.0' compile 'com.squareup.okio:okio:1.11.0' compile 'com.google.code.gson:gson:2.8.0' compile 'org.greenrobot:eventbus:3.0.0' - compile files('libs/gson-2.8.0.jar') - compile files('libs/eventbus-3.0.0.jar') + testCompile 'junit:junit:4.12' + androidTestCompile 'com.android.support:support-annotations:25.1.1' + + // Android runner and rules support + androidTestCompile 'com.android.support.test:runner:0.5' + androidTestCompile 'com.android.support.test:rules:0.5' + // Espresso support + androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + // intent mocking support + androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2' } diff --git a/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/ChangeUserInfoActivityTest.java b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/ChangeUserInfoActivityTest.java new file mode 100644 index 0000000..ac73652 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/ChangeUserInfoActivityTest.java @@ -0,0 +1,148 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.content.Context; +import android.content.Intent; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import junit.framework.AssertionFailedError; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +/** + * Created by Guo Mingxuan on 19/3/2017. + */ + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class ChangeUserInfoActivityTest { + + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule(ChangeUserInfoActivity.class){ + @Override + protected Intent getActivityIntent() { + Context targetContext = InstrumentationRegistry.getInstrumentation() + .getTargetContext(); + Intent result = new Intent(targetContext, ThirdPartySignupActivity.class); + result.putExtra("type", "username"); + return result; + } + }; + + @Test + public void loadToolbar() { + try { + onView(withId(R.id.toolbar_user_activity)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadFrameLayout() { + try { + onView(withId(R.id.fl_user_activity)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadUsernameTextView() { + try { + onView(withId(R.id.setting_fragment_username_tv)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadUsernameEdittext() { + try { + onView(withId(R.id.setting_fragment_username_et)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadCurrentPasswordTextView() { + try { + onView(withId(R.id.setting_fragment_now_password_tv)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadCurrentPasswordEdittext() { + try { + onView(withId(R.id.setting_fragment_now_password_et)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadNewPasswordTextView() { + try { + onView(withId(R.id.setting_fragment_password_tv)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadNewPasswordEdittext() { + try { + onView(withId(R.id.setting_fragment_password_et)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadConfirmPasswordTextView() { + try { + onView(withId(R.id.setting_fragment_repeat_password_tv)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadConfirmPasswordEdittext() { + try { + onView(withId(R.id.setting_fragment_repeat_password_et)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadConfirmButton() { + try { + onView(withId(R.id.setting_fragment_confirm)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadCancelButton() { + try { + onView(withId(R.id.setting_fragment_cancel)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/DisplayActivityTest.java b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/DisplayActivityTest.java new file mode 100644 index 0000000..055819f --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/DisplayActivityTest.java @@ -0,0 +1,57 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.test.InstrumentationRegistry; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import org.example.team_pigeon.movie_pigeon.models.Movie; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; + +import static android.support.test.espresso.Espresso.onData; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +/** + * Created by SHENGX on 2017/3/19. + */ +@RunWith(AndroidJUnit4.class) +public class DisplayActivityTest { + @Rule + public ActivityTestRule displayActivityActivityTestRule = new ActivityTestRule(DisplayActivity.class) { + @Override + protected Intent getActivityIntent() { + ArrayList testMovieList = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + testMovieList.add(new Movie(String.valueOf(i), "id")); + } + Bundle argument = new Bundle(); + argument.putSerializable("movieList", testMovieList); + argument.putString("title", "TestBar"); + argument.putString("type", "test"); + Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + Intent result = new Intent(targetContext, DisplayActivity.class); + result.putExtra("bundle",argument); + return result; + } + }; + + @Test + public void showMovieListProperly() { + onView(withId(R.id.toolbar_display_page)).check(matches(isDisplayed())); + onView(withId(R.id.list_movies)).check(matches(isDisplayed())); + for(int i = 0;i<10;i++) { + onData(withText(String.valueOf(i))).inAdapterView(withId(R.id.list_movies)).atPosition(i); + } + } + +} diff --git a/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/HomePageActivityTest.java b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/HomePageActivityTest.java new file mode 100644 index 0000000..8b2d9b2 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/HomePageActivityTest.java @@ -0,0 +1,67 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.content.Context; +import android.content.Intent; +import android.support.test.InstrumentationRegistry; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +/** + * Created by SHENGX on 2017/3/19. + */ + +@RunWith(AndroidJUnit4.class) +public class HomePageActivityTest { + @Rule + public ActivityTestRule homePageActivityActivityTestRule = new ActivityTestRule(HomePageActivity.class) { + @Override + protected Intent getActivityIntent() { + Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + Intent result = new Intent(targetContext, HomePageActivity.class); + result.putExtra("Token", "test token"); + return result; + } + }; + + @Test + public void ensureUiComponentsDisplayed() { + onView(withId(R.id.rg_tab_bar)) + .check(matches(isDisplayed())); + onView(withId(R.id.rb_now_showing)) + .check(matches(isDisplayed())); + onView(withId(R.id.rb_home)) + .check(matches(isDisplayed())); + onView(withId(R.id.rb_me)) + .check(matches(isDisplayed())); + onView(withId(R.id.view_pager)) + .check(matches(isDisplayed())); + onView(withId(R.id.rg_tab_bar)) + .check(matches(isDisplayed())); + } + + @Test + public void viewPagerSwitchCorrectly() { + onView(withText("Cinemas")).perform(click()); + onView(withId(R.id.spinner_cinema_brand)).check(matches(isDisplayed())); + onView(withText("Me")).perform(click()); + onView(withText("My Ratings")).check(matches(isDisplayed())); + onView(withText("My Bookmarks")).check(matches(isDisplayed())); + onView(withText("Settings")).check(matches(isDisplayed())); + onView(withText("Logout")).check(matches(isDisplayed())); + onView(withText("Home")).perform(click()); + onView(withId(R.id.search_view)).check(matches(isDisplayed())); + onView(withId(R.id.grid_now_showing)).check(matches(isDisplayed())); + onView(withId(R.id.grid_recommended)).check(matches(isDisplayed())); + } +} diff --git a/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/RegistrationActivityTest.java b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/RegistrationActivityTest.java new file mode 100644 index 0000000..a5a47d5 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/RegistrationActivityTest.java @@ -0,0 +1,117 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import junit.framework.AssertionFailedError; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +/** + * Created by Guo Mingxuan on 19/3/2017. + */ + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class RegistrationActivityTest { + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule<>(RegistrationActivity.class); + + @Test + public void loadUsernameTextView() { + try { + onView(withId(R.id.rTVUsername)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadUsernameEdittext() { + try { + onView(withId(R.id.rETUsername)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadEmailTextView() { + try { + onView(withId(R.id.rTVEmail)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadEmailEdittext() { + try { + onView(withId(R.id.rETEmail)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadPasswordTextView() { + try { + onView(withId(R.id.rTVPassword)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadPasswordEdittext() { + try { + onView(withId(R.id.rETPassword)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadConfirmPasswordTextView() { + try { + onView(withId(R.id.rTVConfirmPassword)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadConfirmPasswordEdittext() { + try { + onView(withId(R.id.rETConfirmPassword)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadRegisterButton() { + try { + onView(withId(R.id.rpRegisterButton)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadBackButton() { + try { + onView(withId(R.id.rpBackButton)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/ResetPasswordActivityTest.java b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/ResetPasswordActivityTest.java new file mode 100644 index 0000000..9da4687 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/ResetPasswordActivityTest.java @@ -0,0 +1,73 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import junit.framework.AssertionFailedError; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +/** + * Created by Guo Mingxuan on 19/3/2017. + */ + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class ResetPasswordActivityTest { + + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule<>(ResetPasswordActivity.class); + + @Test + public void loadTitleTextView() { + try { + onView(withId(R.id.tvResetPassword)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadHintTextView() { + try { + onView(withId(R.id.rsHint)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadResetTable() { + try { + onView(withId(R.id.resetTable)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadVCodeButton() { + try { + onView(withId(R.id.rsBVerificationCode)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadBackButton() { + try { + onView(withId(R.id.rsBBack)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/SettingActivityTest.java b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/SettingActivityTest.java new file mode 100644 index 0000000..eb61a73 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/SettingActivityTest.java @@ -0,0 +1,63 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import junit.framework.AssertionFailedError; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +/** + * Created by Guo Mingxuan on 19/3/2017. + */ + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class SettingActivityTest { + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule<>(SettingActivity.class); + + @Test + public void loadToolbar() { + try { + onView(withId(R.id.toolbar_setting_page)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadFrameLayout() { + try { + onView(withId(R.id.frame_layout_setting_page)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadChangUsernameButton() { + try { + onView(withId(R.id.username_setting_page)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadChangePasswordButton() { + try { + onView(withId(R.id.password_setting_page)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/StartActivityTest.java b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/StartActivityTest.java new file mode 100644 index 0000000..03ff3ea --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/StartActivityTest.java @@ -0,0 +1,81 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import junit.framework.AssertionFailedError; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + + +/** + * Created by Guo Mingxuan on 18/3/2017. + */ + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StartActivityTest { + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule<>(StartActivity.class); + + @Test + public void loadLoginTable() { + try { + onView(withId(R.id.loginTable)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadSignInButton() { + try { + onView(withId(R.id.buttonSignIn)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadTraktButton() { + try { + onView(withId(R.id.buttonTrakt)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadTmdbButton() { + try { + onView(withId(R.id.buttonTmdb)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadRegisterButton() { + try { + onView(withId(R.id.buttonRegister)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + @Test + public void loadForgetPwdButton() { + try { + onView(withId(R.id.buttonForgotPassword)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/ThirdPartySignupActivityTest.java b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/ThirdPartySignupActivityTest.java new file mode 100644 index 0000000..4880ce4 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/androidTest/java/org/example/team_pigeon/movie_pigeon/ThirdPartySignupActivityTest.java @@ -0,0 +1,93 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.content.Context; +import android.content.Intent; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import junit.framework.AssertionFailedError; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +/** + * Created by Guo Mingxuan on 19/3/2017. + */ + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class ThirdPartySignupActivityTest { + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule(ThirdPartySignupActivity.class) { + @Override + protected Intent getActivityIntent() { + Context targetContext = InstrumentationRegistry.getInstrumentation() + .getTargetContext(); + Intent result = new Intent(targetContext, ThirdPartySignupActivity.class); + result.putExtra("thirdParty", "The Movie DB"); + return result; + } + }; + + @Test + public void loadPlaceholderTextView() { + try { + onView(withId(R.id.tpsTitle)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadInputEdittext() { + try { + onView(withId(R.id.tpsInput)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadPasswordTextView() { + try { + onView(withId(R.id.tpsPasswordTitle)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadPasswordEdittext() { + try { + onView(withId(R.id.tpsPassword)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadConfirmButton() { + try { + onView(withId(R.id.tpsConfirmButton)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } + + @Test + public void loadBackButton() { + try { + onView(withId(R.id.tpsBackButton)).check(matches(isDisplayed())); + } catch (AssertionFailedError e) { + e.printStackTrace(); + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/AndroidManifest.xml b/frontend/Movie_Pigeon/app/src/main/AndroidManifest.xml index bd9607b..570fc94 100644 --- a/frontend/Movie_Pigeon/app/src/main/AndroidManifest.xml +++ b/frontend/Movie_Pigeon/app/src/main/AndroidManifest.xml @@ -19,13 +19,20 @@ - + + + + + + \ No newline at end of file diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/ChangeUserInfoActivity.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/ChangeUserInfoActivity.java new file mode 100644 index 0000000..7ce8296 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/ChangeUserInfoActivity.java @@ -0,0 +1,87 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.content.IntentFilter; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.MenuItem; +import android.view.View; + +/** + * Created by Guo Mingxuan on 16/3/2017. + */ + +public class ChangeUserInfoActivity extends AppCompatActivity { + private Toolbar toolbar; + private String type; + private FragmentManager fm; + private String TAG = "CUIA"; + private GlobalReceiver globalReceiver; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View view = getLayoutInflater().inflate(R.layout.activity_change_user_info, null); + setContentView(view); + toolbar = (Toolbar) findViewById(R.id.toolbar_user_activity); + type = getIntent().getExtras().getString("type"); + Log.i(TAG, "the type is " + type); + toolbar.setTitle("Change " + type); + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + + fm = getFragmentManager(); + + globalReceiver = new GlobalReceiver(); + IntentFilter filter = new IntentFilter(); + filter.addAction("changeUsername"); + filter.addAction("userUpdate"); + registerReceiver(globalReceiver, filter); + + if (type.equals("username")) { + Log.i(TAG, "Type is username"); + toolbar.setTitle("Change Username"); + SettingFragments sf = new SettingFragments(); + Bundle args = new Bundle(); + args.putString("type", "username"); + sf.setArguments(args); + FragmentTransaction transaction = fm.beginTransaction(); + transaction.replace(R.id.fl_user_activity, sf); + transaction.commit(); + } else if (type.equals("password")) { + Log.i(TAG, "Type is password"); + toolbar.setTitle("Change password"); + SettingFragments sf = new SettingFragments(); + Bundle args = new Bundle(); + args.putString("type", "password"); + sf.setArguments(args); + FragmentTransaction transaction = fm.beginTransaction(); + transaction.replace(R.id.fl_user_activity, sf); + transaction.commit(); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem menuItem) { + if (menuItem.getItemId() == android.R.id.home) { + finish(); + Log.i(TAG, "Back arrow pressed on home"); + } + return false; + } + + @Override + protected void onDestroy() { + super.onDestroy(); + try { + unregisterReceiver(globalReceiver); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/CinemaFragment.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/CinemaFragment.java new file mode 100644 index 0000000..f96aa83 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/CinemaFragment.java @@ -0,0 +1,393 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +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.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.Spinner; +import android.widget.Toast; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import org.example.team_pigeon.movie_pigeon.adapters.CinemaAdapter; +import org.example.team_pigeon.movie_pigeon.adapters.NowShowingListAdapter; +import org.example.team_pigeon.movie_pigeon.eventCenter.AddMovieToMovieListEvent; +import org.example.team_pigeon.movie_pigeon.eventCenter.DeleteMovieFromMovieListEvent; +import org.example.team_pigeon.movie_pigeon.eventCenter.UpdateMovieListEvent; +import org.example.team_pigeon.movie_pigeon.models.Cinema; +import org.example.team_pigeon.movie_pigeon.models.Movie; +import org.example.team_pigeon.movie_pigeon.models.Schedule; +import org.example.team_pigeon.movie_pigeon.utils.TimeUtil; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.io.IOException; +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 okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +public class CinemaFragment extends Fragment implements AdapterView.OnItemSelectedListener,AdapterView.OnItemClickListener{ + private static final String TAG = "CinemaFragment"; + private static final String PROVIDER_GV = "gv"; + private static final String PROVIDER_SB = "sb"; + private static final String PROVIDER_CATHAY = "cathay"; + private static final String GET_CINEMAS = "1"; + private static final String GET_MOVIES = "2"; + private static final int POS_GV = 1; + private static final int POS_SB = 2; + private static final int POS_CATHAY = 3; + private Spinner brandSpinner, outletSpinner, dateSpinner; + private ListView movieListView; + private Gson gson = new Gson(); + private ArrayAdapter brandAdapter; + private String[] brands; + private RequestHttpBuilderSingleton httpRequestBuilder = RequestHttpBuilderSingleton.getInstance(); + private ArrayList cinemas = new ArrayList<>(); + private ArrayList gvCinemas = new ArrayList<>(); + private ArrayList sbCinemas = new ArrayList<>(); + private ArrayList cathayCinemas = new ArrayList<>(); + private ArrayList> oneWeekMovieList; + private ArrayList movieList; + private ArrayList moviesOfTheDay = new ArrayList<>(); + private NowShowingTask nowShowingTask; + private List dateListInString; + private List dateList; + private CinemaAdapter cinemaAdapter = null; + private NowShowingListAdapter nowShowingListAdapter = null; + private boolean isCinemasLoaded = false; + private int currentDay; + private TimeUtil timeUtil = new TimeUtil(); + + + public CinemaFragment() { + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_cinema, container, false); + bindViews(view); + dateList = timeUtil.getDateList(); + dateListInString = timeUtil.getDateListToString_MMDDE(dateList); + brands = this.getActivity().getResources().getStringArray(R.array.cinemaBrands); + brandAdapter = new ArrayAdapter<>(this.getActivity(), R.layout.spinner_list_item,brands); + brandSpinner.setAdapter(brandAdapter); + nowShowingTask = new NowShowingTask(); + nowShowingTask.execute(GET_CINEMAS); + if(!EventBus.getDefault().isRegistered(this)){ + EventBus.getDefault().register(this); + } + view.requestFocus(); + return view; + } + + private void bindViews(View view) { + brandSpinner = (Spinner) view.findViewById(R.id.spinner_cinema_brand); + outletSpinner = (Spinner) view.findViewById(R.id.spinner_cinema_outlet); + dateSpinner = (Spinner) view.findViewById(R.id.spinner_date); + movieListView = (ListView) view.findViewById(R.id.list_now_showing); + brandSpinner.setOnItemSelectedListener(this); + outletSpinner.setOnItemSelectedListener(this); + dateSpinner.setOnItemSelectedListener(this); + movieListView.setOnItemClickListener(this); + } + + private ArrayList> getOneWeekMovieList (ArrayList movieList, List dateList) throws ParseException { + ArrayList> oneWeekMovieList = new ArrayList<>(); + for(int i=0;i<7;i++){ + oneWeekMovieList.add(new ArrayList()); + } + for(int i = 0; i showTime = convertToShowTimeArray(date,movie.getSchedule()); + if(!showTime.isEmpty()){ + movie.setShowTimes(showTime); + oneWeekMovieList.get(i).add(movie); + } + } + } + return oneWeekMovieList; + } + + private ArrayList convertToShowTimeArray(Date date, ArrayList scheduleArrayList) { + String timeString; + Calendar calendarOne = Calendar.getInstance(); + Calendar calendarTwo = Calendar.getInstance(); + calendarOne.setTime(date); + ArrayList showTimeList = new ArrayList<>(); + Date time; + SimpleDateFormat stringToDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + SimpleDateFormat dateToString = new SimpleDateFormat("HH:mm"); + for (Schedule schedule : scheduleArrayList) { + timeString = schedule.getTime(); + try { + time = stringToDate.parse(timeString); + } catch (ParseException e) { + Log.d(TAG,"Parsing schedule with a mistake. TimeString:"+timeString); + return null; + } + calendarTwo.setTime(time); + if (calendarOne.get(Calendar.DAY_OF_MONTH) == calendarTwo.get(Calendar.DAY_OF_MONTH)) { + showTimeList.add(dateToString.format(time)); + } + } + return showTimeList; + } + + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + String cinemaId; + if(isCinemasLoaded) { + switch (parent.getId()) { + case R.id.spinner_cinema_brand: + cinemaAdapter = getOutletSpinnerAdapter(position); + if(cinemaAdapter!=null) { + outletSpinner.setAdapter(cinemaAdapter); + outletSpinner.setVisibility(View.VISIBLE); + dateSpinner.setVisibility(View.INVISIBLE); + } + else{ + outletSpinner.setVisibility(View.GONE); + } + dateSpinner.setVisibility(View.GONE); + movieListView.setVisibility(View.GONE); + break; + case R.id.spinner_cinema_outlet: + if(position!=0) { + cinemaId = cinemaAdapter.getItem(position).getId(); + nowShowingTask = new NowShowingTask(); + nowShowingTask.execute(GET_MOVIES, cinemaId); + } + else { + dateSpinner.setVisibility(View.GONE); + } + movieListView.setVisibility(View.GONE); + break; + case R.id.spinner_date: + if(position!=0) { + currentDay = position-1; + if(nowShowingListAdapter==null) { + //init adapter + moviesOfTheDay.addAll(oneWeekMovieList.get(currentDay)); + if(moviesOfTheDay.isEmpty()){ + Toast.makeText(getActivity(), "Opps, there is no movie schedule on this day yet.", Toast.LENGTH_SHORT).show(); + } + nowShowingListAdapter = new NowShowingListAdapter(moviesOfTheDay, this.getActivity()); + movieListView.setAdapter(nowShowingListAdapter); + } + else{ + moviesOfTheDay.clear(); + moviesOfTheDay.addAll(oneWeekMovieList.get(currentDay)); + if(moviesOfTheDay.isEmpty()){ + Toast.makeText(getActivity(), "Opps, there is no movie schedule on this day yet.", Toast.LENGTH_SHORT).show(); + } + nowShowingListAdapter.notifyDataSetChanged(); + } + movieListView.setVisibility(View.VISIBLE); + } + else { + movieListView.setVisibility(View.GONE); + } + break; + } + } + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + Intent displayActivityIntent = new Intent(getActivity(), DisplayActivity.class); + Bundle arguments = new Bundle(); + arguments.putSerializable("movie",nowShowingListAdapter.getItem(position)); + arguments.putString("type", "moviePage"); + arguments.putInt("position",position); + arguments.putString("title", nowShowingListAdapter.getItem(position).getTitle()); + displayActivityIntent.putExtra("bundle", arguments); + getActivity().startActivity(displayActivityIntent); + } + + private CinemaAdapter getOutletSpinnerAdapter(int position) { + switch (position) { + case POS_GV: + return new CinemaAdapter(this.getActivity(), gvCinemas); + case POS_CATHAY: + return new CinemaAdapter(this.getActivity(), cathayCinemas); + case POS_SB: + return new CinemaAdapter(this.getActivity(), sbCinemas); + } + return null; + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + + @Subscribe + public void onAddMovieToMovieListEvent(AddMovieToMovieListEvent event){ + if(nowShowingListAdapter!=null) { + nowShowingListAdapter.addMovieItemToAdapter(event.movie, event.position); + Log.i(TAG, "New movie is added to local list"); + } + } + + @Subscribe + public void onDeleteMovieFromMovieListEvent(DeleteMovieFromMovieListEvent event){ + if(nowShowingListAdapter!=null) { + nowShowingListAdapter.removeMovieItemToAdapter(event.position); + Log.i(TAG, "A movie is removed from local list"); + } + } + + @Subscribe + public void onUpdateMovieListEvent(UpdateMovieListEvent event){ + if(nowShowingListAdapter!=null) { + nowShowingListAdapter.updateMovieItemToAdapter(event.movie, event.position); + Log.i(TAG, "A movie is updated to local list at pos " + String.valueOf(event.position)); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + private class NowShowingTask extends AsyncTask { + private final int SUCCESSFUL_CINEMALIST = 0; + private final int SUCCESSFUL_MOVIELIST = 1; + private final int ERROR = 2; + private final int NO_RESULT = 3; + private final int NO_INTERNET = 4; + private String requestType, cinemaId; + int status; + + @Override + protected Void doInBackground(String... params) { + requestType = params[0]; + if (requestType.equals(GET_CINEMAS)) { + getCinemas(); + } else if (requestType.equals(GET_MOVIES)) { + cinemaId = params[1]; + getMovies(cinemaId); + } + return null; + } + + @Override + protected void onPreExecute() { + return; + } + + @Override + protected void onPostExecute(Void params) { + switch (status) { + case SUCCESSFUL_CINEMALIST: + Log.i(TAG, "Requset is completed"); + isCinemasLoaded = true; + break; + case SUCCESSFUL_MOVIELIST: + Log.i(TAG,"Request is completed"); + try { + oneWeekMovieList = getOneWeekMovieList(movieList,dateList); + } catch (ParseException e) { + e.printStackTrace(); + } + dateSpinner.setAdapter(new ArrayAdapter<>(getActivity(), R.layout.spinner_list_item, dateListInString)); + dateSpinner.setVisibility(View.VISIBLE); + break; + case ERROR: + Toast.makeText(getActivity(), "Connection error, please check your connection", Toast.LENGTH_SHORT).show(); + break; + + case NO_RESULT: + Toast.makeText(getActivity(), "Sorry, there is no results", Toast.LENGTH_SHORT).show(); + break; + + case NO_INTERNET: + Toast.makeText(getActivity(), "Connection error, please make sure that you have Internet connection.", Toast.LENGTH_SHORT).show(); + break; + } + + } + + protected void getCinemas() { + OkHttpClient client = httpRequestBuilder.getClient(); + Request request = httpRequestBuilder.getCinemasRequest(); + try { + Response response = client.newCall(request).execute(); + if (!response.isSuccessful()) { + Log.i(TAG, "connect failed"); + status = ERROR; + throw new IOException("Unexpected code" + response); + } + //Convert json to Arraylist + cinemas = gson.fromJson(response.body().charStream(), new TypeToken>() {}.getType()); + //Sort the cinema list into list of different brands + if (cinemas.size() == 0) { + status = NO_RESULT; + } else { + status = SUCCESSFUL_CINEMALIST; + for (Cinema cinema : cinemas) { + switch (cinema.getProvider()) { + case PROVIDER_CATHAY: + cathayCinemas.add(cinema); + break; + case PROVIDER_GV: + gvCinemas.add(cinema); + break; + case PROVIDER_SB: + sbCinemas.add(cinema); + break; + } + } + } + } catch (IOException e) { + Log.e(TAG, e.getMessage()); + } + } + + protected void getMovies(String cinemaId) { + OkHttpClient client = httpRequestBuilder.getClient(); + Request request = httpRequestBuilder.getShowingListRequest(cinemaId); + try { + Response response = client.newCall(request).execute(); + if (!response.isSuccessful()) { + Log.i(TAG, "connect failed"); + status = ERROR; + throw new IOException("Unexpected code" + response); + } + //Convert json to Arraylist + movieList = gson.fromJson(response.body().charStream(), new TypeToken>() {}.getType()); + if (movieList.size() == 0) { + status = NO_RESULT; + return; + } else { + status = SUCCESSFUL_MOVIELIST; + return; + } + } catch (IOException e) { + Log.e(TAG, e.getMessage()); + return; + } + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/DisplayActivity.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/DisplayActivity.java index ddc0bb7..956b3fe 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/DisplayActivity.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/DisplayActivity.java @@ -7,11 +7,22 @@ import android.os.Bundle; import android.support.v7.widget.Toolbar; import android.view.Menu; +import android.view.MenuItem; import android.widget.FrameLayout; +import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache; +import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache; +import com.nostra13.universalimageloader.core.ImageLoader; +import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; +import com.nostra13.universalimageloader.core.assist.QueueProcessingType; +import com.nostra13.universalimageloader.utils.StorageUtils; + +import java.io.File; + public class DisplayActivity extends AppCompatActivity { private FrameLayout frameLayout; private android.app.FragmentManager fragmentManager = null; + private String type; @Override protected void onCreate(Bundle savedInstanceState) { @@ -21,15 +32,42 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_display); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_display_page); Bundle argument = getIntent().getBundleExtra("bundle"); + type = argument.getString("type"); toolbar.setTitle(argument.getString("title")); setSupportActionBar(toolbar); fragmentManager = getFragmentManager(); frameLayout = (FrameLayout) findViewById(R.id.fl_content); - MovieListFragment movieListFragment = new MovieListFragment(); - movieListFragment.setArguments(argument); - android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - fragmentTransaction.replace(R.id.fl_content,movieListFragment); - fragmentTransaction.commit(); + if(!ImageLoader.getInstance().isInited()){ + initImageLoaderConfig(); + } + // add back arrow to toolbar + if (getSupportActionBar() != null){ + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + } + //Handle single movie info passed in from showing page + if(type.equals("moviePage")){ + MoviePageFragment moviePageFragment = new MoviePageFragment(); + moviePageFragment.setArguments(argument); + android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.fl_content,moviePageFragment); + fragmentTransaction.commit(); + } + else if(type.equals("search")){ + SearchPageFragment searchPageFragment = new SearchPageFragment(); + searchPageFragment.setArguments(argument); + android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.fl_content, searchPageFragment); + fragmentTransaction.commit(); + } + //Handle movie list requests + else { + MovieListFragment movieListFragment = new MovieListFragment(); + movieListFragment.setArguments(argument); + android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.fl_content, movieListFragment); + fragmentTransaction.commit(); + } } @@ -39,4 +77,33 @@ public boolean onCreateOptionsMenu(Menu menu) { return true; } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + if(fragmentManager.getBackStackEntryCount()==0){ + super.onBackPressed(); + } + else{ + fragmentManager.popBackStack(); + } + } + return false; + } + + private void initImageLoaderConfig(){ + File cacheDir = StorageUtils.getOwnCacheDirectory(getApplicationContext(), "MoviePigeon/cache/poster"); + ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this) + .threadPoolSize(5) + .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) + .memoryCacheSize(5 * 1024 * 1024) + .tasksProcessingOrder(QueueProcessingType.LIFO) + .diskCacheSize(50 * 1024 * 1024) + .diskCacheFileCount(200) + .diskCache(new UnlimitedDiskCache(cacheDir)) + .writeDebugLogs() + .build(); + ImageLoader.getInstance().init(config); + } + } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/GlobalReceiver.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/GlobalReceiver.java index db2d9f2..6a910a8 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/GlobalReceiver.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/GlobalReceiver.java @@ -5,8 +5,9 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.os.Handler; +import android.support.v7.widget.Toolbar; import android.util.Log; -import android.widget.Switch; /** * Created by Guo Mingxuan on 11/2/2017. @@ -15,6 +16,19 @@ class GlobalReceiver extends BroadcastReceiver { String emailSignin, passwordSignin; String TAG = "GlobalReceiver"; + Handler uiHandler; + private final static int VCodeSuccess = 0; + private final static int ResetSuccess = 1; + private final static int changeUsername = 0; + private static UserInfoSingleton userInfoBulk = UserInfoSingleton.getInstance(); + + GlobalReceiver() { + uiHandler = null; + } + + GlobalReceiver(Handler handler) { + uiHandler = handler; + } @Override public void onReceive(Context context, Intent intent) { @@ -23,6 +37,8 @@ public void onReceive(Context context, Intent intent) { switch (action) { case "startHomePageActivity": + // refresh user info singleton + userInfoBulk.reset(); // get token from the broadcast Intent homePageIntent = new Intent(context, HomePageActivity.class); // pass token to the new activity @@ -49,10 +65,39 @@ public void onReceive(Context context, Intent intent) { sBuilder.execute(signInDetails); break; - case "UserUpdate": + case "killRegistration": + Log.i(TAG, "Kill Registration received"); + ((Activity) context).finish(); + break; + + case "userUpdate": Log.i(TAG, "User Update received"); ((Activity) context).finish(); break; + + case "vCodeSuccessful": + Log.i(TAG, "Successful VCode received"); + uiHandler.sendEmptyMessage(VCodeSuccess); + break; + + case "ResetSuccessful": + Log.i(TAG, "Successful VCode received"); + uiHandler.sendEmptyMessage(ResetSuccess); + break; + + case "dataPullingSuccess": + Log.i(TAG, "Successful data pulling received"); + Intent startRegistration = new Intent(context, RegistrationActivity.class); + bundle = intent.getExtras(); + startRegistration.putExtras(bundle); + context.startActivity(startRegistration); + ((Activity)context).finish(); + break; + + case "changeUsername": + Log.i(TAG, "Received msg to update username"); + userInfoBulk.reset(); + break; } } } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/HomePageActivity.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/HomePageActivity.java index 0ab69f1..1afc9d3 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/HomePageActivity.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/HomePageActivity.java @@ -2,9 +2,6 @@ import android.content.Context; import android.content.pm.ActivityInfo; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; @@ -14,17 +11,21 @@ import android.widget.TextView; import android.widget.Toast; +import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache; import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; +import com.nostra13.universalimageloader.core.assist.QueueProcessingType; +import com.nostra13.universalimageloader.utils.StorageUtils; import org.example.team_pigeon.movie_pigeon.adapters.HomeViewPagerAdapter; +import java.io.File; + public class HomePageActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener, ViewPager.OnPageChangeListener{ private TextView txt_title; private ViewPager viewPager; - private RadioButton rb_recommendation; - private RadioButton rb_me; + private RadioButton rb_recommendation,rb_me,rb_showing; private RadioGroup rg_tab_bar; private FrameLayout fl_content; private Context mContext; @@ -34,7 +35,8 @@ public class HomePageActivity extends AppCompatActivity implements RadioGroup.On private long exitTime = 0; public static final int PAGE_RECOMMENDATION = 0; - public static final int PAGE_ME = 1; + public static final int PAGE_ME = 2; + public static final int PAGE_SHOWING = 1; @Override protected void onCreate(Bundle savedInstanceState) { @@ -68,6 +70,7 @@ private void bindViews(){ rg_tab_bar = (RadioGroup)findViewById(R.id.rg_tab_bar); rb_recommendation = (RadioButton)findViewById(R.id.rb_home); rb_me = (RadioButton)findViewById(R.id.rb_me); + rb_showing = (RadioButton) findViewById(R.id.rb_now_showing); rg_tab_bar.setOnCheckedChangeListener(this); viewPager = (ViewPager)findViewById(R.id.view_pager); viewPager.setAdapter(homeViewPagerAdapter); @@ -76,10 +79,15 @@ private void bindViews(){ } private void initImageLoaderConfig(){ + File cacheDir = StorageUtils.getOwnCacheDirectory(getApplicationContext(), "MoviePigeon/cache/poster"); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this) .threadPoolSize(5) .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) - .memoryCacheSize(2 * 1024 * 1024) + .memoryCacheSize(5 * 1024 * 1024) + .tasksProcessingOrder(QueueProcessingType.LIFO) + .diskCacheSize(50 * 1024 * 1024) + .diskCacheFileCount(200) + .diskCache(new UnlimitedDiskCache(cacheDir)) .writeDebugLogs() .build(); ImageLoader.getInstance().init(config); @@ -97,7 +105,7 @@ public void onPageSelected(int position) { @Override public void onPageScrollStateChanged(int state) { - if(state == 2) { + if(state == ViewPager.SCROLL_STATE_SETTLING) { switch (viewPager.getCurrentItem()) { case PAGE_RECOMMENDATION: rb_recommendation.setChecked(true); @@ -105,6 +113,9 @@ public void onPageScrollStateChanged(int state) { case PAGE_ME: rb_me.setChecked(true); break; + case PAGE_SHOWING: + rb_showing.setChecked(true); + break; } } } @@ -118,6 +129,9 @@ public void onCheckedChanged(RadioGroup group, int checkedId) { case R.id.rb_me: viewPager.setCurrentItem(PAGE_ME); break; + case R.id.rb_now_showing: + viewPager.setCurrentItem(PAGE_SHOWING); + break; } } } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/LoadingDialog.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/LoadingDialog.java new file mode 100644 index 0000000..d2c0019 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/LoadingDialog.java @@ -0,0 +1,37 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.app.ProgressDialog; +import android.content.Context; +import android.os.Bundle; +import android.view.WindowManager; + +/** + * Created by SHENGX on 2017/3/15. + */ + +public class LoadingDialog extends ProgressDialog { + private Context mContext; + public LoadingDialog(Context context){ + super(context); + mContext = context; + } + public LoadingDialog(Context context, int theme){ + super(context,theme); + mContext = context; + } + @Override + protected void onCreate(Bundle save){ + super.onCreate(save); + init(mContext); + } + private void init (Context context){ + setCancelable(false); + setCanceledOnTouchOutside(false); + setContentView(R.layout.loading_dialog); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.WRAP_CONTENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + getWindow().setAttributes(params); + } + +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MeFragment.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MeFragment.java index dcaabd7..2bf7b16 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MeFragment.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MeFragment.java @@ -1,17 +1,20 @@ package org.example.team_pigeon.movie_pigeon; - import android.content.Intent; +import android.content.IntentFilter; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; +import android.os.Handler; +import android.os.Message; 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.Button; +import android.widget.TableRow; import android.widget.Toast; +import android.support.v7.widget.Toolbar; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; @@ -28,13 +31,18 @@ public class MeFragment extends Fragment { private final String TAG = "MePage"; - private Button myRatingsButton, myBookmarksButton, settingButton, logoutButton; + private TableRow myRatingsRow, myBookmarksRow, settingsRow, logoutRow; private RequestHttpBuilderSingleton requestHttpBuilder = RequestHttpBuilderSingleton.getInstance(); private Gson gson = new Gson(); private MyTask myTask; private ArrayList movieList; private File credential; private View view; + private Toolbar tbMe; + private UserInfoSingleton userInfoBulk = UserInfoSingleton.getInstance(); + private LoadingDialog loadingDialog; + private GlobalReceiver globalReceiver; + private final int changeUsername = 0; public MeFragment() { } @@ -42,16 +50,18 @@ public MeFragment() { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + userInfoBulk.reset(); + loadingDialog = new LoadingDialog(this.getActivity(),R.style.LoadingDialog); view = inflater.inflate(R.layout.fragment_me, container, false); bindViews(view); - myRatingsButton.setOnClickListener(new View.OnClickListener() { + myRatingsRow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { myTask = new MyTask(); myTask.execute("rating"); } }); - myBookmarksButton.setOnClickListener(new View.OnClickListener() { + myBookmarksRow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { myTask = new MyTask(); @@ -59,7 +69,7 @@ public void onClick(View v) { } }); - logoutButton.setOnClickListener(new View.OnClickListener() { + logoutRow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.i(TAG, "Logout button pressed"); @@ -67,7 +77,7 @@ public void onClick(View v) { } }); - settingButton.setOnClickListener(new View.OnClickListener() { + settingsRow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -78,9 +88,22 @@ public void onClick(View v) { } }); + tbMe = (Toolbar) view.findViewById(R.id.me_toolbar); + tbMe.setTitle("Welcome " + userInfoBulk.getUsername() + "!"); + tbMe.setSubtitle(userInfoBulk.getEmail()); return view; } + @Override + public void onResume(){ + super.onResume(); + Log.i(TAG, "Me fragment resumed"); + userInfoBulk.reset(); + tbMe.setTitle("Welcome " + userInfoBulk.getUsername() + "!"); + tbMe.setSubtitle(userInfoBulk.getEmail()); + Log.i(TAG, "Username now is " + userInfoBulk.getUsername()); + } + private void loggingOut() { Intent loadStartActivity = new Intent(getActivity(), StartActivity.class); credential = new File(Environment.getExternalStorageDirectory() + "/MoviePigeon/Signin/credential"); @@ -96,15 +119,15 @@ private void loggingOut() { getActivity().finish(); } else { Log.e(TAG, "Failed to delete credential"); - Toast.makeText(getContext(), "Failed to logout. Please check storage permissions.", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Failed to logout. Please check storage permissions.", Toast.LENGTH_SHORT).show(); } } private void bindViews(View view){ - myBookmarksButton = (Button)view.findViewById(R.id.button_my_bookmarks); - myRatingsButton = (Button)view.findViewById(R.id.button_my_rating); - logoutButton = (Button)view.findViewById(R.id.button_logout); - settingButton = (Button)view.findViewById(R.id.button_setting); + myBookmarksRow = (TableRow) view.findViewById(R.id.me_bookmark); + myRatingsRow = (TableRow)view.findViewById(R.id.me_rating); + logoutRow = (TableRow)view.findViewById(R.id.me_logout); + settingsRow = (TableRow)view.findViewById(R.id.me_settings); } //Async thread to handle myBookmarks and myRatings request @@ -120,11 +143,11 @@ private class MyTask extends AsyncTask { protected Integer doInBackground(String... params) { try { OkHttpClient client = requestHttpBuilder.getClient(); - if(params[0].equals("rating")){ + if (params[0].equals("rating")) { request = requestHttpBuilder.getRatingListRequest(); successfulStatus = SUCCESSFUL_RATING_LIST; } - if(params[0].equals("bookmark")){ + if (params[0].equals("bookmark")) { request = requestHttpBuilder.getBookmarkListRequest(); successfulStatus = SUCCESSFUL_BOOKMARK_LIST; } @@ -139,7 +162,7 @@ protected Integer doInBackground(String... params) { if (movieList.isEmpty()) { return NO_RESULT; - }else{ + } else { return successfulStatus; } } catch (IOException e) { @@ -151,17 +174,19 @@ protected Integer doInBackground(String... params) { @Override protected void onPreExecute() { Log.i(TAG, "New search request is initialised"); + loadingDialog.show(); return; } @Override protected void onPostExecute(Integer status) { + loadingDialog.dismiss(); Intent displayActivityIntent = new Intent(getActivity(), DisplayActivity.class); Bundle arguments = new Bundle(); switch (status) { case SUCCESSFUL_BOOKMARK_LIST: Log.i(TAG, "Request of bookmark list is completed"); - arguments.putSerializable("movieList",movieList); + arguments.putSerializable("movieList", movieList); arguments.putString("type", "bookmark"); arguments.putString("title", "My Bookmarks"); displayActivityIntent.putExtra("bundle", arguments); @@ -170,7 +195,7 @@ protected void onPostExecute(Integer status) { case SUCCESSFUL_RATING_LIST: Log.i(TAG, "Request of bookmark list is completed"); - arguments.putSerializable("movieList",movieList); + arguments.putSerializable("movieList", movieList); arguments.putString("type", "rating"); arguments.putString("title", "My Rating History"); displayActivityIntent.putExtra("bundle", arguments); @@ -178,15 +203,14 @@ protected void onPostExecute(Integer status) { break; case ERROR: - Toast.makeText(getContext(), "Connection error, please check your connection", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Connection error, please check your connection", Toast.LENGTH_SHORT).show(); break; case NO_RESULT: - Toast.makeText(getContext(), "Sorry, you request has no results", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Sorry, you request has no results", Toast.LENGTH_SHORT).show(); break; } } } - } \ No newline at end of file diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MovieListFragment.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MovieListFragment.java index 3b17d99..0997ce2 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MovieListFragment.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MovieListFragment.java @@ -15,6 +15,8 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import com.nostra13.universalimageloader.core.ImageLoader; +import com.nostra13.universalimageloader.core.listener.PauseOnScrollListener; import org.example.team_pigeon.movie_pigeon.adapters.MovieListAdapter; import org.example.team_pigeon.movie_pigeon.eventCenter.AddMovieToMovieListEvent; @@ -41,16 +43,8 @@ public class MovieListFragment extends Fragment implements AdapterView.OnItemCli private android.app.FragmentManager fragmentManager; private ArrayList movies; private ListView list_movies; - private SearchMoreTask searchMoreTask; private MovieListAdapter movieListAdapter; - private RequestHttpBuilderSingleton searchRequestHttpBuilder; - private Gson gson = new Gson(); public View footerView; - public boolean isLoading = false; - public boolean noMoreResult = false; - private ArrayList searchMovieList; - private MovieWithCount movieListWithCount; - private int resultCount; private Toolbar toolbar; private Bundle bundle; private String type; @@ -74,23 +68,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa if(!EventBus.getDefault().isRegistered(this)){ EventBus.getDefault().register(this); } - if(type.equals("search")){ - toolbar.setSubtitle(bundle.getString("count")); - list_movies.setOnScrollListener(new AbsListView.OnScrollListener() { - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - } - - @Override - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - if(view.getLastVisiblePosition() == totalItemCount-1 && list_movies.getCount() >= 20 && !isLoading && !noMoreResult) { - isLoading = true; - searchMoreTask = new SearchMoreTask(); - searchMoreTask.execute(); - } - } - }); - } + list_movies.setOnScrollListener(new PauseOnScrollListener(ImageLoader.getInstance(),true,true)); return view; } @@ -116,112 +94,29 @@ public void onDestroy() { EventBus.getDefault().unregister(this); } - @Subscribe - public void onEvent(AddMovieToMovieListEvent event){ - movieListAdapter.addMovieItemToAdapter(event.movie, event.position); - Log.i(TAG, "New movie is added to local list"); - } - @Subscribe public void onEvent(DeleteMovieFromMovieListEvent event){ - movieListAdapter.removeMovieItemToAdapter(event.position); - Log.i(TAG, "A movie is removed from local list"); + if(movieListAdapter!=null) { + movieListAdapter.removeMovieItemToAdapter(event.position); + Log.i(TAG, "A movie is removed from local list"); + } } @Subscribe public void onEvent(UpdateMovieListEvent event){ - movieListAdapter.updateMovieItemToAdapter(event.movie, event.position); - Log.i(TAG, "A movie is updated to local list"); - } - - //Async thread to handle search request - private class SearchMoreTask extends AsyncTask { - private final int SUCCESSFUL = 0; - private final int ERROR = 1; - private final int NO_RESULT = 2; - private final int NO_INTERNET = 3; - private final int NO_MORE_RESULT = 4; - int status; - - @Override - protected Void doInBackground(Void... params) { - try { - searchRequestHttpBuilder = RequestHttpBuilderSingleton.getInstance(); - OkHttpClient client = searchRequestHttpBuilder.getClient(); - Request request = searchRequestHttpBuilder.getNextSearchRequest(); - Response response = client.newCall(request).execute(); - if (!response.isSuccessful()) { - Log.i(TAG, "connect failed"); - status = ERROR; - throw new IOException("Unexpected code" + response); - } - //Convert json to Arraylist - movieListWithCount = gson.fromJson(response.body().charStream(), new TypeToken() {}.getType()); - resultCount = movieListWithCount.getCount(); - searchMovieList = movieListWithCount.getMovies(); - - if (resultCount == 0) { - status = NO_RESULT; - } - else if(searchMovieList.size() < searchRequestHttpBuilder.getLimit()){ - status = NO_MORE_RESULT; - } - else { - status = SUCCESSFUL; - } - return null; - } catch (IOException e) { - status = NO_INTERNET; - Log.e(TAG, e.getMessage()); - } - return null; - + if(movieListAdapter!=null) { + movieListAdapter.updateMovieItemToAdapter(event.movie, event.position); + Log.i(TAG, "A movie is updated to local list"); } + } - @Override - protected void onPreExecute() { - Log.i(TAG, "New search request is initialised"); - list_movies.addFooterView(footerView); - return; + @Subscribe + public void onEvent(AddMovieToMovieListEvent event){ + if(movieListAdapter!=null) { + movieListAdapter.addMovieItemToAdapter(event.movie, event.position); + Log.i(TAG, "A movie is added to local list"); } + } - @Override - protected void onPostExecute(Void params) { - switch (status) { - case SUCCESSFUL: - Log.i(TAG, "Search is completed"); - list_movies.removeFooterView(footerView); - movieListAdapter.addListItemToAdapter(searchMovieList); - isLoading = false; - break; - - case ERROR: - Toast.makeText(getContext(), "Connection error, please check your connection", Toast.LENGTH_SHORT).show(); - list_movies.removeFooterView(footerView); - isLoading = false; - break; - - case NO_RESULT: - Toast.makeText(getContext(), "Sorry, there is no more result", Toast.LENGTH_SHORT).show(); - list_movies.removeFooterView(footerView); - noMoreResult = true; - isLoading = false; - break; - - case NO_MORE_RESULT: - list_movies.removeFooterView(footerView); - noMoreResult = true; - isLoading = false; - movieListAdapter.addListItemToAdapter(searchMovieList); - break; - - case NO_INTERNET: - Toast.makeText(getContext(), "Connection error, please make sure that you have Internet connection.", Toast.LENGTH_SHORT).show(); - list_movies.removeFooterView(footerView); - isLoading = false; - break; - } - } - } } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MoviePageFragment.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MoviePageFragment.java index b095d1e..c70746a 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MoviePageFragment.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MoviePageFragment.java @@ -1,8 +1,10 @@ package org.example.team_pigeon.movie_pigeon; import android.app.Fragment; +import android.app.FragmentTransaction; import android.os.AsyncTask; import android.os.Bundle; +import android.support.v4.app.FragmentManager; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -10,6 +12,7 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RatingBar; @@ -18,13 +21,18 @@ import android.widget.Toast; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; +import org.example.team_pigeon.movie_pigeon.configs.ImageConfig; import org.example.team_pigeon.movie_pigeon.eventCenter.AddMovieToMovieListEvent; import org.example.team_pigeon.movie_pigeon.eventCenter.DeleteMovieFromMovieListEvent; import org.example.team_pigeon.movie_pigeon.eventCenter.UpdateMovieListEvent; import org.example.team_pigeon.movie_pigeon.models.Movie; import org.example.team_pigeon.movie_pigeon.models.PublicRating; +import org.example.team_pigeon.movie_pigeon.models.Schedule; import org.example.team_pigeon.movie_pigeon.models.UserBookmark; import org.example.team_pigeon.movie_pigeon.models.UserRating; import org.greenrobot.eventbus.EventBus; @@ -48,6 +56,7 @@ public class MoviePageFragment extends Fragment { private static final String UNBOOKMARK = "unbookmark"; private TextView txt_country, txt_length, txt_director, txt_plot, txt_genres, txt_year, txt_actors, score_imdb, score_douban, score_trakt, text_score; private TableRow row_country, row_length, row_director, row_genres, row_year, row_actors; + private Button btn_showtimes; private LinearLayout linearLayout_ratings; private ImageView image_poster, image_imdb, image_douban, image_trakt; private Movie movie; @@ -59,7 +68,7 @@ public class MoviePageFragment extends Fragment { private String sourceType; private UserBookmark userBookmark; private UserRating userRating; - private EventBus eventBus = EventBus.getDefault(); + private DisplayImageOptions options = new ImageConfig().getDisplayImageOption(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -92,10 +101,12 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.action_bookmark: if(isBookmarked){ + item.setEnabled(false); MyTask bookmarkTask = new MyTask(); bookmarkTask.execute(UNBOOKMARK, movie.getMovieID()); } else{ + item.setEnabled(false); userBookmark = new UserBookmark(movie.getMovieID()); MyTask bookmarkTask = new MyTask(); bookmarkTask.execute(BOOKMARK, movie.getMovieID()); @@ -130,6 +141,7 @@ private void loadViews(View view) { row_actors = (TableRow) view.findViewById(R.id.row_actors); linearLayout_ratings = (LinearLayout) view.findViewById(R.id.linear_ratings); ratingBar = (RatingBar) view.findViewById(R.id.ratingBar); + btn_showtimes = (Button) view.findViewById(R.id.btn_view_schedule); } private void setContent(Bundle argument) { @@ -139,11 +151,7 @@ private void setContent(Bundle argument) { if (movie != null) { //Set movie poster - if (movie.getPosterURL() != null) { - ImageLoader.getInstance().displayImage(movie.getPosterURL(), image_poster); - } else { - image_poster.setImageResource(R.mipmap.image_no_poster_found); - } + ImageLoader.getInstance().displayImage(movie.getPosterURL(), image_poster,options); //Set plot if (movie.getPlot() != null) { @@ -170,6 +178,7 @@ private void setContent(Bundle argument) { //Set Rating Bar if(!movie.getUserRating().isEmpty()){ + ratingBar.setNumStars(5); ratingBar.setRating(Float.parseFloat(movie.getUserRating().get(0).getScore())/2); } @@ -178,11 +187,33 @@ private void setContent(Bundle argument) { public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { if(fromUser){ userRating = new UserRating(movie.getMovieID(), String.valueOf(rating * 2)); + ratingBar.setEnabled(false); MyTask ratingTask = new MyTask(); ratingTask.execute(POST_RATING, movie.getMovieID(), String.valueOf(rating * 2)); } } }); + + //Set Schedule Button + if(!movie.isShowing()){ + btn_showtimes.setVisibility(View.GONE); + } + else { + btn_showtimes.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + android.app.FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + Bundle bundle = new Bundle(); + bundle.putSerializable("movie", movie); + MovieScheduleFragment movieScheduleFragment = new MovieScheduleFragment(); + movieScheduleFragment.setArguments(bundle); + fragmentTransaction.replace(R.id.fl_content, movieScheduleFragment); + fragmentTransaction.addToBackStack(movieScheduleFragment.getClass().getName()); + fragmentTransaction.commit(); + } + }); + } } } @@ -211,6 +242,7 @@ private void setRatingsOtherwiseSetGone(String rating, TextView score, ImageView } private void setBookmarkIcon(boolean isBookmarked){ + bookmarkItem.setEnabled(true); if(isBookmarked){ bookmarkItem.setIcon(R.drawable.ic_bookmark_full); } @@ -219,7 +251,7 @@ private void setBookmarkIcon(boolean isBookmarked){ } } - //Async thread to handle search request + //Async thread to handle http request private class MyTask extends AsyncTask { private int successfulStatus = -1; private final int SUCCESSFUL_UNBOOKMARK = 2; @@ -262,7 +294,7 @@ protected Integer doInBackground(String... params) { OkHttpClient client = requestHttpBuilder.getClient(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) { - Log.i(TAG, "rating failed" + response); + Log.i(TAG, "request" + requestType + "failed" + response); throw new IOException("Unexpected code" + response); } else { status = successfulStatus; @@ -285,42 +317,42 @@ protected void onPostExecute(Integer params) { switch (status) { case SUCCESSFUL_RATE: Log.i(TAG, "Rating is completed"); - Toast.makeText(getContext(), "Update rating successfully!", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Update rating successfully!", Toast.LENGTH_SHORT).show(); + ratingBar.setEnabled(true); movie.getUserRating().clear(); movie.getUserRating().add(userRating); - eventBus.post(new UpdateMovieListEvent(position, movie)); + EventBus.getDefault().post(new UpdateMovieListEvent(position, movie)); break; case SUCCESSFUL_BOOKMARK: Log.i(TAG, "Bookmark is completed"); - Toast.makeText(getContext(), "Bookmark successfully!", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Bookmark successfully!", Toast.LENGTH_SHORT).show(); setBookmarkIcon(true); isBookmarked = true; movie.getUserBookmark().add(userBookmark); if(sourceType.equals("bookmark")){ - eventBus.post(new AddMovieToMovieListEvent(position, movie)); + EventBus.getDefault().post(new AddMovieToMovieListEvent(position, movie)); } else{ - eventBus.post(new UpdateMovieListEvent(position, movie)); + EventBus.getDefault().post(new UpdateMovieListEvent(position, movie)); } break; case SUCCESSFUL_UNBOOKMARK: Log.i(TAG, "Unbookmark is completed"); - Toast.makeText(getContext(), "Unbookmark successfully!", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Unbookmark successfully!", Toast.LENGTH_SHORT).show(); setBookmarkIcon(false); isBookmarked = false; movie.getUserBookmark().clear(); if(sourceType.equals("bookmark")){ - eventBus.post(new DeleteMovieFromMovieListEvent(position)); + EventBus.getDefault().post(new DeleteMovieFromMovieListEvent(position)); } else{ - eventBus.post(new UpdateMovieListEvent(position, movie)); + EventBus.getDefault().post(new UpdateMovieListEvent(position, movie)); } break; - case NO_INTERNET: - Toast.makeText(getContext(), "Connection error, please make sure that you have Internet connection.", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Connection error, please make sure that you have Internet connection.", Toast.LENGTH_SHORT).show(); break; } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MovieScheduleFragment.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MovieScheduleFragment.java new file mode 100644 index 0000000..18a8c4c --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/MovieScheduleFragment.java @@ -0,0 +1,271 @@ +package org.example.team_pigeon.movie_pigeon; + + +import android.app.Fragment; +import android.os.AsyncTask; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.nostra13.universalimageloader.core.DisplayImageOptions; +import com.nostra13.universalimageloader.core.ImageLoader; + +import org.example.team_pigeon.movie_pigeon.adapters.ScheduleListAdapter; +import org.example.team_pigeon.movie_pigeon.configs.ImageConfig; +import org.example.team_pigeon.movie_pigeon.models.Movie; +import org.example.team_pigeon.movie_pigeon.models.Schedule; +import org.example.team_pigeon.movie_pigeon.utils.TimeUtil; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + + +public class MovieScheduleFragment extends Fragment implements AdapterView.OnItemSelectedListener { + private static String TAG = "MovieScheduleFragment"; + private ListView scheduleListView; + private ImageView poster; + private TextView lengthText, genreText; + private Spinner dateSpinner; + private TimeUtil timeUtil = new TimeUtil(); + private List dateList; + private List dateListString; + private ArrayList rawSchedules; + private ArrayList> schedulesOfAWeek = new ArrayList<>(); + private ArrayList adapterList = new ArrayList<>(); + private Movie movie; + private ImageLoader imageLoader = ImageLoader.getInstance(); + private DisplayImageOptions options = new ImageConfig().getDisplayImageOption(); + private Boolean isDataReady = false; + private LoadingDialog loadingDialog; + + @Override + public void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + Bundle bundle = getArguments(); + movie = (Movie)bundle.getSerializable("movie"); + dateList = timeUtil.getDateList(); + dateListString = timeUtil.getDateListToString_YYYYMMDD(dateList); + for (int i = 0; i < 7; i++) { + schedulesOfAWeek.add(new ArrayList()); + adapterList.add(new ScheduleListAdapter(schedulesOfAWeek.get(i), getActivity())); + } + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + loadingDialog = new LoadingDialog(this.getActivity(),R.style.LoadingDialog); + View view = inflater.inflate(R.layout.fragment_movie_schedule, container, false); + bindView(view); + + dateSpinner.setAdapter(new ArrayAdapter<>(getActivity(), R.layout.spinner_list_item, dateListString)); + dateSpinner.setOnItemSelectedListener(this); + //Set movie info views + setMovieInfoViews(); + + //Process raw schedules + GetScheduleTask task = new GetScheduleTask(); + task.execute(movie.getMovieID()); + + return view; + } + + //This method scan through the raw schedule data one by one, and add list item views where is needed. + //FYI, the raw date is sorted by date->cinema->movieType->time + private void prepareScheduleObjects() { + Boolean isValidDate = false; + int currentId = -1; + int currentDay = 0; + String currentDate = ""; + String currentType = ""; + Schedule currentSchedule = null; + ArrayList currentShowtimeArray = null; + + //Firstly, if the starting date of schedule is later than today, find it out. + int startingDay = -1; + for(int i=0;i=0){ + isValidDate = true; + currentSchedule = rawSchedules.get(0); + currentId = currentSchedule.getCinemaId(); + currentDate = currentSchedule.getDate(); + currentType = currentSchedule.getType(); + currentDay = startingDay; + currentSchedule.setShowTimeArray(new ArrayList()); + currentShowtimeArray = currentSchedule.getShowTimeArray(); + ScheduleListAdapter currentAdapter = adapterList.get(currentDay); + currentAdapter.addCinemaToAdapter(currentSchedule); + } + //Secondly, look at each schedule data, the logic is: + //1. find the starting position of with today's date, if the starting position is earlier than today. + //2. Compare each schedule with current date, cinemaId and type accordingly, if all are the same, then add its showtime into current schedule's showtime array. + //3. If any data is different, save the previous showtime array, and load this new schedule as current schedule. + //4. If the difference is date or cinemaId, meaning we need a new cinema title, add it to the adapter. + //5. If the date is different, increment currentDay, new data will be saved in a new adapter. Each day has a separated adapter to make the listView able to update. + for (int i = 0; i < rawSchedules.size() && currentDay < 7; ) { + if (isValidDate) { + if (rawSchedules.get(i).getDate().equals(currentDate)) { + if (rawSchedules.get(i).getCinemaId() == currentId) { + if (rawSchedules.get(i).getType().equals(currentType)) { + currentShowtimeArray.add(rawSchedules.get(i).getShowtime().substring(0, 5)); + i++; + //peek the next schedule, avoid index out of boundary + if (i == rawSchedules.size() || !rawSchedules.get(i).getType().equals(currentType) || rawSchedules.get(i).getCinemaId()!=currentId || !rawSchedules.get(i).getDate().equals(currentDate)) { + adapterList.get(currentDay).addScheduleItemToAdapter(currentSchedule); + } + } else { + currentSchedule = rawSchedules.get(i); + currentType = rawSchedules.get(i).getType(); + currentSchedule.setShowTimeArray(new ArrayList()); + currentShowtimeArray = currentSchedule.getShowTimeArray(); + } + } else { + currentSchedule = rawSchedules.get(i); + adapterList.get(currentDay).addCinemaToAdapter(currentSchedule); + currentId = currentSchedule.getCinemaId(); + currentType = currentSchedule.getType(); + currentSchedule.setShowTimeArray(new ArrayList()); + currentShowtimeArray = currentSchedule.getShowTimeArray(); + } + } else { + currentSchedule = rawSchedules.get(i); + currentDate = currentSchedule.getDate(); + currentDay++; + adapterList.get(currentDay).addCinemaToAdapter(currentSchedule); + currentId = currentSchedule.getCinemaId(); + currentType = currentSchedule.getType(); + currentSchedule.setShowTimeArray(new ArrayList()); + currentShowtimeArray = currentSchedule.getShowTimeArray(); + } + + } + //Find out the starting position, with today's date, ignore the outdated data + else { + if (rawSchedules.get(i).getDate().equals(dateListString.get(0))) { + currentSchedule = rawSchedules.get(i); + currentId = currentSchedule.getCinemaId(); + currentDate = currentSchedule.getDate(); + currentType = currentSchedule.getType(); + currentSchedule.setShowTimeArray(new ArrayList()); + currentShowtimeArray = currentSchedule.getShowTimeArray(); + ScheduleListAdapter currentAdapter = adapterList.get(currentDay); + currentAdapter.addCinemaToAdapter(currentSchedule); + isValidDate = true; + } else { + i++; + } + } + } + isDataReady = true; + } + + private void setMovieInfoViews() { + imageLoader.displayImage(movie.getPosterURL(), poster, options); + if (movie.getLength() != null) { + lengthText.setText(movie.getLength() + " Min"); + } + if (movie.getGenres() != null) { + genreText.setText(movie.getGenres()); + } + } + + private void bindView(View view) { + scheduleListView = (ListView) view.findViewById(R.id.list_schedules); + poster = (ImageView) view.findViewById(R.id.image_schedule_poster); + lengthText = (TextView) view.findViewById(R.id.text_schedule_length); + genreText = (TextView) view.findViewById(R.id.text_schedule_genre); + dateSpinner = (Spinner) view.findViewById(R.id.spinner_date_schedule); + } + + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + if (parent.getId() == R.id.spinner_date_schedule && isDataReady) { + scheduleListView.setAdapter(adapterList.get(position)); + adapterList.get(position).notifyDataSetChanged(); + if(adapterList.get(position).getCount()==0){ + Toast.makeText(getActivity(), "Sorry, there is no schedule available on this day.", Toast.LENGTH_SHORT).show(); + } + } + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + + //Async thread to handle search request + private class GetScheduleTask extends AsyncTask { + private final int SUCCESSFUL_SCHEDULE = 0; + private final int NO_INTERNET = 1; + private int status; + RequestHttpBuilderSingleton requestHttpBuilder = RequestHttpBuilderSingleton.getInstance(); + + @Override + protected Integer doInBackground(String... params) { + String movieId = params[0]; + + Request request = requestHttpBuilder.getScheduleOfMovie(movieId); + try { + OkHttpClient client = requestHttpBuilder.getClient(); + Response response = client.newCall(request).execute(); + if (!response.isSuccessful()) { + throw new IOException("Unexpected code" + response); + } else { + status = SUCCESSFUL_SCHEDULE; + Gson gson = new Gson(); + rawSchedules = gson.fromJson(response.body().charStream(), new TypeToken>() {}.getType()); + } + } catch (IOException e) { + Log.e(TAG, e.getMessage()); + return NO_INTERNET; + } + return null; + } + + @Override + protected void onPreExecute() { + Log.i(TAG, "Get schedule request is initialised"); + loadingDialog.show(); + return; + } + + @Override + protected void onPostExecute(Integer params) { + switch (status) { + case SUCCESSFUL_SCHEDULE: + Log.i(TAG, "Get Schedule succefully"); + prepareScheduleObjects(); + scheduleListView.setAdapter(adapterList.get(0)); + loadingDialog.dismiss(); + break; + + case NO_INTERNET: + Toast.makeText(getActivity(), "Connection error, please make sure that you have Internet connection.", Toast.LENGTH_SHORT).show(); + break; + } + + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RecommendationFragment.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RecommendationFragment.java index a8e11bb..971a116 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RecommendationFragment.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RecommendationFragment.java @@ -1,41 +1,50 @@ package org.example.team_pigeon.movie_pigeon; +import android.app.ProgressDialog; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.util.DisplayMetrics; import android.util.Log; +import android.view.Display; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.GridView; +import android.widget.LinearLayout; import android.widget.SearchView; import android.widget.Toast; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import org.example.team_pigeon.movie_pigeon.adapters.HorizontalListAdapter; import org.example.team_pigeon.movie_pigeon.models.Movie; import org.example.team_pigeon.movie_pigeon.models.MovieWithCount; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -public class RecommendationFragment extends Fragment { +public class RecommendationFragment extends Fragment implements AdapterView.OnItemClickListener { private static final String TAG = "RecommendationFragment"; private SearchView searchView = null; private Gson gson = new Gson(); - private SearchTask searchTask; + private Task nowShowingTask,recommendationTask,searchTask; private Bundle arguments; - private ArrayList searchMovieList; - private ArrayList topMovieList; - private ArrayList recommendedMovieList; + private ArrayList searchMovieList, nowShowingMovieList, recommendedMovieList, filteredNowShowingList; + private HorizontalListAdapter nowShowingMovieAdapter, recommendedMovieAdapter; private MovieWithCount movieWithCount; + private GridView nowShowingGrid, recommendedGrid; private int resultCount = 0; private RequestHttpBuilderSingleton searchRequestHttpBuilder = RequestHttpBuilderSingleton.getInstance(); + private LoadingDialog loadingDialog; public RecommendationFragment() { } @@ -43,17 +52,22 @@ public RecommendationFragment() { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + loadingDialog = new LoadingDialog(this.getActivity(),R.style.LoadingDialog); View view = inflater.inflate(R.layout.fragment_recommendation, container, false); searchView = (SearchView) view.findViewById(R.id.search_view); + nowShowingGrid = (GridView) view.findViewById(R.id.grid_now_showing); + recommendedGrid = (GridView) view.findViewById(R.id.grid_recommended); + nowShowingTask = new Task(); + nowShowingTask.execute("nowshowing"); searchView.setSubmitButtonEnabled(true); - searchView.clearFocus(); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { //Start to search movie if there is query present and submit button is pressed @Override public boolean onQueryTextSubmit(String query) { Log.d(TAG, "Search query submit = " + query); - searchTask = new SearchTask(); - searchTask.execute(query); + filteredNowShowingList = filterNowShowing(nowShowingMovieList,query); + searchTask = new Task(); + searchTask.execute("search",query); return false; } //TODO: Search suggestion @@ -65,43 +79,151 @@ public boolean onQueryTextChange(String newText) { return view; } + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + Intent displayActivityIntent = new Intent(getActivity(), DisplayActivity.class); + Bundle arguments = new Bundle(); + switch (parent.getId()) { + case R.id.grid_now_showing: + arguments.putSerializable("movie", nowShowingMovieAdapter.getItem(position)); + arguments.putString("title", nowShowingMovieAdapter.getItem(position).getTitle()); + break; + case R.id.grid_recommended: + arguments.putSerializable("movie", recommendedMovieAdapter.getItem(position)); + arguments.putString("title", recommendedMovieAdapter.getItem(position).getTitle()); + break; + } + arguments.putString("type", "moviePage"); + arguments.putInt("position",position); + displayActivityIntent.putExtra("bundle", arguments); + getActivity().startActivity(displayActivityIntent); + } + + private void setGridView(GridView gridView, int size){ + int length = 100; + DisplayMetrics dm = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); + float density = dm.density; + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams((int) (size*length*density),LinearLayout.LayoutParams.FILL_PARENT); + gridView.setLayoutParams(params); + gridView.setColumnWidth((int) (length*density)); + gridView.setHorizontalSpacing(0); + gridView.setStretchMode(GridView.NO_STRETCH); + gridView.setNumColumns(size); + } + + private ArrayList filterNowShowing(ArrayList allNowShowing, String keywords){ + ArrayList filteredMovies = new ArrayList<>(); + keywords = keywords.toLowerCase(); + for(Movie movie:allNowShowing){ + if(movie.getTitle().toLowerCase().contains(keywords)){ + filteredMovies.add(movie); + } + } + return filteredMovies; + } + + private void setOnclickListener(GridView gridView){ + gridView.setOnItemClickListener(this); + } + //Async thread to handle search request - private class SearchTask extends AsyncTask { - private final int SUCCESSFUL = 0; + private class Task extends AsyncTask { + private final int SUCCESSFUL_SEARCH = 0; + private final int SUCCESSFUL_NOW_SHOWING = 4; + private final int SUCCESSFUL_RECOMMENDATION = 6; private final int ERROR = 1; private final int NO_RESULT = 2; + private final int NO_RECOMMENDATION = 7; private final int NO_INTERNET = 3; + private final int NO_NOW_SHOWING = 5; int status; + String type; String keyword = null; @Override protected Void doInBackground(String... params) { - try { - keyword = params[0]; - searchRequestHttpBuilder.setKeywords(keyword); - OkHttpClient client = searchRequestHttpBuilder.getClient(); - Request request = searchRequestHttpBuilder.getSearchRequest(); - Response response = client.newCall(request).execute(); - if (!response.isSuccessful()) { - Log.i(TAG, "connect failed"); - status = ERROR; - throw new IOException("Unexpected code" + response); - } - //Convert json to Arraylist - movieWithCount = gson.fromJson(response.body().charStream(), new TypeToken() { - }.getType()); - searchMovieList = movieWithCount.getMovies(); - resultCount = movieWithCount.getCount(); - - if (resultCount == 0) { - status = NO_RESULT; - } else { - status = SUCCESSFUL; - } - return null; - } catch (IOException e) { - status = NO_INTERNET; - Log.e(TAG, e.getMessage()); + type = params[0]; + switch (type){ + case "search": + try { + keyword = params[1]; + searchRequestHttpBuilder.setKeywords(keyword); + OkHttpClient client = searchRequestHttpBuilder.getClient(); + Request request = searchRequestHttpBuilder.getSearchRequest(); + Response response = client.newCall(request).execute(); + if (!response.isSuccessful()) { + Log.i(TAG, "Search connection failed"); + status = ERROR; + throw new IOException("Unexpected code" + response); + } + //Convert json to Arraylist + movieWithCount = gson.fromJson(response.body().charStream(), new TypeToken() { + }.getType()); + searchMovieList = movieWithCount.getMovies(); + resultCount = movieWithCount.getCount(); + + if (resultCount == 0) { + status = NO_RESULT; + } else { + status = SUCCESSFUL_SEARCH; + } + return null; + } catch (IOException e) { + status = NO_INTERNET; + Log.e(TAG, e.getMessage()); + } + break; + case "nowshowing": + try { + OkHttpClient client = searchRequestHttpBuilder.getClient(); + Request request = searchRequestHttpBuilder.getNowShowingListRequest(); + Response response = client.newCall(request).execute(); + if(!response.isSuccessful()){ + Log.i(TAG,"Now showing connection failed"); + status = ERROR; + throw new IOException("Unexpected code"+response); + } + nowShowingMovieList = gson.fromJson(response.body().charStream(), new TypeToken>() {}.getType()); + if(nowShowingMovieList.isEmpty()){ + status = NO_NOW_SHOWING; + } + else{ + status = SUCCESSFUL_NOW_SHOWING; + for(Movie movie:nowShowingMovieList){ + movie.setShowing(true); + } + } + return null; + } + catch (IOException e) { + status = NO_INTERNET; + Log.e(TAG, e.getMessage()); + } + break; + case "recommendation": + try { + OkHttpClient client = searchRequestHttpBuilder.getClient(); + Request request = searchRequestHttpBuilder.getRecommendationRequest(); + Response response = client.newCall(request).execute(); + if(!response.isSuccessful()){ + Log.i(TAG,"Recommendation connection failed"); + status = ERROR; + throw new IOException("Unexpected code"+response); + } + recommendedMovieList = gson.fromJson(response.body().charStream(), new TypeToken>() {}.getType()); + if(recommendedMovieList.isEmpty()){ + status = NO_RECOMMENDATION; + } + else{ + status = SUCCESSFUL_RECOMMENDATION; + } + return null; + } + catch (IOException e) { + status = NO_INTERNET; + Log.e(TAG, e.getMessage()); + } } return null; @@ -109,18 +231,21 @@ protected Void doInBackground(String... params) { @Override protected void onPreExecute() { - Log.i(TAG, "New search request is initialised"); + Log.i(TAG, "Async request is initialised"); + loadingDialog.show(); return; } @Override protected void onPostExecute(Void params) { + loadingDialog.dismiss(); switch (status) { - case SUCCESSFUL: + case SUCCESSFUL_SEARCH: Log.i(TAG, "Search is completed"); Intent displayActivityIntent = new Intent(getActivity(), DisplayActivity.class); arguments = new Bundle(); - arguments.putSerializable("movieList", searchMovieList); + arguments.putSerializable("nowShowingList",filteredNowShowingList); + arguments.putSerializable("allList", searchMovieList); arguments.putString("type","search"); arguments.putString("title", "Result of '" + searchRequestHttpBuilder.getKeywords() + "'"); arguments.putString("count", "Found "+String.valueOf(resultCount)+ " movies"); @@ -129,17 +254,35 @@ protected void onPostExecute(Void params) { searchView.clearFocus(); getActivity().startActivity(displayActivityIntent); break; - + case SUCCESSFUL_NOW_SHOWING: + Log.i(TAG,"Get now showing list successfully"); + //After get now showing list, get recommendation + recommendationTask = new Task(); + recommendationTask.execute("recommendation"); + setGridView(nowShowingGrid,nowShowingMovieList.size()); + nowShowingMovieAdapter = new HorizontalListAdapter(getActivity(),nowShowingMovieList); + nowShowingGrid.setAdapter(nowShowingMovieAdapter); + setOnclickListener(nowShowingGrid); + nowShowingMovieAdapter.notifyDataSetChanged(); + break; + case SUCCESSFUL_RECOMMENDATION: + Log.i(TAG,"Get recommendation list successfully"); + setGridView(recommendedGrid,recommendedMovieList.size()); + recommendedMovieAdapter = new HorizontalListAdapter(getActivity(),recommendedMovieList); + recommendedGrid.setAdapter(recommendedMovieAdapter); + setOnclickListener(recommendedGrid); + recommendedMovieAdapter.notifyDataSetChanged(); + break; case ERROR: - Toast.makeText(getContext(), "Connection error, please check your connection", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Connection error, please check your connection", Toast.LENGTH_SHORT).show(); break; case NO_RESULT: - Toast.makeText(getContext(), "Sorry, the search has no results", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Sorry, the search has no results", Toast.LENGTH_SHORT).show(); break; case NO_INTERNET: - Toast.makeText(getContext(), "Connection error, please make sure that you have Internet connection.", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Connection error, please make sure that you have Internet connection.", Toast.LENGTH_SHORT).show(); break; } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RegisterPage.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RegisterPage.java deleted file mode 100644 index 6bbb1a8..0000000 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RegisterPage.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.example.team_pigeon.movie_pigeon; - -import android.app.Activity; -import android.content.Context; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewManager; -import android.widget.Button; -import android.widget.EditText; -import android.widget.Toast; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Created by Guo Mingxuan on 1/2/2017. - */ - -class RegisterPage { - - String email, username, password, confirmPassword; - int count = 0; - - RegisterPage(final Context mContext, final Activity mActivity) { - - final View register = LayoutInflater.from(mActivity.getApplication()).inflate(R.layout.register_page, null); - mActivity.setContentView(register); - - final EditText etEmail = (EditText) register.findViewById(R.id.rETEmail); - final EditText etUsername = (EditText) register.findViewById(R.id.rETUsername); - final EditText etPassword = (EditText) register.findViewById(R.id.rETPassword); - final EditText etConfirmPassword = (EditText) register.findViewById(R.id.rETConfirmPassword); - - Button registerButton = (Button) register.findViewById(R.id.rpRegisterButton); - Button backButton = (Button) register.findViewById(R.id.rpBackButton); - - backButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((ViewGroup) register.getParent()).removeView(register); - SigninPage sp = new SigninPage(mContext, mActivity); - } - }); - - registerButton.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View v) { - email = String.valueOf(etEmail.getText()); - username = String.valueOf(etUsername.getText()); - password = String.valueOf(etPassword.getText()); - confirmPassword = String.valueOf(etConfirmPassword.getText()); - - if (email.equals("") | username.equals("") | password.equals("") | confirmPassword.equals("")) { - Toast.makeText(mContext, "Must fill in all fields", Toast.LENGTH_SHORT).show(); - } else { - // double check password match - if (!password.equals(confirmPassword)) { - Toast toast = Toast.makeText(mContext, "Passwords entered don't match!", Toast.LENGTH_SHORT); - toast.show(); - } else { - count = emailChecker(email); - // check whether email field contains: no @, or 2 or more @ or does not have enough length as format a@b - if (count == 0 || count > 1 || email.length()<=2) { - Toast.makeText(mContext, "Please enter correct email address", Toast.LENGTH_SHORT).show(); - } else { - System.out.println("Registering"); - String[] registrationDetails = new String[3]; - registrationDetails[0] = email; - registrationDetails[1] = username; - registrationDetails[2] = password; - - Log.i("RegistrationPage", "3 parameters to be passed are " + registrationDetails[0] + " " + registrationDetails[1] + " " + registrationDetails[2]); - new RegistrationHttpBuilder(mContext).execute(registrationDetails); - } - } - } - - } - }); - - } - - private int emailChecker(String email) { - Pattern pattern = Pattern.compile("[@]"); - Matcher matcher = pattern.matcher(email); - int countCharacter = 0; - while(matcher.find()) { - countCharacter++; - } - return countCharacter; - } -} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RegistrationActivity.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RegistrationActivity.java new file mode 100644 index 0000000..5d1dc4f --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RegistrationActivity.java @@ -0,0 +1,131 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.content.IntentFilter; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created by Guo Mingxuan on 1/2/2017. + */ + +public class RegistrationActivity extends AppCompatActivity { + + String email, username, password, confirmPassword; + EditText etEmail, etUsername, etPassword, etConfirmPassword; + View register; + int count = 0; + GlobalReceiver globalReceiver = new GlobalReceiver(); + String thirdParty = "NONE"; + String userInfo = "NONE"; + String thirdPartyPassword = "NONE"; + String TAG = "RegActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + register = getLayoutInflater().inflate(R.layout.register_page, null); + setContentView(register); + + try { + Bundle bundle = getIntent().getExtras(); + thirdParty = bundle.getString("ThirdParty"); + userInfo = bundle.getString("UserInfo"); + thirdPartyPassword = bundle.getString("ThirdPartyPassword"); + Log.i(TAG, "3rd party sign up"); + } catch (NullPointerException e) { + Log.e(TAG, "No 3rd party sign up"); + } + + IntentFilter filter = new IntentFilter(); + filter.addAction("killRegistration"); + registerReceiver(globalReceiver, filter); + + etEmail = (EditText) register.findViewById(R.id.rETEmail); + etUsername = (EditText) register.findViewById(R.id.rETUsername); + etPassword = (EditText) register.findViewById(R.id.rETPassword); + etConfirmPassword = (EditText) register.findViewById(R.id.rETConfirmPassword); + + Button registerButton = (Button) register.findViewById(R.id.rpRegisterButton); + Button backButton = (Button) register.findViewById(R.id.rpBackButton); + + // checking whether using third party sign up + if (thirdParty.equals("TraktTV")) { + etUsername.setText(userInfo); + } else if (thirdParty.equals("The Movie DB")) { + etUsername.setText(userInfo); + } + + backButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + registerButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + email = String.valueOf(etEmail.getText()); + username = String.valueOf(etUsername.getText()); + password = String.valueOf(etPassword.getText()); + confirmPassword = String.valueOf(etConfirmPassword.getText()); + + if (email.equals("") | username.equals("") | password.equals("") | confirmPassword.equals("")) { + Toast.makeText(getApplicationContext(), "Must fill in all fields", Toast.LENGTH_SHORT).show(); + } else { + // double check password match + if (!password.equals(confirmPassword)) { + Toast toast = Toast.makeText(getApplicationContext(), "Passwords entered don't match!", Toast.LENGTH_SHORT); + toast.show(); + } else { + count = emailChecker(email); + // check whether email field contains: no @, or 2 or more @ or does not have enough length as format a@b + if (count == 0 || count > 1 || email.length()<=2) { + Toast.makeText(getApplicationContext(), "Please enter correct email address", Toast.LENGTH_SHORT).show(); + } else { + System.out.println("Registering"); + String[] registrationDetails = new String[6]; + registrationDetails[0] = email; + registrationDetails[1] = username; + registrationDetails[2] = password; + registrationDetails[3] = thirdParty; + registrationDetails[4] = userInfo; + registrationDetails[5] = thirdPartyPassword; + + Log.i("RegistrationPage", "5 parameters to be passed are " + registrationDetails[0] + " " + registrationDetails[1] + " " + registrationDetails[2] + " " + + registrationDetails[3] + " " + registrationDetails[4] + " " + registrationDetails[5]); + new RegistrationHttpBuilder(getApplicationContext()).execute(registrationDetails); + } + } + } + + } + }); + + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(globalReceiver); + } + + private int emailChecker(String email) { + Pattern pattern = Pattern.compile("[@]"); + Matcher matcher = pattern.matcher(email); + int countCharacter = 0; + while(matcher.find()) { + countCharacter++; + } + return countCharacter; + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RegistrationHttpBuilder.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RegistrationHttpBuilder.java index f49268d..97c8d3e 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RegistrationHttpBuilder.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RegistrationHttpBuilder.java @@ -23,10 +23,11 @@ class RegistrationHttpBuilder extends AsyncTask { String TAG = "rHttpBuilder"; - String url = "http://128.199.231.190:8080"; - String registrationURL = "http://128.199.231.190:8080/api/users"; + String url = "http://128.199.167.57:8080"; + String registrationURL = "http://128.199.167.57:8080/api/users"; String charset = java.nio.charset.StandardCharsets.UTF_8.name(); - String param1, param2, param3, query; + String uEmail, uUsername, uPassword, u3rdInfo, u3rdPassword, query; + String u3rdParty = "NONE"; HttpURLConnection connection = null; Context mContext; private boolean connectionError = false; @@ -41,6 +42,13 @@ class RegistrationHttpBuilder extends AsyncTask { private void request(String query) { // build registration request here try { + // check if using 3rd party sign up + if (u3rdParty.equalsIgnoreCase("TraktTV")) { + registrationURL = "http://128.199.167.57:8080/api/traktTV"; + } else if (u3rdParty.equalsIgnoreCase("The Movie DB")) { + registrationURL = "http://128.199.167.57:8080/api/tmdb"; + } + connection = (HttpURLConnection) new URL(registrationURL).openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); @@ -87,14 +95,40 @@ private void request(String query) { } private String formQuery(String email, String username, String password) { - param1 = email; - param2 = username; - param3 = password; + uEmail = email; + uUsername = username; + uPassword = password; try { return String.format("email=%s&username=%s&password=%s", - URLEncoder.encode(param1, charset), - URLEncoder.encode(param2, charset), - URLEncoder.encode(param3, charset)); + URLEncoder.encode(uEmail, charset), + URLEncoder.encode(uUsername, charset), + URLEncoder.encode(uPassword, charset)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + Log.e(TAG, "Unable to encode message"); + return ""; + } + } + + private String formQuery3rdPartyNoPassword(String email, String username, String password, String thirdParty, String thirdPartyInfo) { + uEmail = email; + uUsername = username; + uPassword = password; + u3rdParty = thirdParty; + u3rdInfo = thirdPartyInfo; + String thirdPartyBodyField=""; + if (thirdParty.equalsIgnoreCase("TraktTV")) { + thirdPartyBodyField = "traktTVId"; + } else { + Log.e(TAG, "Error in identifying 3rd party"); + } + String strFormat = "email=%s&username=%s&password=%s&" + thirdPartyBodyField + "=%s"; + try { + return String.format(strFormat, + URLEncoder.encode(uEmail, charset), + URLEncoder.encode(uUsername, charset), + URLEncoder.encode(uPassword, charset), + URLEncoder.encode(u3rdInfo, charset)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); Log.e(TAG, "Unable to encode message"); @@ -102,18 +136,62 @@ private String formQuery(String email, String username, String password) { } } + private String formQuery3rdPartyWithPassword(String email, String username, String password, String thirdParty, String thirdPartyInfo, String thirdPartyPassword) { + uEmail = email; + uUsername = username; + uPassword = password; + u3rdParty = thirdParty; + u3rdInfo = thirdPartyInfo; + u3rdPassword = thirdPartyPassword; + String thirdPartyUsername = ""; + String thirdPartyPwd=""; + if (thirdParty.equalsIgnoreCase("The Movie DB")) { + thirdPartyUsername = "tmdbUsername"; + thirdPartyPwd = "tmdbPassword"; + } else { + Log.e(TAG, "Error in identifying 3rd party"); + } + String strFormat = "email=%s&username=%s&password=%s&" + thirdPartyUsername + "=%s&" + thirdPartyPwd + "=%s"; + try { + return String.format(strFormat, + URLEncoder.encode(uEmail, charset), + URLEncoder.encode(uUsername, charset), + URLEncoder.encode(uPassword, charset), + URLEncoder.encode(u3rdInfo, charset), + URLEncoder.encode(u3rdPassword, charset)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + Log.e(TAG, "Unable to encode message"); + return ""; + } + } @Override protected Void doInBackground(String... params) { - String p1, p2, p3; - p1=params[0]; - p2=params[1]; - p3=params[2]; - Log.i(TAG, "Passed in parameters are " + p1 + " " + p2 + " " + p3); - query = formQuery(p1, p2, p3); - Log.i(TAG, "query formed"); - Log.i(TAG, "Query is " + query); - request(query); + String pEmail, pUsername, pPassword, pThirdParty, pUserInfo, pThirdPartyPassword; + pEmail=params[0]; + pUsername=params[1]; + pPassword=params[2]; + pThirdParty=params[3]; + pUserInfo=params[4]; + pThirdPartyPassword=params[5]; + Log.i(TAG, "Passed in parameters are " + pEmail + " " + pUsername + " " + pPassword + " " + pThirdParty + " " + pUserInfo + " " + pThirdPartyPassword); + if (pThirdParty.equals("TraktTV")) { + query = formQuery3rdPartyNoPassword(pEmail, pUsername, pPassword, pThirdParty, pUserInfo); + Log.i(TAG, "TraktTV 3rd party query formed"); + Log.i(TAG, "Query is " + query); + request(query); + } else if (pThirdParty.equals("The Movie DB")) { + query = formQuery3rdPartyWithPassword(pEmail, pUsername, pPassword, pThirdParty, pUserInfo, pThirdPartyPassword); + Log.i(TAG, "TMDB 3rd party query formed"); + Log.i(TAG, "Query is " + query); + request(query); + } else { + query = formQuery(pEmail, pUsername, pPassword); + Log.i(TAG, "non 3rd party query formed"); + Log.i(TAG, "Query is " + query); + request(query); + } return null; } @@ -127,8 +205,8 @@ protected void onPostExecute(Void v) { Toast.makeText(mContext, "Registration successful!", Toast.LENGTH_SHORT).show(); Intent intent = new Intent("automaticSignin"); Bundle bundle = new Bundle(); - bundle.putString("email", param1); - bundle.putString("password", param3); + bundle.putString("email", uEmail); + bundle.putString("password", uPassword); intent.putExtras(bundle); mContext.sendBroadcast(intent); } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RequestHttpBuilderSingleton.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RequestHttpBuilderSingleton.java index db5836a..4c295b5 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RequestHttpBuilderSingleton.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/RequestHttpBuilderSingleton.java @@ -1,11 +1,10 @@ package org.example.team_pigeon.movie_pigeon; -import android.util.Log; + +import java.util.concurrent.TimeUnit; import okhttp3.FormBody; -import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; -import okhttp3.RequestBody; /** * Created by SHENGX on 2017/2/8. @@ -18,9 +17,15 @@ public class RequestHttpBuilderSingleton { private String token = ""; private int offset = 0; private final int LIMIT = 20; - private final String searchUrl = new String("http://128.199.231.190:8080/api/movies/title"); - private final String ratingUrl = new String("http://128.199.231.190:8080/api/ratings"); - private final String bookmarkUrl = new String("http://128.199.231.190:8080/api/bookmarks"); + private final String searchUrl = "http://128.199.167.57:8080/api/movies/title"; + private final String ratingUrl = "http://128.199.167.57:8080/api/ratings"; + private final String bookmarkUrl = "http://128.199.167.57:8080/api/bookmarks"; + private final String cinemaUrl = "http://128.199.167.57:8080/api/cinemas"; + private final String nowShowingUrl = "http://128.199.167.57:8080/api/showing"; + //Use bookmarks as place holders + private final String recommendationUrl = "http://128.199.167.57:8080/api/bookmarks"; + private final String nowShowingHomePageUrl = "http://128.199.167.57:8080/api/showing/all"; + private final String movieScheduleUrl = "http://128.199.167.57:8080/api/movies/schedule"; protected RequestHttpBuilderSingleton() {} @@ -75,10 +80,30 @@ public Request getRatingListRequest(){ return new Request.Builder().url(ratingUrl).header("Authorization", "Bearer "+ token.trim()).build(); } + public Request getNowShowingListRequest(){ + return new Request.Builder().url(nowShowingHomePageUrl).header("Authorization", "Bearer "+ token.trim()).build(); + } + + public Request getRecommendationRequest(){ + return new Request.Builder().url(recommendationUrl).header("Authorization", "Bearer "+ token.trim()).build(); + } + public Request getBookmarkListRequest(){ return new Request.Builder().url(bookmarkUrl).header("Authorization", "Bearer "+ token.trim()).build(); } + public Request getCinemasRequest(){ + return new Request.Builder().url(cinemaUrl).header("Authorization", "Bearer "+ token.trim()).build(); + } + + public Request getShowingListRequest(String cinemaId){ + return new Request.Builder().url(nowShowingUrl).header("Authorization", "Bearer "+ token.trim()).addHeader("cinema_id",cinemaId).build(); + } + + public Request getScheduleOfMovie(String movieId){ + return new Request.Builder().url(movieScheduleUrl).header("Authorization", "Bearer "+ token.trim()).addHeader("movie_id",movieId).build(); + } + public String getKeywords() { return keywords; } @@ -105,7 +130,12 @@ public void setOffset(int offset) { public OkHttpClient getClient() { if(client == null){ - client = new OkHttpClient(); + //New client with timeout setting + client = new OkHttpClient.Builder(). + connectTimeout(10, TimeUnit.SECONDS). + readTimeout(10,TimeUnit.SECONDS). + writeTimeout(10,TimeUnit.SECONDS). + build(); } return client; } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/ResetPasswordActivity.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/ResetPasswordActivity.java new file mode 100644 index 0000000..6fc6b0e --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/ResetPasswordActivity.java @@ -0,0 +1,357 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.provider.Settings; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; + +/** + * Created by Guo Mingxuan on 4/3/2017. + */ + +public class ResetPasswordActivity extends AppCompatActivity { + EditText emailField, vCodeField, newPwdField, confirmPwdField; + TextView tvEmail, tvVcode, tvNewPwd, tvConfirmPwd; + Button BConfirm, BBack; + Boolean vCodeButtonClicked = false; + String email, type, vCode, newPwd, confirmPwd; + String TAG = "ResetPwd"; + String[] vCodeBundle = new String[2]; + String[] resetBundle = new String[3]; + GlobalReceiver resetPwdReceiver; + private final static int VCodeSuccess = 0; + private final static int ResetSuccess = 1; + TextView hint; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + LayoutInflater inflater = getLayoutInflater(); + View resetView = inflater.inflate(R.layout.activity_reset_password, null); + setContentView(resetView); + + emailField = (EditText) resetView.findViewById(R.id.rsETEmail); + vCodeField = (EditText) resetView.findViewById(R.id.rsETVCode); + newPwdField = (EditText) resetView.findViewById(R.id.rsETPassword); + confirmPwdField = (EditText) resetView.findViewById(R.id.rsETConfirmPassword); + + tvEmail = (TextView) resetView.findViewById(R.id.rsTVEmail); + tvVcode = (TextView) resetView.findViewById(R.id.rsTVVCode); + tvNewPwd = (TextView) resetView.findViewById(R.id.rsTVPassword); + tvConfirmPwd = (TextView) resetView.findViewById(R.id.rsTVConfirmPassword); + + tvVcode.setVisibility(View.INVISIBLE); + tvNewPwd.setVisibility(View.INVISIBLE); + tvConfirmPwd.setVisibility(View.INVISIBLE); + vCodeField.setVisibility(View.INVISIBLE); + newPwdField.setVisibility(View.INVISIBLE); + confirmPwdField.setVisibility(View.INVISIBLE); + + BConfirm = (Button) resetView.findViewById(R.id.rsBVerificationCode); + BBack = (Button) resetView.findViewById(R.id.rsBBack); + hint = (TextView) resetView.findViewById(R.id.rsHint); + + resetPwdReceiver = new GlobalReceiver(new Handler(){ + public void handleMessage(Message msg) { + final int what = msg.what; + switch(what) { + case VCodeSuccess: + Toast.makeText(getApplicationContext(), "Email sent to " + email, Toast.LENGTH_SHORT).show(); + BConfirm.setText("Confirm"); + tvVcode.setVisibility(View.VISIBLE); + tvNewPwd.setVisibility(View.VISIBLE); + tvConfirmPwd.setVisibility(View.VISIBLE); + vCodeField.setVisibility(View.VISIBLE); + newPwdField.setVisibility(View.VISIBLE); + confirmPwdField.setVisibility(View.VISIBLE); + vCodeField.requestFocus(); + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(vCodeField, InputMethodManager.SHOW_IMPLICIT); + vCodeButtonClicked = true; + hint.setText("Please fill in the rest and click 'Confirm'"); + Log.i(TAG, "Successfully sent VCode"); + break; + case ResetSuccess: + Toast.makeText(getApplicationContext(), "Password Reset Successful", Toast.LENGTH_SHORT).show(); + finish(); + break; + } + } + }); + IntentFilter filter = new IntentFilter(); + filter.addAction("vCodeSuccessful"); + filter.addAction("ResetSuccessful"); + registerReceiver(resetPwdReceiver, filter); + + BConfirm.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!vCodeButtonClicked) { + // get email from UI + email = String.valueOf(emailField.getText()); + type = "GetVCode"; + vCodeBundle[0] = email; + vCodeBundle[1] = type; + + // send email to server to get vCode + new ResetPwdWorkingThread(getApplicationContext()).execute(vCodeBundle); + } else { + // send to server with vCode + vCode = String.valueOf(vCodeField.getText()); + newPwd = String.valueOf(newPwdField.getText()); + confirmPwd = String.valueOf(confirmPwdField.getText()); + if (vCode.equals("")) { + Toast.makeText(getApplicationContext(), "Verification code can't be empty", Toast.LENGTH_SHORT).show(); + } else if (newPwd.equals("")) { + Toast.makeText(getApplicationContext(), "New password can't be empty", Toast.LENGTH_SHORT).show(); + } else if (!newPwd.equals(confirmPwd)) { + Toast.makeText(getApplicationContext(), "Passwords don't match", Toast.LENGTH_SHORT).show(); + } else { + resetBundle[0] = vCode; + resetBundle[1] = "Reset"; + resetBundle[2] = newPwd; + + new ResetPwdWorkingThread(getApplicationContext()).execute(resetBundle); + } + + } + } + }); + + BBack.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(resetPwdReceiver); + } +} + +class ResetPwdWorkingThread extends AsyncTask { + String vCodeUrl = "http://128.199.167.57:8080/api/users/resetPassword"; + String resetPwdUrl = "http://128.199.167.57:8080/api/users/password"; + HttpURLConnection connection; + String charset = java.nio.charset.StandardCharsets.UTF_8.name(); + String TAG = "ResetPwdWT"; + Context mContext; + String type = ""; + String id, query; + int status; + private InputStream response; + boolean correctEmail = false; + boolean forbidden = false; + private boolean connectionError = false; + boolean samePwd = false; + + ResetPwdWorkingThread(Context mContext) { + this.mContext = mContext; + } + + @Override + protected Void doInBackground(String... params) { + type = params[1]; + if (type.equals("GetVCode")) { + // get v code + getVCode(params[0]); + } else if (type.equals("Reset")) { + // reset + resetPwd(params[0], params[2]); + } else { + Log.e(TAG, "Unexpected type"); + } + + return null; + } + + private void getVCode(String email) { + // method for getting verification code + String userEmail = email; + try { + connection = (HttpURLConnection) new URL(vCodeUrl).openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setRequestProperty("Accept-Charset", charset); + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset); + + id = Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.ANDROID_ID); + + query = formQueryForVCode(userEmail, id); + + Log.i(TAG, "query is " + query); + + connection.connect(); + + try (OutputStream output = connection.getOutputStream()) { + output.write(query.getBytes(charset)); + } catch (IOException e) { + e.printStackTrace(); + } + + status = connection.getResponseCode(); + + Log.i(TAG, "registering client response status is " + status); + + if (status == 200) { + try { + response = connection.getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + } + BufferedReader br = new BufferedReader(new InputStreamReader(response)); + StringBuffer sb = new StringBuffer(); + String line = ""; + String resp = ""; + Log.i("rHttpBuilder", "Starting to read response"); + while ((line = br.readLine()) != null) { + sb.append(line + "\n"); + resp = "Response>>>" + line; + Log.i(TAG, resp); + } + // check whether email entered is correct + if (!resp.contains("fail")) { + correctEmail = true; + } + + } else { + Log.e(TAG, "getVCode" + status); + connectionError = true; + } + } catch (IOException e) { + e.printStackTrace(); + } + + connection.disconnect(); + } + + private void resetPwd(String vCode, String newPwd) { + // method for resetting pwd + try { + connection = (HttpURLConnection) new URL(resetPwdUrl).openConnection(); + connection.setRequestMethod("PUT"); + connection.setDoOutput(true); + connection.setRequestProperty("Authorization", "Bearer " + vCode); + connection.setRequestProperty("Accept-Charset", charset); + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset); + + connection.connect(); + + query = formQueryForReset(newPwd); + + try (OutputStream output = connection.getOutputStream()) { + output.write(query.getBytes(charset)); + } + + Log.i(TAG, "Finished sending to server"); + + int status = connection.getResponseCode(); + Log.i(TAG, "response status transactionId is " + status); + + if (status == 200) { + InputStream response = connection.getInputStream(); + // process the response + BufferedReader br = new BufferedReader(new InputStreamReader(response)); + StringBuffer sb = new StringBuffer(); + Log.i(TAG, "Starting to read response"); + String line, serverResponse = ""; + while ((line = br.readLine()) != null) { + sb.append(line + "\n"); + serverResponse = "Registration Response>>>" + line; + Log.i(TAG, serverResponse); + } + + correctEmail = true; + + if (serverResponse.contains("Same Password")) { + samePwd = true; + } + + } else if (status == 401) { + forbidden = true; + + } else { + connectionError = true; + Log.i(TAG, "Error code " + status); + } + + } catch (IOException e) { + e.printStackTrace(); + connectionError = true; + Log.e(TAG, "Unable to connect to server"); + } + } + + private String formQueryForVCode(String email, String id) { + try { + return String.format("email=%s&id=%s", + URLEncoder.encode(email, charset), + URLEncoder.encode(id, charset)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + Log.e(TAG, "Unable to encode message"); + return ""; + } + } + + private String formQueryForReset(String password) { + try { + String field = "password=%s"; + return String.format(field, URLEncoder.encode(password, charset)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + Log.e(TAG, "Unable to encode message"); + return ""; + } + } + + @Override + protected void onPostExecute(Void v) { + if (forbidden) { + Toast.makeText(mContext, "Please check your verification code", Toast.LENGTH_SHORT).show(); + } else if (!correctEmail) { + Toast.makeText(mContext, "Wrong email entered", Toast.LENGTH_SHORT).show(); + } else if (samePwd) { + Toast.makeText(mContext, "Same password as old one", Toast.LENGTH_SHORT).show(); + } else if (connectionError) { + Toast.makeText(mContext, "Unable to connect to server", Toast.LENGTH_SHORT).show(); + } else { + if (type.equals("GetVCode")) { + // send vCode intent + Intent intent = new Intent("vCodeSuccessful"); + mContext.sendBroadcast(intent); + } else if (type.equals("Reset")) { + // send reset intent + Intent intent = new Intent("ResetSuccessful"); + mContext.sendBroadcast(intent); + } + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SearchPageFragment.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SearchPageFragment.java index 5910c2f..89229a6 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SearchPageFragment.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SearchPageFragment.java @@ -1,75 +1,250 @@ package org.example.team_pigeon.movie_pigeon; import android.app.Fragment; -import android.app.FragmentManager; -import android.app.FragmentTransaction; import android.os.AsyncTask; import android.os.Bundle; +import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; -import android.widget.EditText; -import android.widget.RadioGroup; -import android.widget.RadioGroup.OnCheckedChangeListener; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.ListView; import android.widget.Toast; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import com.nostra13.universalimageloader.core.ImageLoader; +import com.nostra13.universalimageloader.core.listener.PauseOnScrollListener; +import org.example.team_pigeon.movie_pigeon.adapters.MovieListAdapter; +import org.example.team_pigeon.movie_pigeon.eventCenter.UpdateMovieListEvent; import org.example.team_pigeon.movie_pigeon.models.Movie; +import org.example.team_pigeon.movie_pigeon.models.MovieWithCount; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import static android.content.ContentValues.TAG; - /** * Created by SHENGX on 2017/2/5. */ -public class SearchPageFragment extends Fragment { - private Button btnSearch; - private RadioGroup rgrpSearchBy; - private EditText etSearch; - private FragmentManager fragmentManager; - private ArrayList movies; +public class SearchPageFragment extends Fragment implements AdapterView.OnItemClickListener { + private static final String TAG = "SearchPageFragment"; + private android.app.FragmentManager fragmentManager; + private ListView movieListView; + private SearchMoreTask searchMoreTask; + private MovieListAdapter movieListAdapter; + private RequestHttpBuilderSingleton searchRequestHttpBuilder; private Gson gson = new Gson(); - private Bundle arguments; - private MovieListFragment movieListFragment = new MovieListFragment(); + private View nowShowingHeaderView; + private View footerView; + public boolean isLoading = false; + public boolean noMoreResult = false; + private ArrayList allMovieList, nowShowingMovieList, moreMovieList, displayMovieList; + private MovieWithCount movieListWithCount; + private int resultCount; + private Toolbar toolbar; + private Bundle bundle; + private int nowShowingCount; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, final Bundle savedInstanceState) { + public void onCreate(Bundle saveInstanceState){ + super.onCreate(saveInstanceState); + //Load pass-in content + displayMovieList = new ArrayList<>(); + allMovieList = (ArrayList) getArguments().getSerializable("allList"); + nowShowingMovieList = (ArrayList) getArguments().getSerializable("nowShowingList"); + nowShowingCount = nowShowingMovieList.size(); + if(nowShowingCount==0){ + movieListAdapter = new MovieListAdapter(allMovieList, getActivity()); + } + else { + movieListAdapter = new MovieListAdapter(displayMovieList,getActivity()); + movieListAdapter.addListItemToAdapter(nowShowingMovieList); + movieListAdapter.addHeaderToAdapter(new Movie("***HEADER***","***HEADER***")); + movieListAdapter.addListItemToAdapter(allMovieList); + } + + if (!EventBus.getDefault().isRegistered(this)) { + EventBus.getDefault().register(this); + } - View view = inflater.inflate(R.layout.fragment_search_page, container, false); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saveInstanceState) { + //Load common views fragmentManager = getFragmentManager(); - btnSearch = (Button) view.findViewById(R.id.button_search); - rgrpSearchBy = (RadioGroup) view.findViewById(R.id.rg_search_by); - //To be Implemented in next version - rgrpSearchBy.setVisibility(View.GONE); - etSearch = (EditText) view.findViewById(R.id.editText_search); - rgrpSearchBy.setOnCheckedChangeListener(new OnCheckedChangeListener() { + View view = inflater.inflate(R.layout.fragment_movie_list, container, false); + footerView = inflater.inflate(R.layout.footer_load_more, null); + nowShowingHeaderView = inflater.inflate(R.layout.header_now_showing_list,null); + bindView(view); + bundle = getActivity().getIntent().getBundleExtra("bundle"); + + if(nowShowingCount!=0){ + movieListView.addHeaderView(nowShowingHeaderView,null,false); + } + + movieListView.setOnItemClickListener(this); + movieListView.setAdapter(movieListAdapter); + + toolbar.setTitle(bundle.getString("title")); + toolbar.setSubtitle(bundle.getString("count")); + movieListView.setOnScrollListener(new PauseOnScrollListener(ImageLoader.getInstance(), true, true, new AbsListView.OnScrollListener() { @Override - public void onCheckedChanged(RadioGroup group, int checkedId) { - switch (checkedId) { - case R.id.button_title: - etSearch.setHint("Search movies by title..."); - break; - case R.id.button_actor: - etSearch.setHint("Search movies by actor..."); - break; - case R.id.button_country: - etSearch.setHint("Search movies by country..."); - break; + public void onScrollStateChanged(AbsListView view, int scrollState) { + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + int movieCountThreshold = nowShowingCount==0? 20 : 21+nowShowingCount; + if (view.getLastVisiblePosition() == totalItemCount-1 && movieListView.getCount() >= movieCountThreshold && !isLoading && !noMoreResult) { + isLoading = true; + searchMoreTask = new SearchMoreTask(); + searchMoreTask.execute(); } } - }); + })); return view; } + private void bindView(View view) { + movieListView = (ListView) view.findViewById(R.id.list_movies); + toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar_display_page); + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + boolean needSkip = !(nowShowingCount==0); + if(needSkip && position == nowShowingCount+1) {} + else{ + android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + MoviePageFragment moviePageFragment = new MoviePageFragment(); + Bundle bundle = new Bundle(); + bundle.putSerializable("movie", (Serializable) parent.getAdapter().getItem(position)); + bundle.putInt("position", position); + bundle.putString("type", "search"); + toolbar.setTitle(((Movie) parent.getAdapter().getItem(position)).getTitle()); + toolbar.setSubtitle(null); + moviePageFragment.setArguments(bundle); + fragmentTransaction.replace(R.id.fl_content, moviePageFragment); + fragmentTransaction.addToBackStack(null); + fragmentTransaction.commit(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onEvent(UpdateMovieListEvent event) { + if(movieListAdapter!=null) { + //position =- -1 when there is a header + if(nowShowingCount==0){ + movieListAdapter.updateMovieItemToAdapter(event.movie, event.position); + } + else { + movieListAdapter.updateMovieItemToAdapter(event.movie, event.position - 1); + } + Log.i(TAG, "A movie is updated to local list"); + } + } + + //Async thread to handle search request + private class SearchMoreTask extends AsyncTask { + private final int SUCCESSFUL = 0; + private final int ERROR = 1; + private final int NO_RESULT = 2; + private final int NO_INTERNET = 3; + private final int NO_MORE_RESULT = 4; + int status; + + @Override + protected Void doInBackground(Void... params) { + try { + searchRequestHttpBuilder = RequestHttpBuilderSingleton.getInstance(); + OkHttpClient client = searchRequestHttpBuilder.getClient(); + Request request = searchRequestHttpBuilder.getNextSearchRequest(); + Response response = client.newCall(request).execute(); + if (!response.isSuccessful()) { + Log.i(TAG, "connect failed"); + status = ERROR; + throw new IOException("Unexpected code" + response); + } + //Convert json to Arraylist + movieListWithCount = gson.fromJson(response.body().charStream(), new TypeToken() { + }.getType()); + resultCount = movieListWithCount.getCount(); + moreMovieList = movieListWithCount.getMovies(); + + if (resultCount == 0) { + status = NO_RESULT; + } else if (moreMovieList.size() < searchRequestHttpBuilder.getLimit()) { + status = NO_MORE_RESULT; + } else { + status = SUCCESSFUL; + } + return null; + } catch (IOException e) { + status = NO_INTERNET; + Log.e(TAG, e.getMessage()); + } + return null; + + } + + @Override + protected void onPreExecute() { + Log.i(TAG, "New search request is initialised"); + movieListView.addFooterView(footerView,null,false); + return; + } + + @Override + protected void onPostExecute(Void params) { + movieListView.removeFooterView(footerView); + switch (status) { + case SUCCESSFUL: + Log.i(TAG, "Search is completed"); + movieListAdapter.addListItemToAdapter(moreMovieList); + isLoading = false; + break; + + case ERROR: + Toast.makeText(getActivity(), "Connection error, please check your connection", Toast.LENGTH_SHORT).show(); + isLoading = false; + break; + + case NO_RESULT: + Toast.makeText(getActivity(), "Sorry, there is no more result", Toast.LENGTH_SHORT).show(); + noMoreResult = true; + isLoading = false; + break; + + case NO_MORE_RESULT: + noMoreResult = true; + isLoading = false; + movieListAdapter.addListItemToAdapter(moreMovieList); + break; + + case NO_INTERNET: + Toast.makeText(getActivity(), "Connection error, please make sure that you have Internet connection.", Toast.LENGTH_SHORT).show(); + isLoading = false; + break; + } + + } + } } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SettingActivity.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SettingActivity.java index 683d6f0..c9cbf4f 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SettingActivity.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SettingActivity.java @@ -1,200 +1,69 @@ package org.example.team_pigeon.movie_pigeon; -import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; -import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; -import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.Toast; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; +import android.widget.RelativeLayout; +import android.widget.TableRow; +import android.support.v7.widget.Toolbar; /** * Created by Guo Mingxuan on 22/2/2017. */ public class SettingActivity extends AppCompatActivity { - EditText userInput; - Button bConfirm; - Button bCancel; - String input; - Context mContext; - Spinner spinnerList; - String choice; private String TAG = "SettingActivity"; - private RequestHttpBuilderSingleton singleton = RequestHttpBuilderSingleton.getInstance(); - private GlobalReceiver globalReceiver; + private TableRow usernameRow, passwordRow; + Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mContext = this; - LayoutInflater inflater = getLayoutInflater(); - View settingView = inflater.inflate(R.layout.activity_setting, null); + RelativeLayout settingView = (RelativeLayout) getLayoutInflater().inflate(R.layout.activity_setting, null); setContentView(settingView); + toolbar = (Toolbar) findViewById(R.id.toolbar_setting_page); + toolbar.setTitle("Settings"); + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); - // set up broadcast globalReceiver to receive request from background thread - globalReceiver = new GlobalReceiver(); - IntentFilter filter = new IntentFilter(); - filter.addAction("UserUpdate"); - registerReceiver(globalReceiver, filter); - - userInput = (EditText) settingView.findViewById(R.id.popupUserUpdate); - bConfirm = (Button) settingView.findViewById(R.id.popupButtonConfirm); - bCancel = (Button) settingView.findViewById(R.id.popupButtonCancel); - spinnerList = (Spinner) settingView.findViewById(R.id.popupTitle); + usernameRow = (TableRow) settingView.findViewById(R.id.username_setting_page); + passwordRow = (TableRow) settingView.findViewById(R.id.password_setting_page); - bConfirm.setOnClickListener(new View.OnClickListener() { + usernameRow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - input = String.valueOf(userInput.getText()); - choice = spinnerList.getSelectedItem().toString(); - if (input.equals("")) { - Toast.makeText(mContext, "Please enter your change", Toast.LENGTH_SHORT).show(); - } else { - String[] toPassIn = new String[3]; - toPassIn[0] = choice; - Log.i(TAG, "User wants to change " + choice); - toPassIn[1] = input; - toPassIn[2] = singleton.getToken(); - Log.i(TAG, "Starting working thread"); - new WorkingThread(mContext).execute(toPassIn); - } + Log.i(TAG, "Change username clicked"); + Intent intent = new Intent(getApplicationContext(), ChangeUserInfoActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("type", "username"); + intent.putExtras(bundle); + startActivity(intent); } }); - bCancel.setOnClickListener(new View.OnClickListener() { + passwordRow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - finish(); + Log.i(TAG, "Change password clicked"); + Intent intent = new Intent(getApplicationContext(), ChangeUserInfoActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("type", "password"); + intent.putExtras(bundle); + startActivity(intent); } }); } @Override - protected void onDestroy() { - super.onDestroy(); - unregisterReceiver(globalReceiver); - } -} - -class WorkingThread extends AsyncTask { - String[] inputParams; - String type; - String modification; - private String TAG = "WorkingThread"; - String charset = java.nio.charset.StandardCharsets.UTF_8.name(); - String body; - private HttpURLConnection connection; - String token; - Boolean connectionError = false; - Context mContext; - WorkingThread(Context context) { - mContext = context; - } - - @Override - protected Void doInBackground(String... params) { - inputParams = params; - if (inputParams[0].equals("Change Username")) { - type = "username"; - } else if (inputParams[0].equals("Change Password")) { - type = "password"; - } else { - Log.e(TAG, "Invalid type"); - } - modification = inputParams[1]; - token = inputParams[2]; - Log.i(TAG, "Type is " + type + " and modification is " + modification); - body = formBody(); - request(type); - - return null; - } - - private String formBody() { - try { - String field = type + "=%s"; - return String.format(field, URLEncoder.encode(modification, charset)); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - Log.e(TAG, "Unable to encode message"); - return ""; - } - } - - private void request(String type) { - // find type of the request - - String url = "http://128.199.231.190:8080/api/users/" + type; - - - try { - connection = (HttpURLConnection) new URL(url).openConnection(); - connection.setRequestMethod("PUT"); - connection.setDoOutput(true); - connection.setRequestProperty("Authorization", "Bearer " + token); - connection.setRequestProperty("Accept-Charset", charset); - connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset); - - connection.connect(); - - try (OutputStream output = connection.getOutputStream()) { - output.write(body.getBytes(charset)); - } - - Log.i(TAG, "Finished sending to server"); - - int status = connection.getResponseCode(); - Log.i(TAG, "response status transactionId is " + status); - - if (status == 200) { - InputStream response = connection.getInputStream(); - // process the response - BufferedReader br = new BufferedReader(new InputStreamReader(response)); - StringBuffer sb = new StringBuffer(); - Log.i(TAG, "Starting to read response"); - String line, serverResponse = ""; - while ((line = br.readLine()) != null) { - sb.append(line + "\n"); - serverResponse = "Registration Response>>>" + line; - Log.i(TAG, serverResponse); - } - } else { - connectionError = true; - Log.i(TAG, "Error code " + status); - } - - } catch (IOException e) { - e.printStackTrace(); - connectionError = true; - Log.e(TAG, "Unable to connect to server"); - } - } - - @Override - protected void onPostExecute(Void v) { - if (connectionError) { - Toast.makeText(mContext, "Unable to connect to server", Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(mContext, "Operation successful", Toast.LENGTH_SHORT).show(); - Intent intent = new Intent("UserUpdate"); - mContext.sendBroadcast(intent); + public boolean onOptionsItemSelected(MenuItem menuItem) { + if (menuItem.getItemId() == android.R.id.home) { + finish(); + Log.i(TAG, "Back arrow pressed on home"); } + return false; } } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SettingFragments.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SettingFragments.java new file mode 100644 index 0000000..c689350 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SettingFragments.java @@ -0,0 +1,256 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.app.Fragment; +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.util.Base64; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; + +/** + * Created by Guo Mingxuan on 16/3/2017. + */ + +public class SettingFragments extends Fragment { + private EditText username, pwd, repeatPwd, nowPwd; + private TextView tvUsername, tvPwd, tvRepeatPwd, tvNowPwd; + private String type; + private Button confirm, cancel; + private RequestHttpBuilderSingleton builder = RequestHttpBuilderSingleton.getInstance(); + private String[] inputPackage; + private String TAG = "SettingFragment"; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View view = inflater.inflate(R.layout.fragment_change_user_info, container, false); + type = getArguments().getString("type"); + initViews(view); + setHasOptionsMenu(true); + + confirm.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + talkToServer(); + } + }); + + cancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getActivity().finish(); + } + }); + return view; + } + + private void initViews(View view) { + username = (EditText) view.findViewById(R.id.setting_fragment_username_et); + pwd = (EditText) view.findViewById(R.id.setting_fragment_password_et); + repeatPwd = (EditText) view.findViewById(R.id.setting_fragment_repeat_password_et); + nowPwd = (EditText) view.findViewById(R.id.setting_fragment_now_password_et); + tvUsername = (TextView) view.findViewById(R.id.setting_fragment_username_tv); + tvPwd = (TextView) view.findViewById(R.id.setting_fragment_password_tv); + tvRepeatPwd = (TextView) view.findViewById(R.id.setting_fragment_repeat_password_tv); + tvNowPwd = (TextView) view.findViewById(R.id.setting_fragment_now_password_tv); + confirm = (Button) view.findViewById(R.id.setting_fragment_confirm); + cancel = (Button) view.findViewById(R.id.setting_fragment_cancel); + if (type.equals("username")) { + pwd.setVisibility(View.GONE); + repeatPwd.setVisibility(View.GONE); + nowPwd.setVisibility(View.GONE); + tvPwd.setVisibility(View.GONE); + tvRepeatPwd.setVisibility(View.GONE); + tvNowPwd.setVisibility(View.GONE); + } else if (type.equals("password")){ + username.setVisibility(View.GONE); + tvUsername.setVisibility(View.GONE); + nowPwd.requestFocus(); + } + } + + private void talkToServer() { + if (type.equals("username")) { + inputPackage = new String[3]; + inputPackage[0] = "Change Username"; + inputPackage[1] = String.valueOf(username.getText()); + inputPackage[2] = builder.getToken(); + if (inputPackage[1].equals("")) { + Log.e(TAG, "inputPackage 1 is " + inputPackage[1]); + Toast.makeText(getActivity().getApplicationContext(), "Please enter your changes", Toast.LENGTH_SHORT).show(); + } else { + new SFWorkingThread(getActivity().getApplicationContext()).execute(inputPackage); + } + } else if (type.equals("password")) { + inputPackage = new String[3]; + inputPackage[0] = "Change Password"; + inputPackage[1] = String.valueOf(pwd.getText()); + inputPackage[2] = String.valueOf(nowPwd.getText()); + if (inputPackage[1].equals("")) { + Toast.makeText(getActivity().getApplicationContext(), "Please enter your changes", Toast.LENGTH_SHORT).show(); + } else if (!inputPackage[1].equals(String.valueOf(repeatPwd.getText()))) { + Toast.makeText(getActivity().getApplicationContext(), "New passwords don't match", Toast.LENGTH_SHORT).show(); + } else { + new SFWorkingThread(getActivity().getApplicationContext()).execute(inputPackage); + } + } + } +} + +class SFWorkingThread extends AsyncTask { + String[] inputParams; + String type; + String modification; + private String TAG = "SFWorkingThread"; + String charset = java.nio.charset.StandardCharsets.UTF_8.name(); + String body; + private HttpURLConnection connection; + String criticalInfo; // token or base 64 encoded email + password + Boolean connectionError = false; + Boolean authorized = true; + Boolean newPassword = true; + Context mContext; + private UserInfoSingleton userInfoBulk = UserInfoSingleton.getInstance(); + SFWorkingThread(Context context) { + mContext = context; + } + + @Override + protected Void doInBackground(String... params) { + inputParams = params; + if (inputParams[0].equals("Change Username")) { + type = "username"; + } else if (inputParams[0].equals("Change Password")) { + type = "password"; + } else { + Log.e(TAG, "Invalid type"); + } + modification = inputParams[1]; + criticalInfo = inputParams[2]; + Log.i(TAG, "Type is " + type + " and modification is " + modification + " and critical info is " + criticalInfo); + body = formBody(type); + request(type); + + return null; + } + + private String formBody(String type) { + try { + String field = type + "=%s"; + return String.format(field, URLEncoder.encode(modification, charset)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + Log.e(TAG, "Unable to encode message"); + return ""; + } + } + + private void request(String type) { + // find type of the request + String url = "http://128.199.167.57:8080/api/users/" + type; + + try { + connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setRequestMethod("PUT"); + connection.setDoOutput(true); + if (type.equals("username")) { + connection.setRequestProperty("Authorization", "Bearer " + criticalInfo); + } else if (type.equals("password")) { + String email = userInfoBulk.getEmail(); + Log.i(TAG, "Email is " + email); + String base64EncodedCredentialsForToken = "Basic " + Base64.encodeToString( + (email + ":" + criticalInfo).getBytes(), + Base64.NO_WRAP); + connection.setRequestProperty("Authorization", base64EncodedCredentialsForToken); + } + connection.setRequestProperty("Accept-Charset", charset); + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset); + + connection.connect(); + + try (OutputStream output = connection.getOutputStream()) { + output.write(body.getBytes(charset)); + } + Log.i(TAG, "Finished sending to server"); + + int status = connection.getResponseCode(); + Log.i(TAG, "response status transactionId is " + status); + + if (status == 200) { + InputStream response = connection.getInputStream(); + // process the response + BufferedReader br = new BufferedReader(new InputStreamReader(response)); + StringBuffer sb = new StringBuffer(); + Log.i(TAG, "Starting to read response"); + String line, serverResponse = ""; + while ((line = br.readLine()) != null) { + sb.append(line + "\n"); + serverResponse = "Modification Response>>>" + line; + Log.i(TAG, serverResponse); + } + if (serverResponse.contains("Same Password")) { + newPassword = false; + } + } else if (status == 401) { + Log.i(TAG, "Error code " + status); + authorized = false; + InputStream response = connection.getErrorStream(); + // process the response + BufferedReader br = new BufferedReader(new InputStreamReader(response)); + StringBuffer sb = new StringBuffer(); + Log.i(TAG, "Starting to read response"); + String line, serverResponse = ""; + while ((line = br.readLine()) != null) { + sb.append(line + "\n"); + serverResponse = "Modification Response>>>" + line; + Log.i(TAG, serverResponse); + } + } else { + connectionError = true; + Log.i(TAG, "Error code " + status); + } + + } catch (IOException e) { + e.printStackTrace(); + connectionError = true; + Log.e(TAG, "Unable to connect to server"); + } + } + + @Override + protected void onPostExecute(Void v) { + if (connectionError) { + Toast.makeText(mContext, "Unable to connect to server", Toast.LENGTH_SHORT).show(); + } else if (!authorized) { + Toast.makeText(mContext, "Wrong current password", Toast.LENGTH_SHORT).show(); + } else if (!newPassword) { + Toast.makeText(mContext, "New password is the same as old one", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(mContext, "Change " + type + " successful", Toast.LENGTH_SHORT).show(); + if (type.equals("username")) { + Intent update = new Intent("changeUsername"); + mContext.sendBroadcast(update); + } + Intent intent = new Intent("userUpdate"); + mContext.sendBroadcast(intent); + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SignInHttpBuilder.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SignInHttpBuilder.java index e8f1ed4..1e91880 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SignInHttpBuilder.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SignInHttpBuilder.java @@ -34,10 +34,10 @@ class SignInHttpBuilder extends AsyncTask { private final String TAG = "sHttpBuilder"; - String registerClientUrl = "http://128.199.231.190:8080/api/clients"; + String registerClientUrl = "http://128.199.167.57:8080/api/clients"; String getUrl; String authorizeUrl; - String tokenUrl = "http://128.199.231.190:8080/api/oauth2/token"; + String tokenUrl = "http://128.199.167.57:8080/api/oauth2/token"; HttpURLConnection connection; String charset = java.nio.charset.StandardCharsets.UTF_8.name(); String query, param1, param2, param3; @@ -121,6 +121,17 @@ private void request(Context mContext, String email, String password) { } correctEmailPassword = true; } else if (status == 401) { + + response = connection.getErrorStream(); + + BufferedReader br = new BufferedReader(new InputStreamReader(response)); + StringBuffer sb = new StringBuffer(); + String line = ""; + Log.i("rHttpBuilder", "Starting to read response"); + while ((line = br.readLine()) != null) { + sb.append(line + "\n"); + Log.i(TAG, "Response>>>" + line); + } Log.e(TAG, "Unauthorized"); } else { @@ -140,7 +151,7 @@ private void request(Context mContext, String email, String password) { /*-------------------Login step 2-------------------------------*/ Log.i(TAG, "id is " + id); - getUrl = "http://128.199.231.190:8080/api/oauth2/authorize/transactionId?client_id=" + id + "&response_type=code&redirect_uri=moviepigeon/"; + getUrl = "http://128.199.167.57:8080/api/oauth2/authorize/transactionId?client_id=" + id + "&response_type=code&redirect_uri=moviepigeon/"; Log.i(TAG, "get url is " + getUrl); try { @@ -203,7 +214,7 @@ private void request(Context mContext, String email, String password) { Log.i(TAG, "Obtained transactionId: " + transactionId); // step 2 part 2 - authorizeUrl = "http://128.199.231.190:8080/api/oauth2/authorize/"; + authorizeUrl = "http://128.199.167.57:8080/api/oauth2/authorize/"; try { connection = (HttpURLConnection) new URL(authorizeUrl).openConnection(); connection.setRequestMethod("POST"); @@ -344,6 +355,16 @@ private void request(Context mContext, String email, String password) { } else if (status == 401) { // will never come here theoretically as email and password must be correct to pass step 1 Log.e(TAG, "Unauthorized"); + } else if (status == 404) { + response = connection.getErrorStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(response)); + StringBuffer sb = new StringBuffer(); + String line = ""; + Log.i("rHttpBuilder", "Starting to read response"); + while ((line = br.readLine()) != null) { + sb.append(line + "\n"); + Log.i(TAG, "Response>>>" + line); + } } else { Log.e(TAG, "step 3 " + status); connectionError = true; @@ -415,20 +436,14 @@ private String formQuery(String name, String id, String secret) { /* Checks if external storage is available for read and write */ public boolean isExternalStorageWritable() { String state = Environment.getExternalStorageState(); - if (Environment.MEDIA_MOUNTED.equals(state)) { - return true; - } - return false; + return Environment.MEDIA_MOUNTED.equals(state); } /* Checks if external storage is available to at least read */ public boolean isExternalStorageReadable() { String state = Environment.getExternalStorageState(); - if (Environment.MEDIA_MOUNTED.equals(state) || - Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { - return true; - } - return false; + return Environment.MEDIA_MOUNTED.equals(state) || + Environment.MEDIA_MOUNTED_READ_ONLY.equals(state); } @Override @@ -457,6 +472,10 @@ protected void onPostExecute(Void v) { mContext.sendBroadcast(intent); /*--------------------End of starting HomePageActivity-------------------*/ + + // kill off registration page if there is any + Intent killRegistration = new Intent("killRegistration"); + mContext.sendBroadcast(killRegistration); } } } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SigninPage.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SigninPage.java index d6c0803..c5f37c8 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SigninPage.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/SigninPage.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; @@ -17,35 +18,40 @@ class SigninPage { Context mContext; Activity mActivity; + View signin; + String email, password; + EditText etEmail, etPassword; + String TAG = "SigninPage"; SigninPage(final Context mContext, final Activity mActivity) { this.mContext = mContext; this.mActivity = mActivity; - final View signin = LayoutInflater.from(mActivity.getApplication()).inflate(R.layout.signin_page, null); - final String[] email = new String[1]; - final String[] password = new String[1]; + signin = LayoutInflater.from(mActivity.getApplication()).inflate(R.layout.signin_page, null); Button BSignIn = (Button) signin.findViewById(R.id.buttonSignIn); Button BRegister = (Button) signin.findViewById(R.id.buttonRegister); + Button BForgetPassword = (Button) signin.findViewById(R.id.buttonForgotPassword); + Button BTrakt = (Button) signin.findViewById(R.id.buttonTrakt); + Button BTmdb = (Button) signin.findViewById(R.id.buttonTmdb); mActivity.setContentView(signin); - final EditText etEmail = (EditText) signin.findViewById(R.id.editTextUsername); - final EditText etPassword = (EditText) signin.findViewById(R.id.editTextPassword); + etEmail = (EditText) signin.findViewById(R.id.editTextUsername); + etPassword = (EditText) signin.findViewById(R.id.editTextPassword); BSignIn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Check Credentials and respond accordingly - email[0] = String.valueOf(etEmail.getText()); - password[0] = String.valueOf(etPassword.getText()); - if (email[0].equals("") | password[0].equals("")) { + email = String.valueOf(etEmail.getText()); + password = String.valueOf(etPassword.getText()); + if (email.equals("") | password.equals("")) { Toast.makeText(mContext, "Email or password can't be empty!", Toast.LENGTH_SHORT).show(); - } else if (!email[0].contains("@")) { + } else if (!email.contains("@")) { Toast.makeText(mContext, "Please enter correct email address", Toast.LENGTH_SHORT).show(); } else { - System.out.println(email[0] + " and " + password[0]); + Log.i(TAG, email + " and " + password); String[] signInDetails = new String[2]; - signInDetails[0] = email[0]; - signInDetails[1] = password[0]; + signInDetails[0] = email; + signInDetails[1] = password; SignInHttpBuilder sBuilder = new SignInHttpBuilder(mContext); sBuilder.execute(signInDetails); } @@ -54,7 +60,37 @@ public void onClick(View v) { BRegister.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - RegisterPage register = new RegisterPage(mContext, mActivity); + mContext.startActivity(new Intent(mContext, RegistrationActivity.class)); + } + }); + + BForgetPassword.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent resetIntent = new Intent(mContext, ResetPasswordActivity.class); + mContext.startActivity(resetIntent); + } + }); + + BTrakt.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent thirdPartySignup = new Intent(mContext, ThirdPartySignupActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("thirdParty", "TraktTV"); + thirdPartySignup.putExtras(bundle); + mContext.startActivity(thirdPartySignup); + } + }); + + BTmdb.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent thirdPartySignup = new Intent(mContext, ThirdPartySignupActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("thirdParty", "The Movie DB"); + thirdPartySignup.putExtras(bundle); + mContext.startActivity(thirdPartySignup); } }); } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/StartActivity.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/StartActivity.java index cf44ce8..8c68efe 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/StartActivity.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/StartActivity.java @@ -1,12 +1,18 @@ package org.example.team_pigeon.movie_pigeon; +import android.Manifest; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; import android.os.Environment; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; +import android.widget.Toast; import java.io.BufferedReader; import java.io.File; @@ -19,6 +25,7 @@ public class StartActivity extends AppCompatActivity { private final GlobalReceiver globalReceiver = new GlobalReceiver(); + private final int PERMISSIONS_WRITE_EXTERNAL_STORAGE = 0; private File credential; private FileInputStream fis; private String token = ""; @@ -28,7 +35,6 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //Disable Landscape Mode setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - credential = new File(Environment.getExternalStorageDirectory() + "/MoviePigeon/Signin/credential"); // set up broadcast globalReceiver to receive request from background thread IntentFilter filter = new IntentFilter(); @@ -36,6 +42,44 @@ protected void onCreate(Bundle savedInstanceState) { filter.addAction("automaticSignin"); registerReceiver(globalReceiver, filter); + //Check permission for android 6.0+ devices + int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); + //Ask for permission if there is no permission + if(permissionCheck != PackageManager.PERMISSION_GRANTED){ + Toast.makeText(this, "Please give us permission to save important in your device, otherwise this app may not able to run.", Toast.LENGTH_LONG).show(); + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},PERMISSIONS_WRITE_EXTERNAL_STORAGE); + } + else{ + //Access credential if there is write to external storage permission + loadCredential(); + } + + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { + switch (requestCode) { + case PERMISSIONS_WRITE_EXTERNAL_STORAGE: { + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + loadCredential(); + } else { + //Close the app + System.exit(0); + } + return; + } + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(globalReceiver); + } + + private void loadCredential(){ + credential = new File(Environment.getExternalStorageDirectory() + "/MoviePigeon/Signin/credential"); if (credential.exists()) { // sign-in automatically // read token from file first @@ -55,12 +99,6 @@ protected void onCreate(Bundle savedInstanceState) { } } - @Override - protected void onDestroy() { - super.onDestroy(); - unregisterReceiver(globalReceiver); - } - String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/ThirdPartySignupActivity.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/ThirdPartySignupActivity.java new file mode 100644 index 0000000..8ade8da --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/ThirdPartySignupActivity.java @@ -0,0 +1,202 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * Created by Guo Mingxuan on 7/3/2017. + */ + +public class ThirdPartySignupActivity extends AppCompatActivity { + View mainView; + TextView title, passwordTitle; + EditText inputField, passwordField; + String thirdParty, username, password; + GlobalReceiver globalReceiver = new GlobalReceiver(); + Button BConfirm, BBack; + String[] checkBundle; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mainView = getLayoutInflater().inflate(R.layout.activity_third_party_signup, null); + setContentView(mainView); + + IntentFilter filter = new IntentFilter(); + filter.addAction("dataPullingSuccess"); + registerReceiver(globalReceiver, filter); + + + thirdParty = getIntent().getExtras().getString("thirdParty"); + + inputField = (EditText) mainView.findViewById(R.id.tpsInput); + passwordField = (EditText) mainView.findViewById(R.id.tpsPassword); + title = (TextView) mainView.findViewById(R.id.tpsTitle); + title.setText("Username/Email/ID for " + thirdParty); + passwordTitle = (TextView) mainView.findViewById(R.id.tpsPasswordTitle); + BConfirm = (Button) mainView.findViewById(R.id.tpsConfirmButton); + BBack = (Button) mainView.findViewById(R.id.tpsBackButton); + + if (thirdParty.equals("TraktTV")) { + passwordTitle.setVisibility(View.GONE); + passwordField.setVisibility(View.GONE); + } else if (thirdParty.equals("The Movie DB")) { + // nothing right now + } + + BConfirm.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (thirdParty.equals("TraktTV")) { + username = String.valueOf(inputField.getText()); + if (username.equals("")) { + Toast.makeText(getApplicationContext(), "Username or email can't be empty", Toast.LENGTH_SHORT).show(); + } else { + checkBundle = new String[2]; + checkBundle[0] = username; + checkBundle[1] = thirdParty; + new TPSWorkingThread(getApplicationContext()).execute(checkBundle); + Toast.makeText(getApplicationContext(), "Checking with " + thirdParty + " server", Toast.LENGTH_SHORT).show(); + } + } else if (thirdParty.equals("The Movie DB")) { + username = String.valueOf(inputField.getText()); + password = String.valueOf(passwordField.getText()); + if (username.equals("") || password.equals("")) { + Toast.makeText(getApplicationContext(), "Please fill in all fields", Toast.LENGTH_SHORT).show(); + } else { + checkBundle = new String[3]; + checkBundle[0] = username; + checkBundle[1] = thirdParty; + checkBundle[2] = password; + new TPSWorkingThread(getApplicationContext()).execute(checkBundle); + Toast.makeText(getApplicationContext(), "Checking with " + thirdParty + " server", Toast.LENGTH_SHORT).show(); + } + } + } + }); + + BBack.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(globalReceiver); + } +} + +class TPSWorkingThread extends AsyncTask { + Context mContext; + String userInfo, thirdParty, password; + String url=""; + String TAG = "TPSWT"; + HttpURLConnection connection; + private boolean validated, connectionError = false; + String charset = java.nio.charset.StandardCharsets.UTF_8.name(); + String line, serverResponse; + + TPSWorkingThread(Context context) { + mContext = context; + } + + @Override + protected Void doInBackground(String... params) { + userInfo = params[0]; + thirdParty = params[1]; + Log.i(TAG, "User info and tp are " + userInfo + " " + thirdParty); + if (thirdParty.equals("TraktTV")) { + url = "http://128.199.167.57:8080/api/traktTV"; + password = "NONE"; + } else if (thirdParty.equals("The Movie DB")) { + url = "http://128.199.167.57:8080/api/tmdb"; + password = params[2]; + } else { + Log.e(TAG, "Wrong type of third party"); + } + + validate(); + return null; + } + + private void validate() { + try { + connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("Accept-Charset", charset); + connection.setRequestProperty("username", userInfo); + if (thirdParty.equals("The Movie DB")) { + connection.setRequestProperty("password", password); + } + + connection.connect(); + + Log.i(TAG, "Finished sending to server"); + + int status = connection.getResponseCode(); + Log.i(TAG, "response status transactionId is " + status); + + if (status == 200) { + InputStream response = connection.getInputStream(); + // process the response + BufferedReader br = new BufferedReader(new InputStreamReader(response)); + StringBuffer sb = new StringBuffer(); + Log.i(TAG, "Starting to read response"); + while ((line = br.readLine()) != null) { + sb.append(line + "\n"); + serverResponse = "Registration Response>>>" + line; + Log.i(TAG, serverResponse); + } + if (serverResponse.contains("true")) { + validated = true; + } + } else { + connectionError = true; + Log.e(TAG, "Error code " + status); + } + + } catch (IOException e) { + e.printStackTrace(); + connectionError = true; + Log.e(TAG,"Unable to connect to server"); + } + } + + @Override + protected void onPostExecute(Void v) { + if (connectionError) { + Toast.makeText(mContext, "Unable to connect to server", Toast.LENGTH_SHORT).show(); + } else if (!validated) { + Toast.makeText(mContext, "Can't find the user you entered", Toast.LENGTH_SHORT).show(); + } else { + Intent intent = new Intent("dataPullingSuccess"); + Bundle bundle = new Bundle(); + bundle.putString("ThirdParty", thirdParty); + bundle.putString("UserInfo", userInfo); + bundle.putString("ThirdPartyPassword", password); + intent.putExtras(bundle); + mContext.sendBroadcast(intent); + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/UserInfoSingleton.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/UserInfoSingleton.java new file mode 100644 index 0000000..2cf6e89 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/UserInfoSingleton.java @@ -0,0 +1,207 @@ +package org.example.team_pigeon.movie_pigeon; + +import android.content.Context; +import android.os.AsyncTask; +import android.os.Environment; +import android.util.Log; +import android.widget.Toast; + +import com.google.gson.stream.JsonReader; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * Created by Guo Mingxuan on 16/3/2017. + */ + +class UserInfoSingleton { + private static UserInfoSingleton instance = null; + private static String TAG = "UserInfo"; + private static String email, username; + private static String token; + private File credential = new File(Environment.getExternalStorageDirectory() + "/MoviePigeon/Signin/credential"); + + protected UserInfoSingleton() { + } + + static UserInfoSingleton getInstance() { + if (instance == null) { + instance = new UserInfoSingleton(); + instance.reset(); + } + return instance; + } + + String getEmail() { + return email; + } + + String getUsername() { + return username; + } + + String getToken() { + return token; + } + + void reset() { + token = getStringFromFile(credential.getAbsolutePath()); + new UserInfoGetter().execute(); + } + + String getStringFromFile (String filePath) { + File fl = new File(filePath); + FileInputStream fin = null; + String result = null; + try { + fin = new FileInputStream(fl); + result = convertStreamToString(fin); + fin.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + String convertStreamToString(InputStream is) { + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + StringBuilder sb = new StringBuilder(); + String line = null; + try { + while ((line = reader.readLine()) != null) { + sb.append(line).append("\n"); + } + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return sb.toString(); + } + + static class UserInfoGetter extends AsyncTask { + private HttpURLConnection connection; + private String token, serverResponse; + private String charset = java.nio.charset.StandardCharsets.UTF_8.name(); + private boolean connectionError = false; + private String[] userInfo = new String[2]; + + @Override + protected Void doInBackground(Void... params) { + token = UserInfoSingleton.getInstance().getToken(); + request(); + return null; + } + + private void request() { + String url = "http://128.199.167.57:8080/api/users/"; + + try { + connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("Authorization", "Bearer " + token); + connection.setRequestProperty("Accept-Charset", charset); + + Log.i(TAG, "Token is " + token); + + connection.connect(); + + Log.i(TAG, "Finished sending to server"); + + int status = connection.getResponseCode(); + Log.i(TAG, "get user info status is " + status); + + if (status == 200) { + InputStream response = connection.getInputStream(); + // process the response + BufferedReader br = new BufferedReader(new InputStreamReader(response)); + StringBuffer sb = new StringBuffer(); + Log.i(TAG, "Starting to read response"); + String line; + while ((line = br.readLine()) != null) { + sb.append(line + "\n"); + serverResponse = line; + Log.i(TAG, "Registration Response>>>" + serverResponse); + } + try { + JsonReader reader = new JsonReader(new StringReader(serverResponse)); + reader.beginObject(); + while (reader.hasNext()) { + String readStr = reader.nextName(); + if (readStr.equals("email")) { + userInfo[0] = reader.nextString(); + Log.i(TAG, userInfo[0]); + } else if (readStr.equals("username")) { + userInfo[1] = reader.nextString(); + Log.i(TAG, userInfo[1]); + } else { + reader.skipValue(); //avoid some unhandled events + } + } + reader.endObject(); + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } else if (status == 400) { + Log.i(TAG, "Error code " + status); + InputStream response = connection.getErrorStream(); + // process the response + BufferedReader br = new BufferedReader(new InputStreamReader(response)); + StringBuffer sb = new StringBuffer(); + Log.i(TAG, "Starting to read response"); + String line, serverResponse = ""; + while ((line = br.readLine()) != null) { + sb.append(line + "\n"); + serverResponse = "Retrieve userInfo Response>>>" + line; + Log.i(TAG, serverResponse); + } + } else if (status == 401) { + Log.i(TAG, "Error code " + status); + InputStream response = connection.getErrorStream(); + // process the response + BufferedReader br = new BufferedReader(new InputStreamReader(response)); + StringBuffer sb = new StringBuffer(); + Log.i(TAG, "Starting to read response"); + String line, serverResponse = ""; + while ((line = br.readLine()) != null) { + sb.append(line + "\n"); + serverResponse = "Retrieve userInfo Response>>>" + line; + Log.i(TAG, serverResponse); + } + } else { + connectionError = true; + Log.i(TAG, "Error code " + status); + } + + } catch (IOException e) { + e.printStackTrace(); + connectionError = true; + Log.e(TAG, "Unable to connect to server"); + } + } + + @Override + protected void onPostExecute(Void v) { + if (connectionError) { + Log.e(TAG, "Error in retrieving user info"); + } else { + Log.i(TAG, "Getting user info successful"); + email = userInfo[0]; + username = userInfo[1]; + } + } + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/CinemaAdapter.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/CinemaAdapter.java new file mode 100644 index 0000000..8d35bbb --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/CinemaAdapter.java @@ -0,0 +1,57 @@ +package org.example.team_pigeon.movie_pigeon.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import org.example.team_pigeon.movie_pigeon.R; +import org.example.team_pigeon.movie_pigeon.models.Cinema; + +import java.util.ArrayList; + +/** + * Created by SHENGX on 2017/3/4. + */ + +public class CinemaAdapter extends BaseAdapter{ + private ArrayList list; + private Context mContext; + + public CinemaAdapter(Context context, ArrayList list){ + this.list = list; + mContext = context; + } + @Override + public int getCount() { + return list.size(); + } + + @Override + public Cinema getItem(int position) { + return list.get(position-1); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater layoutInflater = LayoutInflater.from(mContext); + convertView = layoutInflater.inflate(R.layout.spinner_list_item,null); + if(convertView != null){ + TextView name = (TextView) convertView.findViewById(R.id.txt_spinner); + if(position==0){ + name.setText("Please Choose Location"); + } + else { + name.setText(list.get(position-1).getName()); + } + } + return convertView; + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/HomeViewPagerAdapter.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/HomeViewPagerAdapter.java index cd6574d..60d0f6f 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/HomeViewPagerAdapter.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/HomeViewPagerAdapter.java @@ -6,6 +6,7 @@ import org.example.team_pigeon.movie_pigeon.HomePageActivity; import org.example.team_pigeon.movie_pigeon.MeFragment; +import org.example.team_pigeon.movie_pigeon.CinemaFragment; import org.example.team_pigeon.movie_pigeon.RecommendationFragment; /** @@ -13,18 +14,20 @@ */ public class HomeViewPagerAdapter extends FragmentPagerAdapter { - private final int PAGER_COUNT = 2; + private final int PAGER_COUNT = 3; private RecommendationFragment recommendationFragment = null; private MeFragment meFragment = null; + private CinemaFragment cinemaFragment = null; public HomeViewPagerAdapter(FragmentManager fragmentManager){ super(fragmentManager); recommendationFragment = new RecommendationFragment(); meFragment = new MeFragment(); + cinemaFragment = new CinemaFragment(); } @Override public Fragment getItem(int position) { - Fragment fragment = null; + Fragment fragment = null; switch (position){ case HomePageActivity.PAGE_RECOMMENDATION: fragment = recommendationFragment; @@ -32,6 +35,9 @@ public Fragment getItem(int position) { case HomePageActivity.PAGE_ME: fragment = meFragment; break; + case HomePageActivity.PAGE_SHOWING: + fragment = cinemaFragment; + break; } return fragment; } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/HorizontalListAdapter.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/HorizontalListAdapter.java new file mode 100644 index 0000000..f296582 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/HorizontalListAdapter.java @@ -0,0 +1,83 @@ +package org.example.team_pigeon.movie_pigeon.adapters; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.GridView; +import android.widget.ImageView; +import android.widget.RatingBar; +import android.widget.TextView; + +import com.nostra13.universalimageloader.core.DisplayImageOptions; +import com.nostra13.universalimageloader.core.ImageLoader; + +import org.example.team_pigeon.movie_pigeon.R; +import org.example.team_pigeon.movie_pigeon.configs.ImageConfig; +import org.example.team_pigeon.movie_pigeon.models.Movie; + +import java.util.ArrayList; + +/** + * Created by SHENGX on 2017/3/11. + */ + +public class HorizontalListAdapter extends BaseAdapter { + private ArrayList movies; + private Context mContext; + private Movie movie; + private ImageLoader imageLoader = ImageLoader.getInstance(); + private DisplayImageOptions options = new ImageConfig().getDisplayImageOption(); + + public HorizontalListAdapter(Context context, ArrayList movies){ + this.movies = movies; + mContext=context; + } + @Override + public int getCount() { + return movies.size(); + } + + @Override + public Movie getItem(int position) { + return movies.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + public void updateMovieItemToAdapter(Movie movieNew, int position) { + movies.set(position, movieNew); + this.notifyDataSetChanged(); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + LayoutInflater layoutInflater = LayoutInflater.from(mContext); + if(convertView == null){ + convertView = layoutInflater.inflate(R.layout.horizontal_list_item,parent,false); + viewHolder = new ViewHolder(); + viewHolder.txt_title = (TextView) convertView.findViewById(R.id.text_title_horizontal_list_item); + viewHolder.image_poster = (ImageView) convertView.findViewById(R.id.image_poster_horizontal_list_item); + convertView.setTag(viewHolder); + } + else{ + viewHolder = (ViewHolder) convertView.getTag(); + } + movie = movies.get(position); + viewHolder.txt_title.setText(movie.getTitle()); + imageLoader.displayImage(movies.get(position).getPosterURL(), viewHolder.image_poster, options); + return convertView; + } + + + private static class ViewHolder { + TextView txt_title; + ImageView image_poster; + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/MovieListAdapter.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/MovieListAdapter.java index c45ee2f..c2324aa 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/MovieListAdapter.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/MovieListAdapter.java @@ -1,48 +1,74 @@ package org.example.team_pigeon.movie_pigeon.adapters; import android.content.Context; +import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; +import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import org.example.team_pigeon.movie_pigeon.R; +import org.example.team_pigeon.movie_pigeon.configs.ImageConfig; import org.example.team_pigeon.movie_pigeon.models.Movie; import java.util.ArrayList; +import java.util.TreeSet; public class MovieListAdapter extends BaseAdapter { + private static final int TYPE_MOVIE = 0; + private static final int TYPE_SEPARATOR = 1; private ArrayList movieList; + private TreeSet separatorSet = new TreeSet(); private Context mContext; private Movie movie; private ImageLoader imageLoader = ImageLoader.getInstance(); + private DisplayImageOptions options = new ImageConfig().getDisplayImageOption(); - public MovieListAdapter(ArrayListmovieList,Context mContext) { + public MovieListAdapter(ArrayList movieList, Context mContext) { this.mContext = mContext; this.movieList = movieList; } + @Override + public int getItemViewType(int position) { + return separatorSet.contains(position) ? TYPE_SEPARATOR : TYPE_MOVIE; + } + + @Override + public int getViewTypeCount() { + return 2; + } + public void addListItemToAdapter(ArrayList list) { movieList.addAll(list); this.notifyDataSetChanged(); } + public void addHeaderToAdapter(final Movie separator) { + movieList.add(separator); + separatorSet.add(movieList.size() - 1); + this.notifyDataSetChanged(); + } + public void removeMovieItemToAdapter(int position) { movieList.remove(position); this.notifyDataSetChanged(); } public void addMovieItemToAdapter(Movie movie, int position) { - movieList.add(position,movie); + movieList.add(position, movie); this.notifyDataSetChanged(); } public void updateMovieItemToAdapter(Movie movieNew, int position) { - movieList.set(position,movieNew); + movieList.set(position, movieNew); this.notifyDataSetChanged(); } @@ -63,33 +89,36 @@ public long getItemId(int position) { @Override public View getView(int position, View convertView, ViewGroup parent) { - ViewHolder viewHolder; + movie = movieList.get(position); + ViewHolder viewHolder = null; + int type = getItemViewType(position); if (convertView == null) { - convertView = LayoutInflater.from(mContext).inflate(R.layout.movie_list_item, parent, false); viewHolder = new ViewHolder(); - viewHolder.txt_title = (TextView) convertView.findViewById(R.id.text_movie_list_title); - viewHolder.image_poster = (ImageView) convertView.findViewById(R.id.image_movie_list_poster); + switch (type) { + case TYPE_MOVIE: + convertView = LayoutInflater.from(mContext).inflate(R.layout.movie_list_item, null); + viewHolder.txt_title = (TextView) convertView.findViewById(R.id.text_movie_list_title); + viewHolder.image_poster = (ImageView) convertView.findViewById(R.id.image_movie_list_poster); + break; + case TYPE_SEPARATOR: + convertView = LayoutInflater.from(mContext).inflate(R.layout.header_all_search_list, null); + convertView.setClickable(false); + break; + } convertView.setTag(viewHolder); - } - else { + } else { viewHolder = (ViewHolder) convertView.getTag(); } - movie = movieList.get(position); - viewHolder.txt_title.setText(movie.getTitle()); - - if(movie.getPosterURL() != null){ - viewHolder.image_poster.setImageResource(R.mipmap.image_poster_loading); - imageLoader.displayImage(movieList.get(position).getPosterURL(),viewHolder.image_poster); - } - else{ - viewHolder.image_poster.setImageResource(R.mipmap.image_no_poster_found); + if (viewHolder.txt_title != null) { + viewHolder.txt_title.setText(movie.getTitle()); + imageLoader.displayImage(movieList.get(position).getPosterURL(), viewHolder.image_poster, options); } return convertView; } - private static class ViewHolder { - TextView txt_title; - ImageView image_poster; - } + private static class ViewHolder { + TextView txt_title; + ImageView image_poster; } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/NowShowingListAdapter.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/NowShowingListAdapter.java new file mode 100644 index 0000000..834b8a2 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/NowShowingListAdapter.java @@ -0,0 +1,143 @@ +package org.example.team_pigeon.movie_pigeon.adapters; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.BaseAdapter; +import android.widget.GridView; +import android.widget.ImageView; +import android.widget.RatingBar; +import android.widget.TextView; + +import com.nostra13.universalimageloader.core.DisplayImageOptions; +import com.nostra13.universalimageloader.core.ImageLoader; + +import org.example.team_pigeon.movie_pigeon.DisplayActivity; +import org.example.team_pigeon.movie_pigeon.R; +import org.example.team_pigeon.movie_pigeon.configs.ImageConfig; +import org.example.team_pigeon.movie_pigeon.costomizedViews.MultipleColGridView; +import org.example.team_pigeon.movie_pigeon.models.Movie; + +import java.util.ArrayList; +import java.util.Date; + +/** + * Created by SHENGX on 2017/3/1. + */ + +public class NowShowingListAdapter extends BaseAdapter { + private ArrayList movieList; + private Context mContext; + private Movie movie; + private Date date; + private ImageLoader imageLoader = ImageLoader.getInstance(); + private DisplayImageOptions options = new ImageConfig().getDisplayImageOption(); + + public NowShowingListAdapter(ArrayList movieList, Context mContext) { + this.mContext = mContext; + this.movieList = movieList; + } + + public void addListItemToAdapter(ArrayList list) { + movieList.addAll(list); + this.notifyDataSetChanged(); + } + + public void removeMovieItemToAdapter(int position) { + movieList.remove(position); + this.notifyDataSetChanged(); + } + + public void addMovieItemToAdapter(Movie movie, int position) { + movieList.add(position, movie); + this.notifyDataSetChanged(); + } + + public void updateMovieItemToAdapter(Movie movieNew, int position) { + movieList.set(position, movieNew); + this.notifyDataSetChanged(); + } + + @Override + public int getCount() { + return movieList.size(); + } + + @Override + public Movie getItem(int position) { + return movieList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + final int parentPosition = position; + if (convertView == null) { + convertView = LayoutInflater.from(mContext).inflate(R.layout.now_showing_list_item, parent, false); + viewHolder = new ViewHolder(); + viewHolder.txt_title = (TextView) convertView.findViewById(R.id.text_now_showing_list_title); + viewHolder.image_poster = (ImageView) convertView.findViewById(R.id.image_now_showing_list_poster); + viewHolder.txt_length = (TextView) convertView.findViewById(R.id.text_now_showing_list_length); + viewHolder.txt_special = (TextView) convertView.findViewById(R.id.text_now_showing_list_special); + viewHolder.grid_schedule = (MultipleColGridView) convertView.findViewById(R.id.grid_schedule); + viewHolder.ratingBar = (RatingBar) convertView.findViewById(R.id.ratingBar_now_showing); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + movie = movieList.get(position); + viewHolder.txt_title.setText(movie.getTitle()); + viewHolder.txt_special.setText(movie.getSchedule().get(0).getType()); + viewHolder.txt_length.setText(movie.getLength() + " Min"); + setRatingBar(viewHolder.ratingBar, movie); + viewHolder.grid_schedule.setAdapter(new ArrayAdapter<>(this.mContext, R.layout.now_showing_schedule_cell, movie.getShowTimes())); + viewHolder.grid_schedule.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + startActivity(parentPosition); + } + }); + imageLoader.displayImage(movieList.get(position).getPosterURL(), viewHolder.image_poster, options); + return convertView; + } + + private void startActivity(int position){ + Intent displayActivityIntent = new Intent(this.mContext, DisplayActivity.class); + Bundle arguments = new Bundle(); + arguments.putSerializable("movie",movieList.get(position)); + arguments.putString("type", "moviePage"); + arguments.putInt("position",position); + arguments.putString("title", movieList.get(position).getTitle()); + displayActivityIntent.putExtra("bundle", arguments); + this.mContext.startActivity(displayActivityIntent); + } + + private void setRatingBar(RatingBar ratingBar, Movie movie) { + if (!movie.getPublicRatingses().isEmpty()) { + Float ratting = Float.valueOf(movie.getPublicRatingses().get(0).getScore()); + ratingBar.setNumStars(5); + ratingBar.setRating(ratting / 2); + } else { + ratingBar.setVisibility(View.INVISIBLE); + } + } + + private static class ViewHolder { + TextView txt_title; + TextView txt_length; + TextView txt_special; + ImageView image_poster; + MultipleColGridView grid_schedule; + RatingBar ratingBar; + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/ScheduleListAdapter.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/ScheduleListAdapter.java new file mode 100644 index 0000000..512f328 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/adapters/ScheduleListAdapter.java @@ -0,0 +1,113 @@ +package org.example.team_pigeon.movie_pigeon.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.BaseAdapter; +import android.widget.TextView; + + +import org.example.team_pigeon.movie_pigeon.R; +import org.example.team_pigeon.movie_pigeon.costomizedViews.MultipleColGridView; +import org.example.team_pigeon.movie_pigeon.models.Schedule; + +import java.util.ArrayList; +import java.util.TreeSet; + +public class ScheduleListAdapter extends BaseAdapter { + private static final int TYPE_SCHEDULE = 0; + private static final int TYPE_CINEMA = 1; + private ArrayList scheduleList; + private TreeSet cinemaSet = new TreeSet(); + private Context mContext; + private Schedule schedule; + + public ScheduleListAdapter(ArrayList scheduleList, Context mContext) { + this.mContext = mContext; + this.scheduleList = scheduleList; + } + + @Override + public int getItemViewType(int position) { + return cinemaSet.contains(position) ? TYPE_CINEMA : TYPE_SCHEDULE; + } + + @Override + public int getViewTypeCount() { + return 2; + } + + public void addCinemaToAdapter(final Schedule cinema) { + scheduleList.add(cinema); + cinemaSet.add(scheduleList.size() - 1); + this.notifyDataSetChanged(); + } + + + public void addScheduleItemToAdapter(Schedule schedule) { + scheduleList.add(schedule); + this.notifyDataSetChanged(); + } + + @Override + public int getCount() { + return scheduleList.size(); + } + + @Override + public Schedule getItem(int position) { + return scheduleList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + schedule = scheduleList.get(position); + ViewHolder viewHolder = null; + int type = getItemViewType(position); + if (convertView == null) { + viewHolder = new ViewHolder(); + switch (type) { + case TYPE_SCHEDULE: + convertView = LayoutInflater.from(mContext).inflate(R.layout.type_item_schedule, null); + viewHolder.txt_title = (TextView) convertView.findViewById(R.id.text_type_schedule); + viewHolder.grid = (MultipleColGridView) convertView.findViewById(R.id.grid_showtime_schedule); + break; + case TYPE_CINEMA: + convertView = LayoutInflater.from(mContext).inflate(R.layout.cinema_item_schedule, null); + viewHolder.txt_title = (TextView) convertView.findViewById(R.id.text_cinema_name); + break; + } + convertView.setClickable(false); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + switch (type) { + case TYPE_SCHEDULE: + if(!schedule.getType().equals("")) { + viewHolder.txt_title.setText(schedule.getType()); + } + else{ + viewHolder.txt_title.setText("2D"); + } + viewHolder.grid.setAdapter(new ArrayAdapter<>(this.mContext, R.layout.now_showing_schedule_cell, schedule.getShowTimeArray())); + break; + case TYPE_CINEMA: + viewHolder.txt_title.setText(schedule.getCinemaName()); + } + + return convertView; + } + + private static class ViewHolder { + TextView txt_title; + MultipleColGridView grid; + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/configs/ImageConfig.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/configs/ImageConfig.java new file mode 100644 index 0000000..f4eaa02 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/configs/ImageConfig.java @@ -0,0 +1,21 @@ +package org.example.team_pigeon.movie_pigeon.configs; + +import com.nostra13.universalimageloader.core.DisplayImageOptions; + +import org.example.team_pigeon.movie_pigeon.R; + +/** + * Created by SHENGX on 2017/3/3. + */ + +public class ImageConfig { + static DisplayImageOptions options = new DisplayImageOptions.Builder() + .showImageForEmptyUri(R.mipmap.image_no_poster_found) + .showImageOnLoading(R.mipmap.image_poster_loading) + .cacheInMemory(true) + .cacheOnDisk(true) + .build(); + public DisplayImageOptions getDisplayImageOption(){ + return options; + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/costomizedViews/CenterTextView.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/costomizedViews/CenterTextView.java new file mode 100644 index 0000000..f7909c4 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/costomizedViews/CenterTextView.java @@ -0,0 +1,46 @@ +package org.example.team_pigeon.movie_pigeon.costomizedViews; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.widget.TextView; + +/** + * Created by SHENGX on 2017/3/12. + */ + +public class CenterTextView extends TextView +{ + private StaticLayout myStaticLayout; + private TextPaint textPaint; + + public CenterTextView(Context context, AttributeSet attrs) + { + super(context, attrs); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) + { + super.onSizeChanged(w, h, oldw, oldh); + initView(); + } + + private void initView() + { + textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + textPaint.setTextSize(getTextSize()); + textPaint.setColor(getCurrentTextColor()); + myStaticLayout = new StaticLayout(getText(), textPaint, getWidth(), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + } + + @Override + protected void onDraw(Canvas canvas) + { + myStaticLayout.draw(canvas); + } +} \ No newline at end of file diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/costomizedViews/MultipleColGridView.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/costomizedViews/MultipleColGridView.java new file mode 100644 index 0000000..558a516 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/costomizedViews/MultipleColGridView.java @@ -0,0 +1,30 @@ +package org.example.team_pigeon.movie_pigeon.costomizedViews; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.GridView; + +/** + * Created by SHENGX on 2017/3/19. + */ + +public class MultipleColGridView extends GridView { + public MultipleColGridView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public MultipleColGridView(Context context) { + super(context); + } + + public MultipleColGridView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); + super.onMeasure(widthMeasureSpec, expandSpec); + } +} + diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/Cinema.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/Cinema.java new file mode 100644 index 0000000..2b4e155 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/Cinema.java @@ -0,0 +1,45 @@ +package org.example.team_pigeon.movie_pigeon.models; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; + +/** + * Created by SHENGX on 2017/3/4. + */ + +public class Cinema implements Serializable{ + @Expose + @SerializedName("cinema_id") + private String id; + @Expose + @SerializedName("cinema_name") + private String name; + @Expose + private String provider; + + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/Movie.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/Movie.java index 3dcd146..bd9844c 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/Movie.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/Movie.java @@ -4,15 +4,11 @@ * Created by SHENGX on 2017/2/3. */ -import android.os.Parcelable; - import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; import java.io.Serializable; import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; public class Movie implements Serializable{ @Expose @@ -47,7 +43,7 @@ public class Movie implements Serializable{ private String genres; @Expose @SerializedName("public_ratings") - private ArrayList publicRatingses; + private ArrayList publicRatings; @Expose @SerializedName("user_ratings") private ArrayList userRating; @@ -55,9 +51,15 @@ public class Movie implements Serializable{ @SerializedName("bookmarks") private ArrayList userBookmark; private String tempRating; + @Expose + @SerializedName("showings") + private ArrayList schedule; + private ArrayList showTimes; private boolean isRated; private boolean isReleased; private boolean isBookmarked; + @Expose + private boolean isShowing; public Movie(String title,String movieID){ this.title = title; @@ -185,11 +187,11 @@ public void setGenres(String genres) { } public ArrayList getPublicRatingses() { - return publicRatingses; + return publicRatings; } - public void setPublicRatingses(ArrayList publicRatingses) { - this.publicRatingses = publicRatingses; + public void setPublicRatingses(ArrayList publicRatings) { + this.publicRatings = publicRatings; } public ArrayList getUserRating() { @@ -215,4 +217,28 @@ public ArrayList getUserBookmark() { public void setUserBookmark(ArrayList userBookmark) { this.userBookmark = userBookmark; } + + public ArrayList getSchedule() { + return schedule; + } + + public void setSchedule(ArrayList schedule) { + this.schedule = schedule; + } + + public ArrayList getShowTimes() { + return showTimes; + } + + public void setShowTimes(ArrayList showTimes) { + this.showTimes = showTimes; + } + + public boolean isShowing() { + return isShowing; + } + + public void setShowing(boolean showing) { + isShowing = showing; + } } diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/MovieWithCount.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/MovieWithCount.java index f252d90..78863b9 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/MovieWithCount.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/MovieWithCount.java @@ -14,7 +14,7 @@ public class MovieWithCount { @SerializedName("count") private int count; @Expose - @SerializedName("rows") + @SerializedName("raw") private ArrayList movies; public MovieWithCount(int count, ArrayList movies) { diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/PublicRating.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/PublicRating.java index ab6f74c..9c2d451 100644 --- a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/PublicRating.java +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/PublicRating.java @@ -23,7 +23,7 @@ public class PublicRating implements Serializable { @SerializedName("score") private String score; - public PublicRating(){}; + public PublicRating(){} public String getMovieID() { return movieID; diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/Schedule.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/Schedule.java new file mode 100644 index 0000000..1385e75 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/models/Schedule.java @@ -0,0 +1,100 @@ +package org.example.team_pigeon.movie_pigeon.models; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.ArrayList; + +/** + * Created by SHENGX on 2017/3/4. + */ +public class Schedule implements Serializable{ + @Expose + @SerializedName("movie_id") + private String movieId; + @Expose + @SerializedName("cinema_id") + private int cinemaId; + @Expose + @SerializedName("schedule") + private String time; + @Expose + @SerializedName("time") + private String showtime; + @Expose + private String type; + @Expose + @SerializedName("date") + private String date; + @Expose + @SerializedName("cinema_name") + private String cinemaName; + + private ArrayList showTimeArray; + + public String getMovieId() { + return movieId; + } + + public void setMovieId(String movieId) { + this.movieId = movieId; + } + + public int getCinemaId() { + return cinemaId; + } + + public void setCinemaId(int cinemaId) { + this.cinemaId = cinemaId; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getCinemaName() { + return cinemaName; + } + + public void setCinemaName(String cinemaName) { + this.cinemaName = cinemaName; + } + + public ArrayList getShowTimeArray() { + return showTimeArray; + } + + public void setShowTimeArray(ArrayList showTimeArray) { + this.showTimeArray = showTimeArray; + } + + public String getShowtime() { + return showtime; + } + + public void setShowtime(String showtime) { + this.showtime = showtime; + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/utils/TimeUtil.java b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/utils/TimeUtil.java new file mode 100644 index 0000000..7ff0a6f --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/java/org/example/team_pigeon/movie_pigeon/utils/TimeUtil.java @@ -0,0 +1,45 @@ +package org.example.team_pigeon.movie_pigeon.utils; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +/** + * Created by SHENGX on 2017/3/18. + */ + +public class TimeUtil { + + public List getDateList(){ + List week = new ArrayList<>(); + Calendar timeToAdd = Calendar.getInstance(); + Date date; + for(int i=0;i<7;i++){ + date = timeToAdd.getTime(); + week.add(date); + timeToAdd.add(Calendar.DATE,1); + } + return week; + } + + //Used by cinema page + public List getDateListToString_MMDDE(List week){ + List stringList = new ArrayList<>(); + stringList.add("Please Choose Date"); + for(Date date:week){ + stringList.add(new SimpleDateFormat("MM-dd E", Locale.ENGLISH).format(date)); + } + return stringList; + } + + public List getDateListToString_YYYYMMDD(List week){ + List stringList = new ArrayList<>(); + for(Date date:week){ + stringList.add(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).format(date)); + } + return stringList; + } +} diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_logout.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_logout.png new file mode 100644 index 0000000..5c59e7e Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_logout.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_now_showing.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_now_showing.png new file mode 100644 index 0000000..d389e49 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_now_showing.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_now_showing_normal.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_now_showing_normal.png new file mode 100644 index 0000000..c7e3c59 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_now_showing_normal.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_now_showing_selected.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_now_showing_selected.png new file mode 100644 index 0000000..2a1b21f Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_now_showing_selected.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_rating_star.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_rating_star.png new file mode 100644 index 0000000..248e534 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_rating_star.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_settings.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_settings.png new file mode 100644 index 0000000..5e675b1 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_settings.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_tmdb.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_tmdb.png new file mode 100644 index 0000000..952a9a9 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_tmdb.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_trakt.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_trakt.png new file mode 100644 index 0000000..9415eb0 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-hdpi/ic_trakt.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_logout.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_logout.png new file mode 100644 index 0000000..7f71db3 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_logout.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_now_showing.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_now_showing.png new file mode 100644 index 0000000..403521a Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_now_showing.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_now_showing_normal.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_now_showing_normal.png new file mode 100644 index 0000000..c1f37c7 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_now_showing_normal.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_now_showing_selected.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_now_showing_selected.png new file mode 100644 index 0000000..a675b1c Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_now_showing_selected.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_rating_star.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_rating_star.png new file mode 100644 index 0000000..a5f3acf Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_rating_star.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_settings.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_settings.png new file mode 100644 index 0000000..3345c53 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_settings.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_tmdb.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_tmdb.png new file mode 100644 index 0000000..9a901e8 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_tmdb.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_trakt.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_trakt.png new file mode 100644 index 0000000..3f7d6ad Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-mdpi/ic_trakt.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_logout.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_logout.png new file mode 100644 index 0000000..bc22d36 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_logout.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_now_showing.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_now_showing.png new file mode 100644 index 0000000..a4eec57 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_now_showing.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_now_showing_normal.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_now_showing_normal.png new file mode 100644 index 0000000..6a9059b Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_now_showing_normal.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_now_showing_selected.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_now_showing_selected.png new file mode 100644 index 0000000..43c7429 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_now_showing_selected.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_rating_star.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_rating_star.png new file mode 100644 index 0000000..154208f Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_rating_star.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_settings.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_settings.png new file mode 100644 index 0000000..41e2dc1 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_settings.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_tmdb.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_tmdb.png new file mode 100644 index 0000000..266fb3a Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_tmdb.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_trakt.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_trakt.png new file mode 100644 index 0000000..7ccdd27 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xhdpi/ic_trakt.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_logout.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_logout.png new file mode 100644 index 0000000..347ba1f Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_logout.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_now_showing.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_now_showing.png new file mode 100644 index 0000000..615b9b4 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_now_showing.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_now_showing_normal.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_now_showing_normal.png new file mode 100644 index 0000000..b92e068 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_now_showing_normal.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_now_showing_selected.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_now_showing_selected.png new file mode 100644 index 0000000..e8641aa Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_now_showing_selected.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_rating_star.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_rating_star.png new file mode 100644 index 0000000..6e62851 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_rating_star.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_settings.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_settings.png new file mode 100644 index 0000000..527b4a9 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_settings.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_tmdb.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_tmdb.png new file mode 100644 index 0000000..2f63fc2 Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_tmdb.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_trakt.png b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_trakt.png new file mode 100644 index 0000000..236078b Binary files /dev/null and b/frontend/Movie_Pigeon/app/src/main/res/drawable-xxhdpi/ic_trakt.png differ diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable/setting_menu.xml b/frontend/Movie_Pigeon/app/src/main/res/drawable/setting_menu.xml new file mode 100644 index 0000000..49a943f --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/res/drawable/setting_menu.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/frontend/Movie_Pigeon/app/src/main/res/drawable/tab_menu_now_showing.xml b/frontend/Movie_Pigeon/app/src/main/res/drawable/tab_menu_now_showing.xml new file mode 100644 index 0000000..94df553 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/res/drawable/tab_menu_now_showing.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/frontend/Movie_Pigeon/app/src/main/res/layout/activity_change_user_info.xml b/frontend/Movie_Pigeon/app/src/main/res/layout/activity_change_user_info.xml new file mode 100644 index 0000000..df61e8a --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/res/layout/activity_change_user_info.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/frontend/Movie_Pigeon/app/src/main/res/layout/activity_home_page.xml b/frontend/Movie_Pigeon/app/src/main/res/layout/activity_home_page.xml index 3c7597b..809ef5c 100644 --- a/frontend/Movie_Pigeon/app/src/main/res/layout/activity_home_page.xml +++ b/frontend/Movie_Pigeon/app/src/main/res/layout/activity_home_page.xml @@ -4,7 +4,9 @@ android:id="@+id/activity_home_page" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="org.example.team_pigeon.movie_pigeon.HomePageActivity"> + tools:context="org.example.team_pigeon.movie_pigeon.HomePageActivity" + android:focusable="true" + android:focusableInTouchMode="true"> + + diff --git a/frontend/Movie_Pigeon/app/src/main/res/layout/activity_reset_password.xml b/frontend/Movie_Pigeon/app/src/main/res/layout/activity_reset_password.xml new file mode 100644 index 0000000..a755bd3 --- /dev/null +++ b/frontend/Movie_Pigeon/app/src/main/res/layout/activity_reset_password.xml @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +