allow class selection

This commit is contained in:
Phillip Thelen 2016-04-13 17:40:41 +02:00
parent c41e6f02ed
commit 35fe0f78d2
10 changed files with 428 additions and 5 deletions

View file

@ -91,6 +91,17 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.activities.MainActivity" />
</activity>
<activity
android:name=".ui.activities.ClassSelectionActivity"
android:theme="@style/AppThemeWithActionBarBlackText"
android:parentActivityName=".ui.activities.MainActivity"
android:screenOrientation="portrait"
tools:ignore="UnusedAttribute"
android:label="@string/select_class">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.activities.MainActivity" />
</activity>
<activity android:name="com.facebook.FacebookActivity"
android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"

View file

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="@+id/healerWrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardView.Default">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardContent"
android:background="@drawable/selection_highlight">
<ImageView
android:layout_width="@dimen/avatar_header_width"
android:layout_height="@dimen/avatar_header_height"
android:id="@+id/healerImageView" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/healer"
style="@style/CardTitle"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/healer_description"
style="@style/CardText"/>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/mageWrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardView.Default">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardContent"
android:background="@drawable/selection_highlight">
<ImageView
android:layout_width="@dimen/avatar_header_width"
android:layout_height="@dimen/avatar_header_height"
android:id="@+id/mageImageView" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mage"
style="@style/CardTitle" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/mage_description"
style="@style/CardText"/>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/rogueWrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardView.Default">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardContent"
android:background="@drawable/selection_highlight">
<ImageView
android:layout_width="@dimen/avatar_header_width"
android:layout_height="@dimen/avatar_header_height"
android:id="@+id/rogueImageView" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/rogue"
style="@style/CardTitle" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/rogue_description"
style="@style/CardText"/>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/warriorWrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardView.Default">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardContent"
android:background="@drawable/selection_highlight">
<ImageView
android:layout_width="@dimen/avatar_header_width"
android:layout_height="@dimen/avatar_header_height"
android:id="@+id/warriorImageView" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="8dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/warrior"
style="@style/CardTitle" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/warrior_description"
style="@style/CardText"/>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/optOutWrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardView.Default">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
style="@style/CardContent"
android:background="@drawable/selection_highlight">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/opt_out_class"
style="@style/CardTitle" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/opt_out_description"
style="@style/CardText"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
</ScrollView>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AlertDialogTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="colorAccent">@color/brand_100</item>
<item name="android:colorPrimary">@color/brand</item>
<item name="android:textColorPrimary">@color/brand</item>
<item name="android:colorAccent">@color/brand</item>
<item name="colorPrimaryDark">@color/brand</item>
</style>
</resources>

View file

@ -314,4 +314,20 @@ To start, which parts of your life do you want to improve?</string>
<string name="empty_items" formatted="false">You don\'t have any %s</string>
<string name="user_level" formatted="false">LVL %s</string>
<string name="user_level_with_class" formatted="false">LVL %1$s - %2$s</string>
<string name="warrior">Warrior</string>
<string name="rogue">Rogue</string>
<string name="mage">Mage</string>
<string name="healer">Healer</string>
<string name="warrior_description">Warriors score more and better \"critical hits\", which randomly give bonus Gold, Experience, and drop chance for scoring a task. They also deal heavy damage to boss monsters. Play a Warrior if you find motivation from unpredictable jackpot-style rewards, or want to dish out the hurt in boss Quests!</string>
<string name="mage_description">Mages learn swiftly, gaining Experience and Levels faster than other classes. They also get a great deal of Mana for using special abilities. Play a Mage if you enjoy the tactical game aspects of Habit, or if you are strongly motivated by leveling up and unlocking advanced features!</string>
<string name="rogue_description">Rogues love to accumulate wealth, gaining more Gold than anyone else, and are adept at finding random items. Their iconic Stealth ability lets them duck the consequences of missed Dailies. Play a Rogue if you find strong motivation from Rewards and Achievements, striving for loot and badges!</string>
<string name="healer_description">Healers stand impervious against harm, and extend that protection to others. Missed Dailies and bad Habits don\'t faze them much, and they have ways to recover Health from failure. Play a Healer if you enjoy assisting others in your Party, or if the idea of cheating Death through hard work inspires you!</string>
<string name="select_class">Select String</string>
<string name="opt_out_class">Opt Out</string>
<string name="opt_out_description">Can\'t be bothered with classes? Want to choose later? Opt out - you\'ll be a warrior with no special abilities. You can read about the class system later on the wiki and enable classes at any time.</string>
<string name="class_confirmation" formatted="false">Are you sure you want to be a %s?</string>
<string name="choose_class">Choose Class</string>
<string name="dialog_go_back">Go Back</string>
<string name="opt_out_confirmation">Are you sure you want to Opt Out?</string>
</resources>

View file

@ -142,6 +142,8 @@
<style name="AlertDialogTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="colorAccent">@color/brand_100</item>
<item name="android:textColorPrimary">@color/brand</item>
<item name="colorPrimaryDark">@color/brand</item>
</style>
<style name="SectionTitle">

View file

@ -0,0 +1,5 @@
package com.habitrpg.android.habitica.events;
public class SelectClassEvent {
public boolean isInitialSelection;
}

View file

@ -0,0 +1,162 @@
package com.habitrpg.android.habitica.ui.activities;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.userpicture.UserPicture;
import com.magicmicky.habitrpgwrapper.lib.models.Gear;
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
import com.magicmicky.habitrpgwrapper.lib.models.Hair;
import com.magicmicky.habitrpgwrapper.lib.models.Items;
import com.magicmicky.habitrpgwrapper.lib.models.Outfit;
import com.magicmicky.habitrpgwrapper.lib.models.Preferences;
import butterknife.Bind;
import butterknife.OnClick;
public class ClassSelectionActivity extends BaseActivity {
Boolean isInitialSelection;
@Bind(R.id.healerImageView)
ImageView healerImageView;
@Bind(R.id.mageImageView)
ImageView mageImageView;
@Bind(R.id.rogueImageView)
ImageView rogueImageView;
@Bind(R.id.warriorImageView)
ImageView warriorImageView;
@Override
protected int getLayoutResId() {
return R.layout.activity_class_selection;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
isInitialSelection = bundle.getBoolean("isInitialSelection");
Preferences preferences = new Preferences();
preferences.setHair(new Hair());
preferences.setCostume(false);
preferences.setSize(bundle.getString("size"));
preferences.setSkin(bundle.getString("skin"));
preferences.setShirt(bundle.getString("shirt"));
preferences.getHair().setBangs(bundle.getInt("hairBangs"));
preferences.getHair().setBase(bundle.getInt("hairBase"));
preferences.getHair().setColor(bundle.getString("hairColor"));
preferences.getHair().setMustache(bundle.getInt("hairMustache"));
preferences.getHair().setBeard(bundle.getInt("hairBeard"));
Outfit healerOutfit = new Outfit();
healerOutfit.setArmor("armor_healer_5");
healerOutfit.setHead("head_healer_5");
healerOutfit.setShield("shield_healer_5");
healerOutfit.setWeapon("weapon_healer_6");
HabitRPGUser healer = this.makeUser(preferences, healerOutfit);
UserPicture healerUserPicture = new UserPicture(this);
healerUserPicture.setUser(healer);
healerUserPicture.setPictureOn(healerImageView);
Outfit mageOutfit = new Outfit();
mageOutfit.setArmor("armor_wizard_5");
mageOutfit.setHead("head_wizard_5");
mageOutfit.setWeapon("weapon_wizard_6");
HabitRPGUser mage = this.makeUser(preferences, mageOutfit);
UserPicture mageUserPicture = new UserPicture(this);
mageUserPicture.setUser(mage);
mageUserPicture.setPictureOn(mageImageView);
Outfit rogueOutfit = new Outfit();
rogueOutfit.setArmor("armor_rogue_5");
rogueOutfit.setHead("head_rogue_5");
rogueOutfit.setShield("shield_rogue_6");
rogueOutfit.setWeapon("weapon_rogue_6");
HabitRPGUser rogue = this.makeUser(preferences, rogueOutfit);
UserPicture rogueUserPicture = new UserPicture(this);
rogueUserPicture.setUser(rogue);
rogueUserPicture.setPictureOn(rogueImageView);
Outfit warriorOutfit = new Outfit();
warriorOutfit.setArmor("armor_warrior_5");
warriorOutfit.setHead("head_warrior_5");
warriorOutfit.setShield("shield_warrior_5");
warriorOutfit.setWeapon("weapon_warrior_6");
HabitRPGUser warrior = this.makeUser(preferences, warriorOutfit);
UserPicture warriorUserPicture = new UserPicture(this);
warriorUserPicture.setUser(warrior);
warriorUserPicture.setPictureOn(warriorImageView);
}
public HabitRPGUser makeUser(Preferences preferences, Outfit outfit) {
HabitRPGUser user = new HabitRPGUser();
user.setPreferences(preferences);
user.setItems(new Items());
user.getItems().setGear(new Gear());
user.getItems().getGear().setEquipped(outfit);
return user;
}
@OnClick(R.id.healerWrapper)
public void healerSelected() {
displayConfirmationDialogForClass(getString(R.string.healer), "healer");
}
@OnClick(R.id.mageWrapper)
public void mageSelected() {
displayConfirmationDialogForClass(getString(R.string.mage), "wizard");
}
@OnClick(R.id.rogueWrapper)
public void rogueSelected() {
displayConfirmationDialogForClass(getString(R.string.rogue), "rogue");
}
@OnClick(R.id.warriorWrapper)
public void warriorSelected() {
displayConfirmationDialogForClass(getString(R.string.warrior), "warrior");
}
@OnClick(R.id.optOutWrapper)
public void optOutSelected() {
AlertDialog alert = new AlertDialog.Builder(this)
.setTitle(getString(R.string.opt_out_confirmation))
.setNegativeButton(getString(R.string.dialog_go_back), (dialog, which) -> {
dialog.dismiss();
})
.setPositiveButton(getString(R.string.opt_out_class), (dialog, which) -> {
Intent intent = new Intent();
intent.putExtra("optedOut", true);
setResult(RESULT_OK, intent);
finish();
}).create();
alert.show();
}
private void displayConfirmationDialogForClass(String className, String classIdentifier) {
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle(getString(R.string.class_confirmation, className))
.setNegativeButton(getString(R.string.dialog_go_back), (dialog, which) -> {
dialog.dismiss();
})
.setPositiveButton(getString(R.string.choose_class), (dialog, which) -> {
Intent intent = new Intent();
intent.putExtra("selectedClass", classIdentifier);
setResult(RESULT_OK, intent);
finish();
});
AlertDialog alert = builder.create();
alert.show();
}
}

