From 6c431996c77be700aec6276ae832c5d1b15e9644 Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Tue, 22 Jan 2019 12:21:06 -0300 Subject: [PATCH 1/6] Allow to set a display name and choose an avatar --- android/app/src/main/cpp/native.cpp | 28 ++++ .../hifiinterface/MainActivity.java | 31 ++++- .../fragment/ProfileFragment.java | 126 ++++++++++++++++++ .../provider/AvatarProvider.java | 70 ++++++++++ .../hifiinterface/view/AvatarAdapter.java | 111 +++++++++++++++ .../app/src/main/res/layout/avatar_item.xml | 22 +++ .../src/main/res/layout/fragment_profile.xml | 107 +++++++++++++++ .../app/src/main/res/menu/menu_navigation.xml | 4 + android/app/src/main/res/values/dimens.xml | 5 +- android/app/src/main/res/values/strings.xml | 4 + interface/src/AndroidHelper.cpp | 14 ++ interface/src/AndroidHelper.h | 3 + 12 files changed, 523 insertions(+), 2 deletions(-) create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/fragment/ProfileFragment.java create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/provider/AvatarProvider.java create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/view/AvatarAdapter.java create mode 100644 android/app/src/main/res/layout/avatar_item.xml create mode 100644 android/app/src/main/res/layout/fragment_profile.xml diff --git a/android/app/src/main/cpp/native.cpp b/android/app/src/main/cpp/native.cpp index f9c7751a3e..01d805b077 100644 --- a/android/app/src/main/cpp/native.cpp +++ b/android/app/src/main/cpp/native.cpp @@ -493,6 +493,34 @@ Java_io_highfidelity_hifiinterface_SplashActivity_registerLoadCompleteListener(J } +JNIEXPORT jstring JNICALL +Java_io_highfidelity_hifiinterface_fragment_ProfileFragment_getDisplayName(JNIEnv *env, + jobject instance) { + + QString displayName = AndroidHelper::instance().getDisplayName(); + return env->NewStringUTF(displayName.toLatin1().data()); +} + +JNIEXPORT void JNICALL +Java_io_highfidelity_hifiinterface_fragment_ProfileFragment_setDisplayName(JNIEnv *env, + jobject instance, + jstring name_) { + const char *c_name = env->GetStringUTFChars(name_, 0); + const QString name = QString::fromUtf8(c_name); + env->ReleaseStringUTFChars(name_, c_name); + AndroidHelper::instance().setDisplayName(name); +} + +JNIEXPORT void JNICALL +Java_io_highfidelity_hifiinterface_fragment_ProfileFragment_setAvatarUrl(JNIEnv *env, + jobject instance, + jstring url_) { + const char *url = env->GetStringUTFChars(url_, 0); + QString avatarUrl = QString::fromUtf8(url); + AndroidHelper::instance().setMyAvatarUrl(avatarUrl); + env->ReleaseStringUTFChars(url_, url); +} + JNIEXPORT void JNICALL Java_io_highfidelity_hifiinterface_MainActivity_logout(JNIEnv *env, jobject instance) { DependencyManager::get<AccountManager>()->logout(); diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java index e17b530f1c..2e3ca8a5e5 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java @@ -33,13 +33,15 @@ import com.squareup.picasso.Picasso; import io.highfidelity.hifiinterface.fragment.FriendsFragment; import io.highfidelity.hifiinterface.fragment.HomeFragment; import io.highfidelity.hifiinterface.fragment.PolicyFragment; +import io.highfidelity.hifiinterface.fragment.ProfileFragment; import io.highfidelity.hifiinterface.fragment.SettingsFragment; import io.highfidelity.hifiinterface.fragment.SignupFragment; import io.highfidelity.hifiinterface.task.DownloadProfileImageTask; public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, HomeFragment.OnHomeInteractionListener, - FriendsFragment.OnHomeInteractionListener { + FriendsFragment.OnHomeInteractionListener, + ProfileFragment.OnProfileInteractionListener { private static final int PROFILE_PICTURE_PLACEHOLDER = R.drawable.default_profile_avatar; public static final String DEFAULT_FRAGMENT = "Home"; @@ -61,6 +63,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On private View mProfilePanel; private TextView mLogoutOption; private MenuItem mPeopleMenuItem; + private MenuItem mProfileMenuItem; private boolean backToScene; private String backToUrl; @@ -83,6 +86,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On mPeopleMenuItem = mNavigationView.getMenu().findItem(R.id.action_people); + mProfileMenuItem = mNavigationView.getMenu().findItem(R.id.action_profile); + updateDebugMenu(mNavigationView.getMenu()); Toolbar toolbar = findViewById(R.id.toolbar); @@ -162,6 +167,12 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On loadFragment(fragment, getString(R.string.people), getString(R.string.tagFragmentPeople), true, true); } + private void loadProfileFragment() { + Fragment fragment = ProfileFragment.newInstance(); + + loadFragment(fragment, getString(R.string.profile), getString(R.string.tagFragmentProfile), true, true); + } + private void loadSettingsFragment() { SettingsFragment fragment = SettingsFragment.newInstance(); @@ -261,6 +272,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On case R.id.action_people: loadPeopleFragment(); return true; + case R.id.action_profile: + loadProfileFragment(); + break; case R.id.action_debug_settings: loadSettingsFragment(); return true; @@ -351,6 +365,21 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On goToUser(username); } + @Override + public void onCancelProfileEdit() { + getFragmentManager().popBackStack(); + } + + @Override + public void onCompleteProfileEdit() { + getFragmentManager().popBackStack(); + } + + @Override + public void onAvatarChosen() { + getFragmentManager().popBackStack(); + } + private class RoundProfilePictureCallback implements Callback { @Override public void onSuccess() { diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/ProfileFragment.java b/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/ProfileFragment.java new file mode 100644 index 0000000000..e5aa793341 --- /dev/null +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/ProfileFragment.java @@ -0,0 +1,126 @@ +package io.highfidelity.hifiinterface.fragment; + + +import android.app.Fragment; +import android.content.Context; +import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.TextView; + +import io.highfidelity.hifiinterface.R; +import io.highfidelity.hifiinterface.provider.AvatarProvider; +import io.highfidelity.hifiinterface.view.AvatarAdapter; + +public class ProfileFragment extends Fragment { + + private TextView mDisplayName; + + private Button mOkButton; + private OnProfileInteractionListener mListener; + private AvatarProvider mAvatarsProvider; + + private native String getDisplayName(); + private native void setDisplayName(String name); + private native void setAvatarUrl(String url); + + public ProfileFragment() { + // Required empty public constructor + } + + public static ProfileFragment newInstance() { + ProfileFragment fragment = new ProfileFragment(); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_profile, container, false); + + mDisplayName = rootView.findViewById(R.id.displayName); + mDisplayName.setText(getDisplayName()); + mDisplayName.setOnEditorActionListener((textView, actionId, keyEvent) -> onDisplayNameEditorAction(textView, actionId, keyEvent)); + + mOkButton = rootView.findViewById(R.id.okButton); + mOkButton.setOnClickListener(view -> onOkButtonClicked()); + + rootView.findViewById(R.id.cancel).setOnClickListener(view -> onCancelProfileEdit()); + + RecyclerView avatarsView = rootView.findViewById(R.id.gridview); + int numberOfColumns = 1; + mAvatarsProvider = new AvatarProvider(getContext()); + GridLayoutManager gridLayoutMgr = new GridLayoutManager(getContext(), numberOfColumns); + avatarsView.setLayoutManager(gridLayoutMgr); + AvatarAdapter avatarAdapter = new AvatarAdapter(getContext(), mAvatarsProvider); + avatarsView.setAdapter(avatarAdapter); + avatarAdapter.loadAvatars(); + + avatarAdapter.setClickListener((view, position, avatar) -> { + setAvatarUrl(avatar.avatarUrl); + if (mListener != null) { + mListener.onAvatarChosen(); + } + }); + return rootView; + } + + private void onOkButtonClicked() { + setDisplayName(mDisplayName.getText().toString()); + View view = getActivity().getCurrentFocus(); + InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + if (mListener != null) { + mListener.onCompleteProfileEdit(); + } + } + + private boolean onDisplayNameEditorAction(TextView textView, int actionId, KeyEvent keyEvent) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + mOkButton.performClick(); + return true; + } + return false; + } + + private void onCancelProfileEdit() { + View view = getActivity().getCurrentFocus(); + InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + if (mListener != null) { + mListener.onCancelProfileEdit(); + } + } + + /** + * Processes the back pressed event and returns true if it was managed by this Fragment + * @return + */ + public boolean onBackPressed() { + return false; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof OnProfileInteractionListener) { + mListener = (OnProfileInteractionListener) context; + } else { + throw new RuntimeException(context.toString() + + " must implement OnProfileInteractionListener"); + } + } + + public interface OnProfileInteractionListener { + void onCancelProfileEdit(); + void onCompleteProfileEdit(); + void onAvatarChosen(); + } +} diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/provider/AvatarProvider.java b/android/app/src/main/java/io/highfidelity/hifiinterface/provider/AvatarProvider.java new file mode 100644 index 0000000000..5bbb8ee666 --- /dev/null +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/provider/AvatarProvider.java @@ -0,0 +1,70 @@ +package io.highfidelity.hifiinterface.provider; + +import android.content.Context; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import io.highfidelity.hifiinterface.view.AvatarAdapter; + +/** + * Created by gcalero on 1/21/19 + */ +public class AvatarProvider { + + private static final String AVATARS_JSON = "avatars.json"; + private static final String JSON_FIELD_NAME = "name"; + private static final String JSON_FIELD_URL = "url"; + private static final String JSON_FIELD_IMAGE = "preview_image"; + private static final String JSON_FIELD_AVATARS_ARRAY = "avatars"; + private final Context mContext; + + public interface AvatarsCallback { + void retrieveOk(List<AvatarAdapter.Avatar> avatars); + void retrieveError(Exception e, String message); + } + + public AvatarProvider(Context context) { + mContext = context; + } + + public void retrieve(AvatarsCallback avatarsCallback) + { + try { + JSONObject obj = new JSONObject(loadJSONFromAssets()); + JSONArray m_jArry = obj.getJSONArray(JSON_FIELD_AVATARS_ARRAY); + ArrayList<AvatarAdapter.Avatar> avatars = new ArrayList<>(); + + for (int i = 0; i < m_jArry.length(); i++) { + JSONObject jo_inside = m_jArry.getJSONObject(i); + AvatarAdapter.Avatar anAvatar = new AvatarAdapter.Avatar(); + anAvatar.avatarName = jo_inside.getString(JSON_FIELD_NAME); + anAvatar.avatarPreviewUrl = jo_inside.getString(JSON_FIELD_IMAGE); + anAvatar.avatarUrl = jo_inside.getString(JSON_FIELD_URL); + avatars.add(anAvatar); + } + avatarsCallback.retrieveOk(avatars); + } catch (IOException e) { + avatarsCallback.retrieveError(e, "Failed retrieving avatar JSON"); + } catch (JSONException e) { + avatarsCallback.retrieveError(e, "Failed parsing avatar JSON"); + } + } + + private String loadJSONFromAssets() throws IOException { + String json = null; + InputStream is = mContext.getAssets().open(AVATARS_JSON); + int size = is.available(); + byte[] buffer = new byte[size]; + is.read(buffer); + is.close(); + json = new String(buffer, "UTF-8"); + return json; + } +} diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/view/AvatarAdapter.java b/android/app/src/main/java/io/highfidelity/hifiinterface/view/AvatarAdapter.java new file mode 100644 index 0000000000..d88083ff2a --- /dev/null +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/view/AvatarAdapter.java @@ -0,0 +1,111 @@ +package io.highfidelity.hifiinterface.view; + +import android.content.Context; +import android.net.Uri; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.squareup.picasso.Picasso; + +import java.util.ArrayList; +import java.util.List; + +import io.highfidelity.hifiinterface.R; +import io.highfidelity.hifiinterface.provider.AvatarProvider; + +/** + * Created by gcalero on 1/21/19 + */ +public class AvatarAdapter extends RecyclerView.Adapter<AvatarAdapter.ViewHolder> { + + private static final String TAG = "Interface"; + private final Context mContext; + private final LayoutInflater mInflater; + private final AvatarProvider mProvider; + private List<Avatar> mAvatars = new ArrayList<>(); + private ItemClickListener mClickListener; + + public AvatarAdapter(Context context, AvatarProvider provider) { + mContext = context; + mInflater = LayoutInflater.from(mContext); + mProvider = provider; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = mInflater.inflate(R.layout.avatar_item, parent, false); + return new AvatarAdapter.ViewHolder(view); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + AvatarAdapter.Avatar anAvatar = mAvatars.get(position); + assert(holder.mName != null); + holder.mName.setText(anAvatar.avatarName); + Uri uri = Uri.parse(anAvatar.avatarPreviewUrl); + Picasso.get().load(uri).into(holder.mPreviewImage); + } + + @Override + public int getItemCount() { + return mAvatars.size(); + } + + public void loadAvatars() { + mProvider.retrieve(new AvatarProvider.AvatarsCallback() { + @Override + public void retrieveOk(List<AvatarAdapter.Avatar> avatars) { + mAvatars = new ArrayList<>(avatars); + notifyDataSetChanged(); + } + + @Override + public void retrieveError(Exception e, String message) { + Log.e(TAG, message, e); + } + }); + } + + public void setClickListener(ItemClickListener clickListener) { + mClickListener = clickListener; + } + + public interface ItemClickListener { + void onItemClick(View view, int position, Avatar avatar); + } + + public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + + TextView mName; + ImageView mPreviewImage; + + public ViewHolder(View itemView) { + super(itemView); + mName = itemView.findViewById(R.id.avatarName); + assert (mName != null); + mPreviewImage = itemView.findViewById(R.id.avatarPreview); + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + int position= getAdapterPosition(); + if (mClickListener != null) { + mClickListener.onItemClick(view, position, mAvatars.get(position)); + } + } + } + + public static class Avatar { + public String avatarName; + public String avatarUrl; + public String avatarPreviewUrl; + + public Avatar() { } + } +} diff --git a/android/app/src/main/res/layout/avatar_item.xml b/android/app/src/main/res/layout/avatar_item.xml new file mode 100644 index 0000000000..4da6ee1170 --- /dev/null +++ b/android/app/src/main/res/layout/avatar_item.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:paddingTop="5dp" + android:paddingBottom="5dp"> + <TextView + android:id="@+id/avatarName" + android:fontFamily="@font/raleway_bold" + android:textSize="20sp" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center" + android:textColor="@color/colorButton1" /> + <ImageView + android:id="@+id/avatarPreview" + android:layout_width="match_parent" + android:layout_height="190dp" + android:scaleType="fitCenter" + app:layout_constraintTop_toBottomOf="@id/avatarName"/> +</android.support.constraint.ConstraintLayout> \ No newline at end of file diff --git a/android/app/src/main/res/layout/fragment_profile.xml b/android/app/src/main/res/layout/fragment_profile.xml new file mode 100644 index 0000000000..8a5f925ad2 --- /dev/null +++ b/android/app/src/main/res/layout/fragment_profile.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/backgroundLight"> + + <ImageView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@drawable/encourage_login_background" + android:scaleType="fitXY" /> + + <FrameLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#B2000000" /> + + <ImageView + android:id="@+id/header" + android:layout_width="@dimen/header_hifi_width" + android:layout_height="@dimen/header_hifi_height" + android:layout_marginTop="@dimen/header_hifi_margin_top" + android:contentDescription="HighFidelity" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/hifi_header" /> + + <android.support.constraint.ConstraintLayout + android:id="@+id/profileForm" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_marginTop="@dimen/profile_margin_top" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toBottomOf="@id/header" + app:layout_constraintBottom_toBottomOf="parent" + android:visibility="visible"> + <EditText + android:id="@+id/displayName" + android:layout_width="match_parent" + android:layout_height="27dp" + android:layout_marginLeft="@dimen/profile_margin" + android:layout_marginRight="@dimen/profile_margin" + android:layout_marginBottom="@dimen/profile_margin" + android:background="@color/white_opaque" + android:paddingLeft="@dimen/edit_text_padding" + android:ems="10" + android:fontFamily="sans-serif" + android:textSize="@dimen/login_edit_text_size" + android:inputType="textCapWords" + android:textColor="@color/editTextColor" + android:textColorHint="@color/editTextColor" + android:gravity="left|center_vertical" + android:hint="@string/displayName" + app:layout_constraintTop_toTopOf="parent" /> + <FrameLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_constraintTop_toBottomOf="@id/displayName" + app:layout_constraintBottom_toTopOf="@id/okButton" + android:layout_marginTop="@dimen/profile_margin_avatars_top" + android:layout_marginBottom="@dimen/profile_margin_avatars_bottom" + android:layout_marginLeft="@dimen/profile_margin" + android:layout_marginRight="@dimen/profile_margin"> + <android.support.v7.widget.RecyclerView + android:id="@+id/gridview" + android:paddingTop="@dimen/list_vertical_padding" + android:paddingBottom="@dimen/list_vertical_padding" + android:clipToPadding="false" + android:layout_width="match_parent" + android:layout_height="match_parent" + /> + </FrameLayout> + <TextView + android:id="@+id/cancel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="8dp" + app:layout_constraintLeft_toLeftOf="@id/displayName" + app:layout_constraintTop_toTopOf="@id/okButton" + app:layout_constraintBottom_toBottomOf="@id/okButton" + app:layout_constraintRight_toLeftOf="@id/okButton" + android:textColor="@color/white_opaque" + android:fontFamily="@font/raleway_bold" + android:textSize="@dimen/button_medium_text_size" + android:text="@string/cancel_uppercase" /> + + <Button + android:id="@+id/okButton" + android:layout_width="@dimen/button_medium_width" + android:layout_height="@dimen/button_medium_height" + android:background="@drawable/rounded_button_color3" + android:fontFamily="@font/raleway_bold" + android:layout_marginTop="@dimen/button_medium_margin" + android:layout_marginBottom="@dimen/button_medium_margin" + android:text="@string/ok" + android:textColor="@color/white_opaque" + android:textAllCaps="false" + android:textSize="@dimen/button_medium_text_size" + app:layout_constraintRight_toRightOf="@id/displayName" + app:layout_constraintBottom_toBottomOf="parent" /> + </android.support.constraint.ConstraintLayout> + +</android.support.constraint.ConstraintLayout> diff --git a/android/app/src/main/res/menu/menu_navigation.xml b/android/app/src/main/res/menu/menu_navigation.xml index 142af5d146..2bd8a58b4b 100644 --- a/android/app/src/main/res/menu/menu_navigation.xml +++ b/android/app/src/main/res/menu/menu_navigation.xml @@ -9,6 +9,10 @@ android:id="@+id/action_people" android:title="@string/people" /> + <item + android:id="@+id/action_profile" + android:title="@string/profile" + /> <item android:id="@+id/action_debug_settings" android:title="@string/settings" diff --git a/android/app/src/main/res/values/dimens.xml b/android/app/src/main/res/values/dimens.xml index 85d79509ba..81217c0425 100644 --- a/android/app/src/main/res/values/dimens.xml +++ b/android/app/src/main/res/values/dimens.xml @@ -54,5 +54,8 @@ <dimen name="login_menu_button_margin_top">77dp</dimen> <dimen name="login_menu_text_size">20sp</dimen> <dimen name="login_edit_text_padding">14dp</dimen> - + <dimen name="profile_margin_top">20dp</dimen> + <dimen name="profile_margin">35dp</dimen> + <dimen name="profile_margin_avatars_top">40dp</dimen> + <dimen name="profile_margin_avatars_bottom">70dp</dimen> </resources> diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 671f171c3e..b60caf1f2c 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -43,6 +43,7 @@ <string name="tagFragmentSignup">tagFragmentSignup</string> <string name="tagFragmentPolicy">tagFragmentPolicy</string> <string name="tagFragmentPeople">tagFragmentPeople</string> + <string name="tagFragmentProfile">tagFragmentProfile</string> <string name="tagSettings">tagSettings</string> <string name="tagFragmentSignedIn">tagFragmentSignedIn</string> <string name="settings">Settings</string> @@ -54,4 +55,7 @@ <string name="take_me_in_world">No thanks, take me in-world!</string> <string name="be_anywere">BE ANYWHERE, WITH ANYONE \nRIGHT NOW</string> <string name="steam_log_in">STEAM LOG IN</string> + <string name="displayName">Name to display</string> + <string name="ok">OK</string> + <string name="profile">Avatar</string> </resources> diff --git a/interface/src/AndroidHelper.cpp b/interface/src/AndroidHelper.cpp index 708859c00a..4f75d5bdb2 100644 --- a/interface/src/AndroidHelper.cpp +++ b/interface/src/AndroidHelper.cpp @@ -15,6 +15,7 @@ #include <src/ui/LoginDialog.h> #include "Application.h" #include "Constants.h" +#include "avatar/AvatarManager.h" #if defined(qApp) #undef qApp @@ -152,3 +153,16 @@ void AndroidHelper::signupFailed(QNetworkReply* reply) { emit handleSignupFailed(DEFAULT_SIGN_UP_FAILURE_MESSAGE); } } + +QString AndroidHelper::getDisplayName() { + return DependencyManager::get<AvatarManager>()->getMyAvatar()->getDisplayName(); +} + +void AndroidHelper::setDisplayName(const QString &displayName) { + DependencyManager::get<AvatarManager>()->getMyAvatar()->setDisplayName(displayName); +} + +void AndroidHelper::setMyAvatarUrl(const QString &avatarUrl) { + QUrl url = QUrl(avatarUrl); + DependencyManager::get<AvatarManager>()->getMyAvatar()->useFullAvatarURL(url); +} diff --git a/interface/src/AndroidHelper.h b/interface/src/AndroidHelper.h index f0aaa84214..f1cec6a43b 100644 --- a/interface/src/AndroidHelper.h +++ b/interface/src/AndroidHelper.h @@ -41,6 +41,9 @@ public: void operator=(AndroidHelper const&) = delete; void signup(QString email, QString username, QString password); + QString getDisplayName(); + void setDisplayName(const QString &displayName); + void setMyAvatarUrl(const QString &avatarUrl); public slots: void showLoginDialog(QUrl url); From 455d27aeb3f6c111d072b7ef381e160729184fbc Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Tue, 22 Jan 2019 16:18:00 -0300 Subject: [PATCH 2/6] Fix merge --- .../io/highfidelity/hifiinterface/fragment/ProfileFragment.java | 0 .../io/highfidelity/hifiinterface/provider/AvatarProvider.java | 0 .../highfidelity/hifiinterface/provider}/view/AvatarAdapter.java | 0 .../{app => apps/interface}/src/main/res/layout/avatar_item.xml | 0 .../interface}/src/main/res/layout/fragment_profile.xml | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename android/{app => apps/interface}/src/main/java/io/highfidelity/hifiinterface/fragment/ProfileFragment.java (100%) rename android/{app => apps/interface}/src/main/java/io/highfidelity/hifiinterface/provider/AvatarProvider.java (100%) rename android/{app/src/main/java/io/highfidelity/hifiinterface => apps/interface/src/main/java/io/highfidelity/hifiinterface/provider}/view/AvatarAdapter.java (100%) rename android/{app => apps/interface}/src/main/res/layout/avatar_item.xml (100%) rename android/{app => apps/interface}/src/main/res/layout/fragment_profile.xml (100%) diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/ProfileFragment.java b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/fragment/ProfileFragment.java similarity index 100% rename from android/app/src/main/java/io/highfidelity/hifiinterface/fragment/ProfileFragment.java rename to android/apps/interface/src/main/java/io/highfidelity/hifiinterface/fragment/ProfileFragment.java diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/provider/AvatarProvider.java b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/provider/AvatarProvider.java similarity index 100% rename from android/app/src/main/java/io/highfidelity/hifiinterface/provider/AvatarProvider.java rename to android/apps/interface/src/main/java/io/highfidelity/hifiinterface/provider/AvatarProvider.java diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/view/AvatarAdapter.java b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/provider/view/AvatarAdapter.java similarity index 100% rename from android/app/src/main/java/io/highfidelity/hifiinterface/view/AvatarAdapter.java rename to android/apps/interface/src/main/java/io/highfidelity/hifiinterface/provider/view/AvatarAdapter.java diff --git a/android/app/src/main/res/layout/avatar_item.xml b/android/apps/interface/src/main/res/layout/avatar_item.xml similarity index 100% rename from android/app/src/main/res/layout/avatar_item.xml rename to android/apps/interface/src/main/res/layout/avatar_item.xml diff --git a/android/app/src/main/res/layout/fragment_profile.xml b/android/apps/interface/src/main/res/layout/fragment_profile.xml similarity index 100% rename from android/app/src/main/res/layout/fragment_profile.xml rename to android/apps/interface/src/main/res/layout/fragment_profile.xml From 618b27c9525be5ffa9fecefacf13a90a5dccf158 Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Tue, 22 Jan 2019 18:04:54 -0300 Subject: [PATCH 3/6] Add missing json --- .../interface/src/main/assets/avatars.json | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 android/apps/interface/src/main/assets/avatars.json diff --git a/android/apps/interface/src/main/assets/avatars.json b/android/apps/interface/src/main/assets/avatars.json new file mode 100644 index 0000000000..fd5651bf42 --- /dev/null +++ b/android/apps/interface/src/main/assets/avatars.json @@ -0,0 +1,39 @@ +{ + "avatars": [ + { + "name": "Anime-Styled Boy", + "preview_image": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/46e0fd52-3cff-462f-ba97-927338d88295/thumbnail/hifi-mp-46e0fd52-3cff-462f-ba97-927338d88295.jpg", + "url": "http://mpassets.highfidelity.com/46e0fd52-3cff-462f-ba97-927338d88295-v1/AnimeBoy2.fst" + }, + { + "name": "Anime-Styled Girl", + "preview_image": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/1e7e43f6-1757-44d3-baa4-756827d96311/large/hifi-mp-1e7e43f6-1757-44d3-baa4-756827d96311.jpg", + "url": "http://mpassets.highfidelity.com/0dce3426-55c8-4641-8dd5-d76eb575b64a-v1/Anime_F_Outfit.fst" + }, + { + "name": "Last Legends: Male Avatar", + "preview_image": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/28569047-6f1a-4100-af67-8054ec397cc3/thumbnail/hifi-mp-28569047-6f1a-4100-af67-8054ec397cc3.jpg", + "url": "http://mpassets.highfidelity.com/28569047-6f1a-4100-af67-8054ec397cc3-v1/LLMale2.fst" + }, + { + "name": "Last Legends: Female Avatar", + "preview_image": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/8d823be5-6197-4418-b984-eb94160ed956/thumbnail/hifi-mp-8d823be5-6197-4418-b984-eb94160ed956.jpg", + "url": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/46e0fd52-3cff-462f-ba97-927338d88295/thumbnail/hifi-mp-46e0fd52-3cff-462f-ba97-927338d88295.jpg" + }, + { + "name": "Matthew: Photo-real avatar", + "preview_image": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/b652081b-a199-425e-ae5c-7815721bdc09/thumbnail/hifi-mp-b652081b-a199-425e-ae5c-7815721bdc09.jpg", + "url": "http://mpassets.highfidelity.com/b652081b-a199-425e-ae5c-7815721bdc09-v1/matthew.fst" + }, + { + "name": "Priscilla: Photo real avatar", + "preview_image": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/e7565f93-8bc5-47c2-b6eb-b3b31d4a1339/thumbnail/hifi-mp-e7565f93-8bc5-47c2-b6eb-b3b31d4a1339.jpg", + "url": "http://mpassets.highfidelity.com/e7565f93-8bc5-47c2-b6eb-b3b31d4a1339-v1/priscilla.fst" + }, + { + "name": "H1-F1 Optical Interpreter bot", + "preview_image": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/469c8b66-e3c2-47fb-9820-e306b1dd15c4/large/hifi-mp-469c8b66-e3c2-47fb-9820-e306b1dd15c4.jpg", + "url": "http://mpassets.highfidelity.com/469c8b66-e3c2-47fb-9820-e306b1dd15c4-v1/optical_interpreter[1].fst" + } + ] +} \ No newline at end of file From 68feea23cb39ae8ffa35a8edde7dfff6c0cfbac0 Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Thu, 24 Jan 2019 16:21:38 -0300 Subject: [PATCH 4/6] Add the wooden mannequin as an eligible avatar --- android/apps/interface/src/main/assets/avatars.json | 5 +++++ android/apps/interface/src/main/res/layout/avatar_item.xml | 1 + 2 files changed, 6 insertions(+) diff --git a/android/apps/interface/src/main/assets/avatars.json b/android/apps/interface/src/main/assets/avatars.json index fd5651bf42..c736b8b63a 100644 --- a/android/apps/interface/src/main/assets/avatars.json +++ b/android/apps/interface/src/main/assets/avatars.json @@ -1,5 +1,10 @@ { "avatars": [ + { + "name": "Default", + "preview_image": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/7fe80a1e-f445-4800-9e89-40e677b03bee/large/hifi-mp-7fe80a1e-f445-4800-9e89-40e677b03bee.jpg", + "url": "qrc:////meshes/defaultAvatar_full.fst" + }, { "name": "Anime-Styled Boy", "preview_image": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/46e0fd52-3cff-462f-ba97-927338d88295/thumbnail/hifi-mp-46e0fd52-3cff-462f-ba97-927338d88295.jpg", diff --git a/android/apps/interface/src/main/res/layout/avatar_item.xml b/android/apps/interface/src/main/res/layout/avatar_item.xml index 4da6ee1170..6fba708030 100644 --- a/android/apps/interface/src/main/res/layout/avatar_item.xml +++ b/android/apps/interface/src/main/res/layout/avatar_item.xml @@ -15,6 +15,7 @@ android:textColor="@color/colorButton1" /> <ImageView android:id="@+id/avatarPreview" + android:background="@color/backgroundDark" android:layout_width="match_parent" android:layout_height="190dp" android:scaleType="fitCenter" From 4a345a55595d3350dde0dc76327174ef7335af39 Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Thu, 24 Jan 2019 18:53:15 -0300 Subject: [PATCH 5/6] Change default avatar name to Wooden Mannequin --- android/apps/interface/src/main/assets/avatars.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/apps/interface/src/main/assets/avatars.json b/android/apps/interface/src/main/assets/avatars.json index c736b8b63a..b84d904587 100644 --- a/android/apps/interface/src/main/assets/avatars.json +++ b/android/apps/interface/src/main/assets/avatars.json @@ -1,7 +1,7 @@ { "avatars": [ { - "name": "Default", + "name": "Wooden Mannequin", "preview_image": "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/7fe80a1e-f445-4800-9e89-40e677b03bee/large/hifi-mp-7fe80a1e-f445-4800-9e89-40e677b03bee.jpg", "url": "qrc:////meshes/defaultAvatar_full.fst" }, From 3a3bd5922a4e71d148ebe6719fa6b1159d5232f4 Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Fri, 25 Jan 2019 16:01:21 -0300 Subject: [PATCH 6/6] Bugfix: fragment title remains as Avatar after closing it --- .../java/io/highfidelity/hifiinterface/MainActivity.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/MainActivity.java b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/MainActivity.java index 2e3ca8a5e5..e5ea0f998d 100644 --- a/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/MainActivity.java +++ b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/MainActivity.java @@ -367,17 +367,17 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On @Override public void onCancelProfileEdit() { - getFragmentManager().popBackStack(); + loadHomeFragment(false); } @Override public void onCompleteProfileEdit() { - getFragmentManager().popBackStack(); + loadHomeFragment(false); } @Override public void onAvatarChosen() { - getFragmentManager().popBackStack(); + loadHomeFragment(false); } private class RoundProfilePictureCallback implements Callback {