1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-22 22:57:29 +00:00

Remove read/write storage permissions.

Add an activity to select directory.
This commit is contained in:
Ammar Githam 2021-04-04 23:53:10 +09:00
parent 7577e82ac1
commit 9b691a453e
24 changed files with 649 additions and 337 deletions

View File

@ -4,8 +4,8 @@
package="awais.instagrabber"> package="awais.instagrabber">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!--<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />-->
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<!--<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />--> <!--<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />-->
@ -133,6 +133,7 @@
<activity <activity
android:name=".utils.ProcessPhoenix" android:name=".utils.ProcessPhoenix"
android:theme="@style/Theme.AppCompat.Translucent" /> android:theme="@style/Theme.AppCompat.Translucent" />
<activity android:name=".activities.DirectorySelectActivity" />
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"

View File

@ -14,7 +14,6 @@ import java.text.SimpleDateFormat;
import java.util.UUID; import java.util.UUID;
import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.LocaleUtils; import awais.instagrabber.utils.LocaleUtils;
import awais.instagrabber.utils.SettingsHelper; import awais.instagrabber.utils.SettingsHelper;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
@ -27,8 +26,6 @@ import static awais.instagrabber.utils.Utils.clipboardManager;
import static awais.instagrabber.utils.Utils.datetimeParser; import static awais.instagrabber.utils.Utils.datetimeParser;
import static awais.instagrabber.utils.Utils.settingsHelper; import static awais.instagrabber.utils.Utils.settingsHelper;
//import awaisomereport.LogCollector;
//import static awais.instagrabber.utils.Utils.logCollector;
public final class InstaGrabberApplication extends Application { public final class InstaGrabberApplication extends Application {
private static final String TAG = "InstaGrabberApplication"; private static final String TAG = "InstaGrabberApplication";
@ -90,6 +87,5 @@ public final class InstaGrabberApplication extends Application {
if (TextUtils.isEmpty(settingsHelper.getString(Constants.DEVICE_UUID))) { if (TextUtils.isEmpty(settingsHelper.getString(Constants.DEVICE_UUID))) {
settingsHelper.putString(Constants.DEVICE_UUID, UUID.randomUUID().toString()); settingsHelper.putString(Constants.DEVICE_UUID, UUID.randomUUID().toString());
} }
DownloadUtils.init(this);
} }
} }

View File

@ -1,6 +1,5 @@
package awais.instagrabber.activities; package awais.instagrabber.activities;
import android.Manifest;
import android.app.Notification; import android.app.Notification;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -14,10 +13,8 @@ import android.view.WindowManager;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.asyncs.PostFetcher; import awais.instagrabber.asyncs.PostFetcher;
@ -74,11 +71,11 @@ public final class DirectDownload extends AppCompatActivity {
} }
private synchronized void checkPermissions() { private synchronized void checkPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { // if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
doDownload(); doDownload();
return; // return;
} // }
ActivityCompat.requestPermissions(this, DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); // ActivityCompat.requestPermissions(this, DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
} }
@Override @Override

View File

@ -0,0 +1,128 @@
package awais.instagrabber.activities;
import android.content.Intent;
import android.content.UriPermission;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import awais.instagrabber.databinding.ActivityDirectorySelectBinding;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.Utils;
public class DirectorySelectActivity extends BaseLanguageActivity {
private static final String TAG = DirectorySelectActivity.class.getSimpleName();
public static final int SELECT_DIR_REQUEST_CODE = 1090;
private Uri initialUri;
private ActivityDirectorySelectBinding binding;
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityDirectorySelectBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.selectDir.setOnClickListener(v -> openDirectoryChooser());
setInitialUri();
}
private void setInitialUri() {
AppExecutors.getInstance().mainThread().execute(() -> {
final Intent intent = getIntent();
if (intent == null) {
setMessage();
return;
}
final Parcelable initialUriParcelable = intent.getParcelableExtra(Constants.EXTRA_INITIAL_URI);
if (!(initialUriParcelable instanceof Uri)) {
setMessage();
return;
}
initialUri = (Uri) initialUriParcelable;
setMessage();
});
}
private void setMessage() {
if (initialUri == null) {
// default message
binding.message.setText("Select a directory which Barinsta will use for downloads and temp files");
return;
}
if (!initialUri.toString().startsWith("content")) {
final String message = String.format("Android has changed the way apps can access files and directories on storage.\n\n" +
"Please re-select the directory '%s' after clicking the button below",
initialUri.toString());
binding.message.setText(message);
return;
}
final List<UriPermission> existingPermissions = getContentResolver().getPersistedUriPermissions();
final boolean anyMatch = existingPermissions.stream().anyMatch(uriPermission -> uriPermission.getUri().equals(initialUri));
if (!anyMatch) {
// permission revoked message
final String message = "Permissions for the previously selected directory '%s' were revoked by the system.\n\n" +
"Re-select the directory or select a new directory.";
final DocumentFile documentFile = DocumentFile.fromSingleUri(this, initialUri);
String path;
try {
path = URLDecoder.decode(initialUri.toString(), StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
path = initialUri.toString();
}
if (documentFile != null) {
try {
final File file = Utils.getDocumentFileRealPath(this, documentFile);
if (file != null) {
path = file.getAbsolutePath();
}
} catch (Exception e) {
Log.e(TAG, "setMessage: ", e);
}
}
binding.message.setText(String.format(message, path));
}
}
private void openDirectoryChooser() {
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && initialUri != null) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialUri);
}
startActivityForResult(intent, SELECT_DIR_REQUEST_CODE);
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode != SELECT_DIR_REQUEST_CODE) return;
if (resultCode != RESULT_OK) {
// Show error
return;
}
if (data == null || data.getData() == null) {
// show error
return;
}
try {
Utils.setupSelectedDir(this, data);
} catch (Exception e) {
// show error
}
}
}

View File

