/* * Copyright (C) 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.apps.santatracker.presentquest; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.google.android.apps.santatracker.presentquest.model.Avatars; import com.google.android.apps.santatracker.presentquest.model.User; import com.google.android.apps.santatracker.presentquest.model.Workshop; import com.google.android.apps.santatracker.presentquest.ui.BounceInAnimator; import com.google.android.apps.santatracker.presentquest.util.Config; import com.google.android.apps.santatracker.presentquest.util.FuzzyLocationUtil; import com.google.android.apps.santatracker.presentquest.util.PreferencesUtil; import com.google.android.apps.santatracker.util.FontHelper; import com.google.android.apps.santatracker.util.MeasurementManager; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.UiSettings; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MapStyleOptions; import com.google.android.gms.maps.model.MarkerOptions; import com.google.firebase.analytics.FirebaseAnalytics; import java.util.List; public class ProfileActivity extends AppCompatActivity implements View.OnClickListener { private static final String TAG = "PQ(ProfileActivity)"; private static final int MAX_WORKSHOPS = 3; private static final int RC_MOVE_WORKSHOP = 9001; public static final String EXTRA_LEVELED_UP = "extra_leveled_up"; public static final String EXTRA_LAST_LOCATION = "extra_last_location"; private ImageView mAvatarView; private TextView mLevelTextView; private Workshop[] mWorkshops = new Workshop[MAX_WORKSHOPS]; private SupportMapFragment[] mMaps = new SupportMapFragment[MAX_WORKSHOPS]; private WorkshopMapListener[] mListeners = new WorkshopMapListener[MAX_WORKSHOPS]; private int mAvatarIndex; private User mUser; private PreferencesUtil mPrefs; private FirebaseAnalytics mAnalytics; private Config mConfig; private LatLng mLatLng; public static Intent getIntent(Context context, boolean leveledUp, LatLng location) { Intent intent = new Intent(context, ProfileActivity.class); intent.putExtra(EXTRA_LEVELED_UP, leveledUp); intent.putExtra(EXTRA_LAST_LOCATION, location); return intent; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); // [ANALYTICS] mAnalytics = FirebaseAnalytics.getInstance(this); MeasurementManager.recordScreenView(mAnalytics, getString(R.string.analytics_screen_pq_profile)); // Config mConfig = new Config(); // Get the current user mUser = User.get(); // Preferences mPrefs = new PreferencesUtil(this); mAvatarView = (ImageView) findViewById(R.id.profile_user_image); mLevelTextView = (TextView) findViewById(R.id.text_current_level); // Make text santa-style FontHelper.makeLobster((TextView) findViewById(R.id.text_workshops), false); // Set up lock text ((TextView) findViewById(R.id.workshop_2_lock_text)) .setText(getString(R.string.unlock_at_level, User.WORKSHOP_2_LEVEL)); ((TextView) findViewById(R.id.workshop_3_lock_text)) .setText(getString(R.string.unlock_at_level, User.WORKSHOP_3_LEVEL)); // Get position passed in if (getIntent() != null && getIntent().getParcelableExtra(EXTRA_LAST_LOCATION) != null) { mLatLng = getIntent().getParcelableExtra(EXTRA_LAST_LOCATION); } // Click listeners mAvatarView.setOnClickListener(this); findViewById(R.id.button_edit_1).setOnClickListener(this); findViewById(R.id.button_edit_2).setOnClickListener(this); findViewById(R.id.button_edit_3).setOnClickListener(this); findViewById(R.id.arrow_left).setOnClickListener(this); findViewById(R.id.arrow_right).setOnClickListener(this); // Get map fragments FragmentManager fm = getSupportFragmentManager(); mMaps[0] = (SupportMapFragment) fm.findFragmentById(R.id.map_workshop_1); mMaps[1] = (SupportMapFragment) fm.findFragmentById(R.id.map_workshop_2); mMaps[2] = (SupportMapFragment) fm.findFragmentById(R.id.map_workshop_3); // Load workshops loadWorkshops(); // Load map fragments for (int i = 0; i < MAX_WORKSHOPS; i++) { mListeners[i] = new WorkshopMapListener(this, mWorkshops[i]); mMaps[i].getMapAsync(mListeners[i]); } setUserProgress(); } @Override protected void onStart() { super.onStart(); // Special animation for leveling up if (getIntent() != null && getIntent().getBooleanExtra(EXTRA_LEVELED_UP, false)) { bounceInAvatar(); } } private void loadWorkshops() { // Get a list of all workshops in order of ascending ID (aka new to old). List<Workshop> all = Workshop.listAll(Workshop.class, "id ASC"); for (int i = 0; i < MAX_WORKSHOPS; i++) { if (all.size() > i) { mWorkshops[i] = all.get(i); } else { mWorkshops[i] = null; } } } private void refreshWorkshops() { loadWorkshops(); for (int i = 0; i < MAX_WORKSHOPS; i++) { mListeners[i].setWorkshop(mWorkshops[i]); } } private boolean isAnyWorkshopNearby() { for (Workshop workshop : mWorkshops) { if (workshop != null && Distance.between( mLatLng, workshop.getLatLng()) < mConfig.REACHABLE_RADIUS_METERS) { return true; } } return false; } private void setUserProgress() { mAvatarIndex = mUser.getLevel() - 1; mLevelTextView.setText(String.valueOf(mUser.getLevel())); mAvatarView.setImageDrawable(ContextCompat.getDrawable(this, mUser.getAvatar())); // Can't edit workshop 1 location until you've at least collected a present setEditButtonVisible(findViewById(R.id.button_edit_1), mPrefs.getHasCollectedPresent()); // Lock workshop 2 boolean secondWorkshopUnlocked = mUser.getMaxPresentsCollected() >= 2; if (secondWorkshopUnlocked) { findViewById(R.id.workshop_2_scrim).setVisibility(View.GONE); } else { findViewById(R.id.workshop_2_scrim).setVisibility(View.VISIBLE); } setEditButtonVisible(findViewById(R.id.button_edit_2), secondWorkshopUnlocked); // Lock workshop 3 boolean thirdWorkshopUnlocked = mUser.getMaxPresentsCollected() >= 3; if (thirdWorkshopUnlocked) { findViewById(R.id.workshop_3_scrim).setVisibility(View.GONE); } else { findViewById(R.id.workshop_3_scrim).setVisibility(View.GONE); } setEditButtonVisible(findViewById(R.id.button_edit_3), thirdWorkshopUnlocked); // Allow or deny workshop "magnet"-ing if we don't know the location or if the user // is already near a workshop if (mLatLng == null || isAnyWorkshopNearby()) { setEditButtonVisible(findViewById(R.id.button_edit_1), false); setEditButtonVisible(findViewById(R.id.button_edit_2), false); setEditButtonVisible(findViewById(R.id.button_edit_3), false); } } private void setEditButtonVisible(View button, boolean visible) { if (visible) { // Show the button at full strength button.setVisibility(View.VISIBLE); button.setAlpha(1.0f); } else if (isDebug()) { // When debugging never hide the buttons, just dim them button.setAlpha(0.5f); } else { // When not debugging, hide the button fully button.setVisibility(View.GONE); } } private void bounceInAvatar() { mAvatarView.postDelayed(new Runnable() { @Override public void run() { BounceInAnimator.animate(mAvatarView); } }, 750); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == RC_MOVE_WORKSHOP) { if (resultCode == RESULT_OK) { Toast.makeText(this, getString(R.string.workshop_moved), Toast.LENGTH_SHORT).show(); refreshWorkshops(); // [ANALYTICS] MeasurementManager.recordWorkshopMoved(mAnalytics); } else { Toast.makeText(this, getString(R.string.move_canceled), Toast.LENGTH_SHORT).show(); } } } public boolean needsNearbyWorkshop() { if (mLatLng != null && mUser.getBagFillPercentage() >= 100f) { // Check if any workshop is within a certain radius (default 1km) for (Workshop workshop : mWorkshops) { if(Distance.between(workshop.getLatLng(), mLatLng) < mConfig.NEARBY_WORKSHOP_RADIUS) { return false; } } // No close workshops return true; } return false; } public void onMagnetWorkshopClick(Workshop workshop) { // Allow the user to move the workshop if they have not moved it today or if their bag // is full and they don't have any workshops within 1km if (workshop != null && !(workshop.isMovable() || needsNearbyWorkshop())) { Toast.makeText(this, getString(R.string.workshop_move_too_soon), Toast.LENGTH_SHORT).show(); return; } // Move workshop to current location if (mLatLng != null) { // Create workshop if necessary if (workshop == null) { workshop = new Workshop(); } // Update workshop LatLng fuzzyLocation = FuzzyLocationUtil.fuzz(mLatLng); workshop.setLatLng(fuzzyLocation); workshop.saveWithTimestamp(); // [ANALYTICS] MeasurementManager.recordWorkshopMoved(mAnalytics); } // Refresh workshops refreshWorkshops(); } public void onEditWorkshopClick(Workshop workshop) { if (workshop != null && !workshop.isMovable()) { Toast.makeText(this, getString(R.string.workshop_move_too_soon), Toast.LENGTH_SHORT).show(); } else { // May need to create workshop first if (workshop == null) { workshop = new Workshop(); workshop.setLatLng(Workshop.NULL_LATLNG); workshop.save(); } Intent intent = new Intent(this, MapsActivity.class); intent.setAction(MapsActivity.ACTION_MOVE_WORKSHOP); intent.putExtra(MapsActivity.EXTRA_MOVE_WORKSHOP_ID, workshop.getId()); startActivityForResult(intent, RC_MOVE_WORKSHOP); } } private void scrollAvatar(int delta) { mAvatarIndex = mAvatarIndex + delta; // Wrap around 0 --> last if (mAvatarIndex < 0) { mAvatarIndex = Avatars.NUM_AVATARS - 1; } // Wrap around last --> 0 if (mAvatarIndex >= Avatars.NUM_AVATARS) { mAvatarIndex = 0; } // Set image int levelNumber = mAvatarIndex + 1; boolean locked = levelNumber > mUser.getLevel(); if (locked) { mAvatarView.setImageResource(Avatars.AVATARS_LOCKED[mAvatarIndex]); } else { mAvatarView.setImageResource(Avatars.AVATARS_UNLOCKED[mAvatarIndex]); } // Set level text mLevelTextView.setText(String.valueOf(levelNumber)); } @Override public void onClick(View v) { if (v.getId() == R.id.button_edit_1) { onMagnetWorkshopClick(mWorkshops[0]); } if (v.getId() == R.id.button_edit_2) { // Check if user has unlocked second workshop if (mUser.getMaxWorkshops() < 2) { return; } onMagnetWorkshopClick(mWorkshops[1]); } if (v.getId() == R.id.button_edit_3) { // Check if user has unlocked third workshop if (mUser.getMaxWorkshops() < 3) { return; } onMagnetWorkshopClick(mWorkshops[2]); } if (v.getId() == R.id.profile_user_image) { supportFinishAfterTransition(); } if (v.getId() == R.id.arrow_left) { scrollAvatar(-1); } if (v.getId() == R.id.arrow_right) { scrollAvatar(1); } } private boolean isDebug() { return getPackageName().contains("debug"); } private class WorkshopMapListener implements OnMapReadyCallback { Context context; Workshop workshop; GoogleMap googleMap; WorkshopMapListener(Context context, Workshop workshop) { this.context = context; this.workshop = workshop; } @Override public void onMapReady(GoogleMap googleMap) { this.googleMap = googleMap; // Santa Style googleMap.setMapStyle(MapStyleOptions.loadRawResourceStyle(context, R.raw.map_style)); // Control map UI UiSettings settings = googleMap.getUiSettings(); settings.setMapToolbarEnabled(false); settings.setMyLocationButtonEnabled(false); // Prevent Google Maps from launching googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { // TODO: No-op } }); // Show workshop setWorkshop(workshop); } public void setWorkshop(Workshop workshop) { this.workshop = workshop; if (workshop != null && googleMap != null) { LatLng workshopLatLng = workshop.getLatLng(); googleMap.clear(); googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(workshopLatLng, 17f)); googleMap.addMarker(new MarkerOptions() .icon(BitmapDescriptorFactory.fromResource(R.drawable.workshop)) .position(workshopLatLng)); } } } }