View file

@ -15,6 +15,7 @@ import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.Toolbar;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
@ -38,6 +39,7 @@ import com.habitrpg.android.habitica.events.ContentReloadedEvent;
import com.habitrpg.android.habitica.events.DisplayFragmentEvent;
import com.habitrpg.android.habitica.events.DisplayTutorialEvent;
import com.habitrpg.android.habitica.events.ReloadContentEvent;
import com.habitrpg.android.habitica.events.SelectClassEvent;
import com.habitrpg.android.habitica.events.TaskRemovedEvent;
import com.habitrpg.android.habitica.events.ToggledInnStateEvent;
import com.habitrpg.android.habitica.events.commands.BuyRewardCommand;
@ -125,6 +127,7 @@ public class MainActivity extends BaseActivity implements HabitRPGUserCallback.O
GemsPurchaseFragment.Listener, TutorialView.OnTutorialReaction {
private static final int MIN_LEVEL_FOR_SKILLS = 11;
private static final int SELECT_CLASS_RESULT = 11;
@Bind(R.id.floating_menu_wrapper)
FrameLayout floatingMenuWrapper;
@ -633,12 +636,28 @@ public class MainActivity extends BaseActivity implements HabitRPGUserCallback.O
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
checkout.onActivityResult(requestCode, resultCode, data);
if (resultCode == SELECT_CLASS_RESULT) {
if (data.getBooleanExtra("optingOut", false)) {
Map<String, Object> updateData = new HashMap<>();
updateData.put("preferences.disableClasses", true);
updateData.put("flags.classSelected", true);
mAPIHelper.apiService.updateUser(updateData, new HabitRPGUserCallback(this));
} else {
String selectedClass = data.getStringExtra("selectedClass");
if (selectedClass != null) {
Map<String, Object> updateData = new HashMap<>();
updateData.put("class", selectedClass);
mAPIHelper.apiService.changeClass(updateData, new HabitRPGUserCallback(this));
}
}
}
}
@Override
public void onDestroy() {
if (checkout != null)
if (checkout != null) {
checkout.stop();
}
EventBus.getDefault().unregister(this);
super.onDestroy();
@ -969,6 +988,7 @@ public class MainActivity extends BaseActivity implements HabitRPGUserCallback.O
SuppressedModals suppressedModals = user.getPreferences().getSuppressModals();
if (suppressedModals != null) {
if (suppressedModals.getLevelUp()) {
checkClassSelection();
return;
}
}
@ -982,13 +1002,25 @@ public class MainActivity extends BaseActivity implements HabitRPGUserCallback.O
this.dialogUserPicture.setPictureOn(avatarView);
}
AlertDialog dialog = new AlertDialog.Builder(this)
AlertDialog alert = new AlertDialog.Builder(this)
.setTitle(R.string.levelup_header)
.setView(customView)
.setPositiveButton(R.string.levelup_button, null)
.setPositiveButton(R.string.levelup_button, (dialog, which) -> {
checkClassSelection();
})
.create();
dialog.show();
alert.show();
}
private void checkClassSelection() {
if (user.getStats().getLvl() > 10 &&
!user.getPreferences().getDisableClasses() &&
!user.getFlags().getClassSelected()) {
SelectClassEvent event = new SelectClassEvent();
event.isInitialSelection = true;
displayClassSelectionActivity(event);
}
}
@Override
@ -1034,6 +1066,24 @@ public class MainActivity extends BaseActivity implements HabitRPGUserCallback.O
}
}
@Subscribe
public void displayClassSelectionActivity(SelectClassEvent event) {
Bundle bundle = new Bundle();
bundle.putString("size", user.getPreferences().getSize());
bundle.putString("skin", user.getPreferences().getSkin());
bundle.putString("shirt", user.getPreferences().getShirt());
bundle.putInt("hairBangs", user.getPreferences().getHair().getBangs());
bundle.putInt("hairBase", user.getPreferences().getHair().getBase());
bundle.putString("hairColor", user.getPreferences().getHair().getColor());
bundle.putInt("hairMustache", user.getPreferences().getHair().getMustache());
bundle.putInt("hairBeard", user.getPreferences().getHair().getBeard());
bundle.putBoolean("isInitialSelection", event.isInitialSelection);
Intent intent = new Intent(this, ClassSelectionActivity.class);
intent.putExtras(bundle);
startActivityForResult(intent, SELECT_CLASS_RESULT);
}
private void displayTutorialStep(TutorialStep step, String text) {
TutorialView view = new TutorialView(this, step, this);
view.setTutorialText(text);

View file

@ -42,9 +42,9 @@ import com.habitrpg.android.habitica.events.commands.TaskCheckedCommand;
import com.habitrpg.android.habitica.helpers.TagsHelper;
import com.habitrpg.android.habitica.ui.EditTextDrawer;
import com.habitrpg.android.habitica.ui.UiUtils;
import com.habitrpg.android.habitica.ui.activities.ClassSelectionActivity;
import com.habitrpg.android.habitica.ui.activities.MainActivity;
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity;
import com.habitrpg.android.habitica.ui.adapter.IReceiveNewEntries;
import com.habitrpg.android.habitica.ui.adapter.tasks.HabitItemRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
import com.habitrpg.android.habitica.ui.helpers.Debounce;

View file

@ -121,6 +121,9 @@ public interface ApiService {
@POST("/user/class/cast/{skill}")
void useSkill(@Path("skill") String skillName, @Query("targetType") String targetType, Callback<HabitRPGUser> habitRPGUserCallback);
@POST("/user/class/change")
void changeClass(@Body Map<String, Object> updateDictionary, Callback<HabitRPGUser> cb);
/* Group API */
@GET("/groups")