@ -79,6 +79,7 @@ import awais.instagrabber.services.DMSyncAlarmReceiver;
import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils; import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.FlavorTown; import awais.instagrabber.utils.FlavorTown;
import awais.instagrabber.utils.IntentUtils; import awais.instagrabber.utils.IntentUtils;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
@ -92,6 +93,7 @@ import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
import static awais.instagrabber.utils.Constants.EXTRA_INITIAL_URI;
import static awais.instagrabber.utils.NavigationExtensions.setupWithNavController; import static awais.instagrabber.utils.NavigationExtensions.setupWithNavController;
import static awais.instagrabber.utils.Utils.settingsHelper; import static awais.instagrabber.utils.Utils.settingsHelper;
@ -134,6 +136,16 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
@Override @Override
protected void onCreate(@Nullable final Bundle savedInstanceState) { protected void onCreate(@Nullable final Bundle savedInstanceState) {
try {
DownloadUtils.init(this);
} catch (DownloadUtils.ReselectDocumentTreeException e) {
super.onCreate(savedInstanceState);
final Intent intent = new Intent(this, DirectorySelectActivity.class);
intent.putExtra(EXTRA_INITIAL_URI, e.getInitialUri());
startActivity(intent);
finish();
return;
}
RetrofitFactory.setup(this); RetrofitFactory.setup(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater()); binding = ActivityMainBinding.inflate(getLayoutInflater());
@ -221,7 +233,9 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
@Override @Override
protected void onSaveInstanceState(@NonNull final Bundle outState) { protected void onSaveInstanceState(@NonNull final Bundle outState) {
outState.putString(FIRST_FRAGMENT_GRAPH_INDEX_KEY, String.valueOf(firstFragmentGraphIndex)); outState.putString(FIRST_FRAGMENT_GRAPH_INDEX_KEY, String.valueOf(firstFragmentGraphIndex));
if (binding != null) {
outState.putString(LAST_SELECT_NAV_MENU_ID, String.valueOf(binding.bottomNavView.getSelectedItemId())); outState.putString(LAST_SELECT_NAV_MENU_ID, String.valueOf(binding.bottomNavView.getSelectedItemId()));
}
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@ -265,7 +279,9 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
Log.e(TAG, "onDestroy: ", e); Log.e(TAG, "onDestroy: ", e);
} }
unbindActivityCheckerService(); unbindActivityCheckerService();
try {
RetrofitFactory.getInstance().destroy(); RetrofitFactory.getInstance().destroy();
} catch (Exception ignored) {}
} }
@Override @Override

View File

@ -213,7 +213,7 @@ public class CreateBackupDialogFragment extends DialogFragment {
// Optionally, specify a URI for the directory that should be opened in // Optionally, specify a URI for the directory that should be opened in
// the system file picker when your app creates the document. // the system file picker when your app creates the document.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, DownloadUtils.getDownloadDir().getUri()); intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, DownloadUtils.getBackupsDir().getUri());
} }
startActivityForResult(intent, CREATE_FILE_REQUEST_CODE); startActivityForResult(intent, CREATE_FILE_REQUEST_CODE);

View File

@ -15,7 +15,6 @@ import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
@ -109,11 +108,11 @@ public class ProfilePicDialogFragment extends DialogFragment {
binding.download.setOnClickListener(v -> { binding.download.setOnClickListener(v -> {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) { // if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
downloadProfilePicture(); downloadProfilePicture();
return; // return;
} // }
requestPermissions(DownloadUtils.PERMS, 8020); // requestPermissions(DownloadUtils.PERMS, 8020);
}); });
} }

View File

@ -27,7 +27,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.core.graphics.ColorUtils; import androidx.core.graphics.ColorUtils;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController; import androidx.navigation.NavController;
@ -65,9 +64,6 @@ import awais.instagrabber.utils.Utils;
import awais.instagrabber.webservices.CollectionService; import awais.instagrabber.webservices.CollectionService;
import awais.instagrabber.webservices.ServiceCallback; import awais.instagrabber.webservices.ServiceCallback;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
public class CollectionPostsFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { public class CollectionPostsFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "CollectionPostsFragment"; private static final String TAG = "CollectionPostsFragment";
private static final int STORAGE_PERM_REQUEST_CODE = 8020; private static final int STORAGE_PERM_REQUEST_CODE = 8020;
@ -105,12 +101,12 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
if (CollectionPostsFragment.this.selectedFeedModels == null) return false; if (CollectionPostsFragment.this.selectedFeedModels == null) return false;
final Context context = getContext(); final Context context = getContext();
if (context == null) return false; if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(CollectionPostsFragment.this.selectedFeedModels)); DownloadUtils.download(context, ImmutableList.copyOf(CollectionPostsFragment.this.selectedFeedModels));
binding.posts.endSelection(); binding.posts.endSelection();
return true; // return true;
} // }
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
} }
return false; return false;
} }
@ -140,13 +136,13 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
public void onDownloadClick(final Media feedModel, final int childPosition) { public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition); DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return; // return;
} // }
downloadFeedModel = feedModel; // downloadFeedModel = feedModel;
downloadChildPosition = -1; // downloadChildPosition = -1;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
} }
@Override @Override
@ -288,8 +284,7 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
if (item.getItemId() == R.id.layout) { if (item.getItemId() == R.id.layout) {
showPostsLayoutPreferences(); showPostsLayoutPreferences();
return true; return true;
} } else if (item.getItemId() == R.id.delete) {
else if (item.getItemId() == R.id.delete) {
final Context context = getContext(); final Context context = getContext();
new AlertDialog.Builder(context) new AlertDialog.Builder(context)
.setTitle(R.string.delete_collection) .setTitle(R.string.delete_collection)
@ -309,15 +304,13 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
Log.e(TAG, "Error deleting collection", t); Log.e(TAG, "Error deleting collection", t);
try { try {
Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
} } catch (final Throwable e) {}
catch(final Throwable e) {}
} }
}); });
}) })
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.show(); .show();
} } else if (item.getItemId() == R.id.edit) {
else if (item.getItemId() == R.id.edit) {
final Context context = getContext(); final Context context = getContext();
final EditText input = new EditText(context); final EditText input = new EditText(context);
new AlertDialog.Builder(context) new AlertDialog.Builder(context)
@ -339,8 +332,7 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
Log.e(TAG, "Error editing collection", t); Log.e(TAG, "Error editing collection", t);
try { try {
Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
} } catch (final Throwable e) {}
catch(final Throwable e) {}
} }
}); });
}) })

View File

@ -24,7 +24,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDirections; import androidx.navigation.NavDirections;
@ -70,8 +69,6 @@ import awais.instagrabber.webservices.ServiceCallback;
import awais.instagrabber.webservices.StoriesService; import awais.instagrabber.webservices.StoriesService;
import awais.instagrabber.webservices.TagsService; import awais.instagrabber.webservices.TagsService;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
import static awais.instagrabber.utils.Utils.settingsHelper; import static awais.instagrabber.utils.Utils.settingsHelper;
public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
@ -121,13 +118,13 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (HashTagFragment.this.selectedFeedModels == null) return false; if (HashTagFragment.this.selectedFeedModels == null) return false;
final Context context = getContext(); final Context context = getContext();
if (context == null) return false; if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(HashTagFragment.this.selectedFeedModels)); DownloadUtils.download(context, ImmutableList.copyOf(HashTagFragment.this.selectedFeedModels));
binding.posts.endSelection(); binding.posts.endSelection();
return true; return true;
} // }
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
return true; // return true;
} }
return false; return false;
} }
@ -157,13 +154,13 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
public void onDownloadClick(final Media feedModel, final int childPosition) { public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition); DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return; // return;
} // }
downloadFeedModel = feedModel; // downloadFeedModel = feedModel;
downloadChildPosition = childPosition; // downloadChildPosition = childPosition;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
} }
@Override @Override
@ -400,8 +397,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
try { try {
Toast.makeText(getContext(), R.string.error_loading_hashtag, Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), R.string.error_loading_hashtag, Toast.LENGTH_SHORT).show();
binding.swipeRefreshLayout.setEnabled(false); binding.swipeRefreshLayout.setEnabled(false);
} } catch (Exception ignored) {}
catch (Exception ignored) {}
return; return;
} }
setTitle(); setTitle();
@ -438,7 +434,8 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
return; return;
} }
hashtagDetailsBinding.btnFollowTag.setText(R.string.unfollow); hashtagDetailsBinding.btnFollowTag.setText(R.string.unfollow);
hashtagDetailsBinding.btnFollowTag.setChipIconResource(R.drawable.ic_outline_person_add_disabled_24); hashtagDetailsBinding.btnFollowTag
.setChipIconResource(R.drawable.ic_outline_person_add_disabled_24);
} }
@Override @Override

View File

@ -22,7 +22,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDirections; import androidx.navigation.NavDirections;
@ -66,13 +65,8 @@ import awais.instagrabber.webservices.LocationService;
import awais.instagrabber.webservices.ServiceCallback; import awais.instagrabber.webservices.ServiceCallback;
import awais.instagrabber.webservices.StoriesService; import awais.instagrabber.webservices.StoriesService;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
import static awais.instagrabber.utils.Utils.settingsHelper; import static awais.instagrabber.utils.Utils.settingsHelper;
//import awaisomereport.LogCollector;
//import static awais.instagrabber.utils.Utils.logCollector;
public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "LocationFragment"; private static final String TAG = "LocationFragment";
private static final int STORAGE_PERM_REQUEST_CODE = 8020; private static final int STORAGE_PERM_REQUEST_CODE = 8020;
@ -118,12 +112,12 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
if (LocationFragment.this.selectedFeedModels == null) return false; if (LocationFragment.this.selectedFeedModels == null) return false;
final Context context = getContext(); final Context context = getContext();
if (context == null) return false; if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(LocationFragment.this.selectedFeedModels)); DownloadUtils.download(context, ImmutableList.copyOf(LocationFragment.this.selectedFeedModels));
binding.posts.endSelection(); binding.posts.endSelection();
return true; return true;
} // }
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
} }
return false; return false;
} }
@ -153,13 +147,13 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
public void onDownloadClick(final Media feedModel, final int childPosition) { public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition); DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return; // return;
} // }
downloadFeedModel = feedModel; // downloadFeedModel = feedModel;
downloadChildPosition = childPosition; // downloadChildPosition = childPosition;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
} }
@Override @Override
@ -399,8 +393,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
try { try {
Toast.makeText(getContext(), R.string.error_loading_location, Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), R.string.error_loading_location, Toast.LENGTH_SHORT).show();
binding.swipeRefreshLayout.setEnabled(false); binding.swipeRefreshLayout.setEnabled(false);
} } catch (Exception ignored) {}
catch (Exception ignored) {}
return; return;
} }
setTitle(); setTitle();

View File

@ -43,7 +43,6 @@ import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ContextThemeWrapper; import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.PermissionChecker;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.core.widget.NestedScrollView; import androidx.core.widget.NestedScrollView;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
@ -100,9 +99,7 @@ import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.Utils;
import awais.instagrabber.viewmodels.PostViewV2ViewModel; import awais.instagrabber.viewmodels.PostViewV2ViewModel;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG; import static awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
import static awais.instagrabber.utils.Utils.settingsHelper; import static awais.instagrabber.utils.Utils.settingsHelper;
public class PostViewV2Fragment extends SharedElementTransitionDialogFragment implements EditTextDialogFragment.EditTextDialogFragmentCallback { public class PostViewV2Fragment extends SharedElementTransitionDialogFragment implements EditTextDialogFragment.EditTextDialogFragmentCallback {
@ -622,11 +619,11 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
private void setupDownload() { private void setupDownload() {
binding.download.setOnClickListener(v -> { binding.download.setOnClickListener(v -> {
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, viewModel.getMedia(), sliderPosition); DownloadUtils.showDownloadDialog(context, viewModel.getMedia(), sliderPosition);
return; // return;
} // }
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}); });
binding.download.setOnLongClickListener(v -> { binding.download.setOnLongClickListener(v -> {
Utils.displayToastAboveView(context, v, getString(R.string.action_download)); Utils.displayToastAboveView(context, v, getString(R.string.action_download));

View File

@ -18,7 +18,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDirections; import androidx.navigation.NavDirections;
@ -45,8 +44,6 @@ import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.Utils;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
import static awais.instagrabber.utils.Utils.settingsHelper; import static awais.instagrabber.utils.Utils.settingsHelper;
public final class SavedViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { public final class SavedViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
@ -86,12 +83,12 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
if (SavedViewerFragment.this.selectedFeedModels == null) return false; if (SavedViewerFragment.this.selectedFeedModels == null) return false;
final Context context = getContext(); final Context context = getContext();
if (context == null) return false; if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(SavedViewerFragment.this.selectedFeedModels)); DownloadUtils.download(context, ImmutableList.copyOf(SavedViewerFragment.this.selectedFeedModels));
binding.posts.endSelection(); binding.posts.endSelection();
return true; // return true;
} // }
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
} }
return false; return false;
} }
@ -121,13 +118,13 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
public void onDownloadClick(final Media feedModel, final int childPosition) { public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition); DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return; // return;
} // }
downloadFeedModel = feedModel; // downloadFeedModel = feedModel;
downloadChildPosition = childPosition; // downloadChildPosition = childPosition;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
} }
@Override @Override

View File

@ -29,8 +29,6 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.view.GestureDetectorCompat; import androidx.core.view.GestureDetectorCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
@ -210,10 +208,10 @@ public class StoryViewerFragment extends Fragment {
if (context == null) return false; if (context == null) return false;
int itemId = item.getItemId(); int itemId = item.getItemId();
if (itemId == R.id.action_download) { if (itemId == R.id.action_download) {
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) // if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED)
downloadStory(); downloadStory();
else // else
ActivityCompat.requestPermissions(requireActivity(), DownloadUtils.PERMS, 8020); // ActivityCompat.requestPermissions(requireActivity(), DownloadUtils.PERMS, 8020);
return true; return true;
} }
if (itemId == R.id.action_dms) { if (itemId == R.id.action_dms) {

View File

@ -23,7 +23,6 @@ import androidx.activity.OnBackPressedDispatcher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.core.graphics.ColorUtils; import androidx.core.graphics.ColorUtils;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController; import androidx.navigation.NavController;
@ -51,17 +50,14 @@ import awais.instagrabber.databinding.FragmentTopicPostsBinding;
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.fragments.main.DiscoverFragmentDirections; import awais.instagrabber.fragments.main.DiscoverFragmentDirections;
import awais.instagrabber.models.PostsLayoutPreferences; import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.repositories.responses.discover.TopicCluster;
import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.discover.TopicCluster;
import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DownloadUtils; import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.ResponseBodyUtils; import awais.instagrabber.utils.ResponseBodyUtils;
import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.Utils;
import awais.instagrabber.webservices.DiscoverService; import awais.instagrabber.webservices.DiscoverService;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final int STORAGE_PERM_REQUEST_CODE = 8020; private static final int STORAGE_PERM_REQUEST_CODE = 8020;
private static final int STORAGE_PERM_REQUEST_CODE_FOR_SELECTION = 8030; private static final int STORAGE_PERM_REQUEST_CODE_FOR_SELECTION = 8030;
@ -97,12 +93,12 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O
if (TopicPostsFragment.this.selectedFeedModels == null) return false; if (TopicPostsFragment.this.selectedFeedModels == null) return false;
final Context context = getContext(); final Context context = getContext();
if (context == null) return false; if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(TopicPostsFragment.this.selectedFeedModels)); DownloadUtils.download(context, ImmutableList.copyOf(TopicPostsFragment.this.selectedFeedModels));
binding.posts.endSelection(); binding.posts.endSelection();
return true; return true;
} // }
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
} }
return false; return false;
} }
@ -132,13 +128,13 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O
public void onDownloadClick(final Media feedModel, final int childPosition) { public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition); DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return; // return;
} // }
downloadFeedModel = feedModel; // downloadFeedModel = feedModel;
downloadChildPosition = -1; // downloadChildPosition = -1;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
} }
@Override @Override

View File

@ -30,7 +30,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData; import androidx.lifecycle.MediatorLiveData;
@ -1337,13 +1336,13 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
return; return;
} }
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) { // if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
DownloadUtils.download(context, media); DownloadUtils.download(context, media);
Toast.makeText(context, R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show();
return; // return;
} // }
tempMedia = media; // tempMedia = media;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
} }
@NonNull @NonNull

View File

@ -19,7 +19,6 @@ import androidx.activity.OnBackPressedDispatcher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController; import androidx.navigation.NavController;
@ -55,9 +54,6 @@ import awais.instagrabber.viewmodels.FeedStoriesViewModel;
import awais.instagrabber.webservices.ServiceCallback; import awais.instagrabber.webservices.ServiceCallback;
import awais.instagrabber.webservices.StoriesService; import awais.instagrabber.webservices.StoriesService;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "FeedFragment"; private static final String TAG = "FeedFragment";
private static final int STORAGE_PERM_REQUEST_CODE = 8020; private static final int STORAGE_PERM_REQUEST_CODE = 8020;
@ -123,13 +119,13 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
public void onDownloadClick(final Media feedModel, final int childPosition) { public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition); DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return; // return;
} // }
downloadFeedModel = feedModel; // downloadFeedModel = feedModel;
downloadChildPosition = childPosition; // downloadChildPosition = childPosition;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
} }
@Override @Override
@ -204,13 +200,13 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
if (FeedFragment.this.selectedFeedModels == null) return false; if (FeedFragment.this.selectedFeedModels == null) return false;
final Context context = getContext(); final Context context = getContext();
if (context == null) return false; if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(FeedFragment.this.selectedFeedModels)); DownloadUtils.download(context, ImmutableList.copyOf(FeedFragment.this.selectedFeedModels));
binding.feedRecyclerView.endSelection(); binding.feedRecyclerView.endSelection();
return true; return true;
} // }
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
return true; // return true;
} }
return false; return false;
} }

View File

@ -28,7 +28,6 @@ import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.content.res.AppCompatResources;
import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
@ -98,9 +97,7 @@ import awais.instagrabber.webservices.ServiceCallback;
import awais.instagrabber.webservices.StoriesService; import awais.instagrabber.webservices.StoriesService;
import awais.instagrabber.webservices.UserService; import awais.instagrabber.webservices.UserService;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG; import static awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "ProfileFragment"; private static final String TAG = "ProfileFragment";
@ -164,13 +161,13 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (ProfileFragment.this.selectedFeedModels == null) return false; if (ProfileFragment.this.selectedFeedModels == null) return false;
final Context context = getContext(); final Context context = getContext();
if (context == null) return false; if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(ProfileFragment.this.selectedFeedModels)); DownloadUtils.download(context, ImmutableList.copyOf(ProfileFragment.this.selectedFeedModels));
binding.postsRecyclerView.endSelection(); binding.postsRecyclerView.endSelection();
return true; return true;
} // }
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
return true; // return true;
} }
return false; return false;
} }
@ -200,13 +197,13 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
public void onDownloadClick(final Media feedModel, final int childPosition) { public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { // if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition); DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return; // return;
} // }
downloadFeedModel = feedModel; // downloadFeedModel = feedModel;
downloadChildPosition = childPosition; // downloadChildPosition = childPosition;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); // requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
} }
@Override @Override

View File

@ -1,13 +1,11 @@
package awais.instagrabber.fragments.settings; package awais.instagrabber.fragments.settings;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatButton; import androidx.appcompat.widget.AppCompatButton;
import androidx.appcompat.widget.AppCompatTextView; import androidx.appcompat.widget.AppCompatTextView;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
@ -21,15 +19,14 @@ import com.google.android.material.switchmaterial.SwitchMaterial;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import static android.app.Activity.RESULT_OK;
import static awais.instagrabber.utils.Constants.FOLDER_PATH; import static awais.instagrabber.utils.Constants.FOLDER_PATH;
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO; import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
import static awais.instagrabber.utils.Utils.settingsHelper; import static awais.instagrabber.utils.Utils.settingsHelper;
public class DownloadsPreferencesFragment extends BasePreferencesFragment { public class DownloadsPreferencesFragment extends BasePreferencesFragment {
private static final String TAG = DownloadsPreferencesFragment.class.getSimpleName(); private static final String TAG = DownloadsPreferencesFragment.class.getSimpleName();
private static final int SELECT_DIR_REQUEST_CODE = 1;
private SaveToCustomFolderPreference.ResultCallback resultCallback; private SaveToCustomFolderPreference.ResultCallback resultCallback;
@Override @Override
@ -37,7 +34,7 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
screen.addPreference(getDownloadUserFolderPreference(context)); screen.addPreference(getDownloadUserFolderPreference(context));
screen.addPreference(getSaveToCustomFolderPreference(context)); // screen.addPreference(getSaveToCustomFolderPreference(context));
screen.addPreference(getPrependUsernameToFilenamePreference(context)); screen.addPreference(getPrependUsernameToFilenamePreference(context));
} }
@ -49,41 +46,63 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
return preference; return preference;
} }
private Preference getSaveToCustomFolderPreference(@NonNull final Context context) { // private Preference getSaveToCustomFolderPreference(@NonNull final Context context) {
return new SaveToCustomFolderPreference(context, (resultCallback) -> { // return new SaveToCustomFolderPreference(context, checked -> {
// Choose a directory using the system's file picker. // try {
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); // DownloadUtils.init(context);
startActivityForResult(intent, SELECT_DIR_REQUEST_CODE); // } catch (DownloadUtils.ReselectDocumentTreeException e) {
this.resultCallback = resultCallback; // if (!checked) return;
// startDocumentSelector(e.getInitialUri());
// } catch (Exception e) {
// Log.e(TAG, "getSaveToCustomFolderPreference: ", e);
// }
// }, (resultCallback) -> {
// // Choose a directory using the system's file picker.
// startDocumentSelector(null);
// this.resultCallback = resultCallback;
//
// // new DirectoryChooser()
// // .setInitialDirectory(settingsHelper.getString(FOLDER_PATH))
// // .setInteractionListener(file -> {
// // settingsHelper.putString(FOLDER_PATH, file.getAbsolutePath());
// // resultCallback.onResult(file.getAbsolutePath());
// // })
// // .show(getParentFragmentManager(), null);
// });
// }
// new DirectoryChooser() // private void startDocumentSelector(final Uri initialUri) {
// .setInitialDirectory(settingsHelper.getString(FOLDER_PATH)) // final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
// .setInteractionListener(file -> { // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && initialUri != null) {
// settingsHelper.putString(FOLDER_PATH, file.getAbsolutePath()); // intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialUri);
// resultCallback.onResult(file.getAbsolutePath()); // }
// }) // startActivityForResult(intent, SELECT_DIR_REQUEST_CODE);
// .show(getParentFragmentManager(), null); // }
});
}
@Override // @Override
public void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) { // public void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
if (data == null || data.getData() == null) return; // if (requestCode != SELECT_DIR_REQUEST_CODE) return;
if (resultCode != RESULT_OK || requestCode != SELECT_DIR_REQUEST_CODE) return; // final Context context = getContext();
final Context context = getContext(); // if (context == null) return;
if (context == null) return; // if (resultCode != RESULT_OK) {
final Uri dirUri = data.getData(); // try {
Log.d(TAG, "onActivityResult: " + dirUri); // DownloadUtils.init(context, true);
final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // } catch (Exception ignored) {}
context.getContentResolver().takePersistableUriPermission(dirUri, takeFlags); // return;
final DocumentFile root = DocumentFile.fromTreeUri(context, dirUri); // }
settingsHelper.putString(FOLDER_PATH, data.getData().toString()); // if (data == null || data.getData() == null) return;
if (resultCallback != null) { // Utils.setupSelectedDir(context, data);
resultCallback.onResult(root.getName()); // if (resultCallback != null) {
resultCallback = null; // try {
} // final DocumentFile root = DocumentFile.fromTreeUri(context, data.getData());
// Log.d(TAG, "onActivityResult: " + root); // resultCallback.onResult(Utils.getDocumentFileRealPath(context, root).getAbsolutePath());
} // } catch (Exception e) {
// Log.e(TAG, "onActivityResult: ", e);
// }
// resultCallback = null;
// }
// // Log.d(TAG, "onActivityResult: " + root);
// }
private Preference getPrependUsernameToFilenamePreference(@NonNull final Context context) { private Preference getPrependUsernameToFilenamePreference(@NonNull final Context context) {
final SwitchPreferenceCompat preference = new SwitchPreferenceCompat(context); final SwitchPreferenceCompat preference = new SwitchPreferenceCompat(context);
@ -95,11 +114,15 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
public static class SaveToCustomFolderPreference extends Preference { public static class SaveToCustomFolderPreference extends Preference {
private AppCompatTextView customPathTextView; private AppCompatTextView customPathTextView;
private final OnSaveToChangeListener onSaveToChangeListener;
private final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener; private final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener;
private final String key; private final String key;
public SaveToCustomFolderPreference(final Context context, final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener) { public SaveToCustomFolderPreference(final Context context,
final OnSaveToChangeListener onSaveToChangeListener,
final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener) {
super(context); super(context);
this.onSaveToChangeListener = onSaveToChangeListener;
this.onSelectFolderButtonClickListener = onSelectFolderButtonClickListener; this.onSelectFolderButtonClickListener = onSelectFolderButtonClickListener;
key = FOLDER_SAVE_TO; key = FOLDER_SAVE_TO;
setLayoutResource(R.layout.pref_custom_folder); setLayoutResource(R.layout.pref_custom_folder);
@ -117,8 +140,21 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
cbSaveTo.setOnCheckedChangeListener((buttonView, isChecked) -> { cbSaveTo.setOnCheckedChangeListener((buttonView, isChecked) -> {
settingsHelper.putBoolean(FOLDER_SAVE_TO, isChecked); settingsHelper.putBoolean(FOLDER_SAVE_TO, isChecked);
buttonContainer.setVisibility(isChecked ? View.VISIBLE : View.GONE); buttonContainer.setVisibility(isChecked ? View.VISIBLE : View.GONE);
final String customPath = settingsHelper.getString(FOLDER_PATH); final Context context = getContext();
String customPath = settingsHelper.getString(FOLDER_PATH);
if (!TextUtils.isEmpty(customPath) && customPath.startsWith("content") && context != null) {
final Uri uri = Uri.parse(customPath);
final DocumentFile documentFile = DocumentFile.fromSingleUri(context, uri);
try {
customPath = Utils.getDocumentFileRealPath(context, documentFile).getAbsolutePath();
} catch (Exception e) {
Log.e(TAG, "onBindViewHolder: ", e);
}
}
customPathTextView.setText(customPath); customPathTextView.setText(customPath);
if (onSaveToChangeListener != null) {
onSaveToChangeListener.onChange(isChecked);
}
}); });
final boolean savedToEnabled = settingsHelper.getBoolean(key); final boolean savedToEnabled = settingsHelper.getBoolean(key);
holder.itemView.setOnClickListener(v -> cbSaveTo.toggle()); holder.itemView.setOnClickListener(v -> cbSaveTo.toggle());
@ -141,5 +177,9 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
public interface OnSelectFolderButtonClickListener { public interface OnSelectFolderButtonClickListener {
void onClick(ResultCallback resultCallback); void onClick(ResultCallback resultCallback);
} }
public interface OnSaveToChangeListener {
void onChange(boolean checked);
}
} }
} }

View File

@ -123,4 +123,6 @@ public final class Constants {
public static final String DM_THREAD_ACTION_EXTRA_THREAD_TITLE = "thread_title"; public static final String DM_THREAD_ACTION_EXTRA_THREAD_TITLE = "thread_title";
public static final String X_IG_APP_ID = "936619743392459"; public static final String X_IG_APP_ID = "936619743392459";
public static final String EXTRA_INITIAL_URI = "initial_uri";
} }

View File

@ -3,7 +3,6 @@ package awais.instagrabber.utils;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
@ -11,19 +10,14 @@ import android.os.FileObserver;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -95,15 +89,15 @@ public final class DirectoryChooser extends DialogFragment {
if (context == null) context = getContext(); if (context == null) context = getContext();
if (context == null) context = getActivity(); if (context == null) context = getActivity();
if (context == null) return; if (context == null) return;
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) != PackageManager.PERMISSION_GRANTED) { // if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) != PackageManager.PERMISSION_GRANTED) {
final String text = "Storage permissions denied!"; // final String text = "Storage permissions denied!";
if (container == null) { // if (container == null) {
Toast.makeText(context, text, Toast.LENGTH_LONG).show(); // Toast.makeText(context, text, Toast.LENGTH_LONG).show();
} else { // } else {
Snackbar.make(container, text, BaseTransientBottomBar.LENGTH_LONG).show(); // Snackbar.make(container, text, BaseTransientBottomBar.LENGTH_LONG).show();
} // }
dismiss(); // dismiss();
} // }
final View.OnClickListener clickListener = v -> { final View.OnClickListener clickListener = v -> {
if (v == binding.btnConfirm) { if (v == binding.btnConfirm) {
if (interactionListener != null && isValidFile(selectedDir)) if (interactionListener != null && isValidFile(selectedDir))

View File

@ -1,9 +1,9 @@
package awais.instagrabber.utils; package awais.instagrabber.utils;
import android.Manifest;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.UriPermission;
import android.net.Uri; import android.net.Uri;
import android.provider.DocumentsContract; import android.provider.DocumentsContract;
import android.util.Log; import android.util.Log;
@ -49,32 +49,65 @@ import static awais.instagrabber.utils.Constants.FOLDER_PATH;
public final class DownloadUtils { public final class DownloadUtils {
private static final String TAG = DownloadUtils.class.getSimpleName(); private static final String TAG = DownloadUtils.class.getSimpleName();
// private static final String DIR_BARINSTA = "Barinsta";
public static final String WRITE_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE;
public static final String[] PERMS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
private static final String DIR_BARINSTA = "Barinsta";
private static final String DIR_DOWNLOADS = "Downloads"; private static final String DIR_DOWNLOADS = "Downloads";
private static final String DIR_CAMERA = "Camera"; private static final String DIR_CAMERA = "Camera";
private static final String DIR_EDIT = "Edit"; private static final String DIR_EDIT = "Edit";
private static final String TEMP_DIR = "Temp"; private static final String DIR_RECORDINGS = "Recordings";
private static final String DIR_TEMP = "Temp";
private static final String DIR_BACKUPS = "Backups";
// public static final String WRITE_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE;
// public static final String[] PERMS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
private static DocumentFile root; private static DocumentFile root;
// private static DocumentFile DOWNLOADS_DIR_FILE;
public static void init(@NonNull final Context context) { public static void init(@NonNull final Context context) throws ReselectDocumentTreeException {
// if (!Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) return; // if (DOWNLOADS_DIR_FILE == null) {
// final Uri uri = Utils.getSafUris(context, new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS))[0];
// DOWNLOADS_DIR_FILE = DocumentFile.fromTreeUri(context, uri);
// }
// if (!Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
// root = DOWNLOADS_DIR_FILE; // DocumentFile.fromFile(DOWNLOADS_DIR_FILE);
// return;
// }
final String customPath = Utils.settingsHelper.getString(FOLDER_PATH); final String customPath = Utils.settingsHelper.getString(FOLDER_PATH);
if (TextUtils.isEmpty(customPath)) return; if (TextUtils.isEmpty(customPath)) {
// dir = new File(customPath); throw new ReselectDocumentTreeException();
root = DocumentFile.fromTreeUri(context, Uri.parse(customPath)); // root = DOWNLOADS_DIR_FILE; // DocumentFile.fromFile(DOWNLOADS_DIR_FILE);
// return;
}
if (!customPath.startsWith("content")) {
// if (customPath.equals(DOWNLOADS_DIR_FILE.getAbsolutePath())) {
// throw new ReselectDocumentTreeException();
// }
// reselect the folder in selector view
throw new ReselectDocumentTreeException(Uri.parse(customPath));
}
final Uri uri = Uri.parse(customPath);
final List<UriPermission> existingPermissions = context.getContentResolver().getPersistedUriPermissions();
if (existingPermissions.isEmpty()) {
// reselect the folder in selector view
throw new ReselectDocumentTreeException(uri);
}
final boolean anyMatch = existingPermissions.stream().anyMatch(uriPermission -> uriPermission.getUri().equals(uri));
if (!anyMatch) {
// reselect the folder in selector view
throw new ReselectDocumentTreeException(uri);
}
root = DocumentFile.fromTreeUri(context, uri);
Log.d(TAG, "init: " + root); Log.d(TAG, "init: " + root);
// final File parent = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); // final File parent = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
// final DocumentFile documentFile = DocumentFile.fromFile(parent); // final DocumentFile documentFile = DocumentFile.fromFile(parent);
// Log.d(TAG, "init: " + documentFile); // Log.d(TAG, "init: " + documentFile);
} }
@Nullable
public static DocumentFile getDownloadDir(final String... dirs) { public static DocumentFile getDownloadDir(final String... dirs) {
// final File parent = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS); if (root == null) {
// File subDir = new File(parent, DIR_BARINSTA); return null;
}
DocumentFile subDir = root; DocumentFile subDir = root;
if (dirs != null) { if (dirs != null) {
for (final String dir : dirs) { for (final String dir : dirs) {
@ -87,7 +120,7 @@ public final class DownloadUtils {
return subDir; return subDir;
} }
@NonNull @Nullable
public static DocumentFile getDownloadDir() { public static DocumentFile getDownloadDir() {
// final File parent = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS); // final File parent = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS);
// final File dir = new File(new File(parent, "barinsta"), "downloads"); // final File dir = new File(new File(parent, "barinsta"), "downloads");
@ -106,14 +139,26 @@ public final class DownloadUtils {
return getDownloadDir(DIR_DOWNLOADS); return getDownloadDir(DIR_DOWNLOADS);
} }
@Nullable
public static DocumentFile getCameraDir() { public static DocumentFile getCameraDir() {
return getDownloadDir(DIR_CAMERA); return getDownloadDir(DIR_CAMERA);
} }
@Nullable
public static DocumentFile getImageEditDir(final String sessionId) { public static DocumentFile getImageEditDir(final String sessionId) {
return getDownloadDir(DIR_EDIT, sessionId); return getDownloadDir(DIR_EDIT, sessionId);
} }
@Nullable
public static DocumentFile getRecordingsDir() {
return getDownloadDir(DIR_RECORDINGS);
}
@Nullable
public static DocumentFile getBackupsDir() {
return getDownloadDir(DIR_BACKUPS);
}
// @Nullable // @Nullable
// private static DocumentFile getDownloadDir(@NonNull final Context context, @Nullable final String username) { // private static DocumentFile getDownloadDir(@NonNull final Context context, @Nullable final String username) {
// return getDownloadDir(context, username, false); // return getDownloadDir(context, username, false);
@ -156,9 +201,9 @@ public final class DownloadUtils {
} }
private static DocumentFile getTempDir() { private static DocumentFile getTempDir() {
DocumentFile file = root.findFile(TEMP_DIR); DocumentFile file = root.findFile(DIR_TEMP);
if (file == null) { if (file == null) {
file = root.createDirectory(TEMP_DIR); file = root.createDirectory(DIR_TEMP);
} }
return file; return file;
} }
@ -202,7 +247,7 @@ public final class DownloadUtils {
return getDownloadSavePaths(paths, postId, "", displayUrl, username); return getDownloadSavePaths(paths, postId, "", displayUrl, username);
} }
private static Pair<List<String>, String> getDownloadChildSaveFile(final List<String> paths, private static Pair<List<String>, String> getDownloadChildSavePaths(final List<String> paths,
final String postId, final String postId,
final int childPosition, final int childPosition,
final String url, final String url,
@ -231,9 +276,9 @@ public final class DownloadUtils {
return new Pair<>(paths, mimeType); return new Pair<>(paths, mimeType);
} }
public static DocumentFile getTempFile() { // public static DocumentFile getTempFile() {
return getTempFile(null, null); // return getTempFile(null, null);
} // }
public static DocumentFile getTempFile(final String fileName, final String extension) { public static DocumentFile getTempFile(final String fileName, final String extension) {
final DocumentFile dir = getTempDir(); final DocumentFile dir = getTempDir();
@ -317,8 +362,8 @@ public final class DownloadUtils {
final Media child = sliderItems.get(i); final Media child = sliderItems.get(i);
if (child == null) continue; if (child == null) continue;
final String url = ResponseBodyUtils.getImageUrl(child); final String url = ResponseBodyUtils.getImageUrl(child);
final Pair<List<String>, String> file = getDownloadChildSaveFile(userFolderPaths, media.getCode(), i + 1, url, ""); final Pair<List<String>, String> file = getDownloadChildSavePaths(userFolderPaths, media.getCode(), i + 1, url, "");
final Pair<List<String>, String> usernameFile = getDownloadChildSaveFile(userFolderPaths, media.getCode(), i + 1, url, username); final Pair<List<String>, String> usernameFile = getDownloadChildSavePaths(userFolderPaths, media.getCode(), i + 1, url, username);
checkList.add(checkPathExists(context, file.first) || checkPathExists(context, usernameFile.first)); checkList.add(checkPathExists(context, file.first) || checkPathExists(context, usernameFile.first));
} }
break; break;
@ -329,6 +374,7 @@ public final class DownloadUtils {
private static boolean checkPathExists(@NonNull final Context context, private static boolean checkPathExists(@NonNull final Context context,
@NonNull final List<String> paths) { @NonNull final List<String> paths) {
if (root == null) return false;
final String joined = android.text.TextUtils.join("/", paths); final String joined = android.text.TextUtils.join("/", paths);
final Uri userFolderUri = DocumentsContract.buildDocumentUriUsingTree(root.getUri(), joined); final Uri userFolderUri = DocumentsContract.buildDocumentUriUsingTree(root.getUri(), joined);
final DocumentFile userFolder = DocumentFile.fromSingleUri(context, userFolderUri); final DocumentFile userFolder = DocumentFile.fromSingleUri(context, userFolderUri);
@ -455,7 +501,7 @@ public final class DownloadUtils {
final String usernamePrepend = Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_PREPEND_USER_NAME) && mediaUser != null final String usernamePrepend = Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_PREPEND_USER_NAME) && mediaUser != null
? mediaUser.getUsername() ? mediaUser.getUsername()
: ""; : "";
final Pair<List<String>, String> pair = getDownloadChildSaveFile(userFolderPaths, media.getCode(), i + 1, url, final Pair<List<String>, String> pair = getDownloadChildSavePaths(userFolderPaths, media.getCode(), i + 1, url,
usernamePrepend); usernamePrepend);
final DocumentFile file = createFile(pair); final DocumentFile file = createFile(pair);
if (file == null) continue; if (file == null) continue;
@ -469,7 +515,9 @@ public final class DownloadUtils {
download(context, map); download(context, map);
} }
@Nullable
private static DocumentFile createFile(@NonNull final Pair<List<String>, String> pair) { private static DocumentFile createFile(@NonNull final Pair<List<String>, String> pair) {
if (root == null) return null;
if (pair.first == null || pair.second == null) return null; if (pair.first == null || pair.second == null) return null;
DocumentFile dir = root; DocumentFile dir = root;
final List<String> first = pair.first; final List<String> first = pair.first;
@ -558,4 +606,21 @@ public final class DownloadUtils {
WorkManager.getInstance(context) WorkManager.getInstance(context)
.enqueue(downloadWorkRequest); .enqueue(downloadWorkRequest);
} }
public static class ReselectDocumentTreeException extends Exception {
private final Uri initialUri;
public ReselectDocumentTreeException() {
initialUri = null;
}
public ReselectDocumentTreeException(final Uri initialUri) {
this.initialUri = initialUri;
}
public Uri getInitialUri() {
return initialUri;
}
}
} }

View File

@ -36,6 +36,7 @@ import android.widget.Toast;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
@ -70,6 +71,8 @@ import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.Tab; import awais.instagrabber.models.Tab;
import awais.instagrabber.models.enums.FavoriteType; import awais.instagrabber.models.enums.FavoriteType;
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
public final class Utils { public final class Utils {
private static final String TAG = "Utils"; private static final String TAG = "Utils";
private static final int VIDEO_CACHE_MAX_BYTES = 10 * 1024 * 1024; private static final int VIDEO_CACHE_MAX_BYTES = 10 * 1024 * 1024;
@ -520,7 +523,8 @@ public final class Utils {
callback); callback);
} }
private static File getDocumentFileRealPath(Context context, DocumentFile documentFile) public static File getDocumentFileRealPath(@NonNull final Context context,
@NonNull final DocumentFile documentFile)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
final String docId = DocumentsContract.getDocumentId(documentFile.getUri()); final String docId = DocumentsContract.getDocumentId(documentFile.getUri());
final String[] split = docId.split(":"); final String[] split = docId.split(":");
@ -530,18 +534,19 @@ public final class Utils {
return new File(Environment.getExternalStorageDirectory(), split[1]); return new File(Environment.getExternalStorageDirectory(), split[1]);
} else { } else {
if (volumes == null) { if (volumes == null) {
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); final StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Method getVolumeListMethod = sm.getClass().getMethod("getVolumeList"); if (sm == null) return null;
final Method getVolumeListMethod = sm.getClass().getMethod("getVolumeList");
volumes = (Object[]) getVolumeListMethod.invoke(sm); volumes = (Object[]) getVolumeListMethod.invoke(sm);
} }
if (volumes == null) return null;
for (Object volume : volumes) { for (Object volume : volumes) {
Method getUuidMethod = volume.getClass().getMethod("getUuid"); final Method getUuidMethod = volume.getClass().getMethod("getUuid");
String uuid = (String) getUuidMethod.invoke(volume); final String uuid = (String) getUuidMethod.invoke(volume);
if (uuid != null && uuid.equalsIgnoreCase(type)) { if (uuid != null && uuid.equalsIgnoreCase(type)) {
Method getPathMethod = volume.getClass().getMethod("getPath"); final Method getPathMethod = volume.getClass().getMethod("getPath");
String path = (String) getPathMethod.invoke(volume); final String path = (String) getPathMethod.invoke(volume);
return new File(path, split[1]); return new File(path, split[1]);
} }
} }
@ -549,4 +554,72 @@ public final class Utils {
return null; return null;
} }
public static void setupSelectedDir(@NonNull final Context context,
@NonNull final Intent intent) throws DownloadUtils.ReselectDocumentTreeException {
final Uri dirUri = intent.getData();
Log.d(TAG, "onActivityResult: " + dirUri);
if (dirUri == null) return;
final int takeFlags = intent.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
context.getContentResolver().takePersistableUriPermission(dirUri, takeFlags);
settingsHelper.putString(FOLDER_PATH, dirUri.toString());
// re-init DownloadUtils
DownloadUtils.init(context);
}
/**
* Ing.N.Nyerges 2019 V2.0
* <p>
* Storage Access Framework(SAF) Uri's creator from File (java.IO),
* for removable external storages
*
* @param context Application Context
* @param file File path + file name
* @return Uri[]:
* uri[0] = SAF TREE Uri
* uri[1] = SAF DOCUMENT Uri
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static Uri[] getSafUris(Context context, File file) {
Uri[] uri = new Uri[2];
String scheme = "content";
String authority = "com.android.externalstorage.documents";
// Separate each element of the File path
// File format: "/storage/XXXX-XXXX/sub-folder1/sub-folder2..../filename"
// (XXXX-XXXX is external removable number
String[] ele = file.getPath().split(File.separator);
// ele[0] = not used (empty)
// ele[1] = not used (storage name)
// ele[2] = storage number
// ele[3 to (n-1)] = folders
// ele[n] = file name
// Construct folders strings using SAF format
StringBuilder folders = new StringBuilder();
if (ele.length > 4) {
folders.append(ele[3]);
for (int i = 4; i < ele.length - 1; ++i) folders.append("%2F").append(ele[i]);
}
String common = ele[2] + "%3A" + folders.toString();
// Construct TREE Uri
Uri.Builder builder = new Uri.Builder();
builder.scheme(scheme);
builder.authority(authority);
builder.encodedPath("/tree/" + common);
uri[0] = builder.build();
// Construct DOCUMENT Uri
builder = new Uri.Builder();
builder.scheme(scheme);
builder.authority(authority);
if (ele.length > 4) common = common + "%2F";
builder.encodedPath("/document/" + common + file.getName());
uri[1] = builder.build();
return uri;
}
} }

View File

@ -72,7 +72,7 @@ public class DirectThreadViewModel extends AndroidViewModel {
throw new IllegalArgumentException("User is not logged in!"); throw new IllegalArgumentException("User is not logged in!");
} }
contentResolver = application.getContentResolver(); contentResolver = application.getContentResolver();
recordingsDir = DownloadUtils.getDownloadDir("Recordings"); recordingsDir = DownloadUtils.getRecordingsDir();
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance(); final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
threadManager = messagesManager.getThreadManager(threadId, pending, currentUser, contentResolver); threadManager = messagesManager.getThreadManager(threadId, pending, currentUser, contentResolver);
threadManager.fetchPendingRequests(); threadManager.fetchPendingRequests();

View File

@ -0,0 +1,39 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title" />
<com.google.android.material.button.MaterialButton
android:id="@+id/select_dir"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Select Directory"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/message"
app:layout_constraintVertical_bias="1" />
</androidx.constraintlayout.widget.ConstraintLayout>