mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-22 14:47:29 +00:00
Merge branch 'master' into retrofit-intercept-errors
This commit is contained in:
commit
807cf91cd7
@ -66,11 +66,13 @@ android {
|
|||||||
dimension "repo"
|
dimension "repo"
|
||||||
// versionNameSuffix "-github" // appended in assemble task
|
// versionNameSuffix "-github" // appended in assemble task
|
||||||
buildConfigField("String", "dsn", SENTRY_DSN)
|
buildConfigField("String", "dsn", SENTRY_DSN)
|
||||||
|
buildConfigField("boolean", "isPre", "false")
|
||||||
}
|
}
|
||||||
|
|
||||||
fdroid {
|
fdroid {
|
||||||
dimension "repo"
|
dimension "repo"
|
||||||
versionNameSuffix "-fdroid"
|
versionNameSuffix "-fdroid"
|
||||||
|
buildConfigField("boolean", "isPre", "false")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +86,7 @@ android {
|
|||||||
|
|
||||||
def suffix = "${versionName}-${flavor}_${builtType}" // eg. 19.1.0-github_debug or release
|
def suffix = "${versionName}-${flavor}_${builtType}" // eg. 19.1.0-github_debug or release
|
||||||
if (builtType.toString() == 'release' && project.hasProperty("pre")) {
|
if (builtType.toString() == 'release' && project.hasProperty("pre")) {
|
||||||
|
buildConfigField("boolean", "isPre", "true")
|
||||||
// append latest commit short hash for pre-release
|
// append latest commit short hash for pre-release
|
||||||
suffix = "${versionName}.${getGitHash()}-${flavor}" // eg. 19.1.0.b123456-github
|
suffix = "${versionName}.${getGitHash()}-${flavor}" // eg. 19.1.0.b123456-github
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
package awais.instagrabber.utils;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class UpdateChecker {
|
||||||
|
private static final Object LOCK = new Object();
|
||||||
|
private static final String TAG = UpdateChecker.class.getSimpleName();
|
||||||
|
|
||||||
|
private static UpdateChecker instance;
|
||||||
|
|
||||||
|
public static UpdateChecker getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new UpdateChecker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Needs to be called asynchronously
|
||||||
|
*
|
||||||
|
* @return the latest version from f-droid
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getLatestVersion() {
|
||||||
|
HttpURLConnection conn = null;
|
||||||
|
try {
|
||||||
|
conn = (HttpURLConnection) new URL("https://f-droid.org/api/v1/packages/me.austinhuang.instagrabber").openConnection();
|
||||||
|
conn.setUseCaches(false);
|
||||||
|
conn.setRequestProperty("User-Agent", "https://Barinsta.AustinHuang.me / mailto:Barinsta@AustinHuang.me");
|
||||||
|
conn.connect();
|
||||||
|
final int responseCode = conn.getResponseCode();
|
||||||
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||||
|
final JSONObject data = new JSONObject(NetworkUtils.readFromConnection(conn));
|
||||||
|
return "v" + data.getJSONArray("packages").getJSONObject(0).getString("versionName");
|
||||||
|
// if (BuildConfig.VERSION_CODE < data.getInt("suggestedVersionCode")) {
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
Log.e(TAG, "", e);
|
||||||
|
} finally {
|
||||||
|
if (conn != null) {
|
||||||
|
conn.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDownload(@NonNull final AppCompatActivity context) {
|
||||||
|
Utils.openURL(context, "https://f-droid.org/packages/me.austinhuang.instagrabber/");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package awais.instagrabber.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class UpdateChecker {
|
||||||
|
private static final Object LOCK = new Object();
|
||||||
|
private static final String TAG = UpdateChecker.class.getSimpleName();
|
||||||
|
|
||||||
|
private static UpdateChecker instance;
|
||||||
|
|
||||||
|
public static UpdateChecker getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new UpdateChecker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Needs to be called asynchronously
|
||||||
|
*
|
||||||
|
* @return the latest version from Github
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getLatestVersion() {
|
||||||
|
HttpURLConnection conn = null;
|
||||||
|
try {
|
||||||
|
conn = (HttpURLConnection) new URL("https://github.com/austinhuang0131/barinsta/releases/latest").openConnection();
|
||||||
|
conn.setInstanceFollowRedirects(false);
|
||||||
|
conn.setUseCaches(false);
|
||||||
|
conn.setRequestProperty("User-Agent", "https://Barinsta.AustinHuang.me / mailto:Barinsta@AustinHuang.me");
|
||||||
|
conn.connect();
|
||||||
|
final int responseCode = conn.getResponseCode();
|
||||||
|
if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {
|
||||||
|
return "v" + conn.getHeaderField("Location").split("/v")[1];
|
||||||
|
// return !version.equals(BuildConfig.VERSION_NAME);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
Log.e(TAG, "", e);
|
||||||
|
} finally {
|
||||||
|
if (conn != null) {
|
||||||
|
conn.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDownload(@NonNull final Context context) {
|
||||||
|
Utils.openURL(context, "https://github.com/austinhuang0131/instagrabber/releases/latest");
|
||||||
|
}
|
||||||
|
}
|
@ -130,6 +130,9 @@
|
|||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".activities.MainActivity" />
|
android:value=".activities.MainActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".utils.ProcessPhoenix"
|
||||||
|
android:theme="@style/Theme.AppCompat.Translucent" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
@ -59,6 +59,7 @@ import java.util.Deque;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import awais.instagrabber.BuildConfig;
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.SuggestionsAdapter;
|
import awais.instagrabber.adapters.SuggestionsAdapter;
|
||||||
import awais.instagrabber.asyncs.PostFetcher;
|
import awais.instagrabber.asyncs.PostFetcher;
|
||||||
@ -156,8 +157,10 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
setupBottomNavigationBar(true);
|
setupBottomNavigationBar(true);
|
||||||
}
|
}
|
||||||
setupSuggestions();
|
setupSuggestions();
|
||||||
final boolean checkUpdates = settingsHelper.getBoolean(Constants.CHECK_UPDATES);
|
if (!BuildConfig.isPre) {
|
||||||
if (checkUpdates) FlavorTown.updateCheck(this);
|
final boolean checkUpdates = settingsHelper.getBoolean(Constants.CHECK_UPDATES);
|
||||||
|
if (checkUpdates) FlavorTown.updateCheck(this);
|
||||||
|
}
|
||||||
FlavorTown.changelogCheck(this);
|
FlavorTown.changelogCheck(this);
|
||||||
new ViewModelProvider(this).get(AppStateViewModel.class); // Just initiate the App state here
|
new ViewModelProvider(this).get(AppStateViewModel.class); // Just initiate the App state here
|
||||||
final Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
|
@ -12,7 +12,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.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -25,8 +24,10 @@ import awais.instagrabber.db.datasources.AccountDataSource;
|
|||||||
import awais.instagrabber.db.entities.Account;
|
import awais.instagrabber.db.entities.Account;
|
||||||
import awais.instagrabber.db.repositories.AccountRepository;
|
import awais.instagrabber.db.repositories.AccountRepository;
|
||||||
import awais.instagrabber.db.repositories.RepositoryCallback;
|
import awais.instagrabber.db.repositories.RepositoryCallback;
|
||||||
|
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.ProcessPhoenix;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
@ -55,9 +56,14 @@ public class AccountSwitcherDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
CookieUtils.setupCookies(model.getCookie());
|
CookieUtils.setupCookies(model.getCookie());
|
||||||
settingsHelper.putString(Constants.COOKIE, model.getCookie());
|
settingsHelper.putString(Constants.COOKIE, model.getCookie());
|
||||||
final FragmentActivity activity = getActivity();
|
// final FragmentActivity activity = getActivity();
|
||||||
if (activity != null) activity.recreate();
|
// if (activity != null) activity.recreate();
|
||||||
dismiss();
|
// dismiss();
|
||||||
|
AppExecutors.getInstance().mainThread().execute(() -> {
|
||||||
|
final Context context = getContext();
|
||||||
|
if (context == null) return;
|
||||||
|
ProcessPhoenix.triggerRebirth(context);
|
||||||
|
}, 200);
|
||||||
};
|
};
|
||||||
|
|
||||||
private final AccountSwitcherAdapter.OnAccountLongClickListener accountLongClickListener = (model, isCurrent) -> {
|
private final AccountSwitcherAdapter.OnAccountLongClickListener accountLongClickListener = (model, isCurrent) -> {
|
||||||
|
@ -31,7 +31,6 @@ import awais.instagrabber.R;
|
|||||||
import awais.instagrabber.adapters.NotificationsAdapter;
|
import awais.instagrabber.adapters.NotificationsAdapter;
|
||||||
import awais.instagrabber.adapters.NotificationsAdapter.OnNotificationClickListener;
|
import awais.instagrabber.adapters.NotificationsAdapter.OnNotificationClickListener;
|
||||||
import awais.instagrabber.databinding.FragmentNotificationsViewerBinding;
|
import awais.instagrabber.databinding.FragmentNotificationsViewerBinding;
|
||||||
import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections;
|
|
||||||
import awais.instagrabber.models.enums.NotificationType;
|
import awais.instagrabber.models.enums.NotificationType;
|
||||||
import awais.instagrabber.repositories.requests.StoryViewerOptions;
|
import awais.instagrabber.repositories.requests.StoryViewerOptions;
|
||||||
import awais.instagrabber.repositories.responses.FriendshipChangeResponse;
|
import awais.instagrabber.repositories.responses.FriendshipChangeResponse;
|
||||||
@ -79,8 +78,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
|||||||
try {
|
try {
|
||||||
binding.swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshLayout.setRefreshing(false);
|
||||||
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
}
|
} catch (Throwable ignored) {}
|
||||||
catch(Throwable e) {}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,10 +91,10 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
|||||||
@Override
|
@Override
|
||||||
public void onPreviewClick(final Notification model) {
|
public void onPreviewClick(final Notification model) {
|
||||||
final NotificationImage notificationImage = model.getArgs().getMedia().get(0);
|
final NotificationImage notificationImage = model.getArgs().getMedia().get(0);
|
||||||
final long mediaId = Long.valueOf(notificationImage.getId().split("_")[0]);
|
final long mediaId = Long.parseLong(notificationImage.getId().split("_")[0]);
|
||||||
if (model.getType() == NotificationType.RESPONDED_STORY) {
|
if (model.getType() == NotificationType.RESPONDED_STORY) {
|
||||||
final NavDirections action = NotificationsViewerFragmentDirections
|
final NavDirections action = NotificationsViewerFragmentDirections
|
||||||
.actionNotificationsViewerFragmentToStoryViewerFragment(
|
.actionNotificationsToStory(
|
||||||
StoryViewerOptions.forStory(
|
StoryViewerOptions.forStory(
|
||||||
mediaId,
|
mediaId,
|
||||||
model.getArgs().getUsername()));
|
model.getArgs().getUsername()));
|
||||||
@ -278,8 +276,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void openProfile(final String username) {
|
private void openProfile(final String username) {
|
||||||
final NavDirections action = MorePreferencesFragmentDirections
|
final NavDirections action = NotificationsViewerFragmentDirections.actionGlobalProfileFragment("@" + username);
|
||||||
.actionGlobalProfileFragment("@" + username);
|
|
||||||
NavHostFragment.findNavController(this).navigate(action);
|
NavHostFragment.findNavController(this).navigate(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -137,14 +137,14 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
private String[] mentions;
|
private String[] mentions;
|
||||||
private QuizModel quiz;
|
private QuizModel quiz;
|
||||||
private SliderModel slider;
|
private SliderModel slider;
|
||||||
private MenuItem menuDownload;
|
private MenuItem menuDownload, menuDm, menuProfile;
|
||||||
private MenuItem menuDm;
|
|
||||||
private SimpleExoPlayer player;
|
private SimpleExoPlayer player;
|
||||||
// private boolean isHashtag;
|
// private boolean isHashtag;
|
||||||
// private boolean isLoc;
|
// private boolean isLoc;
|
||||||
// private String highlight;
|
// private String highlight;
|
||||||
private String actionBarTitle;
|
private String actionBarTitle, actionBarSubtitle;
|
||||||
private boolean fetching = false, sticking = false, shouldRefresh = true;
|
private boolean fetching = false, sticking = false, shouldRefresh = true;
|
||||||
|
private boolean downloadVisible = false, dmVisible = false, profileVisible = true;
|
||||||
private int currentFeedStoryIndex;
|
private int currentFeedStoryIndex;
|
||||||
private double sliderValue;
|
private double sliderValue;
|
||||||
private StoriesViewModel storiesViewModel;
|
private StoriesViewModel storiesViewModel;
|
||||||
@ -195,8 +195,10 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
menuInflater.inflate(R.menu.story_menu, menu);
|
menuInflater.inflate(R.menu.story_menu, menu);
|
||||||
menuDownload = menu.findItem(R.id.action_download);
|
menuDownload = menu.findItem(R.id.action_download);
|
||||||
menuDm = menu.findItem(R.id.action_dms);
|
menuDm = menu.findItem(R.id.action_dms);
|
||||||
menuDownload.setVisible(false);
|
menuProfile = menu.findItem(R.id.action_profile);
|
||||||
menuDm.setVisible(false);
|
menuDownload.setVisible(downloadVisible);
|
||||||
|
menuDm.setVisible(dmVisible);
|
||||||
|
menuProfile.setVisible(profileVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -215,7 +217,8 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
else
|
else
|
||||||
ActivityCompat.requestPermissions(requireActivity(), DownloadUtils.PERMS, 8020);
|
ActivityCompat.requestPermissions(requireActivity(), DownloadUtils.PERMS, 8020);
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.action_dms) {
|
}
|
||||||
|
if (itemId == R.id.action_dms) {
|
||||||
final EditText input = new EditText(context);
|
final EditText input = new EditText(context);
|
||||||
input.setHint(R.string.reply_hint);
|
input.setHint(R.string.reply_hint);
|
||||||
new AlertDialog.Builder(context)
|
new AlertDialog.Builder(context)
|
||||||
@ -259,6 +262,9 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
.show();
|
.show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (itemId == R.id.action_profile) {
|
||||||
|
openProfile("@" + currentStory.getUsername());
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +287,9 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
actionBar.setTitle(actionBarTitle);
|
actionBar.setTitle(actionBarTitle);
|
||||||
|
actionBar.setSubtitle(actionBarSubtitle);
|
||||||
}
|
}
|
||||||
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -697,6 +705,10 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
lastSlidePos = 0;
|
lastSlidePos = 0;
|
||||||
if (menuDownload != null) menuDownload.setVisible(false);
|
if (menuDownload != null) menuDownload.setVisible(false);
|
||||||
if (menuDm != null) menuDm.setVisible(false);
|
if (menuDm != null) menuDm.setVisible(false);
|
||||||
|
if (menuProfile != null) menuProfile.setVisible(false);
|
||||||
|
downloadVisible = false;
|
||||||
|
dmVisible = false;
|
||||||
|
profileVisible = false;
|
||||||
binding.imageViewer.setController(null);
|
binding.imageViewer.setController(null);
|
||||||
releasePlayer();
|
releasePlayer();
|
||||||
String currentStoryMediaId = null;
|
String currentStoryMediaId = null;
|
||||||
@ -846,7 +858,6 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
|
|
||||||
final MediaItemType itemType = currentStory.getItemType();
|
final MediaItemType itemType = currentStory.getItemType();
|
||||||
|
|
||||||
if (menuDownload != null) menuDownload.setVisible(false);
|
|
||||||
url = itemType == MediaItemType.MEDIA_TYPE_IMAGE ? currentStory.getStoryUrl() : currentStory.getVideoUrl();
|
url = itemType == MediaItemType.MEDIA_TYPE_IMAGE ? currentStory.getStoryUrl() : currentStory.getVideoUrl();
|
||||||
|
|
||||||
if (itemType != MediaItemType.MEDIA_TYPE_LIVE) {
|
if (itemType != MediaItemType.MEDIA_TYPE_LIVE) {
|
||||||
@ -900,9 +911,10 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
else setupImage();
|
else setupImage();
|
||||||
|
|
||||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||||
|
actionBarSubtitle = Utils.datetimeParser.format(new Date(currentStory.getTimestamp() * 1000L));
|
||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
try {
|
try {
|
||||||
actionBar.setSubtitle(Utils.datetimeParser.format(new Date(currentStory.getTimestamp() * 1000L)));
|
actionBar.setSubtitle(actionBarSubtitle);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "refreshStory: ", e);
|
Log.e(TAG, "refreshStory: ", e);
|
||||||
}
|
}
|
||||||
@ -948,11 +960,17 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
final ImageInfo imageInfo,
|
final ImageInfo imageInfo,
|
||||||
final Animatable animatable) {
|
final Animatable animatable) {
|
||||||
if (menuDownload != null) {
|
if (menuDownload != null) {
|
||||||
|
downloadVisible = true;
|
||||||
menuDownload.setVisible(true);
|
menuDownload.setVisible(true);
|
||||||
}
|
}
|
||||||
if (currentStory.canReply() && menuDm != null) {
|
if (currentStory.canReply() && menuDm != null) {
|
||||||
|
dmVisible = true;
|
||||||
menuDm.setVisible(true);
|
menuDm.setVisible(true);
|
||||||
}
|
}
|
||||||
|
if (!TextUtils.isEmpty(currentStory.getUsername())) {
|
||||||
|
profileVisible = true;
|
||||||
|
menuProfile.setVisible(true);
|
||||||
|
}
|
||||||
binding.progressView.setVisibility(View.GONE);
|
binding.progressView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -982,9 +1000,18 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
@Nullable final MediaSource.MediaPeriodId mediaPeriodId,
|
@Nullable final MediaSource.MediaPeriodId mediaPeriodId,
|
||||||
@NonNull final LoadEventInfo loadEventInfo,
|
@NonNull final LoadEventInfo loadEventInfo,
|
||||||
@NonNull final MediaLoadData mediaLoadData) {
|
@NonNull final MediaLoadData mediaLoadData) {
|
||||||
if (menuDownload != null) menuDownload.setVisible(true);
|
if (menuDownload != null) {
|
||||||
if (currentStory.canReply() && menuDm != null)
|
downloadVisible = true;
|
||||||
|
menuDownload.setVisible(true);
|
||||||
|
}
|
||||||
|
if (currentStory.canReply() && menuDm != null) {
|
||||||
|
dmVisible = true;
|
||||||
menuDm.setVisible(true);
|
menuDm.setVisible(true);
|
||||||
|
}
|
||||||
|
if (!TextUtils.isEmpty(currentStory.getUsername()) && menuProfile != null) {
|
||||||
|
profileVisible = true;
|
||||||
|
menuProfile.setVisible(true);
|
||||||
|
}
|
||||||
binding.progressView.setVisibility(View.GONE);
|
binding.progressView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -993,9 +1020,18 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
@Nullable final MediaSource.MediaPeriodId mediaPeriodId,
|
@Nullable final MediaSource.MediaPeriodId mediaPeriodId,
|
||||||
@NonNull final LoadEventInfo loadEventInfo,
|
@NonNull final LoadEventInfo loadEventInfo,
|
||||||
@NonNull final MediaLoadData mediaLoadData) {
|
@NonNull final MediaLoadData mediaLoadData) {
|
||||||
if (menuDownload != null) menuDownload.setVisible(true);
|
if (menuDownload != null) {
|
||||||
if (currentStory.canReply() && menuDm != null)
|
downloadVisible = true;
|
||||||
|
menuDownload.setVisible(true);
|
||||||
|
}
|
||||||
|
if (currentStory.canReply() && menuDm != null) {
|
||||||
|
dmVisible = true;
|
||||||
menuDm.setVisible(true);
|
menuDm.setVisible(true);
|
||||||
|
}
|
||||||
|
if (!TextUtils.isEmpty(currentStory.getUsername()) && menuProfile != null) {
|
||||||
|
profileVisible = true;
|
||||||
|
menuProfile.setVisible(true);
|
||||||
|
}
|
||||||
binding.progressView.setVisibility(View.VISIBLE);
|
binding.progressView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1014,8 +1050,18 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
@NonNull final MediaLoadData mediaLoadData,
|
@NonNull final MediaLoadData mediaLoadData,
|
||||||
@NonNull final IOException error,
|
@NonNull final IOException error,
|
||||||
final boolean wasCanceled) {
|
final boolean wasCanceled) {
|
||||||
if (menuDownload != null) menuDownload.setVisible(false);
|
if (menuDownload != null) {
|
||||||
if (menuDm != null) menuDm.setVisible(false);
|
downloadVisible = false;
|
||||||
|
menuDownload.setVisible(false);
|
||||||
|
}
|
||||||
|
if (menuDm != null) {
|
||||||
|
dmVisible = false;
|
||||||
|
menuDm.setVisible(false);
|
||||||
|
}
|
||||||
|
if (menuProfile != null) {
|
||||||
|
profileVisible = false;
|
||||||
|
menuProfile.setVisible(false);
|
||||||
|
}
|
||||||
binding.progressView.setVisibility(View.GONE);
|
binding.progressView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -83,9 +83,12 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
|
|||||||
new FeedStoriesAdapter.OnFeedStoryClickListener() {
|
new FeedStoriesAdapter.OnFeedStoryClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onFeedStoryClick(FeedStoryModel model, int position) {
|
public void onFeedStoryClick(FeedStoryModel model, int position) {
|
||||||
final NavDirections action = FeedFragmentDirections
|
final NavController navController = NavHostFragment.findNavController(FeedFragment.this);
|
||||||
.actionFeedFragmentToStoryViewerFragment(StoryViewerOptions.forFeedStoryPosition(position));
|
if (isSafeToNavigate(navController)) {
|
||||||
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
|
final NavDirections action = FeedFragmentDirections
|
||||||
|
.actionFeedFragmentToStoryViewerFragment(StoryViewerOptions.forFeedStoryPosition(position));
|
||||||
|
navController.navigate(action);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -437,4 +440,9 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
|
|||||||
binding.feedRecyclerView.smoothScrollToPosition(0);
|
binding.feedRecyclerView.smoothScrollToPosition(0);
|
||||||
// binding.storiesContainer.setExpanded(true);
|
// binding.storiesContainer.setExpanded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSafeToNavigate(final NavController navController) {
|
||||||
|
return navController.getCurrentDestination() != null
|
||||||
|
&& navController.getCurrentDestination().getId() == R.id.feedFragment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
|
|||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Preference getDownloadUserFolderPreference(@NonNull final Context context) {
|
private Preference getDownloadUserFolderPreference(@NonNull final Context context) {
|
||||||
@ -49,6 +50,14 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
|
|||||||
.show(getParentFragmentManager(), null));
|
.show(getParentFragmentManager(), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Preference getPrependUsernameToFilenamePreference(@NonNull final Context context) {
|
||||||
|
final SwitchPreferenceCompat preference = new SwitchPreferenceCompat(context);
|
||||||
|
preference.setKey(Constants.DOWNLOAD_PREPEND_USER_NAME);
|
||||||
|
preference.setTitle(R.string.download_prepend_username);
|
||||||
|
preference.setIconSpaceReserved(false);
|
||||||
|
return preference;
|
||||||
|
}
|
||||||
|
|
||||||
public static class SaveToCustomFolderPreference extends Preference {
|
public static class SaveToCustomFolderPreference extends Preference {
|
||||||
private AppCompatTextView customPathTextView;
|
private AppCompatTextView customPathTextView;
|
||||||
private final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener;
|
private final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener;
|
||||||
|
@ -11,8 +11,6 @@ import android.widget.Toast;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.navigation.NavController;
|
import androidx.navigation.NavController;
|
||||||
import androidx.navigation.NavDirections;
|
import androidx.navigation.NavDirections;
|
||||||
@ -35,9 +33,11 @@ import awais.instagrabber.db.repositories.AccountRepository;
|
|||||||
import awais.instagrabber.db.repositories.RepositoryCallback;
|
import awais.instagrabber.db.repositories.RepositoryCallback;
|
||||||
import awais.instagrabber.dialogs.AccountSwitcherDialogFragment;
|
import awais.instagrabber.dialogs.AccountSwitcherDialogFragment;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
|
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.FlavorTown;
|
import awais.instagrabber.utils.FlavorTown;
|
||||||
|
import awais.instagrabber.utils.ProcessPhoenix;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
import awais.instagrabber.webservices.ServiceCallback;
|
import awais.instagrabber.webservices.ServiceCallback;
|
||||||
@ -71,11 +71,15 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
accountCategory.setSummary(R.string.account_hint);
|
accountCategory.setSummary(R.string.account_hint);
|
||||||
accountCategory.addPreference(getAccountSwitcherPreference(cookie, context));
|
accountCategory.addPreference(getAccountSwitcherPreference(cookie, context));
|
||||||
accountCategory.addPreference(getPreference(R.string.logout, R.string.logout_summary, R.drawable.ic_logout_24, preference -> {
|
accountCategory.addPreference(getPreference(R.string.logout, R.string.logout_summary, R.drawable.ic_logout_24, preference -> {
|
||||||
if (getContext() == null) return false;
|
final Context context1 = getContext();
|
||||||
|
if (context1 == null) return false;
|
||||||
CookieUtils.setupCookies("LOGOUT");
|
CookieUtils.setupCookies("LOGOUT");
|
||||||
shouldRecreate();
|
// shouldRecreate();
|
||||||
Toast.makeText(context, R.string.logout_success, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context1, R.string.logout_success, Toast.LENGTH_SHORT).show();
|
||||||
settingsHelper.putString(Constants.COOKIE, "");
|
settingsHelper.putString(Constants.COOKIE, "");
|
||||||
|
AppExecutors.getInstance().mainThread().execute(() -> {
|
||||||
|
ProcessPhoenix.triggerRebirth(context1);
|
||||||
|
}, 200);
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -103,9 +107,14 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
CookieUtils.removeAllAccounts(context, new RepositoryCallback<Void>() {
|
CookieUtils.removeAllAccounts(context, new RepositoryCallback<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final Void result) {
|
public void onSuccess(final Void result) {
|
||||||
shouldRecreate();
|
// shouldRecreate();
|
||||||
Toast.makeText(context, R.string.logout_success, Toast.LENGTH_SHORT).show();
|
final Context context1 = getContext();
|
||||||
|
if (context1 == null) return;
|
||||||
|
Toast.makeText(context1, R.string.logout_success, Toast.LENGTH_SHORT).show();
|
||||||
settingsHelper.putString(Constants.COOKIE, "");
|
settingsHelper.putString(Constants.COOKIE, "");
|
||||||
|
AppExecutors.getInstance().mainThread().execute(() -> {
|
||||||
|
ProcessPhoenix.triggerRebirth(context1);
|
||||||
|
}, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -222,7 +231,8 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")",
|
BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")",
|
||||||
-1,
|
-1,
|
||||||
preference -> {
|
preference -> {
|
||||||
FlavorTown.updateCheck((AppCompatActivity) requireActivity(), true);
|
if (BuildConfig.isPre) return true;
|
||||||
|
FlavorTown.updateCheck(activity, true);
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
screen.addPreference(getDivider(context));
|
screen.addPreference(getDivider(context));
|
||||||
@ -264,9 +274,14 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
new RepositoryCallback<Account>() {
|
new RepositoryCallback<Account>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final Account result) {
|
public void onSuccess(final Account result) {
|
||||||
final FragmentActivity activity = getActivity();
|
// final FragmentActivity activity = getActivity();
|
||||||
if (activity == null) return;
|
// if (activity == null) return;
|
||||||
activity.recreate();
|
// activity.recreate();
|
||||||
|
AppExecutors.getInstance().mainThread().execute(() -> {
|
||||||
|
final Context context = getContext();
|
||||||
|
if (context == null) return;
|
||||||
|
ProcessPhoenix.triggerRebirth(context);
|
||||||
|
}, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -37,6 +37,14 @@ public class StoriesPreferencesFragment extends BasePreferencesFragment {
|
|||||||
return preference;
|
return preference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Preference getHideMutedReelsPreference(@NonNull final Context context) {
|
||||||
|
final SwitchPreferenceCompat preference = new SwitchPreferenceCompat(context);
|
||||||
|
preference.setKey(Constants.HIDE_MUTED_REELS);
|
||||||
|
preference.setTitle(R.string.hide_muted_reels_setting);
|
||||||
|
preference.setIconSpaceReserved(false);
|
||||||
|
return preference;
|
||||||
|
}
|
||||||
|
|
||||||
private Preference getMarkStoriesSeenPreference(@NonNull final Context context) {
|
private Preference getMarkStoriesSeenPreference(@NonNull final Context context) {
|
||||||
final SwitchPreferenceCompat preference = new SwitchPreferenceCompat(context);
|
final SwitchPreferenceCompat preference = new SwitchPreferenceCompat(context);
|
||||||
preference.setKey(Constants.MARK_AS_SEEN);
|
preference.setKey(Constants.MARK_AS_SEEN);
|
||||||
|
@ -20,6 +20,7 @@ public final class Constants {
|
|||||||
// boolean prefs
|
// boolean prefs
|
||||||
public static final String DOWNLOAD_USER_FOLDER = "download_user_folder";
|
public static final String DOWNLOAD_USER_FOLDER = "download_user_folder";
|
||||||
public static final String TOGGLE_KEYWORD_FILTER = "toggle_keyword_filter";
|
public static final String TOGGLE_KEYWORD_FILTER = "toggle_keyword_filter";
|
||||||
|
public static final String DOWNLOAD_PREPEND_USER_NAME = "download_user_name";
|
||||||
// deprecated: public static final String BOTTOM_TOOLBAR = "bottom_toolbar";
|
// deprecated: public static final String BOTTOM_TOOLBAR = "bottom_toolbar";
|
||||||
public static final String FOLDER_SAVE_TO = "saved_to";
|
public static final String FOLDER_SAVE_TO = "saved_to";
|
||||||
public static final String AUTOPLAY_VIDEOS = "autoplay_videos";
|
public static final String AUTOPLAY_VIDEOS = "autoplay_videos";
|
||||||
@ -28,6 +29,7 @@ public final class Constants {
|
|||||||
public static final String CUSTOM_DATE_TIME_FORMAT_ENABLED = "data_time_custom_enabled";
|
public static final String CUSTOM_DATE_TIME_FORMAT_ENABLED = "data_time_custom_enabled";
|
||||||
public static final String SWAP_DATE_TIME_FORMAT_ENABLED = "swap_date_time_enabled";
|
public static final String SWAP_DATE_TIME_FORMAT_ENABLED = "swap_date_time_enabled";
|
||||||
public static final String MARK_AS_SEEN = "mark_as_seen";
|
public static final String MARK_AS_SEEN = "mark_as_seen";
|
||||||
|
public static final String HIDE_MUTED_REELS = "hide_muted_reels";
|
||||||
public static final String DM_MARK_AS_SEEN = "dm_mark_as_seen";
|
public static final String DM_MARK_AS_SEEN = "dm_mark_as_seen";
|
||||||
// deprecated: public static final String INSTADP = "instadp";
|
// deprecated: public static final String INSTADP = "instadp";
|
||||||
// deprecated: public static final String STORIESIG = "storiesig";
|
// deprecated: public static final String STORIESIG = "storiesig";
|
||||||
@ -79,7 +81,6 @@ public final class Constants {
|
|||||||
// public static final String SIGNATURE_KEY = "9193488027538fd3450b83b7d05286d4ca9599a0f7eeed90d8c85925698a05dc";
|
// public static final String SIGNATURE_KEY = "9193488027538fd3450b83b7d05286d4ca9599a0f7eeed90d8c85925698a05dc";
|
||||||
public static final String BREADCRUMB_KEY = "iN4$aGr0m";
|
public static final String BREADCRUMB_KEY = "iN4$aGr0m";
|
||||||
public static final int LOGIN_RESULT_CODE = 5000;
|
public static final int LOGIN_RESULT_CODE = 5000;
|
||||||
public static final String FDROID_SHA1_FINGERPRINT = "C1661EB8FD09F618307E687786D5E5056F65084D";
|
|
||||||
public static final String SKIPPED_VERSION = "skipped_version";
|
public static final String SKIPPED_VERSION = "skipped_version";
|
||||||
public static final String DEFAULT_TAB = "default_tab";
|
public static final String DEFAULT_TAB = "default_tab";
|
||||||
public static final String PREF_DARK_THEME = "dark_theme";
|
public static final String PREF_DARK_THEME = "dark_theme";
|
||||||
|
@ -98,41 +98,52 @@ public final class DownloadUtils {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private static void dmDownloadImpl(@NonNull final Context context,
|
// private static void dmDownloadImpl(@NonNull final Context context,
|
||||||
@Nullable final String username,
|
// @Nullable final String username,
|
||||||
final String modelId,
|
// final String modelId,
|
||||||
final String url) {
|
// final String url) {
|
||||||
final File dir = getDownloadDir(context, username);
|
// final File dir = getDownloadDir(context, username);
|
||||||
if (dir.exists() || dir.mkdirs()) {
|
// if (dir.exists() || dir.mkdirs()) {
|
||||||
download(context,
|
// download(context,
|
||||||
url,
|
// url,
|
||||||
getDownloadSaveFile(dir, modelId, url).getAbsolutePath());
|
// getDownloadSaveFile(dir, modelId, url).getAbsolutePath());
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
Toast.makeText(context, R.string.error_creating_folders, Toast.LENGTH_SHORT).show();
|
// Toast.makeText(context, R.string.error_creating_folders, Toast.LENGTH_SHORT).show();
|
||||||
}
|
// }
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static File getDownloadSaveFile(final File finalDir,
|
private static File getDownloadSaveFile(final File finalDir,
|
||||||
final String postId,
|
final String postId,
|
||||||
final String displayUrl) {
|
final String displayUrl) {
|
||||||
return getDownloadSaveFile(finalDir, postId, "", displayUrl);
|
return getDownloadSaveFile(finalDir, postId, "", displayUrl, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static File getDownloadSaveFile(final File finalDir,
|
||||||
|
final String postId,
|
||||||
|
final String displayUrl,
|
||||||
|
final String username) {
|
||||||
|
return getDownloadSaveFile(finalDir, postId, "", displayUrl, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static File getDownloadChildSaveFile(final File downloadDir,
|
private static File getDownloadChildSaveFile(final File downloadDir,
|
||||||
final String postId,
|
final String postId,
|
||||||
final int childPosition,
|
final int childPosition,
|
||||||
final String url) {
|
final String url,
|
||||||
|
final String username) {
|
||||||
final String sliderPostfix = "_slide_" + childPosition;
|
final String sliderPostfix = "_slide_" + childPosition;
|
||||||
return getDownloadSaveFile(downloadDir, postId, sliderPostfix, url);
|
return getDownloadSaveFile(downloadDir, postId, sliderPostfix, url, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static File getDownloadSaveFile(final File finalDir,
|
private static File getDownloadSaveFile(final File finalDir,
|
||||||
final String postId,
|
final String postId,
|
||||||
final String sliderPostfix,
|
final String sliderPostfix,
|
||||||
final String displayUrl) {
|
final String displayUrl,
|
||||||
final String fileName = postId + sliderPostfix + getFileExtensionFromUrl(displayUrl);
|
final String username) {
|
||||||
|
final String usernamePrepend = TextUtils.isEmpty(username) ? "" : (username + "_");
|
||||||
|
final String fileName = usernamePrepend + postId + sliderPostfix + getFileExtensionFromUrl(displayUrl);
|
||||||
return new File(finalDir, fileName);
|
return new File(finalDir, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,8 +216,9 @@ public final class DownloadUtils {
|
|||||||
case MEDIA_TYPE_IMAGE:
|
case MEDIA_TYPE_IMAGE:
|
||||||
case MEDIA_TYPE_VIDEO: {
|
case MEDIA_TYPE_VIDEO: {
|
||||||
final String url = ResponseBodyUtils.getImageUrl(media);
|
final String url = ResponseBodyUtils.getImageUrl(media);
|
||||||
final File file = getDownloadSaveFile(downloadDir, media.getCode(), url);
|
final File file = getDownloadSaveFile(downloadDir, media.getCode(), url, "");
|
||||||
checkList.add(file.exists());
|
final File usernamePrependedFile = getDownloadSaveFile(downloadDir, media.getCode(), url, username);
|
||||||
|
checkList.add(file.exists() || usernamePrependedFile.exists());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MEDIA_TYPE_SLIDER:
|
case MEDIA_TYPE_SLIDER:
|
||||||
@ -215,8 +227,9 @@ 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 File file = getDownloadChildSaveFile(downloadDir, media.getCode(), i + 1, url);
|
final File file = getDownloadChildSaveFile(downloadDir, media.getCode(), i + 1, url, "");
|
||||||
checkList.add(file.exists());
|
final File usernamePrependedFile = getDownloadChildSaveFile(downloadDir, media.getCode(), i + 1, url, username);
|
||||||
|
checkList.add(file.exists() || usernamePrependedFile.exists());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -262,10 +275,12 @@ public final class DownloadUtils {
|
|||||||
final String url = storyModel.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO
|
final String url = storyModel.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO
|
||||||
? storyModel.getVideoUrl()
|
? storyModel.getVideoUrl()
|
||||||
: storyModel.getStoryUrl();
|
: storyModel.getStoryUrl();
|
||||||
|
final String baseFileName = storyModel.getStoryMediaId() + "_"
|
||||||
|
+ storyModel.getTimestamp() + DownloadUtils.getFileExtensionFromUrl(url);
|
||||||
|
final String usernamePrepend = Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_PREPEND_USER_NAME)
|
||||||
|
&& storyModel.getUsername() != null ? storyModel.getUsername() + "_" : "";
|
||||||
final File saveFile = new File(downloadDir,
|
final File saveFile = new File(downloadDir,
|
||||||
storyModel.getStoryMediaId()
|
usernamePrepend + baseFileName);
|
||||||
+ "_" + storyModel.getTimestamp()
|
|
||||||
+ DownloadUtils.getFileExtensionFromUrl(url));
|
|
||||||
download(context, url, saveFile.getAbsolutePath());
|
download(context, url, saveFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,13 +306,23 @@ public final class DownloadUtils {
|
|||||||
final Map<String, String> map = new HashMap<>();
|
final Map<String, String> map = new HashMap<>();
|
||||||
for (final Media media : feedModels) {
|
for (final Media media : feedModels) {
|
||||||
final User mediaUser = media.getUser();
|
final User mediaUser = media.getUser();
|
||||||
final File downloadDir = getDownloadDir(context, mediaUser == null ? "" : "@" + mediaUser.getUsername());
|
final File downloadDir = getDownloadDir(context, mediaUser == null ? "" : mediaUser.getUsername());
|
||||||
if (downloadDir == null) return;
|
if (downloadDir == null) return;
|
||||||
switch (media.getMediaType()) {
|
switch (media.getMediaType()) {
|
||||||
case MEDIA_TYPE_IMAGE:
|
case MEDIA_TYPE_IMAGE:
|
||||||
case MEDIA_TYPE_VIDEO: {
|
case MEDIA_TYPE_VIDEO: {
|
||||||
final String url = getUrlOfType(media);
|
final String url = getUrlOfType(media);
|
||||||
final File file = getDownloadSaveFile(downloadDir, media.getCode(), url);
|
String fileName = media.getId();
|
||||||
|
if (mediaUser != null && TextUtils.isEmpty(media.getCode())) {
|
||||||
|
fileName = mediaUser.getUsername() + "_" + fileName;
|
||||||
|
}
|
||||||
|
if (!TextUtils.isEmpty(media.getCode())) {
|
||||||
|
fileName = media.getCode();
|
||||||
|
if (Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_PREPEND_USER_NAME) && mediaUser != null) {
|
||||||
|
fileName = mediaUser.getUsername() + "_" + fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final File file = getDownloadSaveFile(downloadDir, fileName, url);
|
||||||
map.put(url, file.getAbsolutePath());
|
map.put(url, file.getAbsolutePath());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -319,7 +344,8 @@ public final class DownloadUtils {
|
|||||||
}
|
}
|
||||||
final Media child = sliderItems.get(i);
|
final Media child = sliderItems.get(i);
|
||||||
final String url = getUrlOfType(child);
|
final String url = getUrlOfType(child);
|
||||||
final File file = getDownloadChildSaveFile(downloadDir, media.getCode(), i + 1, url);
|
final String usernamePrepend = Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_PREPEND_USER_NAME) && mediaUser != null ? mediaUser.getUsername() : "";
|
||||||
|
final File file = getDownloadChildSaveFile(downloadDir, media.getCode(), i + 1, url, usernamePrepend);
|
||||||
map.put(url, file.getAbsolutePath());
|
map.put(url, file.getAbsolutePath());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -156,12 +156,21 @@ public final class ExportImportUtils {
|
|||||||
query,
|
query,
|
||||||
favoriteType,
|
favoriteType,
|
||||||
favsObject.optString("s"),
|
favsObject.optString("s"),
|
||||||
favoriteType == FavoriteType.HASHTAG ? null
|
favoriteType == FavoriteType.USER ? favsObject.optString("pic_url") : null,
|
||||||
: favsObject.optString("pic_url"),
|
|
||||||
new Date(favsObject.getLong("d")));
|
new Date(favsObject.getLong("d")));
|
||||||
// Log.d(TAG, "importJson: favoriteModel: " + favoriteModel);
|
// Log.d(TAG, "importJson: favoriteModel: " + favoriteModel);
|
||||||
FavoriteRepository.getInstance(FavoriteDataSource.getInstance(context))
|
final FavoriteRepository favRepo = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(context));
|
||||||
.insertOrUpdateFavorite(favorite, null);
|
favRepo.getFavorite(query, favoriteType, new RepositoryCallback<Favorite>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Favorite result) {
|
||||||
|
// local has priority since it's more frequently updated
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {
|
||||||
|
favRepo.insertOrUpdateFavorite(favorite, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,104 +1,72 @@
|
|||||||
package awais.instagrabber.utils;
|
package awais.instagrabber.utils;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.ActivityNotFoundException;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.pm.Signature;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
import java.security.MessageDigest;
|
import java.util.Objects;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
import javax.security.cert.CertificateException;
|
import java.util.regex.Pattern;
|
||||||
import javax.security.cert.X509Certificate;
|
|
||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
import awais.instagrabber.BuildConfig;
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.databinding.DialogUpdateBinding;
|
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
public final class FlavorTown {
|
public final class FlavorTown {
|
||||||
private static final String TAG = "FlavorTown";
|
private static final String TAG = "FlavorTown";
|
||||||
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
|
private static final UpdateChecker UPDATE_CHECKER = UpdateChecker.getInstance();
|
||||||
private static AlertDialog dialog;
|
private static final Pattern VERSION_NAME_PATTERN = Pattern.compile("v?(\\d+\\.\\d+\\.\\d+)(?:_?)(\\w*)(?:-?)(\\w*)");
|
||||||
|
|
||||||
|
private static boolean checking = false;
|
||||||
|
|
||||||
public static void updateCheck(@NonNull final AppCompatActivity context) {
|
public static void updateCheck(@NonNull final AppCompatActivity context) {
|
||||||
updateCheck(context, false);
|
updateCheck(context, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("PackageManagerGetSignatures")
|
public static void updateCheck(@NonNull final AppCompatActivity context,
|
||||||
public static void updateCheck(@NonNull final AppCompatActivity context, final boolean force) {
|
final boolean force) {
|
||||||
boolean isInstalledFromFdroid = false;
|
if (checking) return;
|
||||||
final PackageInfo packageInfo;
|
checking = true;
|
||||||
try {
|
AppExecutors.getInstance().networkIO().execute(() -> {
|
||||||
packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
|
final String onlineVersionName = UPDATE_CHECKER.getLatestVersion();
|
||||||
for (Signature signature : packageInfo.signatures) {
|
if (onlineVersionName == null) return;
|
||||||
final X509Certificate cert = X509Certificate.getInstance(signature.toByteArray());
|
final String onlineVersion = getVersion(onlineVersionName);
|
||||||
final String fingerprint = bytesToHex(MessageDigest.getInstance("SHA-1").digest(cert.getEncoded()));
|
final String localVersion = getVersion(BuildConfig.VERSION_NAME);
|
||||||
isInstalledFromFdroid = fingerprint.equals(Constants.FDROID_SHA1_FINGERPRINT);
|
if (Objects.equals(onlineVersion, localVersion)) {
|
||||||
// Log.d(TAG, "fingerprint:" + fingerprint);
|
if (force) {
|
||||||
}
|
AppExecutors.getInstance().mainThread().execute(() -> {
|
||||||
} catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException | CertificateException e) {
|
final Context applicationContext = context.getApplicationContext();
|
||||||
Log.e(TAG, "Error", e);
|
// Check if app was closed or crashed before reaching here
|
||||||
}
|
if (applicationContext == null) return;
|
||||||
if (isInstalledFromFdroid) return;
|
// Show toast if version number preference was tapped
|
||||||
final DialogUpdateBinding binding = DialogUpdateBinding.inflate(context.getLayoutInflater(), null, false);
|
Toast.makeText(applicationContext, R.string.on_latest_version, Toast.LENGTH_SHORT).show();
|
||||||
binding.skipUpdate.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
});
|
||||||
if (dialog == null) return;
|
}
|
||||||
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(!isChecked);
|
|
||||||
});
|
|
||||||
Resources res = context.getResources();
|
|
||||||
new UpdateChecker(version -> {
|
|
||||||
if (force && version.equals(BuildConfig.VERSION_NAME)) {
|
|
||||||
Toast.makeText(context, "You're already on the latest version", Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final String skippedVersion = settingsHelper.getString(Constants.SKIPPED_VERSION);
|
final boolean shouldShowDialog = UpdateCheckCommon.shouldShowUpdateDialog(force, onlineVersionName);
|
||||||
final boolean shouldShowDialog = force || (!version.equals(BuildConfig.VERSION_NAME) && !BuildConfig.DEBUG && !skippedVersion
|
|
||||||
.equals(version));
|
|
||||||
if (!shouldShowDialog) return;
|
if (!shouldShowDialog) return;
|
||||||
dialog = new AlertDialog.Builder(context)
|
UpdateCheckCommon.showUpdateDialog(context, onlineVersionName, (dialog, which) -> {
|
||||||
.setTitle(res.getString(R.string.update_available, version))
|
UPDATE_CHECKER.onDownload(context);
|
||||||
.setView(binding.getRoot())
|
dialog.dismiss();
|
||||||
.setNeutralButton(R.string.cancel, (dialog, which) -> {
|
});
|
||||||
if (binding.skipUpdate.isChecked()) {
|
});
|
||||||
settingsHelper.putString(Constants.SKIPPED_VERSION, version);
|
}
|
||||||
}
|
|
||||||
dialog.dismiss();
|
private static String getVersion(@NonNull final String versionName) {
|
||||||
})
|
final Matcher matcher = VERSION_NAME_PATTERN.matcher(versionName);
|
||||||
.setPositiveButton(R.string.action_github, (dialog1, which) -> {
|
if (!matcher.matches()) return versionName;
|
||||||
try {
|
try {
|
||||||
context.startActivity(new Intent(Intent.ACTION_VIEW).setData(
|
return matcher.group(1);
|
||||||
Uri.parse("https://github.com/austinhuang0131/instagrabber/releases/latest")));
|
} catch (Exception e) {
|
||||||
} catch (final ActivityNotFoundException e) {
|
Log.e(TAG, "getVersion: ", e);
|
||||||
// do nothing
|
}
|
||||||
}
|
return versionName;
|
||||||
})
|
|
||||||
// if we don't show dialog for fdroid users, is the below required?
|
|
||||||
.setNegativeButton(R.string.action_fdroid, (dialog, which) -> {
|
|
||||||
try {
|
|
||||||
context.startActivity(new Intent(Intent.ACTION_VIEW).setData(
|
|
||||||
Uri.parse("https://f-droid.org/packages/me.austinhuang.instagrabber/")));
|
|
||||||
} catch (final ActivityNotFoundException e) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void changelogCheck(@NonNull final Context context) {
|
public static void changelogCheck(@NonNull final Context context) {
|
||||||
@ -121,14 +89,4 @@ public final class FlavorTown {
|
|||||||
settingsHelper.putInteger(Constants.PREV_INSTALL_VERSION, BuildConfig.VERSION_CODE);
|
settingsHelper.putInteger(Constants.PREV_INSTALL_VERSION, BuildConfig.VERSION_CODE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String bytesToHex(byte[] bytes) {
|
|
||||||
char[] hexChars = new char[bytes.length * 2];
|
|
||||||
for (int j = 0; j < bytes.length; j++) {
|
|
||||||
int v = bytes[j] & 0xFF;
|
|
||||||
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
|
|
||||||
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
|
|
||||||
}
|
|
||||||
return new String(hexChars);
|
|
||||||
}
|
|
||||||
}
|
}
|
111
app/src/main/java/awais/instagrabber/utils/ProcessPhoenix.java
Normal file
111
app/src/main/java/awais/instagrabber/utils/ProcessPhoenix.java
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jake Wharton
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package awais.instagrabber.utils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Process;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process Phoenix facilitates restarting your application process. This should only be used for
|
||||||
|
* things like fundamental state changes in your debug builds (e.g., changing from staging to
|
||||||
|
* production).
|
||||||
|
* <p>
|
||||||
|
* Trigger process recreation by calling {@link #triggerRebirth} with a {@link Context} instance.
|
||||||
|
*/
|
||||||
|
public final class ProcessPhoenix extends Activity {
|
||||||
|
private static final String KEY_RESTART_INTENTS = "phoenix_restart_intents";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call to restart the application process using the {@linkplain Intent#CATEGORY_DEFAULT default}
|
||||||
|
* activity as an intent.
|
||||||
|
* <p>
|
||||||
|
* Behavior of the current process after invoking this method is undefined.
|
||||||
|
*/
|
||||||
|
public static void triggerRebirth(Context context) {
|
||||||
|
triggerRebirth(context, getRestartIntent(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call to restart the application process using the specified intents.
|
||||||
|
* <p>
|
||||||
|
* Behavior of the current process after invoking this method is undefined.
|
||||||
|
*/
|
||||||
|
public static void triggerRebirth(Context context, Intent... nextIntents) {
|
||||||
|
Intent intent = new Intent(context, ProcessPhoenix.class);
|
||||||
|
intent.addFlags(FLAG_ACTIVITY_NEW_TASK); // In case we are called with non-Activity context.
|
||||||
|
intent.putParcelableArrayListExtra(KEY_RESTART_INTENTS, new ArrayList<>(Arrays.asList(nextIntents)));
|
||||||
|
context.startActivity(intent);
|
||||||
|
if (context instanceof Activity) {
|
||||||
|
((Activity) context).finish();
|
||||||
|
}
|
||||||
|
Runtime.getRuntime().exit(0); // Kill kill kill!
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Intent getRestartIntent(Context context) {
|
||||||
|
String packageName = context.getPackageName();
|
||||||
|
Intent defaultIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
|
||||||
|
if (defaultIntent != null) {
|
||||||
|
defaultIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
return defaultIntent;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Unable to determine default activity for "
|
||||||
|
+ packageName
|
||||||
|
+ ". Does an activity specify the DEFAULT category in its intent filter?");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
ArrayList<Intent> intents = getIntent().getParcelableArrayListExtra(KEY_RESTART_INTENTS);
|
||||||
|
startActivities(intents.toArray(new Intent[intents.size()]));
|
||||||
|
finish();
|
||||||
|
Runtime.getRuntime().exit(0); // Kill kill kill!
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the current process is a temporary Phoenix Process.
|
||||||
|
* This can be used to avoid initialisation of unused resources or to prevent running code that
|
||||||
|
* is not multi-process ready.
|
||||||
|
*
|
||||||
|
* @return true if the current process is a temporary Phoenix Process
|
||||||
|
*/
|
||||||
|
public static boolean isPhoenixProcess(Context context) {
|
||||||
|
int currentPid = Process.myPid();
|
||||||
|
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||||
|
List<ActivityManager.RunningAppProcessInfo> runningProcesses = manager.getRunningAppProcesses();
|
||||||
|
if (runningProcesses != null) {
|
||||||
|
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
|
||||||
|
if (processInfo.pid == currentPid && processInfo.processName.endsWith(":phoenix")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -1090,11 +1090,19 @@ public final class ResponseBodyUtils {
|
|||||||
if (imageVersions2 == null) return null;
|
if (imageVersions2 == null) return null;
|
||||||
final List<MediaCandidate> candidates = imageVersions2.getCandidates();
|
final List<MediaCandidate> candidates = imageVersions2.getCandidates();
|
||||||
if (candidates == null || candidates.isEmpty()) return null;
|
if (candidates == null || candidates.isEmpty()) return null;
|
||||||
|
final boolean isSquare = Integer.compare(media.getOriginalWidth(), media.getOriginalHeight()) == 0;
|
||||||
final List<MediaCandidate> sortedCandidates = candidates.stream()
|
final List<MediaCandidate> sortedCandidates = candidates.stream()
|
||||||
.sorted((c1, c2) -> Integer.compare(c2.getWidth(), c1.getWidth()))
|
.sorted((c1, c2) -> Integer.compare(c2.getWidth(), c1.getWidth()))
|
||||||
.filter(c -> c.getWidth() < type.getValue())
|
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
final MediaCandidate candidate = sortedCandidates.get(0);
|
if (sortedCandidates.size() == 1) return sortedCandidates.get(0).getUrl();
|
||||||
|
final List<MediaCandidate> filteredCandidates = sortedCandidates.stream()
|
||||||
|
.filter(c ->
|
||||||
|
c.getWidth() <= media.getOriginalWidth()
|
||||||
|
&& c.getWidth() <= type.getValue()
|
||||||
|
&& (isSquare || Integer.compare(c.getWidth(), c.getHeight()) != 0)
|
||||||
|
)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
final MediaCandidate candidate = filteredCandidates.get(0);
|
||||||
if (candidate == null) return null;
|
if (candidate == null) return null;
|
||||||
return candidate.getUrl();
|
return candidate.getUrl();
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,12 @@ import static awais.instagrabber.utils.Constants.DATE_TIME_SELECTION;
|
|||||||
import static awais.instagrabber.utils.Constants.DEFAULT_TAB;
|
import static awais.instagrabber.utils.Constants.DEFAULT_TAB;
|
||||||
import static awais.instagrabber.utils.Constants.DEVICE_UUID;
|
import static awais.instagrabber.utils.Constants.DEVICE_UUID;
|
||||||
import static awais.instagrabber.utils.Constants.DM_MARK_AS_SEEN;
|
import static awais.instagrabber.utils.Constants.DM_MARK_AS_SEEN;
|
||||||
|
import static awais.instagrabber.utils.Constants.DOWNLOAD_PREPEND_USER_NAME;
|
||||||
import static awais.instagrabber.utils.Constants.DOWNLOAD_USER_FOLDER;
|
import static awais.instagrabber.utils.Constants.DOWNLOAD_USER_FOLDER;
|
||||||
import static awais.instagrabber.utils.Constants.FLAG_SECURE;
|
import static awais.instagrabber.utils.Constants.FLAG_SECURE;
|
||||||
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.Constants.HIDE_MUTED_REELS;
|
||||||
import static awais.instagrabber.utils.Constants.KEYWORD_FILTERS;
|
import static awais.instagrabber.utils.Constants.KEYWORD_FILTERS;
|
||||||
import static awais.instagrabber.utils.Constants.MARK_AS_SEEN;
|
import static awais.instagrabber.utils.Constants.MARK_AS_SEEN;
|
||||||
import static awais.instagrabber.utils.Constants.MUTED_VIDEOS;
|
import static awais.instagrabber.utils.Constants.MUTED_VIDEOS;
|
||||||
@ -159,10 +161,10 @@ public final class SettingsHelper {
|
|||||||
STORY_SORT, PREF_EMOJI_VARIANTS, PREF_REACTIONS, PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT, PREF_TAB_ORDER})
|
STORY_SORT, PREF_EMOJI_VARIANTS, PREF_REACTIONS, PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT, PREF_TAB_ORDER})
|
||||||
public @interface StringSettings {}
|
public @interface StringSettings {}
|
||||||
|
|
||||||
@StringDef({DOWNLOAD_USER_FOLDER, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
|
@StringDef({DOWNLOAD_USER_FOLDER, DOWNLOAD_PREPEND_USER_NAME, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
|
||||||
SHOW_CAPTIONS, CUSTOM_DATE_TIME_FORMAT_ENABLED, MARK_AS_SEEN, DM_MARK_AS_SEEN, CHECK_ACTIVITY,
|
SHOW_CAPTIONS, CUSTOM_DATE_TIME_FORMAT_ENABLED, MARK_AS_SEEN, DM_MARK_AS_SEEN, CHECK_ACTIVITY,
|
||||||
CHECK_UPDATES, SWAP_DATE_TIME_FORMAT_ENABLED, PREF_ENABLE_DM_NOTIFICATIONS, PREF_ENABLE_DM_AUTO_REFRESH,
|
CHECK_UPDATES, SWAP_DATE_TIME_FORMAT_ENABLED, PREF_ENABLE_DM_NOTIFICATIONS, PREF_ENABLE_DM_AUTO_REFRESH,
|
||||||
FLAG_SECURE, TOGGLE_KEYWORD_FILTER, PREF_ENABLE_SENTRY})
|
FLAG_SECURE, TOGGLE_KEYWORD_FILTER, PREF_ENABLE_SENTRY, HIDE_MUTED_REELS})
|
||||||
public @interface BooleanSettings {}
|
public @interface BooleanSettings {}
|
||||||
|
|
||||||
@StringDef({PREV_INSTALL_VERSION, BROWSER_UA_CODE, APP_UA_CODE, PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER})
|
@StringDef({PREV_INSTALL_VERSION, BROWSER_UA_CODE, APP_UA_CODE, PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER})
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package awais.instagrabber.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
|
||||||
|
import awais.instagrabber.BuildConfig;
|
||||||
|
import awais.instagrabber.R;
|
||||||
|
|
||||||
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
|
public final class UpdateCheckCommon {
|
||||||
|
|
||||||
|
public static boolean shouldShowUpdateDialog(final boolean force,
|
||||||
|
@NonNull final String version) {
|
||||||
|
final String skippedVersion = settingsHelper.getString(Constants.SKIPPED_VERSION);
|
||||||
|
return force || (!BuildConfig.DEBUG && !skippedVersion.equals(version));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void showUpdateDialog(@NonNull final Context context,
|
||||||
|
@NonNull final String version,
|
||||||
|
@NonNull final DialogInterface.OnClickListener onDownloadClickListener) {
|
||||||
|
AppExecutors.getInstance().mainThread().execute(() -> {
|
||||||
|
new MaterialAlertDialogBuilder(context)
|
||||||
|
.setTitle(context.getString(R.string.update_available, version))
|
||||||
|
.setNeutralButton(R.string.skip_update, (dialog, which) -> {
|
||||||
|
settingsHelper.putString(Constants.SKIPPED_VERSION, version);
|
||||||
|
dialog.dismiss();
|
||||||
|
})
|
||||||
|
.setPositiveButton(R.string.action_download, onDownloadClickListener)
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,58 +0,0 @@
|
|||||||
package awais.instagrabber.utils;
|
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
|
||||||
import awais.instagrabber.interfaces.FetchListener;
|
|
||||||
|
|
||||||
public final class UpdateChecker extends AsyncTask<Void, Void, Boolean> {
|
|
||||||
private final FetchListener<String> fetchListener;
|
|
||||||
private String version;
|
|
||||||
|
|
||||||
public UpdateChecker(final FetchListener<String> fetchListener) {
|
|
||||||
this.fetchListener = fetchListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(final Void... voids) {
|
|
||||||
try {
|
|
||||||
version = "";
|
|
||||||
|
|
||||||
HttpURLConnection conn =
|
|
||||||
(HttpURLConnection) new URL("https://f-droid.org/api/v1/packages/me.austinhuang.instagrabber").openConnection();
|
|
||||||
conn.setUseCaches(false);
|
|
||||||
conn.setRequestProperty("User-Agent", "https://Barinsta.AustinHuang.me / mailto:Barinsta@AustinHuang.me");
|
|
||||||
conn.connect();
|
|
||||||
|
|
||||||
final int responseCode = conn.getResponseCode();
|
|
||||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
||||||
final JSONObject data = new JSONObject(NetworkUtils.readFromConnection(conn));
|
|
||||||
if (BuildConfig.VERSION_CODE < data.getInt("suggestedVersionCode")) {
|
|
||||||
version = data.getJSONArray("packages").getJSONObject(0).getString("versionName");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.disconnect();
|
|
||||||
} catch (final Exception e) {
|
|
||||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(final Boolean result) {
|
|
||||||
if (result != null && result && fetchListener != null)
|
|
||||||
fetchListener.onResult("v"+version);
|
|
||||||
}
|
|
||||||
}
|
|
@ -31,7 +31,6 @@ import android.webkit.MimeTypeMap;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.IdRes;
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
@ -474,7 +473,11 @@ public final class Utils {
|
|||||||
final List<String> navGraphNameList = Arrays.asList(navGraphNames);
|
final List<String> navGraphNameList = Arrays.asList(navGraphNames);
|
||||||
if (TextUtils.isEmpty(tabOrderString)) {
|
if (TextUtils.isEmpty(tabOrderString)) {
|
||||||
// Use top 5 entries for default list
|
// Use top 5 entries for default list
|
||||||
return navGraphNameList.subList(0, 5);
|
final List<String> top5navGraphNames = navGraphNameList.subList(0, 5);
|
||||||
|
final String newOrderString = android.text.TextUtils.join(",", top5navGraphNames);
|
||||||
|
Utils.settingsHelper.putString(PreferenceKeys.PREF_TAB_ORDER, newOrderString);
|
||||||
|
tabOrderString = newOrderString;
|
||||||
|
return top5navGraphNames;
|
||||||
}
|
}
|
||||||
// Make sure that the list from preference does not contain any invalid values
|
// Make sure that the list from preference does not contain any invalid values
|
||||||
final List<String> orderGraphNames = Arrays.stream(tabOrderString.split(","))
|
final List<String> orderGraphNames = Arrays.stream(tabOrderString.split(","))
|
||||||
@ -489,6 +492,7 @@ public final class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNavRootInCurrentTabs(final String navRootString) {
|
public static boolean isNavRootInCurrentTabs(final String navRootString) {
|
||||||
|
if (navRootString == null || tabOrderString == null) return false;
|
||||||
return tabOrderString.contains(navRootString);
|
return tabOrderString.contains(navRootString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,9 +54,11 @@ public class NewsService extends BaseService {
|
|||||||
callback.onSuccess(null);
|
callback.onSuccess(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final List<Notification> result = new ArrayList<>();
|
final List<Notification> result = new ArrayList<Notification>();
|
||||||
result.addAll(body.getNewStories());
|
final List<Notification> newStories = body.getNewStories();
|
||||||
result.addAll(body.getOldStories());
|
if (newStories != null) result.addAll(newStories);
|
||||||
|
final List<Notification> oldStories = body.getOldStories();
|
||||||
|
if (oldStories != null) result.addAll(oldStories);
|
||||||
callback.onSuccess(result);
|
callback.onSuccess(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ public class StoriesService extends BaseService {
|
|||||||
final JSONArray feedStoriesReel = new JSONObject(body).getJSONArray("tray");
|
final JSONArray feedStoriesReel = new JSONObject(body).getJSONArray("tray");
|
||||||
for (int i = 0; i < feedStoriesReel.length(); ++i) {
|
for (int i = 0; i < feedStoriesReel.length(); ++i) {
|
||||||
final JSONObject node = feedStoriesReel.getJSONObject(i);
|
final JSONObject node = feedStoriesReel.getJSONObject(i);
|
||||||
if (node.optBoolean("hide_from_feed_unit")) continue;
|
if (node.optBoolean("hide_from_feed_unit") && Utils.settingsHelper.getBoolean(Constants.HIDE_MUTED_REELS)) continue;
|
||||||
final JSONObject userJson = node.getJSONObject(node.has("user") ? "user" : "owner");
|
final JSONObject userJson = node.getJSONObject(node.has("user") ? "user" : "owner");
|
||||||
try {
|
try {
|
||||||
final User user = new User(userJson.getLong("pk"),
|
final User user = new User(userJson.getLong("pk"),
|
||||||
@ -177,18 +177,24 @@ public class StoriesService extends BaseService {
|
|||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
final String id = node.getString("id");
|
|
||||||
final long timestamp = node.getLong("latest_reel_media");
|
final long timestamp = node.getLong("latest_reel_media");
|
||||||
final int mediaCount = node.getInt("media_count");
|
|
||||||
final boolean fullyRead = !node.isNull("seen") && node.getLong("seen") == timestamp;
|
final boolean fullyRead = !node.isNull("seen") && node.getLong("seen") == timestamp;
|
||||||
final JSONObject itemJson = node.has("items") ? node.getJSONArray("items").optJSONObject(0) : null;
|
final JSONObject itemJson = node.has("items") ? node.getJSONArray("items").optJSONObject(0) : null;
|
||||||
final boolean isBestie = node.optBoolean("has_besties_media", false);
|
|
||||||
StoryModel firstStoryModel = null;
|
StoryModel firstStoryModel = null;
|
||||||
if (itemJson != null) {
|
if (itemJson != null) {
|
||||||
firstStoryModel = ResponseBodyUtils.parseStoryItem(itemJson, false, null);
|
firstStoryModel = ResponseBodyUtils.parseStoryItem(itemJson, false, null);
|
||||||
}
|
}
|
||||||
feedStoryModels.add(new FeedStoryModel(id, user, fullyRead, timestamp, firstStoryModel, mediaCount, false, isBestie));
|
feedStoryModels.add(new FeedStoryModel(
|
||||||
} catch (Exception e) {} // to cover promotional reels with non-long user pk's
|
node.getString("id"),
|
||||||
|
user,
|
||||||
|
fullyRead,
|
||||||
|
timestamp,
|
||||||
|
firstStoryModel,
|
||||||
|
node.getInt("media_count"),
|
||||||
|
false,
|
||||||
|
node.optBoolean("has_besties_media")));
|
||||||
|
}
|
||||||
|
catch (Exception e) {} // to cover promotional reels with non-long user pk's
|
||||||
}
|
}
|
||||||
final JSONArray broadcasts = new JSONObject(body).getJSONArray("broadcasts");
|
final JSONArray broadcasts = new JSONObject(body).getJSONArray("broadcasts");
|
||||||
for (int i = 0; i < broadcasts.length(); ++i) {
|
for (int i = 0; i < broadcasts.length(); ++i) {
|
||||||
@ -239,13 +245,16 @@ public class StoriesService extends BaseService {
|
|||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
final String id = node.getString("id");
|
feedStoryModels.add(new FeedStoryModel(
|
||||||
final long timestamp = node.getLong("published_time");
|
node.getString("id"),
|
||||||
// final JSONObject itemJson = node.has("items") ? node.getJSONArray("items").getJSONObject(0) : null;
|
user,
|
||||||
final StoryModel firstStoryModel = ResponseBodyUtils.parseBroadcastItem(node);
|
false,
|
||||||
// if (itemJson != null) {
|
node.getLong("published_time"),
|
||||||
// }
|
ResponseBodyUtils.parseBroadcastItem(node),
|
||||||
feedStoryModels.add(new FeedStoryModel(id, user, false, timestamp, firstStoryModel, 1, true, false));
|
1,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
));
|
||||||
}
|
}
|
||||||
callback.onSuccess(sort(feedStoryModels));
|
callback.onSuccess(sort(feedStoryModels));
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
|
@ -326,6 +326,7 @@
|
|||||||
<androidx.constraintlayout.widget.Barrier
|
<androidx.constraintlayout.widget.Barrier
|
||||||
android:id="@+id/highlights_barrier"
|
android:id="@+id/highlights_barrier"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
app:constraint_referenced_ids="mainPostCount, mainFollowers, mainFollowing"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:barrierDirection="bottom" />
|
app:barrierDirection="bottom" />
|
||||||
|
|
||||||
|
@ -5,13 +5,18 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/action_dms"
|
android:id="@+id/action_dms"
|
||||||
android:icon="@drawable/ic_round_send_24"
|
android:icon="@drawable/ic_round_send_24"
|
||||||
android:title="@string/action_dms"
|
android:title="@string/reply_story"
|
||||||
android:titleCondensed="@string/action_dms"
|
android:titleCondensed="@string/reply_story"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_profile"
|
||||||
|
android:title="@string/open_profile"
|
||||||
|
android:titleCondensed="@string/open_profile"
|
||||||
|
app:showAsAction="never" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_download"
|
android:id="@+id/action_download"
|
||||||
android:icon="@drawable/ic_download"
|
android:icon="@drawable/ic_download"
|
||||||
android:title="@string/action_download"
|
android:title="@string/action_download"
|
||||||
android:titleCondensed="@string/action_download"
|
android:titleCondensed="@string/action_download"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="never" />
|
||||||
</menu>
|
</menu>
|
@ -5,24 +5,16 @@
|
|||||||
android:id="@+id/notification_viewer_nav_graph"
|
android:id="@+id/notification_viewer_nav_graph"
|
||||||
app:startDestination="@id/notificationsViewer">
|
app:startDestination="@id/notificationsViewer">
|
||||||
|
|
||||||
<fragment
|
<include app:graph="@navigation/profile_nav_graph" />
|
||||||
android:id="@+id/notificationsViewer"
|
|
||||||
android:name="awais.instagrabber.fragments.NotificationsViewerFragment"
|
<action
|
||||||
android:label="@string/title_notifications"
|
android:id="@+id/action_global_profileFragment"
|
||||||
tools:layout="@layout/fragment_notifications_viewer">
|
app:destination="@id/profile_nav_graph">
|
||||||
<argument
|
<argument
|
||||||
android:name="type"
|
android:name="username"
|
||||||
app:argType="string"
|
app:argType="string"
|
||||||
app:nullable="false"
|
app:nullable="true" />
|
||||||
android:defaultValue="notif"/>
|
</action>
|
||||||
<argument
|
|
||||||
android:name="targetId"
|
|
||||||
android:defaultValue="0L"
|
|
||||||
app:argType="long" />
|
|
||||||
<action
|
|
||||||
android:id="@+id/action_notificationsViewerFragment_to_storyViewerFragment"
|
|
||||||
app:destination="@id/storyViewerFragment" />
|
|
||||||
</fragment>
|
|
||||||
|
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_global_notificationsViewerFragment"
|
android:id="@+id/action_global_notificationsViewerFragment"
|
||||||
@ -89,4 +81,23 @@
|
|||||||
android:name="options"
|
android:name="options"
|
||||||
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
|
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/notificationsViewer"
|
||||||
|
android:name="awais.instagrabber.fragments.NotificationsViewerFragment"
|
||||||
|
android:label="@string/title_notifications"
|
||||||
|
tools:layout="@layout/fragment_notifications_viewer">
|
||||||
|
<argument
|
||||||
|
android:name="type"
|
||||||
|
app:argType="string"
|
||||||
|
app:nullable="false"
|
||||||
|
android:defaultValue="notif"/>
|
||||||
|
<argument
|
||||||
|
android:name="targetId"
|
||||||
|
android:defaultValue="0L"
|
||||||
|
app:argType="long" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_notifications_to_story"
|
||||||
|
app:destination="@id/storyViewerFragment" />
|
||||||
|
</fragment>
|
||||||
</navigation>
|
</navigation>
|
@ -71,11 +71,9 @@
|
|||||||
app:argType="long" />
|
app:argType="long" />
|
||||||
</action>
|
</action>
|
||||||
|
|
||||||
<include app:graph="@navigation/notification_viewer_nav_graph" />
|
|
||||||
|
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_global_notificationsViewerFragment"
|
android:id="@+id/action_global_notificationsViewerFragment"
|
||||||
app:destination="@id/notification_viewer_nav_graph">
|
app:destination="@id/notificationsViewer">
|
||||||
<argument
|
<argument
|
||||||
android:name="type"
|
android:name="type"
|
||||||
app:argType="string"
|
app:argType="string"
|
||||||
@ -86,6 +84,22 @@
|
|||||||
app:argType="long" />
|
app:argType="long" />
|
||||||
</action>
|
</action>
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/notificationsViewer"
|
||||||
|
android:name="awais.instagrabber.fragments.NotificationsViewerFragment"
|
||||||
|
android:label="@string/title_notifications"
|
||||||
|
tools:layout="@layout/fragment_notifications_viewer">
|
||||||
|
<argument
|
||||||
|
android:name="type"
|
||||||
|
app:argType="string"
|
||||||
|
app:nullable="false"
|
||||||
|
android:defaultValue="notif"/>
|
||||||
|
<argument
|
||||||
|
android:name="targetId"
|
||||||
|
android:defaultValue="0L"
|
||||||
|
app:argType="long" />
|
||||||
|
</fragment>
|
||||||
|
|
||||||
<include app:graph="@navigation/saved_nav_graph" />
|
<include app:graph="@navigation/saved_nav_graph" />
|
||||||
|
|
||||||
<action
|
<action
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Cerca actualitzacions a l\'inici</string>
|
<string name="update_check">Cerca actualitzacions a l\'inici</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Descarrega les publicacions a carpetes de nom d\'usuari</string>
|
<string name="download_user_folder">Descarrega les publicacions a carpetes de nom d\'usuari</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Marca les històries com a vistes després de visualitzar-es</string>
|
<string name="mark_as_seen_setting">Marca les històries com a vistes després de visualitzar-es</string>
|
||||||
<string name="mark_as_seen_setting_summary">L\'autor de la història sabrà que l\'has vista</string>
|
<string name="mark_as_seen_setting_summary">L\'autor de la història sabrà que l\'has vista</string>
|
||||||
<string name="dm_mark_as_seen_setting">Marca els missatges com a vists després de visualitzar-los</string>
|
<string name="dm_mark_as_seen_setting">Marca els missatges com a vists després de visualitzar-los</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Zkontrolovat aktualizace při spuštění</string>
|
<string name="update_check">Zkontrolovat aktualizace při spuštění</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Stáhnout příspěvky do složek s uživatelským jménem</string>
|
<string name="download_user_folder">Stáhnout příspěvky do složek s uživatelským jménem</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Označit příběhy po zhlédnutí jako zobrazené</string>
|
<string name="mark_as_seen_setting">Označit příběhy po zhlédnutí jako zobrazené</string>
|
||||||
<string name="mark_as_seen_setting_summary">Autor příběhu bude vědět, že jsi si ho zobrazili</string>
|
<string name="mark_as_seen_setting_summary">Autor příběhu bude vědět, že jsi si ho zobrazili</string>
|
||||||
<string name="dm_mark_as_seen_setting">Označovat přímou zprávu po zobrazení jako zobrazenou</string>
|
<string name="dm_mark_as_seen_setting">Označovat přímou zprávu po zobrazení jako zobrazenou</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Beim Start auf Aktualisierungen prüfen</string>
|
<string name="update_check">Beim Start auf Aktualisierungen prüfen</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Beiträge in Benutzernamen-Ordner herunterladen</string>
|
<string name="download_user_folder">Beiträge in Benutzernamen-Ordner herunterladen</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Stories nach dem Ansehen als gesehen markieren</string>
|
<string name="mark_as_seen_setting">Stories nach dem Ansehen als gesehen markieren</string>
|
||||||
<string name="mark_as_seen_setting_summary">Die Person wird wissen, dass du dir die Story angesehen hast</string>
|
<string name="mark_as_seen_setting_summary">Die Person wird wissen, dass du dir die Story angesehen hast</string>
|
||||||
<string name="dm_mark_as_seen_setting">Direktnachrichten nach dem Ansehen als gesehen markieren</string>
|
<string name="dm_mark_as_seen_setting">Direktnachrichten nach dem Ansehen als gesehen markieren</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Έλεγχος για ενημερώσεις στο ξεκίνημα</string>
|
<string name="update_check">Έλεγχος για ενημερώσεις στο ξεκίνημα</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Λήψη δημοσίευσης στους φακέλους με ονόματα χρηστών</string>
|
<string name="download_user_folder">Λήψη δημοσίευσης στους φακέλους με ονόματα χρηστών</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Επισήμανση ιστοριών ως προβληθέντων μετά την προβολή</string>
|
<string name="mark_as_seen_setting">Επισήμανση ιστοριών ως προβληθέντων μετά την προβολή</string>
|
||||||
<string name="mark_as_seen_setting_summary">Ο συντάκτης της ιστορίας θα ξέρει ότι την προβάλατε</string>
|
<string name="mark_as_seen_setting_summary">Ο συντάκτης της ιστορίας θα ξέρει ότι την προβάλατε</string>
|
||||||
<string name="dm_mark_as_seen_setting">Σήμανση ΠΜ ως αναγνωσμένου μετά την προβολή</string>
|
<string name="dm_mark_as_seen_setting">Σήμανση ΠΜ ως αναγνωσμένου μετά την προβολή</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Buscar actualizaciones al inicio</string>
|
<string name="update_check">Buscar actualizaciones al inicio</string>
|
||||||
<string name="flag_secure">Bloquea capturas de pantalla & vista previa de aplicaciones</string>
|
<string name="flag_secure">Bloquea capturas de pantalla & vista previa de aplicaciones</string>
|
||||||
<string name="download_user_folder">Usar subcarpetas con el nombre de usuario</string>
|
<string name="download_user_folder">Usar subcarpetas con el nombre de usuario</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Marcar historias como vistas después de verlas</string>
|
<string name="mark_as_seen_setting">Marcar historias como vistas después de verlas</string>
|
||||||
<string name="mark_as_seen_setting_summary">El autor de la historia sabrá que lo has visto</string>
|
<string name="mark_as_seen_setting_summary">El autor de la historia sabrá que lo has visto</string>
|
||||||
<string name="dm_mark_as_seen_setting">Marcar Mensaje Directo como visto después de verlo</string>
|
<string name="dm_mark_as_seen_setting">Marcar Mensaje Directo como visto después de verlo</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Bilatu eguneratzeak abioan</string>
|
<string name="update_check">Bilatu eguneratzeak abioan</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Deskargatu bidalketak erabiltzaile-izena duten karpetetara</string>
|
<string name="download_user_folder">Deskargatu bidalketak erabiltzaile-izena duten karpetetara</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Markatu istorioak ikusita gisa ikusi ondoren</string>
|
<string name="mark_as_seen_setting">Markatu istorioak ikusita gisa ikusi ondoren</string>
|
||||||
<string name="mark_as_seen_setting_summary">Istorioaren egileak ikusi duzula jakingo du</string>
|
<string name="mark_as_seen_setting_summary">Istorioaren egileak ikusi duzula jakingo du</string>
|
||||||
<string name="dm_mark_as_seen_setting">Markatu MZ ikusita gisa ikusi ondoren</string>
|
<string name="dm_mark_as_seen_setting">Markatu MZ ikusita gisa ikusi ondoren</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">بررسی بروزرسانی هنگام آغاز برنامه</string>
|
<string name="update_check">بررسی بروزرسانی هنگام آغاز برنامه</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">بارگیری پست ها در پوشه های به نام کاربر</string>
|
<string name="download_user_folder">بارگیری پست ها در پوشه های به نام کاربر</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">نشان کرد استوری ها به عنوان دیده شده بعد از دیدن</string>
|
<string name="mark_as_seen_setting">نشان کرد استوری ها به عنوان دیده شده بعد از دیدن</string>
|
||||||
<string name="mark_as_seen_setting_summary">نویسنده استوری می داند که شما آن را دیده اید</string>
|
<string name="mark_as_seen_setting_summary">نویسنده استوری می داند که شما آن را دیده اید</string>
|
||||||
<string name="dm_mark_as_seen_setting">نشان کردن پیام خصوصی بعنوان دیده شده بعد از دیدن</string>
|
<string name="dm_mark_as_seen_setting">نشان کردن پیام خصوصی بعنوان دیده شده بعد از دیدن</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Rechercher les mises à jours au démarrage</string>
|
<string name="update_check">Rechercher les mises à jours au démarrage</string>
|
||||||
<string name="flag_secure">Bloquer les captures d\'écran & l\'aperçu de l\'application</string>
|
<string name="flag_secure">Bloquer les captures d\'écran & l\'aperçu de l\'application</string>
|
||||||
<string name="download_user_folder">Télécharger les messages dans les dossiers des noms d\'utilisateurs</string>
|
<string name="download_user_folder">Télécharger les messages dans les dossiers des noms d\'utilisateurs</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Marquer les stories comme vues après consultation</string>
|
<string name="mark_as_seen_setting">Marquer les stories comme vues après consultation</string>
|
||||||
<string name="mark_as_seen_setting_summary">L\'auteur de la story saura que vous l\'avez vue</string>
|
<string name="mark_as_seen_setting_summary">L\'auteur de la story saura que vous l\'avez vue</string>
|
||||||
<string name="dm_mark_as_seen_setting">Marquer les messages privés comme vus après consultation</string>
|
<string name="dm_mark_as_seen_setting">Marquer les messages privés comme vus après consultation</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">खुलने पर अपडेट के लिए जाँच करें</string>
|
<string name="update_check">खुलने पर अपडेट के लिए जाँच करें</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">पोस्ट को ब्यबहारकारी के नाम पर किये फोल्डरस में रखें</string>
|
<string name="download_user_folder">पोस्ट को ब्यबहारकारी के नाम पर किये फोल्डरस में रखें</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">स्टोरि को दिखने के बाद \"दिखा गया\" दिखादें</string>
|
<string name="mark_as_seen_setting">स्टोरि को दिखने के बाद \"दिखा गया\" दिखादें</string>
|
||||||
<string name="mark_as_seen_setting_summary">सटोरि के लेखक जानेगा कि तुम देखे हो इसको</string>
|
<string name="mark_as_seen_setting_summary">सटोरि के लेखक जानेगा कि तुम देखे हो इसको</string>
|
||||||
<string name="dm_mark_as_seen_setting">तुम देखने के बाद सीधा संदेश को \"दिखागया\" लिखा जाएगा</string>
|
<string name="dm_mark_as_seen_setting">तुम देखने के बाद सीधा संदेश को \"दिखागया\" लिखा जाएगा</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Cek pembaruan saat memulai</string>
|
<string name="update_check">Cek pembaruan saat memulai</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Unduh kiriman ke folder nama pengguna</string>
|
<string name="download_user_folder">Unduh kiriman ke folder nama pengguna</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Tandai cerita dibaca setelah melihat</string>
|
<string name="mark_as_seen_setting">Tandai cerita dibaca setelah melihat</string>
|
||||||
<string name="mark_as_seen_setting_summary">Pembuat cerita akan tahu Anda melihatnya</string>
|
<string name="mark_as_seen_setting_summary">Pembuat cerita akan tahu Anda melihatnya</string>
|
||||||
<string name="dm_mark_as_seen_setting">Tandai DM dibaca setelah melihat</string>
|
<string name="dm_mark_as_seen_setting">Tandai DM dibaca setelah melihat</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Verifica per aggiornamenti all\'avvio</string>
|
<string name="update_check">Verifica per aggiornamenti all\'avvio</string>
|
||||||
<string name="flag_secure">Blocca screenshot & anteprima app</string>
|
<string name="flag_secure">Blocca screenshot & anteprima app</string>
|
||||||
<string name="download_user_folder">Scarica i post nelle cartelle del nome utente</string>
|
<string name="download_user_folder">Scarica i post nelle cartelle del nome utente</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Segna le storie come viste dopo la visualizzazione</string>
|
<string name="mark_as_seen_setting">Segna le storie come viste dopo la visualizzazione</string>
|
||||||
<string name="mark_as_seen_setting_summary">L\'autore della storia saprà che l\'hai visualizzata</string>
|
<string name="mark_as_seen_setting_summary">L\'autore della storia saprà che l\'hai visualizzata</string>
|
||||||
<string name="dm_mark_as_seen_setting">Segna il DM come visto dopo la visualizzazione</string>
|
<string name="dm_mark_as_seen_setting">Segna il DM come visto dopo la visualizzazione</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">起動時にアップデートを確認</string>
|
<string name="update_check">起動時にアップデートを確認</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">ユーザ名のフォルダに投稿をダウンロード</string>
|
<string name="download_user_folder">ユーザ名のフォルダに投稿をダウンロード</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">ストーリーズを表示後に既読にする</string>
|
<string name="mark_as_seen_setting">ストーリーズを表示後に既読にする</string>
|
||||||
<string name="mark_as_seen_setting_summary">ストーリーの作成者は、あなたが閲覧したことを知ることができます。</string>
|
<string name="mark_as_seen_setting_summary">ストーリーの作成者は、あなたが閲覧したことを知ることができます。</string>
|
||||||
<string name="dm_mark_as_seen_setting">DMを表示後に既読にする</string>
|
<string name="dm_mark_as_seen_setting">DMを表示後に既読にする</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Check for updates at startup</string>
|
<string name="update_check">Check for updates at startup</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Download posts to username folders</string>
|
<string name="download_user_folder">Download posts to username folders</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Mark stories as seen after viewing</string>
|
<string name="mark_as_seen_setting">Mark stories as seen after viewing</string>
|
||||||
<string name="mark_as_seen_setting_summary">Story author will know you viewed it</string>
|
<string name="mark_as_seen_setting_summary">Story author will know you viewed it</string>
|
||||||
<string name="dm_mark_as_seen_setting">Mark DM as seen after viewing</string>
|
<string name="dm_mark_as_seen_setting">Mark DM as seen after viewing</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Провери за ажурирање</string>
|
<string name="update_check">Провери за ажурирање</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Превземи објави во папката со кориснички имиња</string>
|
<string name="download_user_folder">Превземи објави во папката со кориснички имиња</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Означи ги приказните како видени</string>
|
<string name="mark_as_seen_setting">Означи ги приказните како видени</string>
|
||||||
<string name="mark_as_seen_setting_summary">Авторот на приказната ќе знае дека сте ја погледнале приказната</string>
|
<string name="mark_as_seen_setting_summary">Авторот на приказната ќе знае дека сте ја погледнале приказната</string>
|
||||||
<string name="dm_mark_as_seen_setting">Означи порака како видена</string>
|
<string name="dm_mark_as_seen_setting">Означи порака како видена</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Controleer op updates bij het opstarten</string>
|
<string name="update_check">Controleer op updates bij het opstarten</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Download berichten naar gebruikersnaam mappen</string>
|
<string name="download_user_folder">Download berichten naar gebruikersnaam mappen</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Markeer verhalen als gelezen na bekijken</string>
|
<string name="mark_as_seen_setting">Markeer verhalen als gelezen na bekijken</string>
|
||||||
<string name="mark_as_seen_setting_summary">Verhaalmaker zal het weten als je het bekeken hebt</string>
|
<string name="mark_as_seen_setting_summary">Verhaalmaker zal het weten als je het bekeken hebt</string>
|
||||||
<string name="dm_mark_as_seen_setting">Markeer privéberichten als gelezen na bekijken</string>
|
<string name="dm_mark_as_seen_setting">Markeer privéberichten als gelezen na bekijken</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">ଖୋଲିବା ସମୟରେ ଅପଡେଟ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ</string>
|
<string name="update_check">ଖୋଲିବା ସମୟରେ ଅପଡେଟ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">ଡାଉନଲୋଡ ପୋଷ୍ଟକୁ ବ୍ୟବହାରକାରୀଙ୍କ ନାମରେ ହୋଇଥିବା ସ୍ଥାନ ରେ ରଖ</string>
|
<string name="download_user_folder">ଡାଉନଲୋଡ ପୋଷ୍ଟକୁ ବ୍ୟବହାରକାରୀଙ୍କ ନାମରେ ହୋଇଥିବା ସ୍ଥାନ ରେ ରଖ</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">କାହାଣୀଗୁଡିକ ଦେଖିବା ପରେ \'ଦେଖାଗଲା\' ଚିହ୍ନିତ କରନ୍ତୁ |</string>
|
<string name="mark_as_seen_setting">କାହାଣୀଗୁଡିକ ଦେଖିବା ପରେ \'ଦେଖାଗଲା\' ଚିହ୍ନିତ କରନ୍ତୁ |</string>
|
||||||
<string name="mark_as_seen_setting_summary">କାହାଣୀ ପ୍ରେରକ ଜାଣିବେ ତୁମେ ଏହାକୁ ଦେଖିଛ</string>
|
<string name="mark_as_seen_setting_summary">କାହାଣୀ ପ୍ରେରକ ଜାଣିବେ ତୁମେ ଏହାକୁ ଦେଖିଛ</string>
|
||||||
<string name="dm_mark_as_seen_setting">ବାର୍ତା ଦେଖିବା ପରେ \'ଦେଖାଗଲା\' ଚିହ୍ନିତ କରନ୍ତୁ |</string>
|
<string name="dm_mark_as_seen_setting">ବାର୍ତା ଦେଖିବା ପରେ \'ଦେଖାଗଲା\' ଚିହ୍ନିତ କରନ୍ତୁ |</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Sprawdź aktualizacje przy starcie</string>
|
<string name="update_check">Sprawdź aktualizacje przy starcie</string>
|
||||||
<string name="flag_secure">Blokuj zrzuty ekranu & podgląd aplikacji</string>
|
<string name="flag_secure">Blokuj zrzuty ekranu & podgląd aplikacji</string>
|
||||||
<string name="download_user_folder">Pobierz posty do folderów o nazwie użytkownika</string>
|
<string name="download_user_folder">Pobierz posty do folderów o nazwie użytkownika</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Oznacz relacje jako widoczne po wyświetleniu</string>
|
<string name="mark_as_seen_setting">Oznacz relacje jako widoczne po wyświetleniu</string>
|
||||||
<string name="mark_as_seen_setting_summary">Autor relacji będzie widział, że to wyświetliłeś</string>
|
<string name="mark_as_seen_setting_summary">Autor relacji będzie widział, że to wyświetliłeś</string>
|
||||||
<string name="dm_mark_as_seen_setting">Oznacz wiadomość jako przeczytaną</string>
|
<string name="dm_mark_as_seen_setting">Oznacz wiadomość jako przeczytaną</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Verificar se há atualizações ao iniciar</string>
|
<string name="update_check">Verificar se há atualizações ao iniciar</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Baixar publicações para pastas com o nome de usuário</string>
|
<string name="download_user_folder">Baixar publicações para pastas com o nome de usuário</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Marcar stories como vistos após a visualização</string>
|
<string name="mark_as_seen_setting">Marcar stories como vistos após a visualização</string>
|
||||||
<string name="mark_as_seen_setting_summary">O autor do story saberá que você viu</string>
|
<string name="mark_as_seen_setting_summary">O autor do story saberá que você viu</string>
|
||||||
<string name="dm_mark_as_seen_setting">Marcar DM como vista após a visualização</string>
|
<string name="dm_mark_as_seen_setting">Marcar DM como vista após a visualização</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Проверять наличие обновлений при запуске</string>
|
<string name="update_check">Проверять наличие обновлений при запуске</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Скачать публикации в папки с именем пользователя</string>
|
<string name="download_user_folder">Скачать публикации в папки с именем пользователя</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Отметить истории как увиденные после просмотра</string>
|
<string name="mark_as_seen_setting">Отметить истории как увиденные после просмотра</string>
|
||||||
<string name="mark_as_seen_setting_summary">Автор истории узнает, что вы просмотрели её</string>
|
<string name="mark_as_seen_setting_summary">Автор истории узнает, что вы просмотрели её</string>
|
||||||
<string name="dm_mark_as_seen_setting">Отметить ЛС как увиденные после просмотра</string>
|
<string name="dm_mark_as_seen_setting">Отметить ЛС как увиденные после просмотра</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Kontrolovať aktualizácie pri štarte</string>
|
<string name="update_check">Kontrolovať aktualizácie pri štarte</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Ukľadať do priečinkov podľa mena</string>
|
<string name="download_user_folder">Ukľadať do priečinkov podľa mena</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Označiť príbehy po videní ako videné</string>
|
<string name="mark_as_seen_setting">Označiť príbehy po videní ako videné</string>
|
||||||
<string name="mark_as_seen_setting_summary">Autor príbehu bude vedieť že ste ho videli</string>
|
<string name="mark_as_seen_setting_summary">Autor príbehu bude vedieť že ste ho videli</string>
|
||||||
<string name="dm_mark_as_seen_setting">Po prečítaní, označiť správu ako prečítanú</string>
|
<string name="dm_mark_as_seen_setting">Po prečítaní, označiť správu ako prečítanú</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Güncellemeleri başlangıçta kontrol et</string>
|
<string name="update_check">Güncellemeleri başlangıçta kontrol et</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">İndirmeleri kullanıcı adından oluşan bir alt klasörün içine yap</string>
|
<string name="download_user_folder">İndirmeleri kullanıcı adından oluşan bir alt klasörün içine yap</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Hikayeleri gördükten sonra görüldü olarak işaretle</string>
|
<string name="mark_as_seen_setting">Hikayeleri gördükten sonra görüldü olarak işaretle</string>
|
||||||
<string name="mark_as_seen_setting_summary">Hikayeyi paylaşan gördüğünüzü bilecek</string>
|
<string name="mark_as_seen_setting_summary">Hikayeyi paylaşan gördüğünüzü bilecek</string>
|
||||||
<string name="dm_mark_as_seen_setting">DM\'leri gördükten sonra görüldü olarak işaretle</string>
|
<string name="dm_mark_as_seen_setting">DM\'leri gördükten sonra görüldü olarak işaretle</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">Kiểm tra cập nhật khi khởi động</string>
|
<string name="update_check">Kiểm tra cập nhật khi khởi động</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Tải bài viết xuống theo thư mục tên người dùng trong Downloads</string>
|
<string name="download_user_folder">Tải bài viết xuống theo thư mục tên người dùng trong Downloads</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Đánh dấu story là đã xem sau khi xem</string>
|
<string name="mark_as_seen_setting">Đánh dấu story là đã xem sau khi xem</string>
|
||||||
<string name="mark_as_seen_setting_summary">Người đăng story sẽ biết bạn đã xem nó</string>
|
<string name="mark_as_seen_setting_summary">Người đăng story sẽ biết bạn đã xem nó</string>
|
||||||
<string name="dm_mark_as_seen_setting">Đánh dấu DM là đã xem sau khi xem</string>
|
<string name="dm_mark_as_seen_setting">Đánh dấu DM là đã xem sau khi xem</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">启动时检查更新</string>
|
<string name="update_check">启动时检查更新</string>
|
||||||
<string name="flag_secure">屏蔽截图及应用预览</string>
|
<string name="flag_secure">屏蔽截图及应用预览</string>
|
||||||
<string name="download_user_folder">下载帖子到用户名文件夹</string>
|
<string name="download_user_folder">下载帖子到用户名文件夹</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">查看快拍后将其标记为已读</string>
|
<string name="mark_as_seen_setting">查看快拍后将其标记为已读</string>
|
||||||
<string name="mark_as_seen_setting_summary">快拍作者会知道您已看过</string>
|
<string name="mark_as_seen_setting_summary">快拍作者会知道您已看过</string>
|
||||||
<string name="dm_mark_as_seen_setting">查看私信后将其标记为已读</string>
|
<string name="dm_mark_as_seen_setting">查看私信后将其标记为已读</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="update_check">啟動時檢查更新</string>
|
<string name="update_check">啟動時檢查更新</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">將貼文下載到用戶名資料夾</string>
|
<string name="download_user_folder">將貼文下載到用戶名資料夾</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">檢視完限時動態後標記為已讀</string>
|
<string name="mark_as_seen_setting">檢視完限時動態後標記為已讀</string>
|
||||||
<string name="mark_as_seen_setting_summary">限時動態的作者會知道您已查看了此限時動態</string>
|
<string name="mark_as_seen_setting_summary">限時動態的作者會知道您已查看了此限時動態</string>
|
||||||
<string name="dm_mark_as_seen_setting">檢視完訊息後標記為已讀</string>
|
<string name="dm_mark_as_seen_setting">檢視完訊息後標記為已讀</string>
|
||||||
|
@ -26,8 +26,10 @@
|
|||||||
<string name="update_check">Check for updates at startup</string>
|
<string name="update_check">Check for updates at startup</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
<string name="download_user_folder">Download posts to username folders</string>
|
<string name="download_user_folder">Download posts to username folders</string>
|
||||||
|
<string name="download_prepend_username">Prepend Username to Filename</string>
|
||||||
<string name="mark_as_seen_setting">Mark stories as seen after viewing</string>
|
<string name="mark_as_seen_setting">Mark stories as seen after viewing</string>
|
||||||
<string name="mark_as_seen_setting_summary">Story author will know you viewed it</string>
|
<string name="mark_as_seen_setting_summary">Story author will know you viewed it</string>
|
||||||
|
<string name="hide_muted_reels_setting">Hide muted stories from feed</string>
|
||||||
<string name="dm_mark_as_seen_setting">Mark DM as seen after viewing</string>
|
<string name="dm_mark_as_seen_setting">Mark DM as seen after viewing</string>
|
||||||
<string name="dm_mark_as_seen_setting_summary">Other members will know you viewed it</string>
|
<string name="dm_mark_as_seen_setting_summary">Other members will know you viewed it</string>
|
||||||
<string name="activity_setting">Enable activity notifications</string>
|
<string name="activity_setting">Enable activity notifications</string>
|
||||||
@ -483,6 +485,8 @@
|
|||||||
<string name="crash_report_title">Select an email app to send crash logs</string>
|
<string name="crash_report_title">Select an email app to send crash logs</string>
|
||||||
<string name="not_found">Not found!</string>
|
<string name="not_found">Not found!</string>
|
||||||
<string name="rate_limit">Your IP has been rate limited by Instagram. Wait for an hour and try again.</string>
|
<string name="rate_limit">Your IP has been rate limited by Instagram. Wait for an hour and try again.</string>
|
||||||
|
<string name="skip_update">Skip this update</string>
|
||||||
|
<string name="on_latest_version">You\'re already on the latest version</string>
|
||||||
<string name="tab_order">Screen order</string>
|
<string name="tab_order">Screen order</string>
|
||||||
<string name="other_tabs">Other tabs</string>
|
<string name="other_tabs">Other tabs</string>
|
||||||
<string name="tab_order_start_next_launch">The tab order will be reflected on next launch</string>
|
<string name="tab_order_start_next_launch">The tab order will be reflected on next launch</string>
|
||||||
|
@ -1 +0,0 @@
|
|||||||
{}
|
|
@ -1 +0,0 @@
|
|||||||
{}
|
|
Loading…
Reference in New Issue
Block a user