Austin Huang
4 years ago
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
52 changed files with 507 additions and 113 deletions
-
1app/src/main/java/awais/instagrabber/MainHelper.java
-
4app/src/main/java/awais/instagrabber/activities/CommentsViewer.java
-
14app/src/main/java/awais/instagrabber/activities/DirectMessagesActivity.java
-
3app/src/main/java/awais/instagrabber/activities/FollowViewer.java
-
1app/src/main/java/awais/instagrabber/activities/Login.java
-
9app/src/main/java/awais/instagrabber/activities/Main.java
-
5app/src/main/java/awais/instagrabber/activities/NotificationsViewer.java
-
6app/src/main/java/awais/instagrabber/activities/PostViewer.java
-
10app/src/main/java/awais/instagrabber/activities/ProfileViewer.java
-
21app/src/main/java/awais/instagrabber/activities/StoryViewer.java
-
55app/src/main/java/awais/instagrabber/adapters/DirectMessageMembersAdapter.java
-
7app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java
-
8app/src/main/java/awais/instagrabber/adapters/NotificationsAdapter.java
-
7app/src/main/java/awais/instagrabber/adapters/PostsAdapter.java
-
1app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java
-
1app/src/main/java/awais/instagrabber/adapters/viewholder/NotificationViewHolder.java
-
1app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectMessageActionLogViewHolder.java
-
1app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectMessagePlaceholderViewHolder.java
-
2app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java
-
2app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java
-
2app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java
-
1app/src/main/java/awais/instagrabber/asyncs/ProfilePictureFetcher.java
-
2app/src/main/java/awais/instagrabber/asyncs/direct_messages/DirectMessageInboxThreadFetcher.java
-
6app/src/main/java/awais/instagrabber/asyncs/i/iStoryStatusFetcher.java
-
2app/src/main/java/awais/instagrabber/asyncs/i/iTopicFetcher.java
-
1app/src/main/java/awais/instagrabber/dialogs/QuickAccessDialog.java
-
5app/src/main/java/awais/instagrabber/dialogs/SettingsDialog.java
-
2app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java
-
10app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java
-
209app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java
-
47app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java
-
4app/src/main/java/awais/instagrabber/models/FeedModel.java
-
2app/src/main/java/awais/instagrabber/models/NotificationModel.java
-
1app/src/main/java/awais/instagrabber/models/ViewerPostModel.java
-
1app/src/main/java/awais/instagrabber/utils/Constants.java
-
9app/src/main/java/awais/instagrabber/utils/FlavorTown.java
-
3app/src/main/java/awais/instagrabber/utils/SettingsHelper.java
-
10app/src/main/res/drawable-anydpi/ic_submit.xml
-
BINapp/src/main/res/drawable-hdpi/ic_submit.png
-
BINapp/src/main/res/drawable-mdpi/ic_submit.png
-
BINapp/src/main/res/drawable-xhdpi/ic_submit.png
-
BINapp/src/main/res/drawable-xxhdpi/ic_submit.png
-
18app/src/main/res/layout/activity_direct_messages.xml
-
1app/src/main/res/layout/activity_saved.xml
-
25app/src/main/res/layout/dialog_main_settings.xml
-
68app/src/main/res/layout/fragment_direct_messages_settings.xml
-
1app/src/main/res/layout/item_feed_top.xml
-
10app/src/main/res/layout/item_follow.xml
-
1app/src/main/res/layout/item_notification.xml
-
2app/src/main/res/layout/layout_include_notif_item.xml
-
14app/src/main/res/navigation/direct_messages_nav_graph.xml
-
4app/src/main/res/values/strings.xml
@ -0,0 +1,55 @@ |
|||||
|
package awais.instagrabber.adapters; |
||||
|
|
||||
|
import android.content.Context; |
||||
|
import android.view.LayoutInflater; |
||||
|
import android.view.View; |
||||
|
import android.view.ViewGroup; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.recyclerview.widget.RecyclerView; |
||||
|
|
||||
|
import com.bumptech.glide.Glide; |
||||
|
|
||||
|
import awais.instagrabber.R; |
||||
|
import awais.instagrabber.adapters.viewholder.FollowsViewHolder; |
||||
|
import awais.instagrabber.models.ProfileModel; |
||||
|
|
||||
|
public final class DirectMessageMembersAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { |
||||
|
private final ProfileModel[] profileModels; |
||||
|
private final View.OnClickListener onClickListener; |
||||
|
private final LayoutInflater layoutInflater; |
||||
|
|
||||
|
public DirectMessageMembersAdapter(final ProfileModel[] profileModels, final Context context, final View.OnClickListener onClickListener) { |
||||
|
this.profileModels = profileModels; |
||||
|
this.layoutInflater = LayoutInflater.from(context); |
||||
|
this.onClickListener = onClickListener; |
||||
|
} |
||||
|
|
||||
|
@NonNull |
||||
|
@Override |
||||
|
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { |
||||
|
final View view = layoutInflater.inflate(R.layout.item_follow, parent, false); |
||||
|
return new FollowsViewHolder(view); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) { |
||||
|
final ProfileModel model = profileModels[position]; |
||||
|
|
||||
|
final FollowsViewHolder followHolder = (FollowsViewHolder) holder; |
||||
|
if (model != null) { |
||||
|
followHolder.itemView.setTag(model); |
||||
|
followHolder.itemView.setOnClickListener(onClickListener); |
||||
|
|
||||
|
followHolder.tvUsername.setText(model.getUsername()); |
||||
|
followHolder.tvFullName.setText(model.getName()); |
||||
|
|
||||
|
Glide.with(layoutInflater.getContext()).load(model.getSdProfilePic()).into(followHolder.profileImage); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int getItemCount() { |
||||
|
return profileModels.length; |
||||
|
} |
||||
|
} |
@ -0,0 +1,209 @@ |
|||||
|
package awais.instagrabber.fragments.directmessages; |
||||
|
|
||||
|
import android.content.Intent; |
||||
|
import android.os.AsyncTask; |
||||
|
import android.os.Bundle; |
||||
|
import android.text.Editable; |
||||
|
import android.text.TextWatcher; |
||||
|
import android.util.Log; |
||||
|
import android.view.LayoutInflater; |
||||
|
import android.view.View; |
||||
|
import android.view.ViewGroup; |
||||
|
import android.widget.EditText; |
||||
|
import android.widget.LinearLayout; |
||||
|
import android.widget.Toast; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.annotation.Nullable; |
||||
|
import androidx.appcompat.app.AlertDialog; |
||||
|
import androidx.appcompat.widget.AppCompatButton; |
||||
|
import androidx.appcompat.widget.AppCompatImageView; |
||||
|
import androidx.fragment.app.Fragment; |
||||
|
import androidx.fragment.app.FragmentActivity; |
||||
|
import androidx.navigation.fragment.NavHostFragment; |
||||
|
import androidx.recyclerview.widget.LinearLayoutManager; |
||||
|
import androidx.recyclerview.widget.RecyclerView; |
||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; |
||||
|
|
||||
|
import java.io.DataOutputStream; |
||||
|
import java.net.HttpURLConnection; |
||||
|
import java.net.URL; |
||||
|
import java.net.URLEncoder; |
||||
|
|
||||
|
import awais.instagrabber.BuildConfig; |
||||
|
import awais.instagrabber.R; |
||||
|
import awais.instagrabber.activities.ProfileViewer; |
||||
|
import awais.instagrabber.adapters.DirectMessageMembersAdapter; |
||||
|
import awais.instagrabber.asyncs.direct_messages.DirectMessageInboxThreadFetcher; |
||||
|
import awais.instagrabber.databinding.FragmentDirectMessagesSettingsBinding; |
||||
|
import awais.instagrabber.interfaces.FetchListener; |
||||
|
import awais.instagrabber.models.ProfileModel; |
||||
|
import awais.instagrabber.models.direct_messages.InboxThreadModel; |
||||
|
import awais.instagrabber.utils.Constants; |
||||
|
import awais.instagrabber.utils.Utils; |
||||
|
|
||||
|
public class DirectMessageSettingsFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { |
||||
|
private static final String TAG = "DirectMessagesSettingsFrag"; |
||||
|
|
||||
|
private FragmentActivity fragmentActivity; |
||||
|
private RecyclerView userList; |
||||
|
private EditText titleText; |
||||
|
private AppCompatImageView titleSend; |
||||
|
private AppCompatButton btnLeave; |
||||
|
private LinearLayoutManager layoutManager; |
||||
|
private String threadId, threadTitle; |
||||
|
private final String cookie = Utils.settingsHelper.getString(Constants.COOKIE); |
||||
|
private AsyncTask<Void, Void, InboxThreadModel> currentlyRunning; |
||||
|
private DirectMessageMembersAdapter memberAdapter; |
||||
|
private View.OnClickListener clickListener; |
||||
|
|
||||
|
private final FetchListener<InboxThreadModel> fetchListener = new FetchListener<InboxThreadModel>() { |
||||
|
@Override |
||||
|
public void doBefore() {} |
||||
|
|
||||
|
@Override |
||||
|
public void onResult(final InboxThreadModel threadModel) { |
||||
|
memberAdapter = new DirectMessageMembersAdapter(threadModel.getUsers(), requireContext(), clickListener); |
||||
|
userList.setAdapter(memberAdapter); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
@Override |
||||
|
public void onCreate(@Nullable final Bundle savedInstanceState) { |
||||
|
super.onCreate(savedInstanceState); |
||||
|
fragmentActivity = requireActivity(); |
||||
|
|
||||
|
clickListener = v -> { |
||||
|
final Object tag = v.getTag(); |
||||
|
if (tag instanceof ProfileModel) { |
||||
|
// TODO: kick dialog |
||||
|
ProfileModel model = (ProfileModel) tag; |
||||
|
startActivity( |
||||
|
new Intent(requireContext(), ProfileViewer.class) |
||||
|
.putExtra(Constants.EXTRAS_USERNAME, model.getUsername()) |
||||
|
); |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public View onCreateView(@NonNull final LayoutInflater inflater, |
||||
|
final ViewGroup container, |
||||
|
final Bundle savedInstanceState) { |
||||
|
final FragmentDirectMessagesSettingsBinding binding = FragmentDirectMessagesSettingsBinding.inflate(inflater, container, false); |
||||
|
final LinearLayout root = binding.getRoot(); |
||||
|
layoutManager = new LinearLayoutManager(requireContext()); |
||||
|
|
||||
|
threadId = DirectMessageSettingsFragmentArgs.fromBundle(getArguments()).getThreadId(); |
||||
|
threadTitle = DirectMessageSettingsFragmentArgs.fromBundle(getArguments()).getTitle(); |
||||
|
binding.swipeRefreshLayout.setEnabled(false); |
||||
|
|
||||
|
userList = binding.userList; |
||||
|
userList.setHasFixedSize(true); |
||||
|
userList.setLayoutManager(layoutManager); |
||||
|
|
||||
|
titleText = binding.titleText; |
||||
|
titleText.setText(threadTitle); |
||||
|
|
||||
|
titleSend = binding.titleSend; |
||||
|
titleSend.setOnClickListener(v -> { |
||||
|
new ChangeSettings().execute("update_title"); |
||||
|
}); |
||||
|
|
||||
|
titleText.addTextChangedListener(new TextWatcher() { |
||||
|
@Override |
||||
|
public void afterTextChanged(Editable s) {} |
||||
|
|
||||
|
@Override |
||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {} |
||||
|
|
||||
|
@Override |
||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) { |
||||
|
titleSend.setVisibility(s.toString().equals(threadTitle) ? View.GONE : View.VISIBLE); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
btnLeave = binding.btnLeave; |
||||
|
btnLeave.setOnClickListener(v -> { |
||||
|
new AlertDialog.Builder(requireContext()).setTitle(R.string.dms_action_leave_question) |
||||
|
.setPositiveButton(R.string.yes, (x,y) -> { |
||||
|
new ChangeSettings().execute("leave"); |
||||
|
}) |
||||
|
.setNegativeButton(R.string.no, null) |
||||
|
.show(); |
||||
|
}); |
||||
|
|
||||
|
currentlyRunning = new DirectMessageInboxThreadFetcher(threadId, null, null, fetchListener).execute(); |
||||
|
return root; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onRefresh() { |
||||
|
stopCurrentExecutor(); |
||||
|
currentlyRunning = new DirectMessageInboxThreadFetcher(threadId, null, null, fetchListener).execute(); |
||||
|
} |
||||
|
|
||||
|
private void stopCurrentExecutor() { |
||||
|
if (currentlyRunning != null) { |
||||
|
try { |
||||
|
currentlyRunning.cancel(true); |
||||
|
} catch (final Exception e) { |
||||
|
if (BuildConfig.DEBUG) Log.e(TAG, "", e); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class ChangeSettings extends AsyncTask<String, Void, Void> { |
||||
|
String action; |
||||
|
boolean ok = false; |
||||
|
|
||||
|
protected Void doInBackground(String... rawAction) { |
||||
|
action = rawAction[0]; |
||||
|
final String url = "https://i.instagram.com/api/v1/direct_v2/threads/"+threadId+"/"+action+"/"; |
||||
|
try { |
||||
|
String urlParameters = "_csrftoken=" + cookie.split("csrftoken=")[1].split(";")[0] |
||||
|
+"&_uuid=" + Utils.settingsHelper.getString(Constants.DEVICE_UUID); |
||||
|
if (action.equals("update_title")) |
||||
|
urlParameters += "&title=" + URLEncoder.encode(titleText.getText().toString(), "UTF-8") |
||||
|
.replaceAll("\\+", "%20").replaceAll("%21", "!").replaceAll("%27", "'") |
||||
|
.replaceAll("%28", "(").replaceAll("%29", ")").replaceAll("%7E", "~"); |
||||
|
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); |
||||
|
urlConnection.setRequestMethod("POST"); |
||||
|
urlConnection.setUseCaches(false); |
||||
|
urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT); |
||||
|
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |
||||
|
urlConnection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length)); |
||||
|
urlConnection.setDoOutput(true); |
||||
|
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream()); |
||||
|
wr.writeBytes(urlParameters); |
||||
|
wr.flush(); |
||||
|
wr.close(); |
||||
|
urlConnection.connect(); |
||||
|
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { |
||||
|
ok = true; |
||||
|
} |
||||
|
urlConnection.disconnect(); |
||||
|
} catch (Throwable ex) { |
||||
|
Log.e("austin_debug", "unsend: " + ex); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void onPostExecute(Void result) { |
||||
|
if (ok) { |
||||
|
Toast.makeText(requireContext(), R.string.dms_action_success, Toast.LENGTH_SHORT).show(); |
||||
|
if (action.equals("update_title")) { |
||||
|
threadTitle = titleText.getText().toString(); |
||||
|
titleSend.setVisibility(View.GONE); |
||||
|
titleText.clearFocus(); |
||||
|
} |
||||
|
else if (action.equals("leave")) { |
||||
|
DirectMessageInboxFragment.afterLeave = true; |
||||
|
NavHostFragment.findNavController(DirectMessageSettingsFragment.this).popBackStack(R.id.directMessagesInboxFragment, false); |
||||
|
} |
||||
|
} |
||||
|
else Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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> |
After Width: 36 | Height: 36 | Size: 186 B |
After Width: 24 | Height: 24 | Size: 139 B |
After Width: 48 | Height: 48 | Size: 323 B |
After Width: 72 | Height: 72 | Size: 337 B |
@ -0,0 +1,68 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="match_parent" |
||||
|
android:orientation="vertical"> |
||||
|
|
||||
|
<LinearLayout |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content"> |
||||
|
|
||||
|
<EditText |
||||
|
android:id="@+id/titleText" |
||||
|
android:layout_width="0dp" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_weight="1" |
||||
|
android:gravity="bottom" |
||||
|
android:importantForAutofill="no" |
||||
|
android:inputType="textMultiLine" |
||||
|
android:maxLength="2200" |
||||
|
android:maxLines="10" |
||||
|
android:paddingStart="8dp" |
||||
|
android:paddingLeft="8dp" |
||||
|
android:paddingEnd="4dp" |
||||
|
android:paddingRight="4dp" |
||||
|
android:scrollHorizontally="false" /> |
||||
|
|
||||
|
<androidx.appcompat.widget.AppCompatImageView |
||||
|
android:id="@+id/titleSend" |
||||
|
android:layout_width="wrap_content" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_gravity="center" |
||||
|
android:background="?selectableItemBackgroundBorderless" |
||||
|
android:clickable="true" |
||||
|
android:focusable="true" |
||||
|
android:paddingStart="4dp" |
||||
|
android:paddingLeft="4dp" |
||||
|
android:paddingTop="4dp" |
||||
|
android:paddingEnd="8dp" |
||||
|
android:paddingRight="8dp" |
||||
|
android:paddingBottom="4dp" |
||||
|
android:visibility="gone" |
||||
|
app:srcCompat="@drawable/ic_submit" /> |
||||
|
</LinearLayout> |
||||
|
|
||||
|
<androidx.appcompat.widget.AppCompatButton |
||||
|
android:id="@+id/btnLeave" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_marginLeft="8dp" |
||||
|
android:layout_marginStart="6dp" |
||||
|
android:layout_marginRight="8dp" |
||||
|
android:text="@string/dms_action_leave" |
||||
|
android:textColor="@color/btn_red_text_color" |
||||
|
android:textSize="18sp" |
||||
|
app:backgroundTint="@color/btn_red_background" /> |
||||
|
|
||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout |
||||
|
android:id="@+id/swipeRefreshLayout" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="0dp" |
||||
|
android:layout_weight="1"> |
||||
|
<androidx.recyclerview.widget.RecyclerView |
||||
|
android:id="@+id/userList" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="match_parent" /> |
||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> |
||||
|
</LinearLayout> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue