Browse Source
Add account switcher in MorePreferencesFragment
renovate/org.robolectric-robolectric-4.x
Add account switcher in MorePreferencesFragment
renovate/org.robolectric-robolectric-4.x
Ammar Githam
4 years ago
24 changed files with 761 additions and 155 deletions
-
35app/src/main/java/awais/instagrabber/activities/Login.java
-
5app/src/main/java/awais/instagrabber/activities/MainActivity.java
-
112app/src/main/java/awais/instagrabber/adapters/AccountSwitcherListAdapter.java
-
8app/src/main/java/awais/instagrabber/dialogs/QuickAccessDialog.java
-
19app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java
-
215app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java
-
7app/src/main/java/awais/instagrabber/fragments/settings/SettingsPreferencesFragment.java
-
11app/src/main/java/awais/instagrabber/repositories/ProfileRepository.java
-
41app/src/main/java/awais/instagrabber/repositories/responses/UserInfo.java
-
3app/src/main/java/awais/instagrabber/services/AddCookiesInterceptor.java
-
4app/src/main/java/awais/instagrabber/services/FeedService.java
-
2app/src/main/java/awais/instagrabber/services/FriendshipService.java
-
18app/src/main/java/awais/instagrabber/services/LoggingInterceptor.java
-
69app/src/main/java/awais/instagrabber/services/ProfileService.java
-
159app/src/main/java/awais/instagrabber/utils/DataBox.java
-
17app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java
-
8app/src/main/java/awais/instagrabber/utils/NavigationExtensions.java
-
1app/src/main/java/awais/instagrabber/utils/Utils.java
-
10app/src/main/res/drawable/ic_arrow_drop_down_24.xml
-
10app/src/main/res/drawable/ic_check_24.xml
-
65app/src/main/res/layout/pref_account_switcher.xml
-
1app/src/main/res/values/arrays.xml
-
1app/src/main/res/values/dimens.xml
-
3app/src/main/res/values/strings.xml
@ -0,0 +1,112 @@ |
|||
package awais.instagrabber.adapters; |
|||
|
|||
import android.annotation.SuppressLint; |
|||
import android.content.Context; |
|||
import android.graphics.Typeface; |
|||
import android.text.TextUtils; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.widget.ArrayAdapter; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.annotation.Nullable; |
|||
|
|||
import java.util.List; |
|||
|
|||
import awais.instagrabber.R; |
|||
import awais.instagrabber.databinding.PrefAccountSwitcherBinding; |
|||
import awais.instagrabber.utils.Constants; |
|||
import awais.instagrabber.utils.DataBox; |
|||
|
|||
import static awais.instagrabber.utils.Utils.settingsHelper; |
|||
|
|||
public class AccountSwitcherListAdapter extends ArrayAdapter<DataBox.CookieModel> { |
|||
private static final String TAG = "AccountSwitcherListAdap"; |
|||
|
|||
private final OnAccountClickListener clickListener; |
|||
private final OnAccountLongClickListener longClickListener; |
|||
|
|||
public AccountSwitcherListAdapter(@NonNull final Context context, |
|||
final int resource, |
|||
@NonNull final List<DataBox.CookieModel> allUsers, |
|||
final OnAccountClickListener clickListener, |
|||
final OnAccountLongClickListener longClickListener) { |
|||
super(context, resource, allUsers); |
|||
this.clickListener = clickListener; |
|||
this.longClickListener = longClickListener; |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public View getView(final int position, @Nullable final View convertView, @NonNull final ViewGroup parent) { |
|||
final DataBox.CookieModel model = getItem(position); |
|||
final String cookie = settingsHelper.getString(Constants.COOKIE); |
|||
if (convertView == null) { |
|||
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); |
|||
final PrefAccountSwitcherBinding binding = PrefAccountSwitcherBinding.inflate(layoutInflater, parent, false); |
|||
final ViewHolder viewHolder = new ViewHolder(binding); |
|||
viewHolder.itemView.setTag(viewHolder); |
|||
if (model == null) return viewHolder.itemView; |
|||
final boolean equals = model.getCookie().equals(cookie); |
|||
viewHolder.bind(model, equals, clickListener, longClickListener); |
|||
return viewHolder.itemView; |
|||
} |
|||
final ViewHolder viewHolder = (ViewHolder) convertView.getTag(); |
|||
if (model == null) return viewHolder.itemView; |
|||
final boolean equals = model.getCookie().equals(cookie); |
|||
viewHolder.bind(model, equals, clickListener, longClickListener); |
|||
return viewHolder.itemView; |
|||
} |
|||
|
|||
public interface OnAccountClickListener { |
|||
void onAccountClick(final DataBox.CookieModel model, final boolean isCurrent); |
|||
} |
|||
|
|||
public interface OnAccountLongClickListener { |
|||
boolean onAccountLongClick(final DataBox.CookieModel model, final boolean isCurrent); |
|||
} |
|||
|
|||
private static class ViewHolder { |
|||
private final View itemView; |
|||
private final PrefAccountSwitcherBinding binding; |
|||
|
|||
public ViewHolder(final PrefAccountSwitcherBinding binding) { |
|||
this.itemView = binding.getRoot(); |
|||
this.binding = binding; |
|||
binding.arrowDown.setImageResource(R.drawable.ic_check_24); |
|||
} |
|||
|
|||
@SuppressLint("SetTextI18n") |
|||
public void bind(final DataBox.CookieModel model, |
|||
final boolean isCurrent, |
|||
final OnAccountClickListener clickListener, |
|||
final OnAccountLongClickListener longClickListener) { |
|||
// Log.d(TAG, model.getFullName()); |
|||
itemView.setOnClickListener(v -> { |
|||
if (clickListener == null) return; |
|||
clickListener.onAccountClick(model, isCurrent); |
|||
}); |
|||
itemView.setOnLongClickListener(v -> { |
|||
if (longClickListener == null) return false; |
|||
return longClickListener.onAccountLongClick(model, isCurrent); |
|||
}); |
|||
binding.profilePic.setImageURI(model.getProfilePic()); |
|||
binding.username.setText("@" + model.getUsername()); |
|||
binding.fullName.setTypeface(null); |
|||
final String fullName = model.getFullName(); |
|||
if (TextUtils.isEmpty(fullName)) { |
|||
binding.fullName.setVisibility(View.GONE); |
|||
} else { |
|||
binding.fullName.setVisibility(View.VISIBLE); |
|||
binding.fullName.setText(fullName); |
|||
} |
|||
if (!isCurrent) { |
|||
binding.arrowDown.setVisibility(View.GONE); |
|||
return; |
|||
} |
|||
binding.fullName.setTypeface(binding.fullName.getTypeface(), Typeface.BOLD); |
|||
binding.arrowDown.setVisibility(View.VISIBLE); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,11 @@ |
|||
package awais.instagrabber.repositories; |
|||
|
|||
import retrofit2.Call; |
|||
import retrofit2.http.GET; |
|||
import retrofit2.http.Path; |
|||
|
|||
public interface ProfileRepository { |
|||
|
|||
@GET("api/v1/users/{uid}/info/") |
|||
Call<String> getUserInfo(@Path("uid") final String uid); |
|||
} |
@ -0,0 +1,41 @@ |
|||
package awais.instagrabber.repositories.responses; |
|||
|
|||
public class UserInfo { |
|||
private final String pk; |
|||
private final String username; |
|||
private final String fullName; |
|||
private final String profilePicUrl; |
|||
|
|||
public UserInfo(final String pk, final String username, final String fullName, final String profilePicUrl) { |
|||
this.pk = pk; |
|||
this.username = username; |
|||
this.fullName = fullName; |
|||
this.profilePicUrl = profilePicUrl; |
|||
} |
|||
|
|||
public String getPk() { |
|||
return pk; |
|||
} |
|||
|
|||
public String getUsername() { |
|||
return username; |
|||
} |
|||
|
|||
public String getFullName() { |
|||
return fullName; |
|||
} |
|||
|
|||
public String getProfilePicUrl() { |
|||
return profilePicUrl; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "UserInfo{" + |
|||
"uid='" + pk + '\'' + |
|||
", username='" + username + '\'' + |
|||
", fullName='" + fullName + '\'' + |
|||
", profilePicUrl='" + profilePicUrl + '\'' + |
|||
'}'; |
|||
} |
|||
} |
@ -1,4 +0,0 @@ |
|||
package awais.instagrabber.services; |
|||
|
|||
public interface FeedService { |
|||
} |
@ -0,0 +1,69 @@ |
|||
package awais.instagrabber.services; |
|||
|
|||
import android.util.Log; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
|
|||
import org.json.JSONException; |
|||
import org.json.JSONObject; |
|||
|
|||
import awais.instagrabber.repositories.ProfileRepository; |
|||
import awais.instagrabber.repositories.responses.UserInfo; |
|||
import awais.instagrabber.utils.Constants; |
|||
import retrofit2.Call; |
|||
import retrofit2.Callback; |
|||
import retrofit2.Response; |
|||
import retrofit2.Retrofit; |
|||
|
|||
public class ProfileService extends BaseService { |
|||
private static final String TAG = "ProfileService"; |
|||
|
|||
private final ProfileRepository repository; |
|||
|
|||
private static ProfileService instance; |
|||
|
|||
private ProfileService() { |
|||
final Retrofit retrofit = getRetrofitBuilder() |
|||
.baseUrl("https://i.instagram.com") |
|||
.build(); |
|||
repository = retrofit.create(ProfileRepository.class); |
|||
} |
|||
|
|||
public static ProfileService getInstance() { |
|||
if (instance == null) { |
|||
instance = new ProfileService(); |
|||
} |
|||
return instance; |
|||
} |
|||
|
|||
public void getUserInfo(final String uid, final ServiceCallback<UserInfo> callback) { |
|||
final Call<String> request = repository.getUserInfo(uid); |
|||
request.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
final String body = response.body(); |
|||
if (body == null) return; |
|||
try { |
|||
final JSONObject jsonObject = new JSONObject(body); |
|||
final JSONObject user = jsonObject.optJSONObject(Constants.EXTRAS_USER); |
|||
if (user == null) return; |
|||
// Log.d(TAG, "user: " + user.toString()); |
|||
final UserInfo userInfo = new UserInfo( |
|||
uid, |
|||
user.getString(Constants.EXTRAS_USERNAME), |
|||
user.optString("full_name"), |
|||
user.optString("profile_pic_url") |
|||
); |
|||
callback.onSuccess(userInfo); |
|||
} catch (JSONException e) { |
|||
Log.e(TAG, "Error parsing json", e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |
|||
callback.onFailure(t); |
|||
} |
|||
}); |
|||
} |
|||
} |
@ -0,0 +1,10 @@ |
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
|||
android:width="24dp" |
|||
android:height="24dp" |
|||
android:viewportWidth="24" |
|||
android:viewportHeight="24" |
|||
android:tint="?attr/colorControlNormal"> |
|||
<path |
|||
android:fillColor="@android:color/white" |
|||
android:pathData="M7,10l5,5 5,-5z"/> |
|||
</vector> |
@ -0,0 +1,10 @@ |
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
|||
android:width="24dp" |
|||
android:height="24dp" |
|||
android:viewportWidth="24" |
|||
android:viewportHeight="24" |
|||
android:tint="?attr/colorControlNormal"> |
|||
<path |
|||
android:fillColor="@android:color/white" |
|||
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/> |
|||
</vector> |
@ -0,0 +1,65 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<androidx.constraintlayout.widget.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="wrap_content" |
|||
android:background="?attr/selectableItemBackground" |
|||
android:clickable="true" |
|||
android:focusable="true" |
|||
android:padding="16dp"> |
|||
|
|||
<com.facebook.drawee.view.SimpleDraweeView |
|||
android:id="@+id/profile_pic" |
|||
android:layout_width="@dimen/image_size_40" |
|||
android:layout_height="@dimen/image_size_40" |
|||
android:scaleType="centerCrop" |
|||
app:layout_constraintStart_toStartOf="parent" |
|||
app:layout_constraintTop_toTopOf="parent" |
|||
app:roundAsCircle="true" /> |
|||
|
|||
<androidx.appcompat.widget.AppCompatTextView |
|||
android:id="@+id/full_name" |
|||
android:layout_width="0dp" |
|||
android:layout_height="0dp" |
|||
android:gravity="center_vertical" |
|||
android:paddingStart="16dp" |
|||
android:paddingLeft="16dp" |
|||
android:paddingEnd="16dp" |
|||
android:paddingRight="16dp" |
|||
android:textAppearance="@style/TextAppearance.AppCompat.Body1" |
|||
android:textStyle="bold" |
|||
app:layout_constraintBottom_toTopOf="@id/username" |
|||
app:layout_constraintEnd_toStartOf="@id/arrow_down" |
|||
app:layout_constraintStart_toEndOf="@id/profile_pic" |
|||
app:layout_constraintTop_toTopOf="parent" |
|||
tools:text="full name" /> |
|||
|
|||
<androidx.appcompat.widget.AppCompatTextView |
|||
android:id="@+id/username" |
|||
android:layout_width="0dp" |
|||
android:layout_height="0dp" |
|||
android:gravity="center_vertical" |
|||
android:paddingStart="16dp" |
|||
android:paddingLeft="16dp" |
|||
android:paddingEnd="16dp" |
|||
android:paddingRight="16dp" |
|||
app:layout_constraintBottom_toBottomOf="parent" |
|||
app:layout_constraintEnd_toStartOf="@id/arrow_down" |
|||
app:layout_constraintStart_toEndOf="@id/profile_pic" |
|||
app:layout_constraintTop_toBottomOf="@id/full_name" |
|||
tools:text="\@username" /> |
|||
|
|||
<androidx.appcompat.widget.AppCompatImageView |
|||
android:id="@+id/arrow_down" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:padding="8dp" |
|||
app:layout_constraintBottom_toBottomOf="parent" |
|||
app:layout_constraintEnd_toEndOf="parent" |
|||
app:layout_constraintStart_toEndOf="@id/full_name" |
|||
app:layout_constraintTop_toTopOf="parent" |
|||
app:srcCompat="@drawable/ic_arrow_drop_down_24" |
|||
app:tint="?colorAccent" /> |
|||
|
|||
</androidx.constraintlayout.widget.ConstraintLayout> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue