mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-22 22:57:29 +00:00
Merge pull request #400 from ammargitham/add-room
Add Room Persistence Library
This commit is contained in:
commit
7964df976d
@ -17,6 +17,12 @@ android {
|
|||||||
|
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
vectorDrawables.generatedDensities = []
|
vectorDrawables.generatedDensities = []
|
||||||
|
|
||||||
|
javaCompileOptions {
|
||||||
|
annotationProcessorOptions {
|
||||||
|
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@ -32,8 +38,13 @@ android {
|
|||||||
aaptOptions { additionalParameters '--no-version-vectors' }
|
aaptOptions { additionalParameters '--no-version-vectors' }
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
debug {
|
||||||
|
minifyEnabled true
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,19 +56,19 @@ configurations.all {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.0'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'
|
||||||
|
|
||||||
def appcompat_version = "1.2.0"
|
def appcompat_version = "1.2.0"
|
||||||
def nav_version = '2.3.1'
|
def nav_version = '2.3.2'
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.3.0-alpha03'
|
implementation 'com.google.android.material:material:1.3.0-alpha04'
|
||||||
|
|
||||||
implementation 'com.google.android.exoplayer:exoplayer-core:2.12.0'
|
implementation 'com.google.android.exoplayer:exoplayer-core:2.12.0'
|
||||||
implementation 'com.google.android.exoplayer:exoplayer-ui:2.12.0'
|
implementation 'com.google.android.exoplayer:exoplayer-ui:2.12.0'
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
||||||
implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
|
implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
|
||||||
implementation "androidx.recyclerview:recyclerview:1.2.0-alpha06"
|
implementation "androidx.recyclerview:recyclerview:1.2.0-beta01"
|
||||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||||
implementation "androidx.viewpager2:viewpager2:1.0.0"
|
implementation "androidx.viewpager2:viewpager2:1.0.0"
|
||||||
implementation "androidx.navigation:navigation-fragment:$nav_version"
|
implementation "androidx.navigation:navigation-fragment:$nav_version"
|
||||||
@ -69,6 +80,12 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'com.google.guava:guava:27.0.1-android'
|
implementation 'com.google.guava:guava:27.0.1-android'
|
||||||
|
|
||||||
|
// Room
|
||||||
|
def room_version = "2.2.5"
|
||||||
|
implementation "androidx.room:room-runtime:$room_version"
|
||||||
|
implementation "androidx.room:room-guava:$room_version"
|
||||||
|
annotationProcessor "androidx.room:room-compiler:$room_version"
|
||||||
|
|
||||||
// implementation 'com.github.hendrawd:StorageUtil:1.1.0'
|
// implementation 'com.github.hendrawd:StorageUtil:1.1.0'
|
||||||
implementation 'com.github.ammargitham:AutoLinkTextViewV2:master-SNAPSHOT'
|
implementation 'com.github.ammargitham:AutoLinkTextViewV2:master-SNAPSHOT'
|
||||||
|
|
||||||
|
7
app/proguard-rules.pro
vendored
7
app/proguard-rules.pro
vendored
@ -19,3 +19,10 @@
|
|||||||
# If you keep the line number information, uncomment this to
|
# If you keep the line number information, uncomment this to
|
||||||
# hide the original source file name.
|
# hide the original source file name.
|
||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
|
#noinspection ShrinkerUnresolvedReference
|
||||||
|
#-keep class !com.google.android.exoplayer2.**, ** { *; }
|
||||||
|
|
||||||
|
#-keep class !awais.instagrabber.** { *; }
|
||||||
|
|
||||||
|
-dontobfuscate
|
114
app/schemas/awais.instagrabber.db.AppDatabase/4.json
Normal file
114
app/schemas/awais.instagrabber.db.AppDatabase/4.json
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 4,
|
||||||
|
"identityHash": "538d64adaeb8c3a98db9204955932e59",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "accounts",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `uid` TEXT, `username` TEXT, `cookie` TEXT, `full_name` TEXT, `profile_pic` TEXT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "username",
|
||||||
|
"columnName": "username",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "cookie",
|
||||||
|
"columnName": "cookie",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "fullName",
|
||||||
|
"columnName": "full_name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "profilePic",
|
||||||
|
"columnName": "profile_pic",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "favorites",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `query_text` TEXT, `type` TEXT, `display_name` TEXT, `pic_url` TEXT, `date_added` INTEGER)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "query",
|
||||||
|
"columnName": "query_text",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "displayName",
|
||||||
|
"columnName": "display_name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "picUrl",
|
||||||
|
"columnName": "pic_url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "dateAdded",
|
||||||
|
"columnName": "date_added",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '538d64adaeb8c3a98db9204955932e59')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -108,7 +108,8 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".activities.Login"
|
android:name=".activities.Login"
|
||||||
android:label="@string/login"
|
android:label="@string/login"
|
||||||
android:parentActivityName=".activities.MainActivity">
|
android:parentActivityName=".activities.MainActivity"
|
||||||
|
android:theme="@style/AppTheme.Light.White">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".activities.MainActivity" />
|
android:value=".activities.MainActivity" />
|
||||||
|
@ -13,7 +13,6 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.DataBox;
|
|
||||||
import awais.instagrabber.utils.LocaleUtils;
|
import awais.instagrabber.utils.LocaleUtils;
|
||||||
import awais.instagrabber.utils.SettingsHelper;
|
import awais.instagrabber.utils.SettingsHelper;
|
||||||
import awaisomereport.CrashReporter;
|
import awaisomereport.CrashReporter;
|
||||||
@ -21,7 +20,6 @@ import awaisomereport.LogCollector;
|
|||||||
|
|
||||||
import static awais.instagrabber.utils.CookieUtils.NET_COOKIE_MANAGER;
|
import static awais.instagrabber.utils.CookieUtils.NET_COOKIE_MANAGER;
|
||||||
import static awais.instagrabber.utils.Utils.clipboardManager;
|
import static awais.instagrabber.utils.Utils.clipboardManager;
|
||||||
import static awais.instagrabber.utils.Utils.dataBox;
|
|
||||||
import static awais.instagrabber.utils.Utils.datetimeParser;
|
import static awais.instagrabber.utils.Utils.datetimeParser;
|
||||||
import static awais.instagrabber.utils.Utils.logCollector;
|
import static awais.instagrabber.utils.Utils.logCollector;
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
@ -58,11 +56,6 @@ public final class InstaGrabberApplication extends Application {
|
|||||||
|
|
||||||
CookieHandler.setDefault(NET_COOKIE_MANAGER);
|
CookieHandler.setDefault(NET_COOKIE_MANAGER);
|
||||||
|
|
||||||
final Context appContext = getApplicationContext();
|
|
||||||
|
|
||||||
if (dataBox == null)
|
|
||||||
dataBox = DataBox.getInstance(appContext);
|
|
||||||
|
|
||||||
if (settingsHelper == null)
|
if (settingsHelper == null)
|
||||||
settingsHelper = new SettingsHelper(this);
|
settingsHelper = new SettingsHelper(this);
|
||||||
|
|
||||||
|
@ -26,9 +26,11 @@ import awais.instagrabber.models.FeedModel;
|
|||||||
import awais.instagrabber.models.IntentModel;
|
import awais.instagrabber.models.IntentModel;
|
||||||
import awais.instagrabber.models.enums.IntentModelType;
|
import awais.instagrabber.models.enums.IntentModelType;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
import awais.instagrabber.utils.DownloadUtils;
|
import awais.instagrabber.utils.DownloadUtils;
|
||||||
import awais.instagrabber.utils.IntentUtils;
|
import awais.instagrabber.utils.IntentUtils;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
public final class DirectDownload extends AppCompatActivity {
|
public final class DirectDownload extends AppCompatActivity {
|
||||||
private static final int NOTIFICATION_ID = 1900000000;
|
private static final int NOTIFICATION_ID = 1900000000;
|
||||||
@ -88,6 +90,7 @@ public final class DirectDownload extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void doDownload() {
|
private synchronized void doDownload() {
|
||||||
|
CookieUtils.setupCookies(Utils.settingsHelper.getString(Constants.COOKIE));
|
||||||
notificationManager = NotificationManagerCompat.from(getApplicationContext());
|
notificationManager = NotificationManagerCompat.from(getApplicationContext());
|
||||||
final Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
final String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
|
@ -14,21 +14,21 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.databinding.PrefAccountSwitcherBinding;
|
import awais.instagrabber.databinding.PrefAccountSwitcherBinding;
|
||||||
|
import awais.instagrabber.db.entities.Account;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.DataBox;
|
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
public class AccountSwitcherAdapter extends ListAdapter<DataBox.CookieModel, AccountSwitcherAdapter.ViewHolder> {
|
public class AccountSwitcherAdapter extends ListAdapter<Account, AccountSwitcherAdapter.ViewHolder> {
|
||||||
private static final String TAG = "AccountSwitcherAdapter";
|
private static final String TAG = "AccountSwitcherAdapter";
|
||||||
private static final DiffUtil.ItemCallback<DataBox.CookieModel> DIFF_CALLBACK = new DiffUtil.ItemCallback<DataBox.CookieModel>() {
|
private static final DiffUtil.ItemCallback<Account> DIFF_CALLBACK = new DiffUtil.ItemCallback<Account>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean areItemsTheSame(@NonNull final DataBox.CookieModel oldItem, @NonNull final DataBox.CookieModel newItem) {
|
public boolean areItemsTheSame(@NonNull final Account oldItem, @NonNull final Account newItem) {
|
||||||
return oldItem.getUid().equals(newItem.getUid());
|
return oldItem.getUid().equals(newItem.getUid());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean areContentsTheSame(@NonNull final DataBox.CookieModel oldItem, @NonNull final DataBox.CookieModel newItem) {
|
public boolean areContentsTheSame(@NonNull final Account oldItem, @NonNull final Account newItem) {
|
||||||
return oldItem.getUid().equals(newItem.getUid());
|
return oldItem.getUid().equals(newItem.getUid());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -53,7 +53,7 @@ public class AccountSwitcherAdapter extends ListAdapter<DataBox.CookieModel, Acc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
|
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
|
||||||
final DataBox.CookieModel model = getItem(position);
|
final Account model = getItem(position);
|
||||||
if (model == null) return;
|
if (model == null) return;
|
||||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||||
final boolean isCurrent = model.getCookie().equals(cookie);
|
final boolean isCurrent = model.getCookie().equals(cookie);
|
||||||
@ -61,11 +61,11 @@ public class AccountSwitcherAdapter extends ListAdapter<DataBox.CookieModel, Acc
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface OnAccountClickListener {
|
public interface OnAccountClickListener {
|
||||||
void onAccountClick(final DataBox.CookieModel model, final boolean isCurrent);
|
void onAccountClick(final Account model, final boolean isCurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnAccountLongClickListener {
|
public interface OnAccountLongClickListener {
|
||||||
boolean onAccountLongClick(final DataBox.CookieModel model, final boolean isCurrent);
|
boolean onAccountLongClick(final Account model, final boolean isCurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
@ -78,7 +78,7 @@ public class AccountSwitcherAdapter extends ListAdapter<DataBox.CookieModel, Acc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
public void bind(final DataBox.CookieModel model,
|
public void bind(final Account model,
|
||||||
final boolean isCurrent,
|
final boolean isCurrent,
|
||||||
final OnAccountClickListener clickListener,
|
final OnAccountClickListener clickListener,
|
||||||
final OnAccountLongClickListener longClickListener) {
|
final OnAccountLongClickListener longClickListener) {
|
||||||
|
@ -20,8 +20,8 @@ import awais.instagrabber.R;
|
|||||||
import awais.instagrabber.adapters.viewholder.FavoriteViewHolder;
|
import awais.instagrabber.adapters.viewholder.FavoriteViewHolder;
|
||||||
import awais.instagrabber.databinding.ItemFavSectionHeaderBinding;
|
import awais.instagrabber.databinding.ItemFavSectionHeaderBinding;
|
||||||
import awais.instagrabber.databinding.ItemSuggestionBinding;
|
import awais.instagrabber.databinding.ItemSuggestionBinding;
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
import awais.instagrabber.models.enums.FavoriteType;
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
import awais.instagrabber.utils.DataBox;
|
|
||||||
|
|
||||||
public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||||||
return getItem(position).isHeader() ? 0 : 1;
|
return getItem(position).isHeader() ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void submitList(@Nullable final List<DataBox.FavoriteModel> list) {
|
public void submitList(@Nullable final List<Favorite> list) {
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
differ.submitList(null);
|
differ.submitList(null);
|
||||||
return;
|
return;
|
||||||
@ -110,7 +110,7 @@ public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||||||
differ.submitList(sectionAndSort(list));
|
differ.submitList(sectionAndSort(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void submitList(@Nullable final List<DataBox.FavoriteModel> list, @Nullable final Runnable commitCallback) {
|
public void submitList(@Nullable final List<Favorite> list, @Nullable final Runnable commitCallback) {
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
differ.submitList(null, commitCallback);
|
differ.submitList(null, commitCallback);
|
||||||
return;
|
return;
|
||||||
@ -119,8 +119,8 @@ public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private List<FavoriteModelOrHeader> sectionAndSort(@NonNull final List<DataBox.FavoriteModel> list) {
|
private List<FavoriteModelOrHeader> sectionAndSort(@NonNull final List<Favorite> list) {
|
||||||
final List<DataBox.FavoriteModel> listCopy = new ArrayList<>(list);
|
final List<Favorite> listCopy = new ArrayList<>(list);
|
||||||
Collections.sort(listCopy, (o1, o2) -> {
|
Collections.sort(listCopy, (o1, o2) -> {
|
||||||
if (o1.getType() == o2.getType()) return 0;
|
if (o1.getType() == o2.getType()) return 0;
|
||||||
// keep users at top
|
// keep users at top
|
||||||
@ -133,7 +133,7 @@ public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||||||
});
|
});
|
||||||
final List<FavoriteModelOrHeader> modelOrHeaders = new ArrayList<>();
|
final List<FavoriteModelOrHeader> modelOrHeaders = new ArrayList<>();
|
||||||
for (int i = 0; i < listCopy.size(); i++) {
|
for (int i = 0; i < listCopy.size(); i++) {
|
||||||
final DataBox.FavoriteModel model = listCopy.get(i);
|
final Favorite model = listCopy.get(i);
|
||||||
final FavoriteModelOrHeader prev = modelOrHeaders.isEmpty() ? null : modelOrHeaders.get(modelOrHeaders.size() - 1);
|
final FavoriteModelOrHeader prev = modelOrHeaders.isEmpty() ? null : modelOrHeaders.get(modelOrHeaders.size() - 1);
|
||||||
boolean prevWasSameType = prev != null && prev.model.getType() == model.getType();
|
boolean prevWasSameType = prev != null && prev.model.getType() == model.getType();
|
||||||
if (prevWasSameType) {
|
if (prevWasSameType) {
|
||||||
@ -156,7 +156,7 @@ public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||||||
|
|
||||||
private static class FavoriteModelOrHeader {
|
private static class FavoriteModelOrHeader {
|
||||||
FavoriteType header;
|
FavoriteType header;
|
||||||
DataBox.FavoriteModel model;
|
Favorite model;
|
||||||
|
|
||||||
boolean isHeader() {
|
boolean isHeader() {
|
||||||
return header != null;
|
return header != null;
|
||||||
@ -164,11 +164,11 @@ public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface OnFavoriteClickListener {
|
public interface OnFavoriteClickListener {
|
||||||
void onClick(final DataBox.FavoriteModel model);
|
void onClick(final Favorite model);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnFavoriteLongClickListener {
|
public interface OnFavoriteLongClickListener {
|
||||||
boolean onLongClick(final DataBox.FavoriteModel model);
|
boolean onLongClick(final Favorite model);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FavSectionViewHolder extends RecyclerView.ViewHolder {
|
public static class FavSectionViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
@ -7,9 +7,9 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
|
|
||||||
import awais.instagrabber.adapters.FavoritesAdapter;
|
import awais.instagrabber.adapters.FavoritesAdapter;
|
||||||
import awais.instagrabber.databinding.ItemSuggestionBinding;
|
import awais.instagrabber.databinding.ItemSuggestionBinding;
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
import awais.instagrabber.models.enums.FavoriteType;
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.DataBox;
|
|
||||||
|
|
||||||
public class FavoriteViewHolder extends RecyclerView.ViewHolder {
|
public class FavoriteViewHolder extends RecyclerView.ViewHolder {
|
||||||
private static final String TAG = "FavoriteViewHolder";
|
private static final String TAG = "FavoriteViewHolder";
|
||||||
@ -22,7 +22,7 @@ public class FavoriteViewHolder extends RecyclerView.ViewHolder {
|
|||||||
binding.isVerified.setVisibility(View.GONE);
|
binding.isVerified.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind(final DataBox.FavoriteModel model,
|
public void bind(final Favorite model,
|
||||||
final FavoritesAdapter.OnFavoriteClickListener clickListener,
|
final FavoritesAdapter.OnFavoriteClickListener clickListener,
|
||||||
final FavoritesAdapter.OnFavoriteLongClickListener longClickListener) {
|
final FavoritesAdapter.OnFavoriteLongClickListener longClickListener) {
|
||||||
// Log.d(TAG, "bind: " + model);
|
// Log.d(TAG, "bind: " + model);
|
||||||
|
@ -16,13 +16,11 @@ import awais.instagrabber.interfaces.FetchListener;
|
|||||||
import awais.instagrabber.models.NotificationModel;
|
import awais.instagrabber.models.NotificationModel;
|
||||||
import awais.instagrabber.models.enums.NotificationType;
|
import awais.instagrabber.models.enums.NotificationType;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
|
||||||
import awais.instagrabber.utils.LocaleUtils;
|
import awais.instagrabber.utils.LocaleUtils;
|
||||||
import awais.instagrabber.utils.NetworkUtils;
|
import awais.instagrabber.utils.NetworkUtils;
|
||||||
import awaisomereport.LogCollector;
|
import awaisomereport.LogCollector;
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Utils.logCollector;
|
import static awais.instagrabber.utils.Utils.logCollector;
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
|
||||||
|
|
||||||
public final class NotificationsFetcher extends AsyncTask<Void, Void, List<NotificationModel>> {
|
public final class NotificationsFetcher extends AsyncTask<Void, Void, List<NotificationModel>> {
|
||||||
private static final String TAG = "NotificationsFetcher";
|
private static final String TAG = "NotificationsFetcher";
|
||||||
@ -37,8 +35,6 @@ public final class NotificationsFetcher extends AsyncTask<Void, Void, List<Notif
|
|||||||
protected List<NotificationModel> doInBackground(final Void... voids) {
|
protected List<NotificationModel> doInBackground(final Void... voids) {
|
||||||
List<NotificationModel> result = new ArrayList<>();
|
List<NotificationModel> result = new ArrayList<>();
|
||||||
final String url = "https://www.instagram.com/accounts/activity/?__a=1";
|
final String url = "https://www.instagram.com/accounts/activity/?__a=1";
|
||||||
CookieUtils.setupCookies(settingsHelper.getString(Constants.COOKIE));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||||
conn.setInstanceFollowRedirects(false);
|
conn.setInstanceFollowRedirects(false);
|
||||||
|
@ -17,11 +17,9 @@ import awais.instagrabber.models.PostChild;
|
|||||||
import awais.instagrabber.models.ProfileModel;
|
import awais.instagrabber.models.ProfileModel;
|
||||||
import awais.instagrabber.models.enums.MediaItemType;
|
import awais.instagrabber.models.enums.MediaItemType;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
|
||||||
import awais.instagrabber.utils.NetworkUtils;
|
import awais.instagrabber.utils.NetworkUtils;
|
||||||
import awais.instagrabber.utils.ResponseBodyUtils;
|
import awais.instagrabber.utils.ResponseBodyUtils;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
|
||||||
import awaisomereport.LogCollector;
|
import awaisomereport.LogCollector;
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Utils.logCollector;
|
import static awais.instagrabber.utils.Utils.logCollector;
|
||||||
@ -39,7 +37,6 @@ public final class PostFetcher extends AsyncTask<Void, Void, FeedModel> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FeedModel doInBackground(final Void... voids) {
|
protected FeedModel doInBackground(final Void... voids) {
|
||||||
CookieUtils.setupCookies(Utils.settingsHelper.getString(Constants.COOKIE)); // <- direct download
|
|
||||||
HttpURLConnection conn = null;
|
HttpURLConnection conn = null;
|
||||||
try {
|
try {
|
||||||
conn = (HttpURLConnection) new URL("https://www.instagram.com/p/" + shortCode + "/?__a=1").openConnection();
|
conn = (HttpURLConnection) new URL("https://www.instagram.com/p/" + shortCode + "/?__a=1").openConnection();
|
||||||
|
229
app/src/main/java/awais/instagrabber/db/AppDatabase.java
Normal file
229
app/src/main/java/awais/instagrabber/db/AppDatabase.java
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
package awais.instagrabber.db;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.room.Database;
|
||||||
|
import androidx.room.Room;
|
||||||
|
import androidx.room.RoomDatabase;
|
||||||
|
import androidx.room.TypeConverters;
|
||||||
|
import androidx.room.migration.Migration;
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.db.dao.AccountDao;
|
||||||
|
import awais.instagrabber.db.dao.FavoriteDao;
|
||||||
|
import awais.instagrabber.db.entities.Account;
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
|
@Database(entities = {Account.class, Favorite.class},
|
||||||
|
version = 4)
|
||||||
|
@TypeConverters({Converters.class})
|
||||||
|
public abstract class AppDatabase extends RoomDatabase {
|
||||||
|
private static final String TAG = AppDatabase.class.getSimpleName();
|
||||||
|
|
||||||
|
private static AppDatabase INSTANCE;
|
||||||
|
|
||||||
|
public abstract AccountDao accountDao();
|
||||||
|
|
||||||
|
public abstract FavoriteDao favoriteDao();
|
||||||
|
|
||||||
|
public static AppDatabase getDatabase(final Context context) {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
synchronized (AppDatabase.class) {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "cookiebox.db")
|
||||||
|
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
|
||||||
|
@Override
|
||||||
|
public void migrate(@NonNull SupportSQLiteDatabase db) {
|
||||||
|
db.execSQL("ALTER TABLE cookies ADD " + Account.COL_FULL_NAME + " TEXT");
|
||||||
|
db.execSQL("ALTER TABLE cookies ADD " + Account.COL_PROFILE_PIC + " TEXT");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
|
||||||
|
@Override
|
||||||
|
public void migrate(@NonNull SupportSQLiteDatabase db) {
|
||||||
|
final List<Favorite> oldFavorites = backupOldFavorites(db);
|
||||||
|
// recreate with new columns (as there will be no doubt about the `query_display` column being present or not in the future versions)
|
||||||
|
db.execSQL("DROP TABLE " + Favorite.TABLE_NAME);
|
||||||
|
db.execSQL("CREATE TABLE " + Favorite.TABLE_NAME + " ("
|
||||||
|
+ Favorite.COL_ID + " INTEGER PRIMARY KEY,"
|
||||||
|
+ Favorite.COL_QUERY + " TEXT,"
|
||||||
|
+ Favorite.COL_TYPE + " TEXT,"
|
||||||
|
+ Favorite.COL_DISPLAY_NAME + " TEXT,"
|
||||||
|
+ Favorite.COL_PIC_URL + " TEXT,"
|
||||||
|
+ Favorite.COL_DATE_ADDED + " INTEGER)");
|
||||||
|
// add the old favorites back
|
||||||
|
for (final Favorite oldFavorite : oldFavorites) {
|
||||||
|
insertOrUpdateFavorite(db, oldFavorite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static final Migration MIGRATION_3_4 = new Migration(3, 4) {
|
||||||
|
@Override
|
||||||
|
public void migrate(@NonNull SupportSQLiteDatabase db) {
|
||||||
|
// Required when migrating to Room.
|
||||||
|
// The original table primary keys were not 'NOT NULL', so the migration to Room were failing without the below migration.
|
||||||
|
// Taking this opportunity to rename cookies table to accounts
|
||||||
|
|
||||||
|
// Create new table with name 'accounts'
|
||||||
|
db.execSQL("CREATE TABLE " + Account.TABLE_NAME + " ("
|
||||||
|
+ Account.COL_ID + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
|
||||||
|
+ Account.COL_UID + " TEXT,"
|
||||||
|
+ Account.COL_USERNAME + " TEXT,"
|
||||||
|
+ Account.COL_COOKIE + " TEXT,"
|
||||||
|
+ Account.COL_FULL_NAME + " TEXT,"
|
||||||
|
+ Account.COL_PROFILE_PIC + " TEXT)");
|
||||||
|
// Insert all data from table 'cookies' to 'accounts'
|
||||||
|
db.execSQL("INSERT INTO " + Account.TABLE_NAME + " ("
|
||||||
|
+ Account.COL_UID + ","
|
||||||
|
+ Account.COL_USERNAME + ","
|
||||||
|
+ Account.COL_COOKIE + ","
|
||||||
|
+ Account.COL_FULL_NAME + ","
|
||||||
|
+ Account.COL_PROFILE_PIC + ") "
|
||||||
|
+ "SELECT "
|
||||||
|
+ Account.COL_UID + ","
|
||||||
|
+ Account.COL_USERNAME + ","
|
||||||
|
+ Account.COL_COOKIE + ","
|
||||||
|
+ Account.COL_FULL_NAME + ","
|
||||||
|
+ Account.COL_PROFILE_PIC
|
||||||
|
+ " FROM cookies");
|
||||||
|
// Drop old cookies table
|
||||||
|
db.execSQL("DROP TABLE cookies");
|
||||||
|
|
||||||
|
// Create favorite backup table
|
||||||
|
db.execSQL("CREATE TABLE " + Favorite.TABLE_NAME + "_backup ("
|
||||||
|
+ Favorite.COL_ID + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
|
||||||
|
+ Favorite.COL_QUERY + " TEXT,"
|
||||||
|
+ Favorite.COL_TYPE + " TEXT,"
|
||||||
|
+ Favorite.COL_DISPLAY_NAME + " TEXT,"
|
||||||
|
+ Favorite.COL_PIC_URL + " TEXT,"
|
||||||
|
+ Favorite.COL_DATE_ADDED + " INTEGER)");
|
||||||
|
// Insert all data from table 'favorite' to 'favorite_backup'
|
||||||
|
db.execSQL("INSERT INTO " + Favorite.TABLE_NAME + "_backup ("
|
||||||
|
+ Favorite.COL_QUERY + ","
|
||||||
|
+ Favorite.COL_TYPE + ","
|
||||||
|
+ Favorite.COL_DISPLAY_NAME + ","
|
||||||
|
+ Favorite.COL_PIC_URL + ","
|
||||||
|
+ Favorite.COL_DATE_ADDED + ") "
|
||||||
|
+ "SELECT "
|
||||||
|
+ Favorite.COL_QUERY + ","
|
||||||
|
+ Favorite.COL_TYPE + ","
|
||||||
|
+ Favorite.COL_DISPLAY_NAME + ","
|
||||||
|
+ Favorite.COL_PIC_URL + ","
|
||||||
|
+ Favorite.COL_DATE_ADDED
|
||||||
|
+ " FROM " + Favorite.TABLE_NAME);
|
||||||
|
// Drop favorites
|
||||||
|
db.execSQL("DROP TABLE " + Favorite.TABLE_NAME);
|
||||||
|
// Rename favorite_backup to favorites
|
||||||
|
db.execSQL("ALTER TABLE " + Favorite.TABLE_NAME + "_backup RENAME TO " + Favorite.TABLE_NAME);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static List<Favorite> backupOldFavorites(@NonNull final SupportSQLiteDatabase db) {
|
||||||
|
// check if old favorites table had the column query_display
|
||||||
|
final boolean queryDisplayExists = checkColumnExists(db, Favorite.TABLE_NAME, "query_display");
|
||||||
|
Log.d(TAG, "backupOldFavorites: queryDisplayExists: " + queryDisplayExists);
|
||||||
|
final List<Favorite> oldModels = new ArrayList<>();
|
||||||
|
final String sql = "SELECT "
|
||||||
|
+ "query_text,"
|
||||||
|
+ "date_added"
|
||||||
|
+ (queryDisplayExists ? ",query_display" : "")
|
||||||
|
+ " FROM " + Favorite.TABLE_NAME;
|
||||||
|
try (final Cursor cursor = db.query(sql)) {
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
final String queryText = cursor.getString(cursor.getColumnIndex("query_text"));
|
||||||
|
final Pair<FavoriteType, String> favoriteTypeQueryPair = Utils.migrateOldFavQuery(queryText);
|
||||||
|
if (favoriteTypeQueryPair == null) continue;
|
||||||
|
final FavoriteType type = favoriteTypeQueryPair.first;
|
||||||
|
final String query = favoriteTypeQueryPair.second;
|
||||||
|
oldModels.add(new Favorite(
|
||||||
|
-1,
|
||||||
|
query,
|
||||||
|
type,
|
||||||
|
queryDisplayExists ? cursor.getString(cursor.getColumnIndex("query_display"))
|
||||||
|
: null,
|
||||||
|
null,
|
||||||
|
new Date(cursor.getLong(cursor.getColumnIndex("date_added")))
|
||||||
|
));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "onUpgrade", e);
|
||||||
|
}
|
||||||
|
} while (cursor.moveToNext());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "onUpgrade", e);
|
||||||
|
}
|
||||||
|
Log.d(TAG, "backupOldFavorites: oldModels:" + oldModels);
|
||||||
|
return oldModels;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized void insertOrUpdateFavorite(@NonNull final SupportSQLiteDatabase db, @NonNull final Favorite model) {
|
||||||
|
final ContentValues values = new ContentValues();
|
||||||
|
values.put(Favorite.COL_QUERY, model.getQuery());
|
||||||
|
values.put(Favorite.COL_TYPE, model.getType().toString());
|
||||||
|
values.put(Favorite.COL_DISPLAY_NAME, model.getDisplayName());
|
||||||
|
values.put(Favorite.COL_PIC_URL, model.getPicUrl());
|
||||||
|
values.put(Favorite.COL_DATE_ADDED, model.getDateAdded().getTime());
|
||||||
|
int rows;
|
||||||
|
if (model.getId() >= 1) {
|
||||||
|
rows = db.update(Favorite.TABLE_NAME,
|
||||||
|
SQLiteDatabase.CONFLICT_IGNORE,
|
||||||
|
values,
|
||||||
|
Favorite.COL_ID + "=?",
|
||||||
|
new String[]{String.valueOf(model.getId())});
|
||||||
|
} else {
|
||||||
|
rows = db.update(Favorite.TABLE_NAME,
|
||||||
|
SQLiteDatabase.CONFLICT_IGNORE,
|
||||||
|
values,
|
||||||
|
Favorite.COL_QUERY + "=?" + " AND " + Favorite.COL_TYPE + "=?",
|
||||||
|
new String[]{model.getQuery(), model.getType().toString()});
|
||||||
|
}
|
||||||
|
if (rows != 1) {
|
||||||
|
db.insert(Favorite.TABLE_NAME, SQLiteDatabase.CONFLICT_IGNORE, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkColumnExists(@NonNull final SupportSQLiteDatabase db,
|
||||||
|
@NonNull final String tableName,
|
||||||
|
@NonNull final String columnName) {
|
||||||
|
boolean exists = false;
|
||||||
|
try (Cursor cursor = db.query("PRAGMA table_info(" + tableName + ")")) {
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
final String currentColumn = cursor.getString(cursor.getColumnIndex("name"));
|
||||||
|
if (currentColumn.equals(columnName)) {
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
} while (cursor.moveToNext());
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Log.e(TAG, "checkColumnExists", ex);
|
||||||
|
}
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
}
|
33
app/src/main/java/awais/instagrabber/db/Converters.java
Normal file
33
app/src/main/java/awais/instagrabber/db/Converters.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package awais.instagrabber.db;
|
||||||
|
|
||||||
|
import androidx.room.TypeConverter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
|
|
||||||
|
public class Converters {
|
||||||
|
@TypeConverter
|
||||||
|
public static Date fromTimestamp(Long value) {
|
||||||
|
return value == null ? null : new Date(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
public static Long dateToTimestamp(Date date) {
|
||||||
|
return date == null ? null : date.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
public static FavoriteType fromFavoriteTypeString(String value) {
|
||||||
|
try {
|
||||||
|
return FavoriteType.valueOf(value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
public static String favoriteTypeToString(FavoriteType favoriteType) {
|
||||||
|
return favoriteType == null ? null : favoriteType.toString();
|
||||||
|
}
|
||||||
|
}
|
34
app/src/main/java/awais/instagrabber/db/dao/AccountDao.java
Normal file
34
app/src/main/java/awais/instagrabber/db/dao/AccountDao.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package awais.instagrabber.db.dao;
|
||||||
|
|
||||||
|
import androidx.room.Dao;
|
||||||
|
import androidx.room.Delete;
|
||||||
|
import androidx.room.Insert;
|
||||||
|
import androidx.room.OnConflictStrategy;
|
||||||
|
import androidx.room.Query;
|
||||||
|
import androidx.room.Update;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.db.entities.Account;
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
public interface AccountDao {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM accounts")
|
||||||
|
List<Account> getAllAccounts();
|
||||||
|
|
||||||
|
@Query("SELECT * FROM accounts WHERE uid = :uid")
|
||||||
|
Account findAccountByUid(String uid);
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
List<Long> insertAccounts(Account... accounts);
|
||||||
|
|
||||||
|
@Update
|
||||||
|
void updateAccounts(Account... accounts);
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
void deleteAccounts(Account... accounts);
|
||||||
|
|
||||||
|
@Query("DELETE from accounts")
|
||||||
|
void deleteAllAccounts();
|
||||||
|
}
|
35
app/src/main/java/awais/instagrabber/db/dao/FavoriteDao.java
Normal file
35
app/src/main/java/awais/instagrabber/db/dao/FavoriteDao.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package awais.instagrabber.db.dao;
|
||||||
|
|
||||||
|
import androidx.room.Dao;
|
||||||
|
import androidx.room.Delete;
|
||||||
|
import androidx.room.Insert;
|
||||||
|
import androidx.room.OnConflictStrategy;
|
||||||
|
import androidx.room.Query;
|
||||||
|
import androidx.room.Update;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
public interface FavoriteDao {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM favorites")
|
||||||
|
List<Favorite> getAllFavorites();
|
||||||
|
|
||||||
|
@Query("SELECT * FROM favorites WHERE query_text = :query and type = :type")
|
||||||
|
Favorite findFavoriteByQueryAndType(String query, FavoriteType type);
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
List<Long> insertFavorites(Favorite... favorites);
|
||||||
|
|
||||||
|
@Update
|
||||||
|
void updateFavorites(Favorite... favorites);
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
void deleteFavorites(Favorite... favorites);
|
||||||
|
|
||||||
|
@Query("DELETE from favorites")
|
||||||
|
void deleteAllFavorites();
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package awais.instagrabber.db.datasources;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.db.AppDatabase;
|
||||||
|
import awais.instagrabber.db.dao.AccountDao;
|
||||||
|
import awais.instagrabber.db.entities.Account;
|
||||||
|
|
||||||
|
public class AccountDataSource {
|
||||||
|
private static final String TAG = AccountDataSource.class.getSimpleName();
|
||||||
|
|
||||||
|
private static AccountDataSource INSTANCE;
|
||||||
|
|
||||||
|
private final AccountDao accountDao;
|
||||||
|
|
||||||
|
private AccountDataSource(final AccountDao accountDao) {
|
||||||
|
this.accountDao = accountDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AccountDataSource getInstance(@NonNull Context context) {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
synchronized (AccountDataSource.class) {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
final AppDatabase database = AppDatabase.getDatabase(context);
|
||||||
|
INSTANCE = new AccountDataSource(database.accountDao());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public final Account getAccount(final String uid) {
|
||||||
|
return accountDao.findAccountByUid(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final List<Account> getAllAccounts() {
|
||||||
|
return accountDao.getAllAccounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void insertOrUpdateAccount(final String uid,
|
||||||
|
final String username,
|
||||||
|
final String cookie,
|
||||||
|
final String fullName,
|
||||||
|
final String profilePicUrl) {
|
||||||
|
final Account account = getAccount(uid);
|
||||||
|
final Account toUpdate = new Account(account == null ? 0 : account.getId(), uid, username, cookie, fullName, profilePicUrl);
|
||||||
|
if (account != null) {
|
||||||
|
accountDao.updateAccounts(toUpdate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
accountDao.insertAccounts(toUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void deleteAccount(@NonNull final Account account) {
|
||||||
|
accountDao.deleteAccounts(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void deleteAllAccounts() {
|
||||||
|
accountDao.deleteAllAccounts();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package awais.instagrabber.db.datasources;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.db.AppDatabase;
|
||||||
|
import awais.instagrabber.db.dao.FavoriteDao;
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
|
|
||||||
|
public class FavoriteDataSource {
|
||||||
|
private static final String TAG = FavoriteDataSource.class.getSimpleName();
|
||||||
|
|
||||||
|
private static FavoriteDataSource INSTANCE;
|
||||||
|
|
||||||
|
private final FavoriteDao favoriteDao;
|
||||||
|
|
||||||
|
private FavoriteDataSource(final FavoriteDao favoriteDao) {
|
||||||
|
this.favoriteDao = favoriteDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized FavoriteDataSource getInstance(@NonNull Context context) {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
synchronized (FavoriteDataSource.class) {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
final AppDatabase database = AppDatabase.getDatabase(context);
|
||||||
|
INSTANCE = new FavoriteDataSource(database.favoriteDao());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public final Favorite getFavorite(@NonNull final String query, @NonNull final FavoriteType type) {
|
||||||
|
return favoriteDao.findFavoriteByQueryAndType(query, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final List<Favorite> getAllFavorites() {
|
||||||
|
return favoriteDao.getAllFavorites();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void insertOrUpdateFavorite(@NonNull final Favorite favorite) {
|
||||||
|
if (favorite.getId() > 0) {
|
||||||
|
favoriteDao.updateFavorites(favorite);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
favoriteDao.insertFavorites(favorite);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void deleteFavorite(@NonNull final String query, @NonNull final FavoriteType type) {
|
||||||
|
final Favorite favorite = getFavorite(query, type);
|
||||||
|
if (favorite == null) return;
|
||||||
|
favoriteDao.deleteFavorites(favorite);
|
||||||
|
}
|
||||||
|
}
|
124
app/src/main/java/awais/instagrabber/db/entities/Account.java
Normal file
124
app/src/main/java/awais/instagrabber/db/entities/Account.java
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package awais.instagrabber.db.entities;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.util.ObjectsCompat;
|
||||||
|
import androidx.room.ColumnInfo;
|
||||||
|
import androidx.room.Entity;
|
||||||
|
import androidx.room.Ignore;
|
||||||
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
import awais.instagrabber.utils.Constants;
|
||||||
|
import awais.instagrabber.utils.TextUtils;
|
||||||
|
|
||||||
|
@Entity(tableName = Account.TABLE_NAME)
|
||||||
|
public class Account {
|
||||||
|
public final static String TABLE_NAME = "accounts";
|
||||||
|
public final static String COL_ID = "id";
|
||||||
|
public final static String COL_USERNAME = Constants.EXTRAS_USERNAME;
|
||||||
|
public final static String COL_COOKIE = "cookie";
|
||||||
|
public final static String COL_UID = "uid";
|
||||||
|
public final static String COL_FULL_NAME = "full_name";
|
||||||
|
public final static String COL_PROFILE_PIC = "profile_pic";
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ColumnInfo(name = COL_ID)
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
@ColumnInfo(name = COL_UID)
|
||||||
|
private final String uid;
|
||||||
|
|
||||||
|
@ColumnInfo(name = COL_USERNAME)
|
||||||
|
private final String username;
|
||||||
|
|
||||||
|
@ColumnInfo(name = COL_COOKIE)
|
||||||
|
private final String cookie;
|
||||||
|
|
||||||
|
@ColumnInfo(name = COL_FULL_NAME)
|
||||||
|
private final String fullName;
|
||||||
|
|
||||||
|
@ColumnInfo(name = COL_PROFILE_PIC)
|
||||||
|
private final String profilePic;
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
private boolean selected;
|
||||||
|
|
||||||
|
public Account(final int id,
|
||||||
|
final String uid,
|
||||||
|
final String username,
|
||||||
|
final String cookie,
|
||||||
|
final String fullName,
|
||||||
|
final String profilePic) {
|
||||||
|
this.id = id;
|
||||||
|
this.uid = uid;
|
||||||
|
this.username = username;
|
||||||
|
this.cookie = cookie;
|
||||||
|
this.fullName = fullName;
|
||||||
|
this.profilePic = profilePic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUid() {
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCookie() {
|
||||||
|
return cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullName() {
|
||||||
|
return fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProfilePic() {
|
||||||
|
return profilePic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSelected() {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelected(final boolean selected) {
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return !TextUtils.isEmpty(uid)
|
||||||
|
&& !TextUtils.isEmpty(username)
|
||||||
|
&& !TextUtils.isEmpty(cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final Account that = (Account) o;
|
||||||
|
return ObjectsCompat.equals(uid, that.uid) &&
|
||||||
|
ObjectsCompat.equals(username, that.username) &&
|
||||||
|
ObjectsCompat.equals(cookie, that.cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return ObjectsCompat.hash(uid, username, cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Account{" +
|
||||||
|
"uid='" + uid + '\'' +
|
||||||
|
", username='" + username + '\'' +
|
||||||
|
", cookie='" + cookie + '\'' +
|
||||||
|
", fullName='" + fullName + '\'' +
|
||||||
|
", profilePic='" + profilePic + '\'' +
|
||||||
|
", selected=" + selected +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
110
app/src/main/java/awais/instagrabber/db/entities/Favorite.java
Normal file
110
app/src/main/java/awais/instagrabber/db/entities/Favorite.java
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package awais.instagrabber.db.entities;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.util.ObjectsCompat;
|
||||||
|
import androidx.room.ColumnInfo;
|
||||||
|
import androidx.room.Entity;
|
||||||
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
|
|
||||||
|
@Entity(tableName = Favorite.TABLE_NAME)
|
||||||
|
public class Favorite {
|
||||||
|
public final static String TABLE_NAME = "favorites";
|
||||||
|
public final static String COL_ID = "id";
|
||||||
|
public final static String COL_QUERY = "query_text";
|
||||||
|
public final static String COL_TYPE = "type";
|
||||||
|
public final static String COL_DISPLAY_NAME = "display_name";
|
||||||
|
public final static String COL_PIC_URL = "pic_url";
|
||||||
|
public final static String COL_DATE_ADDED = "date_added";
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ColumnInfo(name = COL_ID)
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
@ColumnInfo(name = COL_QUERY)
|
||||||
|
private final String query;
|
||||||
|
|
||||||
|
@ColumnInfo(name = COL_TYPE)
|
||||||
|
private final FavoriteType type;
|
||||||
|
|
||||||
|
@ColumnInfo(name = COL_DISPLAY_NAME)
|
||||||
|
private final String displayName;
|
||||||
|
|
||||||
|
@ColumnInfo(name = COL_PIC_URL)
|
||||||
|
private final String picUrl;
|
||||||
|
|
||||||
|
@ColumnInfo(name = COL_DATE_ADDED)
|
||||||
|
private final Date dateAdded;
|
||||||
|
|
||||||
|
public Favorite(final int id,
|
||||||
|
final String query,
|
||||||
|
final FavoriteType type,
|
||||||
|
final String displayName,
|
||||||
|
final String picUrl,
|
||||||
|
final Date dateAdded) {
|
||||||
|
this.id = id;
|
||||||
|
this.query = query;
|
||||||
|
this.type = type;
|
||||||
|
this.displayName = displayName;
|
||||||
|
this.picUrl = picUrl;
|
||||||
|
this.dateAdded = dateAdded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQuery() {
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FavoriteType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPicUrl() {
|
||||||
|
return picUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDateAdded() {
|
||||||
|
return dateAdded;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final Favorite that = (Favorite) o;
|
||||||
|
return id == that.id &&
|
||||||
|
ObjectsCompat.equals(query, that.query) &&
|
||||||
|
type == that.type &&
|
||||||
|
ObjectsCompat.equals(displayName, that.displayName) &&
|
||||||
|
ObjectsCompat.equals(picUrl, that.picUrl) &&
|
||||||
|
ObjectsCompat.equals(dateAdded, that.dateAdded);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return ObjectsCompat.hash(id, query, type, displayName, picUrl, dateAdded);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "FavoriteModel{" +
|
||||||
|
"id=" + id +
|
||||||
|
", query='" + query + '\'' +
|
||||||
|
", type=" + type +
|
||||||
|
", displayName='" + displayName + '\'' +
|
||||||
|
", picUrl='" + picUrl + '\'' +
|
||||||
|
", dateAdded=" + dateAdded +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,131 @@
|
|||||||
|
package awais.instagrabber.db.repositories;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.db.datasources.AccountDataSource;
|
||||||
|
import awais.instagrabber.db.entities.Account;
|
||||||
|
import awais.instagrabber.utils.AppExecutors;
|
||||||
|
|
||||||
|
public class AccountRepository {
|
||||||
|
private static final String TAG = AccountRepository.class.getSimpleName();
|
||||||
|
|
||||||
|
private static AccountRepository instance;
|
||||||
|
|
||||||
|
private final AppExecutors appExecutors;
|
||||||
|
private final AccountDataSource accountDataSource;
|
||||||
|
|
||||||
|
// private List<Account> cachedAccounts;
|
||||||
|
|
||||||
|
private AccountRepository(final AppExecutors appExecutors, final AccountDataSource accountDataSource) {
|
||||||
|
this.appExecutors = appExecutors;
|
||||||
|
this.accountDataSource = accountDataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AccountRepository getInstance(final AccountDataSource accountDataSource) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new AccountRepository(AppExecutors.getInstance(), accountDataSource);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAccount(final String uid,
|
||||||
|
final RepositoryCallback<Account> callback) {
|
||||||
|
// request on the I/O thread
|
||||||
|
appExecutors.diskIO().execute(() -> {
|
||||||
|
final Account account = accountDataSource.getAccount(uid);
|
||||||
|
// notify on the main thread
|
||||||
|
appExecutors.mainThread().execute(() -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
if (account == null) {
|
||||||
|
callback.onDataNotAvailable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback.onSuccess(account);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAllAccounts(final RepositoryCallback<List<Account>> callback) {
|
||||||
|
// request on the I/O thread
|
||||||
|
appExecutors.diskIO().execute(() -> {
|
||||||
|
final List<Account> accounts = accountDataSource.getAllAccounts();
|
||||||
|
// notify on the main thread
|
||||||
|
appExecutors.mainThread().execute(() -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
if (accounts == null) {
|
||||||
|
callback.onDataNotAvailable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// cachedAccounts = accounts;
|
||||||
|
callback.onSuccess(accounts);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertOrUpdateAccounts(final List<Account> accounts,
|
||||||
|
final RepositoryCallback<Void> callback) {
|
||||||
|
// request on the I/O thread
|
||||||
|
appExecutors.diskIO().execute(() -> {
|
||||||
|
for (final Account account : accounts) {
|
||||||
|
accountDataSource.insertOrUpdateAccount(account.getUid(),
|
||||||
|
account.getUsername(),
|
||||||
|
account.getCookie(),
|
||||||
|
account.getFullName(),
|
||||||
|
account.getProfilePic());
|
||||||
|
}
|
||||||
|
// notify on the main thread
|
||||||
|
appExecutors.mainThread().execute(() -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
callback.onSuccess(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertOrUpdateAccount(final String uid,
|
||||||
|
final String username,
|
||||||
|
final String cookie,
|
||||||
|
final String fullName,
|
||||||
|
final String profilePicUrl,
|
||||||
|
final RepositoryCallback<Account> callback) {
|
||||||
|
// request on the I/O thread
|
||||||
|
appExecutors.diskIO().execute(() -> {
|
||||||
|
accountDataSource.insertOrUpdateAccount(uid, username, cookie, fullName, profilePicUrl);
|
||||||
|
final Account updated = accountDataSource.getAccount(uid);
|
||||||
|
// notify on the main thread
|
||||||
|
appExecutors.mainThread().execute(() -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
if (updated == null) {
|
||||||
|
callback.onDataNotAvailable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback.onSuccess(updated);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAccount(final Account account,
|
||||||
|
final RepositoryCallback<Void> callback) {
|
||||||
|
// request on the I/O thread
|
||||||
|
appExecutors.diskIO().execute(() -> {
|
||||||
|
accountDataSource.deleteAccount(account);
|
||||||
|
// notify on the main thread
|
||||||
|
appExecutors.mainThread().execute(() -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
callback.onSuccess(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAllAccounts(final RepositoryCallback<Void> callback) {
|
||||||
|
// request on the I/O thread
|
||||||
|
appExecutors.diskIO().execute(() -> {
|
||||||
|
accountDataSource.deleteAllAccounts();
|
||||||
|
// notify on the main thread
|
||||||
|
appExecutors.mainThread().execute(() -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
callback.onSuccess(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package awais.instagrabber.db.repositories;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.db.datasources.FavoriteDataSource;
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
|
import awais.instagrabber.utils.AppExecutors;
|
||||||
|
|
||||||
|
public class FavoriteRepository {
|
||||||
|
private static final String TAG = FavoriteRepository.class.getSimpleName();
|
||||||
|
|
||||||
|
private static FavoriteRepository instance;
|
||||||
|
|
||||||
|
private final AppExecutors appExecutors;
|
||||||
|
private final FavoriteDataSource favoriteDataSource;
|
||||||
|
|
||||||
|
private FavoriteRepository(final AppExecutors appExecutors, final FavoriteDataSource favoriteDataSource) {
|
||||||
|
this.appExecutors = appExecutors;
|
||||||
|
this.favoriteDataSource = favoriteDataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FavoriteRepository getInstance(final FavoriteDataSource favoriteDataSource) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new FavoriteRepository(AppExecutors.getInstance(), favoriteDataSource);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getFavorite(final String query, final FavoriteType type, final RepositoryCallback<Favorite> callback) {
|
||||||
|
// request on the I/O thread
|
||||||
|
appExecutors.diskIO().execute(() -> {
|
||||||
|
final Favorite favorite = favoriteDataSource.getFavorite(query, type);
|
||||||
|
// notify on the main thread
|
||||||
|
appExecutors.mainThread().execute(() -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
if (favorite == null) {
|
||||||
|
callback.onDataNotAvailable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback.onSuccess(favorite);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAllFavorites(final RepositoryCallback<List<Favorite>> callback) {
|
||||||
|
// request on the I/O thread
|
||||||
|
appExecutors.diskIO().execute(() -> {
|
||||||
|
final List<Favorite> favorites = favoriteDataSource.getAllFavorites();
|
||||||
|
// notify on the main thread
|
||||||
|
appExecutors.mainThread().execute(() -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
if (favorites == null) {
|
||||||
|
callback.onDataNotAvailable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback.onSuccess(favorites);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertOrUpdateFavorite(final Favorite favorite,
|
||||||
|
final RepositoryCallback<Void> callback) {
|
||||||
|
// request on the I/O thread
|
||||||
|
appExecutors.diskIO().execute(() -> {
|
||||||
|
favoriteDataSource.insertOrUpdateFavorite(favorite);
|
||||||
|
// notify on the main thread
|
||||||
|
appExecutors.mainThread().execute(() -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
callback.onSuccess(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteFavorite(final String query,
|
||||||
|
final FavoriteType type,
|
||||||
|
final RepositoryCallback<Void> callback) {
|
||||||
|
// request on the I/O thread
|
||||||
|
appExecutors.diskIO().execute(() -> {
|
||||||
|
favoriteDataSource.deleteFavorite(query, type);
|
||||||
|
// notify on the main thread
|
||||||
|
appExecutors.mainThread().execute(() -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
callback.onSuccess(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package awais.instagrabber.db.repositories;
|
||||||
|
|
||||||
|
import androidx.annotation.MainThread;
|
||||||
|
|
||||||
|
public interface RepositoryCallback<T> {
|
||||||
|
@MainThread
|
||||||
|
void onSuccess(T result);
|
||||||
|
|
||||||
|
@MainThread
|
||||||
|
void onDataNotAvailable();
|
||||||
|
}
|
@ -21,9 +21,12 @@ import java.util.List;
|
|||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.AccountSwitcherAdapter;
|
import awais.instagrabber.adapters.AccountSwitcherAdapter;
|
||||||
import awais.instagrabber.databinding.DialogAccountSwitcherBinding;
|
import awais.instagrabber.databinding.DialogAccountSwitcherBinding;
|
||||||
|
import awais.instagrabber.db.datasources.AccountDataSource;
|
||||||
|
import awais.instagrabber.db.entities.Account;
|
||||||
|
import awais.instagrabber.db.repositories.AccountRepository;
|
||||||
|
import awais.instagrabber.db.repositories.RepositoryCallback;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
import awais.instagrabber.utils.DataBox;
|
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
@ -31,9 +34,20 @@ import static awais.instagrabber.utils.Utils.settingsHelper;
|
|||||||
|
|
||||||
public class AccountSwitcherDialogFragment extends DialogFragment {
|
public class AccountSwitcherDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
private final OnAddAccountClickListener onAddAccountClickListener;
|
private AccountRepository accountRepository;
|
||||||
|
|
||||||
|
private OnAddAccountClickListener onAddAccountClickListener;
|
||||||
private DialogAccountSwitcherBinding binding;
|
private DialogAccountSwitcherBinding binding;
|
||||||
|
|
||||||
|
public AccountSwitcherDialogFragment() {
|
||||||
|
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountSwitcherDialogFragment(final OnAddAccountClickListener onAddAccountClickListener) {
|
||||||
|
this.onAddAccountClickListener = onAddAccountClickListener;
|
||||||
|
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext()));
|
||||||
|
}
|
||||||
|
|
||||||
private final AccountSwitcherAdapter.OnAccountClickListener accountClickListener = (model, isCurrent) -> {
|
private final AccountSwitcherAdapter.OnAccountClickListener accountClickListener = (model, isCurrent) -> {
|
||||||
if (isCurrent) {
|
if (isCurrent) {
|
||||||
dismiss();
|
dismiss();
|
||||||
@ -59,8 +73,18 @@ public class AccountSwitcherDialogFragment extends DialogFragment {
|
|||||||
new AlertDialog.Builder(context)
|
new AlertDialog.Builder(context)
|
||||||
.setMessage(getString(R.string.quick_access_confirm_delete, model.getUsername()))
|
.setMessage(getString(R.string.quick_access_confirm_delete, model.getUsername()))
|
||||||
.setPositiveButton(R.string.yes, (dialog, which) -> {
|
.setPositiveButton(R.string.yes, (dialog, which) -> {
|
||||||
Utils.dataBox.delUserCookie(model);
|
if (accountRepository == null) return;
|
||||||
dismiss();
|
accountRepository.deleteAccount(model, new RepositoryCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Void result) {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
.show();
|
.show();
|
||||||
@ -68,10 +92,6 @@ public class AccountSwitcherDialogFragment extends DialogFragment {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
public AccountSwitcherDialogFragment(final OnAddAccountClickListener onAddAccountClickListener) {
|
|
||||||
this.onAddAccountClickListener = onAddAccountClickListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull final LayoutInflater inflater,
|
public View onCreateView(@NonNull final LayoutInflater inflater,
|
||||||
final ViewGroup container,
|
final ViewGroup container,
|
||||||
@ -102,11 +122,19 @@ public class AccountSwitcherDialogFragment extends DialogFragment {
|
|||||||
private void init() {
|
private void init() {
|
||||||
final AccountSwitcherAdapter adapter = new AccountSwitcherAdapter(accountClickListener, accountLongClickListener);
|
final AccountSwitcherAdapter adapter = new AccountSwitcherAdapter(accountClickListener, accountLongClickListener);
|
||||||
binding.accounts.setAdapter(adapter);
|
binding.accounts.setAdapter(adapter);
|
||||||
final List<DataBox.CookieModel> allUsers = Utils.dataBox.getAllCookies();
|
if (accountRepository == null) return;
|
||||||
if (allUsers == null) return;
|
accountRepository.getAllAccounts(new RepositoryCallback<List<Account>>() {
|
||||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
@Override
|
||||||
sortUserList(cookie, allUsers);
|
public void onSuccess(final List<Account> accounts) {
|
||||||
adapter.submitList(allUsers);
|
if (accounts == null) return;
|
||||||
|
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||||
|
sortUserList(cookie, accounts);
|
||||||
|
adapter.submitList(accounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {}
|
||||||
|
});
|
||||||
binding.addAccountBtn.setOnClickListener(v -> {
|
binding.addAccountBtn.setOnClickListener(v -> {
|
||||||
if (onAddAccountClickListener == null) return;
|
if (onAddAccountClickListener == null) return;
|
||||||
onAddAccountClickListener.onAddAccountClick(this);
|
onAddAccountClickListener.onAddAccountClick(this);
|
||||||
@ -125,9 +153,9 @@ public class AccountSwitcherDialogFragment extends DialogFragment {
|
|||||||
* @param cookie active cookie
|
* @param cookie active cookie
|
||||||
* @param allUsers list of users
|
* @param allUsers list of users
|
||||||
*/
|
*/
|
||||||
private void sortUserList(final String cookie, final List<DataBox.CookieModel> allUsers) {
|
private void sortUserList(final String cookie, final List<Account> allUsers) {
|
||||||
boolean sortByName = true;
|
boolean sortByName = true;
|
||||||
for (final DataBox.CookieModel user : allUsers) {
|
for (final Account user : allUsers) {
|
||||||
if (TextUtils.isEmpty(user.getFullName())) {
|
if (TextUtils.isEmpty(user.getFullName())) {
|
||||||
sortByName = false;
|
sortByName = false;
|
||||||
break;
|
break;
|
||||||
|
@ -19,6 +19,8 @@ import androidx.fragment.app.DialogFragment;
|
|||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import awais.instagrabber.databinding.DialogCreateBackupBinding;
|
import awais.instagrabber.databinding.DialogCreateBackupBinding;
|
||||||
@ -32,6 +34,7 @@ import static awais.instagrabber.utils.DownloadUtils.PERMS;
|
|||||||
|
|
||||||
public class CreateBackupDialogFragment extends DialogFragment {
|
public class CreateBackupDialogFragment extends DialogFragment {
|
||||||
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
|
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
|
||||||
|
private static final SimpleDateFormat BACKUP_FILE_DATE_TIME_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
|
||||||
|
|
||||||
private final OnResultListener onResultListener;
|
private final OnResultListener onResultListener;
|
||||||
private DialogCreateBackupBinding binding;
|
private DialogCreateBackupBinding binding;
|
||||||
@ -139,7 +142,8 @@ public class CreateBackupDialogFragment extends DialogFragment {
|
|||||||
final DirectoryChooser directoryChooser = new DirectoryChooser()
|
final DirectoryChooser directoryChooser = new DirectoryChooser()
|
||||||
.setInitialDirectory(folderPath)
|
.setInitialDirectory(folderPath)
|
||||||
.setInteractionListener(path -> {
|
.setInteractionListener(path -> {
|
||||||
final File file = new File(path, String.format(Locale.ENGLISH, "barinsta_%d.backup", System.currentTimeMillis()));
|
final Date now = new Date();
|
||||||
|
final File file = new File(path, String.format("barinsta_%s.backup", BACKUP_FILE_DATE_TIME_FORMAT.format(now)));
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (binding.cbExportFavorites.isChecked()) {
|
if (binding.cbExportFavorites.isChecked()) {
|
||||||
flags |= ExportImportUtils.FLAG_FAVORITES;
|
flags |= ExportImportUtils.FLAG_FAVORITES;
|
||||||
@ -150,12 +154,12 @@ public class CreateBackupDialogFragment extends DialogFragment {
|
|||||||
if (binding.cbExportLogins.isChecked()) {
|
if (binding.cbExportLogins.isChecked()) {
|
||||||
flags |= ExportImportUtils.FLAG_COOKIES;
|
flags |= ExportImportUtils.FLAG_COOKIES;
|
||||||
}
|
}
|
||||||
ExportImportUtils.exportData(password, flags, file, result -> {
|
ExportImportUtils.exportData(context, flags, file, password, result -> {
|
||||||
if (onResultListener != null) {
|
if (onResultListener != null) {
|
||||||
onResultListener.onResult(result);
|
onResultListener.onResult(result);
|
||||||
}
|
}
|
||||||
dismiss();
|
dismiss();
|
||||||
}, context);
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
directoryChooser.setEnterTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
|
directoryChooser.setEnterTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
|
||||||
|
@ -4,6 +4,7 @@ import android.app.Dialog;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -93,7 +94,7 @@ public class RestoreBackupDialogFragment extends DialogFragment {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
binding.btnRestore.setEnabled(false);
|
binding.btnRestore.setEnabled(false);
|
||||||
binding.btnRestore.setOnClickListener(v -> {
|
binding.btnRestore.setOnClickListener(v -> new Handler().post(() -> {
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (binding.cbFavorites.isChecked()) {
|
if (binding.cbFavorites.isChecked()) {
|
||||||
flags |= ExportImportUtils.FLAG_FAVORITES;
|
flags |= ExportImportUtils.FLAG_FAVORITES;
|
||||||
@ -122,7 +123,7 @@ public class RestoreBackupDialogFragment extends DialogFragment {
|
|||||||
} catch (IncorrectPasswordException e) {
|
} catch (IncorrectPasswordException e) {
|
||||||
binding.passwordField.setError("Incorrect password");
|
binding.passwordField.setError("Incorrect password");
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
binding.etPassword.addTextChangedListener(new TextWatcher() {
|
binding.etPassword.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {}
|
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {}
|
||||||
|
@ -28,9 +28,11 @@ import awais.instagrabber.adapters.FavoritesAdapter;
|
|||||||
import awais.instagrabber.asyncs.LocationFetcher;
|
import awais.instagrabber.asyncs.LocationFetcher;
|
||||||
import awais.instagrabber.asyncs.ProfileFetcher;
|
import awais.instagrabber.asyncs.ProfileFetcher;
|
||||||
import awais.instagrabber.databinding.FragmentFavoritesBinding;
|
import awais.instagrabber.databinding.FragmentFavoritesBinding;
|
||||||
import awais.instagrabber.utils.DataBox;
|
import awais.instagrabber.db.datasources.FavoriteDataSource;
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
|
import awais.instagrabber.db.repositories.FavoriteRepository;
|
||||||
|
import awais.instagrabber.db.repositories.RepositoryCallback;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
|
||||||
import awais.instagrabber.viewmodels.FavoritesViewModel;
|
import awais.instagrabber.viewmodels.FavoritesViewModel;
|
||||||
|
|
||||||
public class FavoritesFragment extends Fragment {
|
public class FavoritesFragment extends Fragment {
|
||||||
@ -41,6 +43,13 @@ public class FavoritesFragment extends Fragment {
|
|||||||
private RecyclerView root;
|
private RecyclerView root;
|
||||||
private FavoritesViewModel favoritesViewModel;
|
private FavoritesViewModel favoritesViewModel;
|
||||||
private FavoritesAdapter adapter;
|
private FavoritesAdapter adapter;
|
||||||
|
private FavoriteRepository favoriteRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext()));
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
@ -68,9 +77,16 @@ public class FavoritesFragment extends Fragment {
|
|||||||
if (favoritesViewModel == null || adapter == null) return;
|
if (favoritesViewModel == null || adapter == null) return;
|
||||||
// refresh list every time in onViewStateRestored since it is cheaper than implementing pull down to refresh
|
// refresh list every time in onViewStateRestored since it is cheaper than implementing pull down to refresh
|
||||||
favoritesViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
favoritesViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
||||||
final List<DataBox.FavoriteModel> allFavorites = Utils.dataBox.getAllFavorites();
|
favoriteRepository.getAllFavorites(new RepositoryCallback<List<Favorite>>() {
|
||||||
favoritesViewModel.getList().postValue(allFavorites);
|
@Override
|
||||||
fetchMissingInfo(allFavorites);
|
public void onSuccess(final List<Favorite> favorites) {
|
||||||
|
favoritesViewModel.getList().postValue(favorites);
|
||||||
|
fetchMissingInfo(favorites);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
@ -114,30 +130,43 @@ public class FavoritesFragment extends Fragment {
|
|||||||
if (context == null) return false;
|
if (context == null) return false;
|
||||||
new MaterialAlertDialogBuilder(context)
|
new MaterialAlertDialogBuilder(context)
|
||||||
.setMessage(getString(R.string.quick_access_confirm_delete, model.getQuery()))
|
.setMessage(getString(R.string.quick_access_confirm_delete, model.getQuery()))
|
||||||
.setPositiveButton(R.string.yes, (d, which) -> {
|
.setPositiveButton(R.string.yes, (d, which) -> favoriteRepository
|
||||||
Utils.dataBox.deleteFavorite(model.getQuery(), model.getType());
|
.deleteFavorite(model.getQuery(), model.getType(), new RepositoryCallback<Void>() {
|
||||||
d.dismiss();
|
@Override
|
||||||
favoritesViewModel.getList().postValue(Utils.dataBox.getAllFavorites());
|
public void onSuccess(final Void result) {
|
||||||
})
|
d.dismiss();
|
||||||
|
favoriteRepository.getAllFavorites(new RepositoryCallback<List<Favorite>>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final List<Favorite> result) {
|
||||||
|
favoritesViewModel.getList().postValue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {}
|
||||||
|
}))
|
||||||
.setNegativeButton(R.string.no, null)
|
.setNegativeButton(R.string.no, null)
|
||||||
.show();
|
.show();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
binding.favoriteList.setAdapter(adapter);
|
binding.favoriteList.setAdapter(adapter);
|
||||||
// favoritesViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetchMissingInfo(final List<DataBox.FavoriteModel> allFavorites) {
|
private void fetchMissingInfo(final List<Favorite> allFavorites) {
|
||||||
final Runnable runnable = () -> {
|
final Runnable runnable = () -> {
|
||||||
final List<DataBox.FavoriteModel> updatedList = new ArrayList<>(allFavorites);
|
final List<Favorite> updatedList = new ArrayList<>(allFavorites);
|
||||||
// cyclic barrier is to make the async calls synchronous
|
// cyclic barrier is to make the async calls synchronous
|
||||||
final CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> {
|
final CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> {
|
||||||
// Log.d(TAG, "fetchMissingInfo: barrier action");
|
// Log.d(TAG, "fetchMissingInfo: barrier action");
|
||||||
favoritesViewModel.getList().postValue(new ArrayList<>(updatedList));
|
favoritesViewModel.getList().postValue(new ArrayList<>(updatedList));
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
for (final DataBox.FavoriteModel model : allFavorites) {
|
for (final Favorite model : allFavorites) {
|
||||||
cyclicBarrier.reset();
|
cyclicBarrier.reset();
|
||||||
// if the model has missing pic or display name (for user and location), fetch those details
|
// if the model has missing pic or display name (for user and location), fetch those details
|
||||||
switch (model.getType()) {
|
switch (model.getType()) {
|
||||||
@ -145,27 +174,37 @@ public class FavoritesFragment extends Fragment {
|
|||||||
if (TextUtils.isEmpty(model.getDisplayName())
|
if (TextUtils.isEmpty(model.getDisplayName())
|
||||||
|| TextUtils.isEmpty(model.getPicUrl())) {
|
|| TextUtils.isEmpty(model.getPicUrl())) {
|
||||||
new LocationFetcher(model.getQuery(), result -> {
|
new LocationFetcher(model.getQuery(), result -> {
|
||||||
try {
|
if (result == null) return;
|
||||||
if (result == null) return;
|
final int i = updatedList.indexOf(model);
|
||||||
final int i = updatedList.indexOf(model);
|
updatedList.remove(i);
|
||||||
updatedList.remove(i);
|
final Favorite updated = new Favorite(
|
||||||
final DataBox.FavoriteModel updated = new DataBox.FavoriteModel(
|
model.getId(),
|
||||||
model.getId(),
|
model.getQuery(),
|
||||||
model.getQuery(),
|
model.getType(),
|
||||||
model.getType(),
|
result.getName(),
|
||||||
result.getName(),
|
result.getSdProfilePic(),
|
||||||
result.getSdProfilePic(),
|
model.getDateAdded()
|
||||||
model.getDateAdded()
|
);
|
||||||
);
|
favoriteRepository.insertOrUpdateFavorite(updated, new RepositoryCallback<Void>() {
|
||||||
Utils.dataBox.addOrUpdateFavorite(updated);
|
@Override
|
||||||
updatedList.add(i, updated);
|
public void onSuccess(final Void result) {
|
||||||
} finally {
|
updatedList.add(i, updated);
|
||||||
try {
|
try {
|
||||||
cyclicBarrier.await();
|
cyclicBarrier.await();
|
||||||
} catch (BrokenBarrierException | InterruptedException e) {
|
} catch (BrokenBarrierException | InterruptedException e) {
|
||||||
Log.e(TAG, "fetchMissingInfo: ", e);
|
Log.e(TAG, "fetchMissingInfo: ", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {
|
||||||
|
try {
|
||||||
|
cyclicBarrier.await();
|
||||||
|
} catch (BrokenBarrierException | InterruptedException e) {
|
||||||
|
Log.e(TAG, "fetchMissingInfo: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}).execute();
|
}).execute();
|
||||||
cyclicBarrier.await();
|
cyclicBarrier.await();
|
||||||
}
|
}
|
||||||
@ -174,27 +213,37 @@ public class FavoritesFragment extends Fragment {
|
|||||||
if (TextUtils.isEmpty(model.getDisplayName())
|
if (TextUtils.isEmpty(model.getDisplayName())
|
||||||
|| TextUtils.isEmpty(model.getPicUrl())) {
|
|| TextUtils.isEmpty(model.getPicUrl())) {
|
||||||
new ProfileFetcher(model.getQuery(), result -> {
|
new ProfileFetcher(model.getQuery(), result -> {
|
||||||
try {
|
if (result == null) return;
|
||||||
if (result == null) return;
|
final int i = updatedList.indexOf(model);
|
||||||
final int i = updatedList.indexOf(model);
|
updatedList.remove(i);
|
||||||
updatedList.remove(i);
|
final Favorite updated = new Favorite(
|
||||||
final DataBox.FavoriteModel updated = new DataBox.FavoriteModel(
|
model.getId(),
|
||||||
model.getId(),
|
model.getQuery(),
|
||||||
model.getQuery(),
|
model.getType(),
|
||||||
model.getType(),
|
result.getName(),
|
||||||
result.getName(),
|
result.getSdProfilePic(),
|
||||||
result.getSdProfilePic(),
|
model.getDateAdded()
|
||||||
model.getDateAdded()
|
);
|
||||||
);
|
favoriteRepository.insertOrUpdateFavorite(updated, new RepositoryCallback<Void>() {
|
||||||
Utils.dataBox.addOrUpdateFavorite(updated);
|
@Override
|
||||||
updatedList.add(i, updated);
|
public void onSuccess(final Void result) {
|
||||||
} finally {
|
try {
|
||||||
try {
|
cyclicBarrier.await();
|
||||||
cyclicBarrier.await();
|
} catch (BrokenBarrierException | InterruptedException e) {
|
||||||
} catch (BrokenBarrierException | InterruptedException e) {
|
Log.e(TAG, "fetchMissingInfo: ", e);
|
||||||
Log.e(TAG, "fetchMissingInfo: ", e);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {
|
||||||
|
try {
|
||||||
|
cyclicBarrier.await();
|
||||||
|
} catch (BrokenBarrierException | InterruptedException e) {
|
||||||
|
Log.e(TAG, "fetchMissingInfo: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
updatedList.add(i, updated);
|
||||||
}).execute();
|
}).execute();
|
||||||
cyclicBarrier.await();
|
cyclicBarrier.await();
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,10 @@ import awais.instagrabber.asyncs.PostFetcher;
|
|||||||
import awais.instagrabber.customviews.PrimaryActionModeCallback;
|
import awais.instagrabber.customviews.PrimaryActionModeCallback;
|
||||||
import awais.instagrabber.databinding.FragmentHashtagBinding;
|
import awais.instagrabber.databinding.FragmentHashtagBinding;
|
||||||
import awais.instagrabber.databinding.LayoutHashtagDetailsBinding;
|
import awais.instagrabber.databinding.LayoutHashtagDetailsBinding;
|
||||||
|
import awais.instagrabber.db.datasources.FavoriteDataSource;
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
|
import awais.instagrabber.db.repositories.FavoriteRepository;
|
||||||
|
import awais.instagrabber.db.repositories.RepositoryCallback;
|
||||||
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
|
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
|
||||||
import awais.instagrabber.models.FeedModel;
|
import awais.instagrabber.models.FeedModel;
|
||||||
import awais.instagrabber.models.HashtagModel;
|
import awais.instagrabber.models.HashtagModel;
|
||||||
@ -57,7 +61,6 @@ import awais.instagrabber.models.StoryModel;
|
|||||||
import awais.instagrabber.models.enums.FavoriteType;
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
import awais.instagrabber.utils.DataBox;
|
|
||||||
import awais.instagrabber.utils.DownloadUtils;
|
import awais.instagrabber.utils.DownloadUtils;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
@ -454,40 +457,60 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
} else {
|
} else {
|
||||||
hashtagDetailsBinding.btnFollowTag.setVisibility(View.GONE);
|
hashtagDetailsBinding.btnFollowTag.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
final DataBox.FavoriteModel favorite = Utils.dataBox.getFavorite(hashtag.substring(1), FavoriteType.HASHTAG);
|
|
||||||
final boolean isFav = favorite != null;
|
|
||||||
hashtagDetailsBinding.favChip.setVisibility(View.VISIBLE);
|
hashtagDetailsBinding.favChip.setVisibility(View.VISIBLE);
|
||||||
hashtagDetailsBinding.favChip.setChipIconResource(isFav ? R.drawable.ic_star_check_24
|
final FavoriteRepository favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext()));
|
||||||
: R.drawable.ic_outline_star_plus_24);
|
favoriteRepository.getFavorite(hashtag.substring(1), FavoriteType.HASHTAG, new RepositoryCallback<Favorite>() {
|
||||||
hashtagDetailsBinding.favChip.setText(isFav ? R.string.favorite_short : R.string.add_to_favorites);
|
@Override
|
||||||
hashtagDetailsBinding.favChip.setOnClickListener(v -> {
|
public void onSuccess(final Favorite result) {
|
||||||
final DataBox.FavoriteModel fav = Utils.dataBox.getFavorite(hashtag.substring(1), FavoriteType.HASHTAG);
|
|
||||||
final boolean isFavorite = fav != null;
|
|
||||||
final String message;
|
|
||||||
if (isFavorite) {
|
|
||||||
Utils.dataBox.deleteFavorite(hashtag.substring(1), FavoriteType.HASHTAG);
|
|
||||||
hashtagDetailsBinding.favChip.setText(R.string.add_to_favorites);
|
|
||||||
hashtagDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
|
|
||||||
message = getString(R.string.removed_from_favs);
|
|
||||||
} else {
|
|
||||||
Utils.dataBox.addOrUpdateFavorite(new DataBox.FavoriteModel(
|
|
||||||
-1,
|
|
||||||
hashtag.substring(1),
|
|
||||||
FavoriteType.HASHTAG,
|
|
||||||
hashtagModel.getName(),
|
|
||||||
null,
|
|
||||||
new Date()
|
|
||||||
));
|
|
||||||
hashtagDetailsBinding.favChip.setText(R.string.favorite_short);
|
|
||||||
hashtagDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
|
hashtagDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
|
||||||
message = getString(R.string.added_to_favs);
|
hashtagDetailsBinding.favChip.setText(R.string.favorite_short);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {
|
||||||
|
hashtagDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
|
||||||
|
hashtagDetailsBinding.favChip.setText(R.string.add_to_favorites);
|
||||||
}
|
}
|
||||||
final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG);
|
|
||||||
snackbar.setAction(R.string.ok, v1 -> snackbar.dismiss())
|
|
||||||
.setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE)
|
|
||||||
.setAnchorView(fragmentActivity.getBottomNavView())
|
|
||||||
.show();
|
|
||||||
});
|
});
|
||||||
|
hashtagDetailsBinding.favChip.setOnClickListener(
|
||||||
|
v -> favoriteRepository.getFavorite(hashtag.substring(1), FavoriteType.HASHTAG, new RepositoryCallback<Favorite>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Favorite result) {
|
||||||
|
favoriteRepository.deleteFavorite(hashtag.substring(1), FavoriteType.HASHTAG, new RepositoryCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Void result) {
|
||||||
|
hashtagDetailsBinding.favChip.setText(R.string.add_to_favorites);
|
||||||
|
hashtagDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
|
||||||
|
showSnackbar(getString(R.string.removed_from_favs));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {
|
||||||
|
favoriteRepository.insertOrUpdateFavorite(new Favorite(
|
||||||
|
-1,
|
||||||
|
hashtag.substring(1),
|
||||||
|
FavoriteType.HASHTAG,
|
||||||
|
hashtagModel.getName(),
|
||||||
|
null,
|
||||||
|
new Date()
|
||||||
|
), new RepositoryCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Void result) {
|
||||||
|
hashtagDetailsBinding.favChip.setText(R.string.favorite_short);
|
||||||
|
hashtagDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
|
||||||
|
showSnackbar(getString(R.string.added_to_favs));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
hashtagDetailsBinding.mainHashtagImage.setImageURI(hashtagModel.getSdProfilePic());
|
hashtagDetailsBinding.mainHashtagImage.setImageURI(hashtagModel.getSdProfilePic());
|
||||||
final String postCount = String.valueOf(hashtagModel.getPostCount());
|
final String postCount = String.valueOf(hashtagModel.getPostCount());
|
||||||
final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count_inline, postCount));
|
final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count_inline, postCount));
|
||||||
@ -504,6 +527,14 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showSnackbar(final String message) {
|
||||||
|
final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG);
|
||||||
|
snackbar.setAction(R.string.ok, v1 -> snackbar.dismiss())
|
||||||
|
.setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE)
|
||||||
|
.setAnchorView(fragmentActivity.getBottomNavView())
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void fetchStories() {
|
private void fetchStories() {
|
||||||
if (!isLoggedIn) return;
|
if (!isLoggedIn) return;
|
||||||
storiesFetching = true;
|
storiesFetching = true;
|
||||||
|
@ -52,6 +52,10 @@ import awais.instagrabber.asyncs.PostFetcher;
|
|||||||
import awais.instagrabber.customviews.PrimaryActionModeCallback;
|
import awais.instagrabber.customviews.PrimaryActionModeCallback;
|
||||||
import awais.instagrabber.databinding.FragmentLocationBinding;
|
import awais.instagrabber.databinding.FragmentLocationBinding;
|
||||||
import awais.instagrabber.databinding.LayoutLocationDetailsBinding;
|
import awais.instagrabber.databinding.LayoutLocationDetailsBinding;
|
||||||
|
import awais.instagrabber.db.datasources.FavoriteDataSource;
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
|
import awais.instagrabber.db.repositories.FavoriteRepository;
|
||||||
|
import awais.instagrabber.db.repositories.RepositoryCallback;
|
||||||
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
|
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
|
||||||
import awais.instagrabber.models.FeedModel;
|
import awais.instagrabber.models.FeedModel;
|
||||||
import awais.instagrabber.models.LocationModel;
|
import awais.instagrabber.models.LocationModel;
|
||||||
@ -60,7 +64,6 @@ import awais.instagrabber.models.StoryModel;
|
|||||||
import awais.instagrabber.models.enums.FavoriteType;
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
import awais.instagrabber.utils.DataBox;
|
|
||||||
import awais.instagrabber.utils.DownloadUtils;
|
import awais.instagrabber.utils.DownloadUtils;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
@ -443,39 +446,63 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
|
|||||||
locationDetailsBinding.locationUrl.setVisibility(View.VISIBLE);
|
locationDetailsBinding.locationUrl.setVisibility(View.VISIBLE);
|
||||||
locationDetailsBinding.locationUrl.setText(TextUtils.getSpannableUrl(url));
|
locationDetailsBinding.locationUrl.setText(TextUtils.getSpannableUrl(url));
|
||||||
}
|
}
|
||||||
final DataBox.FavoriteModel favorite = Utils.dataBox.getFavorite(locationId, FavoriteType.LOCATION);
|
final FavoriteDataSource dataSource = FavoriteDataSource.getInstance(getContext());
|
||||||
final boolean isFav = favorite != null;
|
final FavoriteRepository favoriteRepository = FavoriteRepository.getInstance(dataSource);
|
||||||
locationDetailsBinding.favChip.setVisibility(View.VISIBLE);
|
locationDetailsBinding.favChip.setVisibility(View.VISIBLE);
|
||||||
locationDetailsBinding.favChip.setChipIconResource(isFav ? R.drawable.ic_star_check_24
|
favoriteRepository.getFavorite(locationId, FavoriteType.LOCATION, new RepositoryCallback<Favorite>() {
|
||||||
: R.drawable.ic_outline_star_plus_24);
|
@Override
|
||||||
locationDetailsBinding.favChip.setText(isFav ? R.string.favorite_short : R.string.add_to_favorites);
|
public void onSuccess(final Favorite result) {
|
||||||
locationDetailsBinding.favChip.setOnClickListener(v -> {
|
|
||||||
final DataBox.FavoriteModel fav = Utils.dataBox.getFavorite(locationId, FavoriteType.LOCATION);
|
|
||||||
final boolean isFavorite = fav != null;
|
|
||||||
final String message;
|
|
||||||
if (isFavorite) {
|
|
||||||
Utils.dataBox.deleteFavorite(locationId, FavoriteType.LOCATION);
|
|
||||||
locationDetailsBinding.favChip.setText(R.string.add_to_favorites);
|
|
||||||
locationDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
|
|
||||||
message = getString(R.string.removed_from_favs);
|
|
||||||
} else {
|
|
||||||
Utils.dataBox.addOrUpdateFavorite(new DataBox.FavoriteModel(
|
|
||||||
-1,
|
|
||||||
locationId,
|
|
||||||
FavoriteType.LOCATION,
|
|
||||||
locationModel.getName(),
|
|
||||||
locationModel.getSdProfilePic(),
|
|
||||||
new Date()
|
|
||||||
));
|
|
||||||
locationDetailsBinding.favChip.setText(R.string.favorite_short);
|
|
||||||
locationDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
|
locationDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
|
||||||
message = getString(R.string.added_to_favs);
|
locationDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
|
||||||
|
locationDetailsBinding.favChip.setText(R.string.favorite_short);
|
||||||
}
|
}
|
||||||
final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG);
|
|
||||||
snackbar.setAction(R.string.ok, v1 -> snackbar.dismiss())
|
@Override
|
||||||
.setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE)
|
public void onDataNotAvailable() {
|
||||||
.setAnchorView(fragmentActivity.getBottomNavView())
|
locationDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
|
||||||
.show();
|
locationDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
|
||||||
|
locationDetailsBinding.favChip.setText(R.string.add_to_favorites);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
locationDetailsBinding.favChip.setOnClickListener(v -> {
|
||||||
|
favoriteRepository.getFavorite(locationId, FavoriteType.LOCATION, new RepositoryCallback<Favorite>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Favorite result) {
|
||||||
|
favoriteRepository.deleteFavorite(locationId, FavoriteType.LOCATION, new RepositoryCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Void result) {
|
||||||
|
locationDetailsBinding.favChip.setText(R.string.add_to_favorites);
|
||||||
|
locationDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
|
||||||
|
showSnackbar(getString(R.string.removed_from_favs));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {
|
||||||
|
favoriteRepository.insertOrUpdateFavorite(new Favorite(
|
||||||
|
-1,
|
||||||
|
locationId,
|
||||||
|
FavoriteType.LOCATION,
|
||||||
|
locationModel.getName(),
|
||||||
|
locationModel.getSdProfilePic(),
|
||||||
|
new Date()
|
||||||
|
), new RepositoryCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Void result) {
|
||||||
|
locationDetailsBinding.favChip.setText(R.string.favorite_short);
|
||||||
|
locationDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
|
||||||
|
showSnackbar(getString(R.string.added_to_favs));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
locationDetailsBinding.mainLocationImage.setOnClickListener(v -> {
|
locationDetailsBinding.mainLocationImage.setOnClickListener(v -> {
|
||||||
if (hasStories) {
|
if (hasStories) {
|
||||||
@ -487,6 +514,14 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showSnackbar(final String message) {
|
||||||
|
final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG);
|
||||||
|
snackbar.setAction(R.string.ok, v1 -> snackbar.dismiss())
|
||||||
|
.setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE)
|
||||||
|
.setAnchorView(fragmentActivity.getBottomNavView())
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void fetchStories() {
|
private void fetchStories() {
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
storiesFetching = true;
|
storiesFetching = true;
|
||||||
|
@ -43,6 +43,8 @@ import awais.instagrabber.webservices.FriendshipService;
|
|||||||
import awais.instagrabber.webservices.NewsService;
|
import awais.instagrabber.webservices.NewsService;
|
||||||
import awais.instagrabber.webservices.ServiceCallback;
|
import awais.instagrabber.webservices.ServiceCallback;
|
||||||
|
|
||||||
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
public final class NotificationsViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
public final class NotificationsViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||||
private static final String TAG = "NotificationsViewer";
|
private static final String TAG = "NotificationsViewer";
|
||||||
|
|
||||||
@ -189,10 +191,12 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
|
final Context context = getContext();
|
||||||
|
CookieUtils.setupCookies(settingsHelper.getString(Constants.COOKIE));
|
||||||
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||||
notificationViewModel = new ViewModelProvider(this).get(NotificationViewModel.class);
|
notificationViewModel = new ViewModelProvider(this).get(NotificationViewModel.class);
|
||||||
final NotificationsAdapter adapter = new NotificationsAdapter(clickListener, mentionClickListener);
|
final NotificationsAdapter adapter = new NotificationsAdapter(clickListener, mentionClickListener);
|
||||||
binding.rvComments.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.rvComments.setLayoutManager(new LinearLayoutManager(context));
|
||||||
binding.rvComments.setAdapter(adapter);
|
binding.rvComments.setAdapter(adapter);
|
||||||
notificationViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
notificationViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
||||||
onRefresh();
|
onRefresh();
|
||||||
|
@ -63,6 +63,13 @@ import awais.instagrabber.customviews.PrimaryActionModeCallback;
|
|||||||
import awais.instagrabber.customviews.PrimaryActionModeCallback.CallbacksHelper;
|
import awais.instagrabber.customviews.PrimaryActionModeCallback.CallbacksHelper;
|
||||||
import awais.instagrabber.databinding.FragmentProfileBinding;
|
import awais.instagrabber.databinding.FragmentProfileBinding;
|
||||||
import awais.instagrabber.databinding.LayoutProfileDetailsBinding;
|
import awais.instagrabber.databinding.LayoutProfileDetailsBinding;
|
||||||
|
import awais.instagrabber.db.datasources.AccountDataSource;
|
||||||
|
import awais.instagrabber.db.datasources.FavoriteDataSource;
|
||||||
|
import awais.instagrabber.db.entities.Account;
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
|
import awais.instagrabber.db.repositories.AccountRepository;
|
||||||
|
import awais.instagrabber.db.repositories.FavoriteRepository;
|
||||||
|
import awais.instagrabber.db.repositories.RepositoryCallback;
|
||||||
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
|
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
|
||||||
import awais.instagrabber.dialogs.ProfilePicDialogFragment;
|
import awais.instagrabber.dialogs.ProfilePicDialogFragment;
|
||||||
import awais.instagrabber.fragments.PostViewV2Fragment;
|
import awais.instagrabber.fragments.PostViewV2Fragment;
|
||||||
@ -77,7 +84,6 @@ import awais.instagrabber.repositories.responses.FriendshipRepoChangeRootRespons
|
|||||||
import awais.instagrabber.repositories.responses.FriendshipRepoRestrictRootResponse;
|
import awais.instagrabber.repositories.responses.FriendshipRepoRestrictRootResponse;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
import awais.instagrabber.utils.DataBox;
|
|
||||||
import awais.instagrabber.utils.DownloadUtils;
|
import awais.instagrabber.utils.DownloadUtils;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
@ -283,6 +289,8 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
private LayoutProfileDetailsBinding profileDetailsBinding;
|
private LayoutProfileDetailsBinding profileDetailsBinding;
|
||||||
|
private AccountRepository accountRepository;
|
||||||
|
private FavoriteRepository favoriteRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
@ -290,6 +298,8 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
fragmentActivity = (MainActivity) requireActivity();
|
fragmentActivity = (MainActivity) requireActivity();
|
||||||
friendshipService = FriendshipService.getInstance();
|
friendshipService = FriendshipService.getInstance();
|
||||||
storiesService = StoriesService.getInstance();
|
storiesService = StoriesService.getInstance();
|
||||||
|
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext()));
|
||||||
|
favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext()));
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,19 +508,26 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
setUsernameDelayed();
|
setUsernameDelayed();
|
||||||
fetchProfileDetails();
|
fetchProfileDetails();
|
||||||
};
|
};
|
||||||
boolean found = false;
|
accountRepository.getAccount(uid, new RepositoryCallback<Account>() {
|
||||||
final DataBox.CookieModel cookieModel = Utils.dataBox.getCookie(uid);
|
@Override
|
||||||
if (cookieModel != null) {
|
public void onSuccess(final Account account) {
|
||||||
final String username = cookieModel.getUsername();
|
boolean found = false;
|
||||||
if (!TextUtils.isEmpty(username)) {
|
if (account != null) {
|
||||||
found = true;
|
final String username = account.getUsername();
|
||||||
fetchListener.onResult("@" + username);
|
if (!TextUtils.isEmpty(username)) {
|
||||||
|
found = true;
|
||||||
|
fetchListener.onResult("@" + username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
// if not in database, fetch info from instagram
|
||||||
|
new UsernameFetcher(uid, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!found) {
|
@Override
|
||||||
// if not in database, fetch info from instagram
|
public void onDataNotAvailable() {}
|
||||||
new UsernameFetcher(uid, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
});
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fetchProfileDetails();
|
fetchProfileDetails();
|
||||||
@ -556,9 +573,19 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
setupButtons(profileId, myId);
|
setupButtons(profileId, myId);
|
||||||
if (!profileId.equals(myId)) {
|
if (!profileId.equals(myId)) {
|
||||||
profileDetailsBinding.favCb.setVisibility(View.VISIBLE);
|
profileDetailsBinding.favCb.setVisibility(View.VISIBLE);
|
||||||
final boolean isFav = Utils.dataBox.getFavorite(username.substring(1), FavoriteType.USER) != null;
|
favoriteRepository.getFavorite(username.substring(1), FavoriteType.USER, new RepositoryCallback<Favorite>() {
|
||||||
profileDetailsBinding.favCb.setChecked(isFav);
|
@Override
|
||||||
profileDetailsBinding.favCb.setButtonDrawable(isFav ? R.drawable.ic_star_check_24 : R.drawable.ic_outline_star_plus_24);
|
public void onSuccess(final Favorite result) {
|
||||||
|
profileDetailsBinding.favCb.setChecked(true);
|
||||||
|
profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_star_check_24);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {
|
||||||
|
profileDetailsBinding.favCb.setChecked(false);
|
||||||
|
profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_outline_star_plus_24);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
profileDetailsBinding.favCb.setVisibility(View.GONE);
|
profileDetailsBinding.favCb.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
@ -842,41 +869,67 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
});
|
});
|
||||||
profileDetailsBinding.favCb.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
profileDetailsBinding.favCb.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
// do not do anything if state matches the db, as listener is set before profile details are set
|
// do not do anything if state matches the db, as listener is set before profile details are set
|
||||||
|
final Context context = getContext();
|
||||||
|
if (context == null) return;
|
||||||
final String finalUsername = username.startsWith("@") ? username.substring(1) : username;
|
final String finalUsername = username.startsWith("@") ? username.substring(1) : username;
|
||||||
final DataBox.FavoriteModel favorite = Utils.dataBox.getFavorite(finalUsername, FavoriteType.USER);
|
favoriteRepository.getFavorite(finalUsername, FavoriteType.USER, new RepositoryCallback<Favorite>() {
|
||||||
if ((isChecked && favorite != null) || (!isChecked && favorite == null)) {
|
@Override
|
||||||
return;
|
public void onSuccess(final Favorite result) {
|
||||||
}
|
if (isChecked) return; // already a fav
|
||||||
buttonView.setVisibility(View.GONE);
|
buttonView.setVisibility(View.GONE);
|
||||||
profileDetailsBinding.favProgress.setVisibility(View.VISIBLE);
|
profileDetailsBinding.favProgress.setVisibility(View.VISIBLE);
|
||||||
final String message;
|
favoriteRepository.deleteFavorite(finalUsername, FavoriteType.USER, new RepositoryCallback<Void>() {
|
||||||
if (isChecked) {
|
@Override
|
||||||
final DataBox.FavoriteModel model = new DataBox.FavoriteModel(
|
public void onSuccess(final Void result) {
|
||||||
-1,
|
profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_outline_star_plus_24);
|
||||||
finalUsername,
|
profileDetailsBinding.favProgress.setVisibility(View.GONE);
|
||||||
FavoriteType.USER,
|
profileDetailsBinding.favCb.setVisibility(View.VISIBLE);
|
||||||
profileModel.getName(),
|
showSnackbar(getString(R.string.removed_from_favs));
|
||||||
profileModel.getSdProfilePic(),
|
}
|
||||||
new Date()
|
|
||||||
);
|
@Override
|
||||||
Utils.dataBox.addOrUpdateFavorite(model);
|
public void onDataNotAvailable() {}
|
||||||
profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_star_check_24);
|
});
|
||||||
message = getString(R.string.added_to_favs);
|
}
|
||||||
} else {
|
|
||||||
Utils.dataBox.deleteFavorite(finalUsername, FavoriteType.USER);
|
@Override
|
||||||
message = getString(R.string.removed_from_favs);
|
public void onDataNotAvailable() {
|
||||||
profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_outline_star_plus_24);
|
if (!isChecked) return; // not in fav already
|
||||||
}
|
buttonView.setVisibility(View.GONE);
|
||||||
final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG);
|
profileDetailsBinding.favProgress.setVisibility(View.VISIBLE);
|
||||||
snackbar.setAction(R.string.ok, v -> snackbar.dismiss())
|
final Favorite model = new Favorite(
|
||||||
.setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE)
|
-1,
|
||||||
.setAnchorView(fragmentActivity.getBottomNavView())
|
finalUsername,
|
||||||
.show();
|
FavoriteType.USER,
|
||||||
profileDetailsBinding.favProgress.setVisibility(View.GONE);
|
profileModel.getName(),
|
||||||
profileDetailsBinding.favCb.setVisibility(View.VISIBLE);
|
profileModel.getSdProfilePic(),
|
||||||
|
new Date()
|
||||||
|
);
|
||||||
|
favoriteRepository.insertOrUpdateFavorite(model, new RepositoryCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Void result) {
|
||||||
|
profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_star_check_24);
|
||||||
|
profileDetailsBinding.favProgress.setVisibility(View.GONE);
|
||||||
|
profileDetailsBinding.favCb.setVisibility(View.VISIBLE);
|
||||||
|
showSnackbar(getString(R.string.added_to_favs));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showSnackbar(final String message) {
|
||||||
|
final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG);
|
||||||
|
snackbar.setAction(R.string.ok, v -> snackbar.dismiss())
|
||||||
|
.setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE)
|
||||||
|
.setAnchorView(fragmentActivity.getBottomNavView())
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void showProfilePicDialog() {
|
private void showProfilePicDialog() {
|
||||||
if (profileModel != null) {
|
if (profileModel != null) {
|
||||||
final FragmentManager fragmentManager = getParentFragmentManager();
|
final FragmentManager fragmentManager = getParentFragmentManager();
|
||||||
|
@ -8,6 +8,7 @@ import android.util.Log;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
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.appcompat.app.AppCompatActivity;
|
||||||
@ -26,14 +27,16 @@ import awais.instagrabber.BuildConfig;
|
|||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.activities.Login;
|
import awais.instagrabber.activities.Login;
|
||||||
import awais.instagrabber.databinding.PrefAccountSwitcherBinding;
|
import awais.instagrabber.databinding.PrefAccountSwitcherBinding;
|
||||||
|
import awais.instagrabber.db.datasources.AccountDataSource;
|
||||||
|
import awais.instagrabber.db.entities.Account;
|
||||||
|
import awais.instagrabber.db.repositories.AccountRepository;
|
||||||
|
import awais.instagrabber.db.repositories.RepositoryCallback;
|
||||||
import awais.instagrabber.dialogs.AccountSwitcherDialogFragment;
|
import awais.instagrabber.dialogs.AccountSwitcherDialogFragment;
|
||||||
import awais.instagrabber.repositories.responses.UserInfo;
|
import awais.instagrabber.repositories.responses.UserInfo;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
import awais.instagrabber.utils.DataBox;
|
|
||||||
import awais.instagrabber.utils.FlavorTown;
|
import awais.instagrabber.utils.FlavorTown;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
|
||||||
import awais.instagrabber.webservices.ProfileService;
|
import awais.instagrabber.webservices.ProfileService;
|
||||||
import awais.instagrabber.webservices.ServiceCallback;
|
import awais.instagrabber.webservices.ServiceCallback;
|
||||||
|
|
||||||
@ -42,20 +45,23 @@ import static awais.instagrabber.utils.Utils.settingsHelper;
|
|||||||
public class MorePreferencesFragment extends BasePreferencesFragment {
|
public class MorePreferencesFragment extends BasePreferencesFragment {
|
||||||
private static final String TAG = "MorePreferencesFragment";
|
private static final String TAG = "MorePreferencesFragment";
|
||||||
|
|
||||||
|
private final AccountRepository accountRepository;
|
||||||
|
|
||||||
|
public MorePreferencesFragment() {
|
||||||
|
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void setupPreferenceScreen(final PreferenceScreen screen) {
|
void setupPreferenceScreen(final PreferenceScreen screen) {
|
||||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||||
final boolean isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) != null;
|
final boolean isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) != null;
|
||||||
// screen.addPreference(new MoreHeaderPreference(getContext()));
|
// screen.addPreference(new MoreHeaderPreference(getContext()));
|
||||||
|
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
final PreferenceCategory accountCategory = new PreferenceCategory(context);
|
final PreferenceCategory accountCategory = new PreferenceCategory(context);
|
||||||
accountCategory.setTitle(R.string.account);
|
accountCategory.setTitle(R.string.account);
|
||||||
accountCategory.setIconSpaceReserved(false);
|
accountCategory.setIconSpaceReserved(false);
|
||||||
screen.addPreference(accountCategory);
|
screen.addPreference(accountCategory);
|
||||||
final List<DataBox.CookieModel> allCookies = Utils.dataBox.getAllCookies();
|
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
accountCategory.setSummary(R.string.account_hint);
|
accountCategory.setSummary(R.string.account_hint);
|
||||||
accountCategory.addPreference(getAccountSwitcherPreference(cookie));
|
accountCategory.addPreference(getAccountSwitcherPreference(cookie));
|
||||||
@ -67,34 +73,59 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
settingsHelper.putString(Constants.COOKIE, "");
|
settingsHelper.putString(Constants.COOKIE, "");
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
} else {
|
|
||||||
if (allCookies != null && allCookies.size() > 0) {
|
|
||||||
accountCategory.addPreference(getAccountSwitcherPreference(null));
|
|
||||||
}
|
|
||||||
// Need to show something to trigger login activity
|
|
||||||
accountCategory.addPreference(getPreference(R.string.add_account, R.drawable.ic_add, preference -> {
|
|
||||||
startActivityForResult(new Intent(getContext(), Login.class), Constants.LOGIN_RESULT_CODE);
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
accountRepository.getAllAccounts(new RepositoryCallback<List<Account>>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(@NonNull final List<Account> accounts) {
|
||||||
|
if (!isLoggedIn) {
|
||||||
|
if (accounts.size() > 0) {
|
||||||
|
accountCategory.addPreference(getAccountSwitcherPreference(null));
|
||||||
|
}
|
||||||
|
// Need to show something to trigger login activity
|
||||||
|
accountCategory.addPreference(getPreference(R.string.add_account, R.drawable.ic_add, preference -> {
|
||||||
|
startActivityForResult(new Intent(getContext(), Login.class), Constants.LOGIN_RESULT_CODE);
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if (accounts.size() > 0) {
|
||||||
|
accountCategory
|
||||||
|
.addPreference(getPreference(R.string.remove_all_acc, null, R.drawable.ic_account_multiple_remove_24, preference -> {
|
||||||
|
if (getContext() == null) return false;
|
||||||
|
new AlertDialog.Builder(getContext())
|
||||||
|
.setTitle(R.string.logout)
|
||||||
|
.setMessage(R.string.remove_all_acc_warning)
|
||||||
|
.setPositiveButton(R.string.yes, (dialog, which) -> {
|
||||||
|
CookieUtils.removeAllAccounts(context, new RepositoryCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Void result) {
|
||||||
|
shouldRecreate();
|
||||||
|
Toast.makeText(context, R.string.logout_success, Toast.LENGTH_SHORT).show();
|
||||||
|
settingsHelper.putString(Constants.COOKIE, "");
|
||||||
|
}
|
||||||
|
|
||||||
if (allCookies != null && allCookies.size() > 0) {
|
@Override
|
||||||
accountCategory.addPreference(getPreference(R.string.remove_all_acc, null, R.drawable.ic_account_multiple_remove_24, preference -> {
|
public void onDataNotAvailable() {}
|
||||||
if (getContext() == null) return false;
|
});
|
||||||
new AlertDialog.Builder(getContext())
|
})
|
||||||
.setTitle(R.string.logout)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
.setMessage(R.string.remove_all_acc_warning)
|
.show();
|
||||||
.setPositiveButton(R.string.yes, (dialog, which) -> {
|
return true;
|
||||||
CookieUtils.setupCookies("REMOVE");
|
}));
|
||||||
shouldRecreate();
|
}
|
||||||
Toast.makeText(context, R.string.logout_success, Toast.LENGTH_SHORT).show();
|
}
|
||||||
settingsHelper.putString(Constants.COOKIE, "");
|
|
||||||
})
|
@Override
|
||||||
.setNegativeButton(R.string.cancel, null)
|
public void onDataNotAvailable() {
|
||||||
.show();
|
Log.d(TAG, "onDataNotAvailable");
|
||||||
return true;
|
if (!isLoggedIn) {
|
||||||
}));
|
// Need to show something to trigger login activity
|
||||||
}
|
accountCategory.addPreference(getPreference(R.string.add_account, R.drawable.ic_add, preference -> {
|
||||||
|
startActivityForResult(new Intent(getContext(), Login.class), Constants.LOGIN_RESULT_CODE);
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// final PreferenceCategory generalCategory = new PreferenceCategory(context);
|
// final PreferenceCategory generalCategory = new PreferenceCategory(context);
|
||||||
// generalCategory.setTitle(R.string.pref_category_general);
|
// generalCategory.setTitle(R.string.pref_category_general);
|
||||||
@ -163,11 +194,26 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
public void onSuccess(final UserInfo result) {
|
public void onSuccess(final UserInfo result) {
|
||||||
// Log.d(TAG, "adding userInfo: " + result);
|
// Log.d(TAG, "adding userInfo: " + result);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
Utils.dataBox.addOrUpdateUser(uid, result.getUsername(), cookie, result.getFullName(), result.getProfilePicUrl());
|
accountRepository.insertOrUpdateAccount(
|
||||||
|
uid,
|
||||||
|
result.getUsername(),
|
||||||
|
cookie,
|
||||||
|
result.getFullName(),
|
||||||
|
result.getProfilePicUrl(),
|
||||||
|
new RepositoryCallback<Account>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Account result) {
|
||||||
|
final FragmentActivity activity = getActivity();
|
||||||
|
if (activity == null) return;
|
||||||
|
activity.recreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {
|
||||||
|
Log.e(TAG, "onDataNotAvailable: insert failed");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
final FragmentActivity activity = getActivity();
|
|
||||||
if (activity == null) return;
|
|
||||||
activity.recreate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -181,7 +227,7 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
private AccountSwitcherPreference getAccountSwitcherPreference(final String cookie) {
|
private AccountSwitcherPreference getAccountSwitcherPreference(final String cookie) {
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
if (context == null) return null;
|
if (context == null) return null;
|
||||||
return new AccountSwitcherPreference(context, cookie, v -> showAccountSwitcherDialog());
|
return new AccountSwitcherPreference(context, cookie, accountRepository, v -> showAccountSwitcherDialog());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showAccountSwitcherDialog() {
|
private void showAccountSwitcherDialog() {
|
||||||
@ -244,13 +290,16 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
public static class AccountSwitcherPreference extends Preference {
|
public static class AccountSwitcherPreference extends Preference {
|
||||||
|
|
||||||
private final String cookie;
|
private final String cookie;
|
||||||
|
private final AccountRepository accountRepository;
|
||||||
private final View.OnClickListener onClickListener;
|
private final View.OnClickListener onClickListener;
|
||||||
|
|
||||||
public AccountSwitcherPreference(final Context context,
|
public AccountSwitcherPreference(final Context context,
|
||||||
final String cookie,
|
final String cookie,
|
||||||
|
final AccountRepository accountRepository,
|
||||||
final View.OnClickListener onClickListener) {
|
final View.OnClickListener onClickListener) {
|
||||||
super(context);
|
super(context);
|
||||||
this.cookie = cookie;
|
this.cookie = cookie;
|
||||||
|
this.accountRepository = accountRepository;
|
||||||
this.onClickListener = onClickListener;
|
this.onClickListener = onClickListener;
|
||||||
setLayoutResource(R.layout.pref_account_switcher);
|
setLayoutResource(R.layout.pref_account_switcher);
|
||||||
}
|
}
|
||||||
@ -263,11 +312,20 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
final PrefAccountSwitcherBinding binding = PrefAccountSwitcherBinding.bind(root);
|
final PrefAccountSwitcherBinding binding = PrefAccountSwitcherBinding.bind(root);
|
||||||
final String uid = CookieUtils.getUserIdFromCookie(cookie);
|
final String uid = CookieUtils.getUserIdFromCookie(cookie);
|
||||||
if (uid == null) return;
|
if (uid == null) return;
|
||||||
final DataBox.CookieModel user = Utils.dataBox.getCookie(uid);
|
accountRepository.getAccount(uid, new RepositoryCallback<Account>() {
|
||||||
if (user == null) return;
|
@Override
|
||||||
binding.fullName.setText(user.getFullName());
|
public void onSuccess(final Account account) {
|
||||||
binding.username.setText("@" + user.getUsername());
|
binding.getRoot().post(() -> {
|
||||||
binding.profilePic.setImageURI(user.getProfilePic());
|
binding.fullName.setText(account.getFullName());
|
||||||
|
binding.username.setText("@" + account.getUsername());
|
||||||
|
binding.profilePic.setImageURI(account.getProfilePic());
|
||||||
|
binding.getRoot().requestLayout();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
98
app/src/main/java/awais/instagrabber/utils/AppExecutors.java
Normal file
98
app/src/main/java/awais/instagrabber/utils/AppExecutors.java
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global executor pools for the whole application.
|
||||||
|
* <p>
|
||||||
|
* Grouping tasks like this avoids the effects of task starvation (e.g. disk reads don't wait behind
|
||||||
|
* webservice requests).
|
||||||
|
*/
|
||||||
|
public class AppExecutors {
|
||||||
|
|
||||||
|
private static final int THREAD_COUNT = 3;
|
||||||
|
private static final Object LOCK = new Object();
|
||||||
|
|
||||||
|
private static AppExecutors instance;
|
||||||
|
|
||||||
|
private final Executor diskIO;
|
||||||
|
private final Executor networkIO;
|
||||||
|
private final Executor mainThread;
|
||||||
|
private final ListeningExecutorService tasksThread;
|
||||||
|
|
||||||
|
private AppExecutors(Executor diskIO,
|
||||||
|
Executor networkIO,
|
||||||
|
Executor mainThread,
|
||||||
|
ListeningExecutorService tasksThread) {
|
||||||
|
this.diskIO = diskIO;
|
||||||
|
this.networkIO = networkIO;
|
||||||
|
this.mainThread = mainThread;
|
||||||
|
this.tasksThread = tasksThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AppExecutors getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new AppExecutors(Executors.newSingleThreadExecutor(),
|
||||||
|
Executors.newFixedThreadPool(THREAD_COUNT),
|
||||||
|
new MainThreadExecutor(),
|
||||||
|
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Executor diskIO() {
|
||||||
|
return diskIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Executor networkIO() {
|
||||||
|
return networkIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ListeningExecutorService tasksThread() {
|
||||||
|
return tasksThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Executor mainThread() {
|
||||||
|
return mainThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MainThreadExecutor implements Executor {
|
||||||
|
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(@NonNull Runnable command) {
|
||||||
|
mainThreadHandler.post(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package awais.instagrabber.utils;
|
package awais.instagrabber.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.webkit.CookieManager;
|
import android.webkit.CookieManager;
|
||||||
|
|
||||||
@ -17,9 +18,13 @@ import java.util.regex.Matcher;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
import awais.instagrabber.BuildConfig;
|
||||||
|
import awais.instagrabber.db.datasources.AccountDataSource;
|
||||||
|
import awais.instagrabber.db.repositories.AccountRepository;
|
||||||
|
import awais.instagrabber.db.repositories.RepositoryCallback;
|
||||||
import awaisomereport.LogCollector;
|
import awaisomereport.LogCollector;
|
||||||
|
|
||||||
public final class CookieUtils {
|
public final class CookieUtils {
|
||||||
|
private static final String TAG = CookieUtils.class.getSimpleName();
|
||||||
public static final CookieManager COOKIE_MANAGER = CookieManager.getInstance();
|
public static final CookieManager COOKIE_MANAGER = CookieManager.getInstance();
|
||||||
public static final java.net.CookieManager NET_COOKIE_MANAGER = new java.net.CookieManager(null, CookiePolicy.ACCEPT_ALL);
|
public static final java.net.CookieManager NET_COOKIE_MANAGER = new java.net.CookieManager(null, CookiePolicy.ACCEPT_ALL);
|
||||||
|
|
||||||
@ -28,11 +33,7 @@ public final class CookieUtils {
|
|||||||
if (cookieStore == null || TextUtils.isEmpty(cookieRaw)) {
|
if (cookieStore == null || TextUtils.isEmpty(cookieRaw)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cookieRaw.equals("REMOVE")) {
|
if (cookieRaw.equals("LOGOUT")) {
|
||||||
cookieStore.removeAll();
|
|
||||||
Utils.dataBox.deleteAllUserCookies();
|
|
||||||
return;
|
|
||||||
} else if (cookieRaw.equals("LOGOUT")) {
|
|
||||||
cookieStore.removeAll();
|
cookieStore.removeAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -53,7 +54,19 @@ public final class CookieUtils {
|
|||||||
} catch (final URISyntaxException e) {
|
} catch (final URISyntaxException e) {
|
||||||
if (Utils.logCollector != null)
|
if (Utils.logCollector != null)
|
||||||
Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "setupCookies");
|
Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "setupCookies");
|
||||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeAllAccounts(final Context context, final RepositoryCallback<Void> callback) {
|
||||||
|
final CookieStore cookieStore = NET_COOKIE_MANAGER.getCookieStore();
|
||||||
|
if (cookieStore == null) return;
|
||||||
|
cookieStore.removeAll();
|
||||||
|
try {
|
||||||
|
AccountRepository.getInstance(AccountDataSource.getInstance(context))
|
||||||
|
.deleteAllAccounts(callback);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "setupCookies", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,26 +1,12 @@
|
|||||||
package awais.instagrabber.utils;
|
package awais.instagrabber.utils;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.util.ObjectsCompat;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
|
||||||
import awais.instagrabber.models.enums.FavoriteType;
|
|
||||||
import awaisomereport.LogCollector;
|
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Utils.logCollector;
|
|
||||||
|
|
||||||
public final class DataBox extends SQLiteOpenHelper {
|
public final class DataBox extends SQLiteOpenHelper {
|
||||||
private static final String TAG = "DataBox";
|
private static final String TAG = "DataBox";
|
||||||
@ -28,22 +14,6 @@ public final class DataBox extends SQLiteOpenHelper {
|
|||||||
private static DataBox sInstance;
|
private static DataBox sInstance;
|
||||||
|
|
||||||
private final static int VERSION = 3;
|
private final static int VERSION = 3;
|
||||||
private final static String TABLE_COOKIES = "cookies";
|
|
||||||
private final static String TABLE_FAVORITES = "favorites";
|
|
||||||
|
|
||||||
private final static String KEY_ID = "id";
|
|
||||||
private final static String KEY_USERNAME = Constants.EXTRAS_USERNAME;
|
|
||||||
private final static String KEY_COOKIE = "cookie";
|
|
||||||
private final static String KEY_UID = "uid";
|
|
||||||
private final static String KEY_FULL_NAME = "full_name";
|
|
||||||
private final static String KEY_PROFILE_PIC = "profile_pic";
|
|
||||||
|
|
||||||
private final static String FAV_COL_ID = "id";
|
|
||||||
private final static String FAV_COL_QUERY = "query_text";
|
|
||||||
private final static String FAV_COL_TYPE = "type";
|
|
||||||
private final static String FAV_COL_DISPLAY_NAME = "display_name";
|
|
||||||
private final static String FAV_COL_PIC_URL = "pic_url";
|
|
||||||
private final static String FAV_COL_DATE_ADDED = "date_added";
|
|
||||||
|
|
||||||
public static synchronized DataBox getInstance(final Context context) {
|
public static synchronized DataBox getInstance(final Context context) {
|
||||||
if (sInstance == null) sInstance = new DataBox(context.getApplicationContext());
|
if (sInstance == null) sInstance = new DataBox(context.getApplicationContext());
|
||||||
@ -57,21 +27,6 @@ public final class DataBox extends SQLiteOpenHelper {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(@NonNull final SQLiteDatabase db) {
|
public void onCreate(@NonNull final SQLiteDatabase db) {
|
||||||
Log.i(TAG, "Creating tables...");
|
Log.i(TAG, "Creating tables...");
|
||||||
db.execSQL("CREATE TABLE " + TABLE_COOKIES + " ("
|
|
||||||
+ KEY_ID + " INTEGER PRIMARY KEY,"
|
|
||||||
+ KEY_UID + " TEXT,"
|
|
||||||
+ KEY_USERNAME + " TEXT,"
|
|
||||||
+ KEY_COOKIE + " TEXT,"
|
|
||||||
+ KEY_FULL_NAME + " TEXT,"
|
|
||||||
+ KEY_PROFILE_PIC + " TEXT)");
|
|
||||||
// db.execSQL("CREATE TABLE favorites (id INTEGER PRIMARY KEY, query_text TEXT, date_added INTEGER, query_display TEXT)");
|
|
||||||
db.execSQL("CREATE TABLE " + TABLE_FAVORITES + " ("
|
|
||||||
+ FAV_COL_ID + " INTEGER PRIMARY KEY,"
|
|
||||||
+ FAV_COL_QUERY + " TEXT,"
|
|
||||||
+ FAV_COL_TYPE + " TEXT,"
|
|
||||||
+ FAV_COL_DISPLAY_NAME + " TEXT,"
|
|
||||||
+ FAV_COL_PIC_URL + " TEXT,"
|
|
||||||
+ FAV_COL_DATE_ADDED + " INTEGER)");
|
|
||||||
Log.i(TAG, "Tables created!");
|
Log.i(TAG, "Tables created!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,515 +36,8 @@ public final class DataBox extends SQLiteOpenHelper {
|
|||||||
// switch without break, so that all migrations from a previous version to new are run
|
// switch without break, so that all migrations from a previous version to new are run
|
||||||
switch (oldVersion) {
|
switch (oldVersion) {
|
||||||
case 1:
|
case 1:
|
||||||
db.execSQL("ALTER TABLE " + TABLE_COOKIES + " ADD " + KEY_FULL_NAME + " TEXT");
|
|
||||||
db.execSQL("ALTER TABLE " + TABLE_COOKIES + " ADD " + KEY_PROFILE_PIC + " TEXT");
|
|
||||||
case 2:
|
case 2:
|
||||||
final List<FavoriteModel> oldFavorites = backupOldFavorites(db);
|
|
||||||
// recreate with new columns (as there will be no doubt about the `query_display` column being present or not in the future versions)
|
|
||||||
db.execSQL("DROP TABLE " + TABLE_FAVORITES);
|
|
||||||
db.execSQL("CREATE TABLE " + TABLE_FAVORITES + " ("
|
|
||||||
+ FAV_COL_ID + " INTEGER PRIMARY KEY,"
|
|
||||||
+ FAV_COL_QUERY + " TEXT,"
|
|
||||||
+ FAV_COL_TYPE + " TEXT,"
|
|
||||||
+ FAV_COL_DISPLAY_NAME + " TEXT,"
|
|
||||||
+ FAV_COL_PIC_URL + " TEXT,"
|
|
||||||
+ FAV_COL_DATE_ADDED + " INTEGER)");
|
|
||||||
// add the old favorites back
|
|
||||||
for (final FavoriteModel oldFavorite : oldFavorites) {
|
|
||||||
addOrUpdateFavorite(db, oldFavorite);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Log.i(TAG, String.format("DB update from v%d to v%d completed!", oldVersion, newVersion));
|
Log.i(TAG, String.format("DB update from v%d to v%d completed!", oldVersion, newVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private List<FavoriteModel> backupOldFavorites(@NonNull final SQLiteDatabase db) {
|
|
||||||
// check if old favorites table had the column query_display
|
|
||||||
final boolean queryDisplayExists = checkColumnExists(db, TABLE_FAVORITES, "query_display");
|
|
||||||
Log.d(TAG, "backupOldFavorites: queryDisplayExists: " + queryDisplayExists);
|
|
||||||
final List<FavoriteModel> oldModels = new ArrayList<>();
|
|
||||||
final String sql = "SELECT "
|
|
||||||
+ "query_text,"
|
|
||||||
+ "date_added"
|
|
||||||
+ (queryDisplayExists ? ",query_display" : "")
|
|
||||||
+ " FROM " + TABLE_FAVORITES;
|
|
||||||
try (final Cursor cursor = db.rawQuery(sql, null)) {
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
final String queryText = cursor.getString(cursor.getColumnIndex("query_text"));
|
|
||||||
final Pair<FavoriteType, String> favoriteTypeQueryPair = Utils.migrateOldFavQuery(queryText);
|
|
||||||
if (favoriteTypeQueryPair == null) continue;
|
|
||||||
final FavoriteType type = favoriteTypeQueryPair.first;
|
|
||||||
final String query = favoriteTypeQueryPair.second;
|
|
||||||
oldModels.add(new FavoriteModel(
|
|
||||||
-1,
|
|
||||||
query,
|
|
||||||
type,
|
|
||||||
queryDisplayExists ? cursor.getString(cursor.getColumnIndex("query_display"))
|
|
||||||
: null,
|
|
||||||
null,
|
|
||||||
new Date(cursor.getLong(cursor.getColumnIndex("date_added")))
|
|
||||||
));
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "onUpgrade", e);
|
|
||||||
}
|
|
||||||
} while (cursor.moveToNext());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "onUpgrade", e);
|
|
||||||
}
|
|
||||||
Log.d(TAG, "backupOldFavorites: oldModels:" + oldModels);
|
|
||||||
return oldModels;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkColumnExists(@NonNull final SQLiteDatabase db,
|
|
||||||
@NonNull final String tableName,
|
|
||||||
@NonNull final String columnName) {
|
|
||||||
boolean exists = false;
|
|
||||||
try (Cursor cursor = db.rawQuery("PRAGMA table_info(" + tableName + ")", null)) {
|
|
||||||
if (cursor.moveToFirst()) {
|
|
||||||
do {
|
|
||||||
final String currentColumn = cursor.getString(cursor.getColumnIndex("name"));
|
|
||||||
if (currentColumn.equals(columnName)) {
|
|
||||||
exists = true;
|
|
||||||
}
|
|
||||||
} while (cursor.moveToNext());
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Log.e(TAG, "checkColumnExists", ex);
|
|
||||||
}
|
|
||||||
return exists;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void addOrUpdateFavorite(@NonNull final FavoriteModel model) {
|
|
||||||
final String query = model.getQuery();
|
|
||||||
if (!TextUtils.isEmpty(query)) {
|
|
||||||
try (final SQLiteDatabase db = getWritableDatabase()) {
|
|
||||||
db.beginTransaction();
|
|
||||||
try {
|
|
||||||
addOrUpdateFavorite(db, model);
|
|
||||||
db.setTransactionSuccessful();
|
|
||||||
} catch (final Exception e) {
|
|
||||||
if (logCollector != null) {
|
|
||||||
logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "addOrUpdateFavorite");
|
|
||||||
}
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.e(TAG, "Error adding/updating favorite", e);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
db.endTransaction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addOrUpdateFavorite(@NonNull final SQLiteDatabase db, @NonNull final FavoriteModel model) {
|
|
||||||
final ContentValues values = new ContentValues();
|
|
||||||
values.put(FAV_COL_QUERY, model.getQuery());
|
|
||||||
values.put(FAV_COL_TYPE, model.getType().toString());
|
|
||||||
values.put(FAV_COL_DISPLAY_NAME, model.getDisplayName());
|
|
||||||
values.put(FAV_COL_PIC_URL, model.getPicUrl());
|
|
||||||
values.put(FAV_COL_DATE_ADDED, model.getDateAdded().getTime());
|
|
||||||
int rows;
|
|
||||||
if (model.getId() >= 1) {
|
|
||||||
rows = db.update(TABLE_FAVORITES, values, FAV_COL_ID + "=?", new String[]{String.valueOf(model.getId())});
|
|
||||||
} else {
|
|
||||||
rows = db.update(TABLE_FAVORITES,
|
|
||||||
values,
|
|
||||||
FAV_COL_QUERY + "=?" +
|
|
||||||
" AND " + FAV_COL_TYPE + "=?",
|
|
||||||
new String[]{model.getQuery(), model.getType().toString()});
|
|
||||||
}
|
|
||||||
if (rows != 1) {
|
|
||||||
db.insertOrThrow(TABLE_FAVORITES, null, values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final synchronized void deleteFavorite(@NonNull final String query, @NonNull final FavoriteType type) {
|
|
||||||
if (!TextUtils.isEmpty(query)) {
|
|
||||||
try (final SQLiteDatabase db = getWritableDatabase()) {
|
|
||||||
db.beginTransaction();
|
|
||||||
try {
|
|
||||||
final int rowsDeleted = db.delete(TABLE_FAVORITES,
|
|
||||||
FAV_COL_QUERY + "=?" +
|
|
||||||
" AND " + FAV_COL_TYPE + "=?",
|
|
||||||
new String[]{query, type.toString()});
|
|
||||||
|
|
||||||
if (rowsDeleted > 0) db.setTransactionSuccessful();
|
|
||||||
} catch (final Exception e) {
|
|
||||||
if (logCollector != null) {
|
|
||||||
logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "deleteFavorite");
|
|
||||||
}
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.e(TAG, "Error", e);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
db.endTransaction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public final List<FavoriteModel> getAllFavorites() {
|
|
||||||
final List<FavoriteModel> favorites = new ArrayList<>();
|
|
||||||
final SQLiteDatabase db = getWritableDatabase();
|
|
||||||
try (final Cursor cursor = db.rawQuery("SELECT "
|
|
||||||
+ FAV_COL_ID + ","
|
|
||||||
+ FAV_COL_QUERY + ","
|
|
||||||
+ FAV_COL_TYPE + ","
|
|
||||||
+ FAV_COL_DISPLAY_NAME + ","
|
|
||||||
+ FAV_COL_PIC_URL + ","
|
|
||||||
+ FAV_COL_DATE_ADDED
|
|
||||||
+ " FROM " + TABLE_FAVORITES,
|
|
||||||
null)) {
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
db.beginTransaction();
|
|
||||||
FavoriteModel tempFav;
|
|
||||||
do {
|
|
||||||
FavoriteType type = null;
|
|
||||||
try {
|
|
||||||
type = FavoriteType.valueOf(cursor.getString(cursor.getColumnIndex(FAV_COL_TYPE)));
|
|
||||||
} catch (IllegalArgumentException ignored) {}
|
|
||||||
tempFav = new FavoriteModel(
|
|
||||||
cursor.getInt(cursor.getColumnIndex(FAV_COL_ID)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(FAV_COL_QUERY)),
|
|
||||||
type,
|
|
||||||
cursor.getString(cursor.getColumnIndex(FAV_COL_DISPLAY_NAME)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(FAV_COL_PIC_URL)),
|
|
||||||
new Date(cursor.getLong(cursor.getColumnIndex(FAV_COL_DATE_ADDED)))
|
|
||||||
);
|
|
||||||
favorites.add(tempFav);
|
|
||||||
} while (cursor.moveToNext());
|
|
||||||
db.endTransaction();
|
|
||||||
}
|
|
||||||
} catch (final Exception e) {
|
|
||||||
Log.e(TAG, "", e);
|
|
||||||
}
|
|
||||||
return favorites;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public final FavoriteModel getFavorite(@NonNull final String query, @NonNull final FavoriteType type) {
|
|
||||||
try (final SQLiteDatabase db = getReadableDatabase();
|
|
||||||
final Cursor cursor = db.rawQuery("SELECT "
|
|
||||||
+ FAV_COL_ID + ","
|
|
||||||
+ FAV_COL_QUERY + ","
|
|
||||||
+ FAV_COL_TYPE + ","
|
|
||||||
+ FAV_COL_DISPLAY_NAME + ","
|
|
||||||
+ FAV_COL_PIC_URL + ","
|
|
||||||
+ FAV_COL_DATE_ADDED
|
|
||||||
+ " FROM " + TABLE_FAVORITES
|
|
||||||
+ " WHERE " + FAV_COL_QUERY + "='" + query + "'"
|
|
||||||
+ " AND " + FAV_COL_TYPE + "='" + type.toString() + "'",
|
|
||||||
null)) {
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
FavoriteType favoriteType = null;
|
|
||||||
try {
|
|
||||||
favoriteType = FavoriteType.valueOf(cursor.getString(cursor.getColumnIndex(FAV_COL_TYPE)));
|
|
||||||
} catch (IllegalArgumentException ignored) {}
|
|
||||||
return new FavoriteModel(
|
|
||||||
cursor.getInt(cursor.getColumnIndex(FAV_COL_ID)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(FAV_COL_QUERY)),
|
|
||||||
favoriteType,
|
|
||||||
cursor.getString(cursor.getColumnIndex(FAV_COL_DISPLAY_NAME)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(FAV_COL_PIC_URL)),
|
|
||||||
new Date(cursor.getLong(cursor.getColumnIndex(FAV_COL_DATE_ADDED)))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void addOrUpdateUser(@NonNull final DataBox.CookieModel cookieModel) {
|
|
||||||
addOrUpdateUser(
|
|
||||||
cookieModel.getUid(),
|
|
||||||
cookieModel.getUsername(),
|
|
||||||
cookieModel.getCookie(),
|
|
||||||
cookieModel.getFullName(),
|
|
||||||
cookieModel.getProfilePic()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void addOrUpdateUser(final String uid,
|
|
||||||
final String username,
|
|
||||||
final String cookie,
|
|
||||||
final String fullName,
|
|
||||||
final String profilePicUrl) {
|
|
||||||
if (TextUtils.isEmpty(uid)) return;
|
|
||||||
try (final SQLiteDatabase db = getWritableDatabase()) {
|
|
||||||
db.beginTransaction();
|
|
||||||
try {
|
|
||||||
final ContentValues values = new ContentValues();
|
|
||||||
values.put(KEY_USERNAME, username);
|
|
||||||
values.put(KEY_COOKIE, cookie);
|
|
||||||
values.put(KEY_UID, uid);
|
|
||||||
values.put(KEY_FULL_NAME, fullName);
|
|
||||||
values.put(KEY_PROFILE_PIC, profilePicUrl);
|
|
||||||
|
|
||||||
final int rows = db.update(TABLE_COOKIES, values, KEY_UID + "=?", new String[]{uid});
|
|
||||||
|
|
||||||
if (rows != 1)
|
|
||||||
db.insertOrThrow(TABLE_COOKIES, null, values);
|
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
|
||||||
} catch (final Exception e) {
|
|
||||||
if (BuildConfig.DEBUG) Log.e(TAG, "Error", e);
|
|
||||||
} finally {
|
|
||||||
db.endTransaction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final synchronized void delUserCookie(@NonNull final CookieModel cookieModel) {
|
|
||||||
final String cookieModelUid = cookieModel.getUid();
|
|
||||||
if (!TextUtils.isEmpty(cookieModelUid)) {
|
|
||||||
try (final SQLiteDatabase db = getWritableDatabase()) {
|
|
||||||
db.beginTransaction();
|
|
||||||
try {
|
|
||||||
final int rowsDeleted = db.delete(TABLE_COOKIES, KEY_UID + "=? AND " + KEY_USERNAME + "=? AND " + KEY_COOKIE + "=?",
|
|
||||||
new String[]{cookieModelUid, cookieModel.getUsername(), cookieModel.getCookie()});
|
|
||||||
|
|
||||||
if (rowsDeleted > 0) db.setTransactionSuccessful();
|
|
||||||
} catch (final Exception e) {
|
|
||||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
|
||||||
} finally {
|
|
||||||
db.endTransaction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final synchronized void deleteAllUserCookies() {
|
|
||||||
try (final SQLiteDatabase db = getWritableDatabase()) {
|
|
||||||
db.beginTransaction();
|
|
||||||
try {
|
|
||||||
final int rowsDeleted = db.delete(TABLE_COOKIES, null, null);
|
|
||||||
|
|
||||||
if (rowsDeleted > 0) db.setTransactionSuccessful();
|
|
||||||
} catch (final Exception e) {
|
|
||||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
|
||||||
} finally {
|
|
||||||
db.endTransaction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public final CookieModel getCookie(final String uid) {
|
|
||||||
CookieModel cookie = null;
|
|
||||||
try (final SQLiteDatabase db = getReadableDatabase();
|
|
||||||
final Cursor cursor = db.rawQuery(
|
|
||||||
"SELECT "
|
|
||||||
+ KEY_UID + ","
|
|
||||||
+ KEY_USERNAME + ","
|
|
||||||
+ KEY_COOKIE + ","
|
|
||||||
+ KEY_FULL_NAME + ","
|
|
||||||
+ KEY_PROFILE_PIC
|
|
||||||
+ " FROM " + TABLE_COOKIES
|
|
||||||
+ " WHERE " + KEY_UID + " = ?",
|
|
||||||
new String[]{uid})
|
|
||||||
) {
|
|
||||||
if (cursor != null && cursor.moveToFirst())
|
|
||||||
cookie = new CookieModel(
|
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_UID)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_USERNAME)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_COOKIE)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_FULL_NAME)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_PROFILE_PIC))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return cookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public final List<CookieModel> getAllCookies() {
|
|
||||||
final List<CookieModel> cookies = new ArrayList<>();
|
|
||||||
try (final SQLiteDatabase db = getReadableDatabase();
|
|
||||||
final Cursor cursor = db.rawQuery(
|
|
||||||
"SELECT "
|
|
||||||
+ KEY_UID + ","
|
|
||||||
+ KEY_USERNAME + ","
|
|
||||||
+ KEY_COOKIE + ","
|
|
||||||
+ KEY_FULL_NAME + ","
|
|
||||||
+ KEY_PROFILE_PIC
|
|
||||||
+ " FROM " + TABLE_COOKIES, null)
|
|
||||||
) {
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
do {
|
|
||||||
cookies.add(new CookieModel(
|
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_UID)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_USERNAME)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_COOKIE)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_FULL_NAME)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_PROFILE_PIC))
|
|
||||||
));
|
|
||||||
} while (cursor.moveToNext());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class CookieModel {
|
|
||||||
private final String uid;
|
|
||||||
private final String username;
|
|
||||||
private final String cookie;
|
|
||||||
private final String fullName;
|
|
||||||
private final String profilePic;
|
|
||||||
private boolean selected;
|
|
||||||
|
|
||||||
public CookieModel(final String uid,
|
|
||||||
final String username,
|
|
||||||
final String cookie,
|
|
||||||
final String fullName,
|
|
||||||
final String profilePic) {
|
|
||||||
this.uid = uid;
|
|
||||||
this.username = username;
|
|
||||||
this.cookie = cookie;
|
|
||||||
this.fullName = fullName;
|
|
||||||
this.profilePic = profilePic;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUid() {
|
|
||||||
return uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCookie() {
|
|
||||||
return cookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFullName() {
|
|
||||||
return fullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getProfilePic() {
|
|
||||||
return profilePic;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSelected() {
|
|
||||||
return selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelected(final boolean selected) {
|
|
||||||
this.selected = selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isValid() {
|
|
||||||
return !TextUtils.isEmpty(uid)
|
|
||||||
&& !TextUtils.isEmpty(username)
|
|
||||||
&& !TextUtils.isEmpty(cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
final CookieModel that = (CookieModel) o;
|
|
||||||
return ObjectsCompat.equals(uid, that.uid) &&
|
|
||||||
ObjectsCompat.equals(username, that.username) &&
|
|
||||||
ObjectsCompat.equals(cookie, that.cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return ObjectsCompat.hash(uid, username, cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "CookieModel{" +
|
|
||||||
"uid='" + uid + '\'' +
|
|
||||||
", username='" + username + '\'' +
|
|
||||||
", cookie='" + cookie + '\'' +
|
|
||||||
", fullName='" + fullName + '\'' +
|
|
||||||
", profilePic='" + profilePic + '\'' +
|
|
||||||
", selected=" + selected +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class FavoriteModel {
|
|
||||||
private final int id;
|
|
||||||
private final String query;
|
|
||||||
private final FavoriteType type;
|
|
||||||
private final String displayName;
|
|
||||||
private final String picUrl;
|
|
||||||
private final Date dateAdded;
|
|
||||||
|
|
||||||
public FavoriteModel(final int id,
|
|
||||||
final String query,
|
|
||||||
final FavoriteType type,
|
|
||||||
final String displayName,
|
|
||||||
final String picUrl,
|
|
||||||
final Date dateAdded) {
|
|
||||||
this.id = id;
|
|
||||||
this.query = query;
|
|
||||||
this.type = type;
|
|
||||||
this.displayName = displayName;
|
|
||||||
this.picUrl = picUrl;
|
|
||||||
this.dateAdded = dateAdded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getQuery() {
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FavoriteType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDisplayName() {
|
|
||||||
return displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPicUrl() {
|
|
||||||
return picUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getDateAdded() {
|
|
||||||
return dateAdded;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
final FavoriteModel that = (FavoriteModel) o;
|
|
||||||
return id == that.id &&
|
|
||||||
ObjectsCompat.equals(query, that.query) &&
|
|
||||||
type == that.type &&
|
|
||||||
ObjectsCompat.equals(displayName, that.displayName) &&
|
|
||||||
ObjectsCompat.equals(picUrl, that.picUrl) &&
|
|
||||||
ObjectsCompat.equals(dateAdded, that.dateAdded);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return ObjectsCompat.hash(id, query, type, displayName, picUrl, dateAdded);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "FavoriteModel{" +
|
|
||||||
"id=" + id +
|
|
||||||
", query='" + query + '\'' +
|
|
||||||
", type=" + type +
|
|
||||||
", displayName='" + displayName + '\'' +
|
|
||||||
", picUrl='" + picUrl + '\'' +
|
|
||||||
", dateAdded=" + dateAdded +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -9,8 +9,14 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -18,12 +24,20 @@ import org.json.JSONObject;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
import awais.instagrabber.BuildConfig;
|
||||||
|
import awais.instagrabber.db.datasources.AccountDataSource;
|
||||||
|
import awais.instagrabber.db.datasources.FavoriteDataSource;
|
||||||
|
import awais.instagrabber.db.entities.Account;
|
||||||
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
|
import awais.instagrabber.db.repositories.AccountRepository;
|
||||||
|
import awais.instagrabber.db.repositories.FavoriteRepository;
|
||||||
|
import awais.instagrabber.db.repositories.RepositoryCallback;
|
||||||
import awais.instagrabber.interfaces.FetchListener;
|
import awais.instagrabber.interfaces.FetchListener;
|
||||||
import awais.instagrabber.models.enums.FavoriteType;
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
import awais.instagrabber.utils.PasswordUtils.IncorrectPasswordException;
|
import awais.instagrabber.utils.PasswordUtils.IncorrectPasswordException;
|
||||||
@ -39,47 +53,6 @@ public final class ExportImportUtils {
|
|||||||
public static final int FLAG_FAVORITES = 1 << 1;
|
public static final int FLAG_FAVORITES = 1 << 1;
|
||||||
public static final int FLAG_SETTINGS = 1 << 2;
|
public static final int FLAG_SETTINGS = 1 << 2;
|
||||||
|
|
||||||
@IntDef(value = {FLAG_COOKIES, FLAG_FAVORITES, FLAG_SETTINGS}, flag = true)
|
|
||||||
@interface ExportImportFlags {}
|
|
||||||
|
|
||||||
public static void exportData(@Nullable final String password,
|
|
||||||
@ExportImportFlags final int flags,
|
|
||||||
@NonNull final File filePath,
|
|
||||||
final FetchListener<Boolean> fetchListener,
|
|
||||||
@NonNull final Context context) {
|
|
||||||
final String exportString = getExportString(flags, context);
|
|
||||||
if (TextUtils.isEmpty(exportString)) return;
|
|
||||||
final boolean isPass = !TextUtils.isEmpty(password);
|
|
||||||
byte[] exportBytes = null;
|
|
||||||
if (isPass) {
|
|
||||||
final byte[] passwordBytes = password.getBytes();
|
|
||||||
final byte[] bytes = new byte[32];
|
|
||||||
System.arraycopy(passwordBytes, 0, bytes, 0, Math.min(passwordBytes.length, 32));
|
|
||||||
try {
|
|
||||||
exportBytes = PasswordUtils.enc(exportString, bytes);
|
|
||||||
} catch (final Exception e) {
|
|
||||||
if (fetchListener != null) fetchListener.onResult(false);
|
|
||||||
if (logCollector != null)
|
|
||||||
logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::isPass");
|
|
||||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
exportBytes = Base64.encode(exportString.getBytes(), Base64.DEFAULT | Base64.NO_WRAP | Base64.NO_PADDING);
|
|
||||||
}
|
|
||||||
if (exportBytes != null && exportBytes.length > 1) {
|
|
||||||
try (final FileOutputStream fos = new FileOutputStream(filePath)) {
|
|
||||||
fos.write(isPass ? 'A' : 'Z');
|
|
||||||
fos.write(exportBytes);
|
|
||||||
if (fetchListener != null) fetchListener.onResult(true);
|
|
||||||
} catch (final Exception e) {
|
|
||||||
if (fetchListener != null) fetchListener.onResult(false);
|
|
||||||
if (logCollector != null)
|
|
||||||
logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::notPass");
|
|
||||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
|
||||||
}
|
|
||||||
} else if (fetchListener != null) fetchListener.onResult(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void importData(@NonNull final Context context,
|
public static void importData(@NonNull final Context context,
|
||||||
@ExportImportFlags final int flags,
|
@ExportImportFlags final int flags,
|
||||||
@NonNull final File file,
|
@NonNull final File file,
|
||||||
@ -99,7 +72,8 @@ public final class ExportImportUtils {
|
|||||||
final byte[] passwordBytes = password.getBytes();
|
final byte[] passwordBytes = password.getBytes();
|
||||||
final byte[] bytes = new byte[32];
|
final byte[] bytes = new byte[32];
|
||||||
System.arraycopy(passwordBytes, 0, bytes, 0, Math.min(passwordBytes.length, 32));
|
System.arraycopy(passwordBytes, 0, bytes, 0, Math.min(passwordBytes.length, 32));
|
||||||
importJson(new String(PasswordUtils.dec(builder.toString(), bytes)),
|
importJson(context,
|
||||||
|
new String(PasswordUtils.dec(builder.toString(), bytes)),
|
||||||
flags,
|
flags,
|
||||||
fetchListener);
|
fetchListener);
|
||||||
} catch (final IncorrectPasswordException e) {
|
} catch (final IncorrectPasswordException e) {
|
||||||
@ -111,7 +85,8 @@ public final class ExportImportUtils {
|
|||||||
if (BuildConfig.DEBUG) Log.e(TAG, "Error importing backup", e);
|
if (BuildConfig.DEBUG) Log.e(TAG, "Error importing backup", e);
|
||||||
}
|
}
|
||||||
} else if (configType == 'Z') {
|
} else if (configType == 'Z') {
|
||||||
importJson(new String(Base64.decode(builder.toString(), Base64.DEFAULT | Base64.NO_PADDING | Base64.NO_WRAP)),
|
importJson(context,
|
||||||
|
new String(Base64.decode(builder.toString(), Base64.DEFAULT | Base64.NO_PADDING | Base64.NO_WRAP)),
|
||||||
flags,
|
flags,
|
||||||
fetchListener);
|
fetchListener);
|
||||||
|
|
||||||
@ -129,7 +104,8 @@ public final class ExportImportUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void importJson(@NonNull final String json,
|
private static void importJson(final Context context,
|
||||||
|
@NonNull final String json,
|
||||||
@ExportImportFlags final int flags,
|
@ExportImportFlags final int flags,
|
||||||
final FetchListener<Boolean> fetchListener) {
|
final FetchListener<Boolean> fetchListener) {
|
||||||
try {
|
try {
|
||||||
@ -138,10 +114,10 @@ public final class ExportImportUtils {
|
|||||||
importSettings(jsonObject);
|
importSettings(jsonObject);
|
||||||
}
|
}
|
||||||
if ((flags & FLAG_COOKIES) == FLAG_COOKIES && jsonObject.has("cookies")) {
|
if ((flags & FLAG_COOKIES) == FLAG_COOKIES && jsonObject.has("cookies")) {
|
||||||
importAccounts(jsonObject);
|
importAccounts(context, jsonObject);
|
||||||
}
|
}
|
||||||
if ((flags & FLAG_FAVORITES) == FLAG_FAVORITES && jsonObject.has("favs")) {
|
if ((flags & FLAG_FAVORITES) == FLAG_FAVORITES && jsonObject.has("favs")) {
|
||||||
importFavorites(jsonObject);
|
importFavorites(context, jsonObject);
|
||||||
}
|
}
|
||||||
if (fetchListener != null) fetchListener.onResult(true);
|
if (fetchListener != null) fetchListener.onResult(true);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
@ -151,7 +127,7 @@ public final class ExportImportUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void importFavorites(final JSONObject jsonObject) throws JSONException {
|
private static void importFavorites(final Context context, final JSONObject jsonObject) throws JSONException {
|
||||||
final JSONArray favs = jsonObject.getJSONArray("favs");
|
final JSONArray favs = jsonObject.getJSONArray("favs");
|
||||||
for (int i = 0; i < favs.length(); i++) {
|
for (int i = 0; i < favs.length(); i++) {
|
||||||
final JSONObject favsObject = favs.getJSONObject(i);
|
final JSONObject favsObject = favs.getJSONObject(i);
|
||||||
@ -175,7 +151,7 @@ public final class ExportImportUtils {
|
|||||||
if (query == null || favoriteType == null) {
|
if (query == null || favoriteType == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final DataBox.FavoriteModel favoriteModel = new DataBox.FavoriteModel(
|
final Favorite favorite = new Favorite(
|
||||||
-1,
|
-1,
|
||||||
query,
|
query,
|
||||||
favoriteType,
|
favoriteType,
|
||||||
@ -184,41 +160,55 @@ public final class ExportImportUtils {
|
|||||||
: favsObject.optString("pic_url"),
|
: 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);
|
||||||
Utils.dataBox.addOrUpdateFavorite(favoriteModel);
|
FavoriteRepository.getInstance(FavoriteDataSource.getInstance(context))
|
||||||
|
.insertOrUpdateFavorite(favorite, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void importAccounts(final JSONObject jsonObject) throws JSONException {
|
private static void importAccounts(final Context context,
|
||||||
final JSONArray cookies = jsonObject.getJSONArray("cookies");
|
final JSONObject jsonObject) {
|
||||||
for (int i = 0; i < cookies.length(); i++) {
|
final List<Account> accounts = new ArrayList<>();
|
||||||
final JSONObject cookieObject = cookies.getJSONObject(i);
|
try {
|
||||||
final DataBox.CookieModel cookieModel = new DataBox.CookieModel(
|
final JSONArray cookies = jsonObject.getJSONArray("cookies");
|
||||||
cookieObject.optString("i"),
|
for (int i = 0; i < cookies.length(); i++) {
|
||||||
cookieObject.optString("u"),
|
final JSONObject cookieObject = cookies.getJSONObject(i);
|
||||||
cookieObject.optString("c"),
|
final Account account = new Account(
|
||||||
cookieObject.optString("full_name"),
|
-1,
|
||||||
cookieObject.optString("profile_pic")
|
cookieObject.optString("i"),
|
||||||
);
|
cookieObject.optString("u"),
|
||||||
if (!cookieModel.isValid()) continue;
|
cookieObject.optString("c"),
|
||||||
// Log.d(TAG, "importJson: cookieModel: " + cookieModel);
|
cookieObject.optString("full_name"),
|
||||||
Utils.dataBox.addOrUpdateUser(cookieModel);
|
cookieObject.optString("profile_pic")
|
||||||
}
|
);
|
||||||
}
|
if (!account.isValid()) continue;
|
||||||
|
accounts.add(account);
|
||||||
private static void importSettings(final JSONObject jsonObject) throws JSONException {
|
|
||||||
final JSONObject objSettings = jsonObject.getJSONObject("settings");
|
|
||||||
final Iterator<String> keys = objSettings.keys();
|
|
||||||
while (keys.hasNext()) {
|
|
||||||
final String key = keys.next();
|
|
||||||
final Object val = objSettings.opt(key);
|
|
||||||
// Log.d(TAG, "importJson: key: " + key + ", val: " + val);
|
|
||||||
if (val instanceof String) {
|
|
||||||
settingsHelper.putString(key, (String) val);
|
|
||||||
} else if (val instanceof Integer) {
|
|
||||||
settingsHelper.putInteger(key, (int) val);
|
|
||||||
} else if (val instanceof Boolean) {
|
|
||||||
settingsHelper.putBoolean(key, (boolean) val);
|
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "importAccounts: Error parsing json", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AccountRepository.getInstance(AccountDataSource.getInstance(context))
|
||||||
|
.insertOrUpdateAccounts(accounts, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void importSettings(final JSONObject jsonObject) {
|
||||||
|
try {
|
||||||
|
final JSONObject objSettings = jsonObject.getJSONObject("settings");
|
||||||
|
final Iterator<String> keys = objSettings.keys();
|
||||||
|
while (keys.hasNext()) {
|
||||||
|
final String key = keys.next();
|
||||||
|
final Object val = objSettings.opt(key);
|
||||||
|
// Log.d(TAG, "importJson: key: " + key + ", val: " + val);
|
||||||
|
if (val instanceof String) {
|
||||||
|
settingsHelper.putString(key, (String) val);
|
||||||
|
} else if (val instanceof Integer) {
|
||||||
|
settingsHelper.putInteger(key, (int) val);
|
||||||
|
} else if (val instanceof Boolean) {
|
||||||
|
settingsHelper.putBoolean(key, (boolean) val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "importSettings error", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,97 +224,209 @@ public final class ExportImportUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
public static void exportData(@NonNull final Context context,
|
||||||
private static String getExportString(@ExportImportFlags final int flags,
|
@ExportImportFlags final int flags,
|
||||||
@NonNull final Context context) {
|
@NonNull final File filePath,
|
||||||
String result = null;
|
final String password,
|
||||||
try {
|
final FetchListener<Boolean> fetchListener) {
|
||||||
final JSONObject jsonObject = new JSONObject();
|
getExportString(flags, context, exportString -> {
|
||||||
if ((flags & FLAG_SETTINGS) == FLAG_SETTINGS) {
|
if (TextUtils.isEmpty(exportString)) return;
|
||||||
jsonObject.put("settings", getSettings(context));
|
final boolean isPass = !TextUtils.isEmpty(password);
|
||||||
}
|
byte[] exportBytes = null;
|
||||||
if ((flags & FLAG_COOKIES) == FLAG_COOKIES) {
|
if (isPass) {
|
||||||
jsonObject.put("cookies", getCookies());
|
final byte[] passwordBytes = password.getBytes();
|
||||||
}
|
final byte[] bytes = new byte[32];
|
||||||
if ((flags & FLAG_FAVORITES) == FLAG_FAVORITES) {
|
System.arraycopy(passwordBytes, 0, bytes, 0, Math.min(passwordBytes.length, 32));
|
||||||
jsonObject.put("favs", getFavorites());
|
try {
|
||||||
|
exportBytes = PasswordUtils.enc(exportString, bytes);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
if (fetchListener != null) fetchListener.onResult(false);
|
||||||
|
if (logCollector != null)
|
||||||
|
logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::isPass");
|
||||||
|
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
exportBytes = Base64.encode(exportString.getBytes(), Base64.DEFAULT | Base64.NO_WRAP | Base64.NO_PADDING);
|
||||||
}
|
}
|
||||||
|
if (exportBytes != null && exportBytes.length > 1) {
|
||||||
|
try (final FileOutputStream fos = new FileOutputStream(filePath)) {
|
||||||
|
fos.write(isPass ? 'A' : 'Z');
|
||||||
|
fos.write(exportBytes);
|
||||||
|
if (fetchListener != null) fetchListener.onResult(true);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
if (fetchListener != null) fetchListener.onResult(false);
|
||||||
|
if (logCollector != null)
|
||||||
|
logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::notPass");
|
||||||
|
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||||
|
}
|
||||||
|
} else if (fetchListener != null) fetchListener.onResult(false);
|
||||||
|
});
|
||||||
|
|
||||||
result = jsonObject.toString();
|
}
|
||||||
|
|
||||||
|
private static void getExportString(@ExportImportFlags final int flags,
|
||||||
|
@NonNull final Context context,
|
||||||
|
final OnExportStringCreatedCallback callback) {
|
||||||
|
if (callback == null) return;
|
||||||
|
try {
|
||||||
|
final ImmutableList.Builder<ListenableFuture<?>> futures = ImmutableList.builder();
|
||||||
|
futures.add((flags & FLAG_SETTINGS) == FLAG_SETTINGS
|
||||||
|
? getSettings(context)
|
||||||
|
: Futures.immediateFuture(null));
|
||||||
|
futures.add((flags & FLAG_COOKIES) == FLAG_COOKIES
|
||||||
|
? getCookies(context)
|
||||||
|
: Futures.immediateFuture(null));
|
||||||
|
futures.add((flags & FLAG_FAVORITES) == FLAG_FAVORITES
|
||||||
|
? getFavorites(context)
|
||||||
|
: Futures.immediateFuture(null));
|
||||||
|
//noinspection UnstableApiUsage
|
||||||
|
final ListenableFuture<List<Object>> allFutures = Futures.allAsList(futures.build());
|
||||||
|
Futures.addCallback(allFutures, new FutureCallback<List<Object>>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(@NullableDecl final List<Object> result) {
|
||||||
|
final JSONObject jsonObject = new JSONObject();
|
||||||
|
if (result == null) {
|
||||||
|
callback.onCreated(jsonObject.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final JSONObject settings = (JSONObject) result.get(0);
|
||||||
|
if (settings != null) {
|
||||||
|
jsonObject.put("settings", settings);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "error getting settings: ", e);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final JSONArray accounts = (JSONArray) result.get(1);
|
||||||
|
if (accounts != null) {
|
||||||
|
jsonObject.put("cookies", accounts);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "error getting accounts", e);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final JSONArray favorites = (JSONArray) result.get(2);
|
||||||
|
if (favorites != null) {
|
||||||
|
jsonObject.put("favs", favorites);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "error getting favorites: ", e);
|
||||||
|
}
|
||||||
|
callback.onCreated(jsonObject.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull final Throwable t) {
|
||||||
|
Log.e(TAG, "onFailure: ", t);
|
||||||
|
callback.onCreated(null);
|
||||||
|
}
|
||||||
|
}, AppExecutors.getInstance().tasksThread());
|
||||||
|
return;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getExportString");
|
if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getExportString");
|
||||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||||
}
|
}
|
||||||
return result;
|
callback.onCreated(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static JSONObject getSettings(@NonNull final Context context) {
|
private static ListenableFuture<JSONObject> getSettings(@NonNull final Context context) {
|
||||||
final SharedPreferences sharedPreferences = context.getSharedPreferences(Constants.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
final SharedPreferences sharedPreferences = context.getSharedPreferences(Constants.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||||
final Map<String, ?> allPrefs = sharedPreferences.getAll();
|
return AppExecutors.getInstance().tasksThread().submit(() -> {
|
||||||
if (allPrefs == null) {
|
final Map<String, ?> allPrefs = sharedPreferences.getAll();
|
||||||
|
if (allPrefs == null) {
|
||||||
|
return new JSONObject();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final JSONObject jsonObject = new JSONObject(allPrefs);
|
||||||
|
jsonObject.remove(Constants.COOKIE);
|
||||||
|
jsonObject.remove(Constants.DEVICE_UUID);
|
||||||
|
jsonObject.remove(Constants.PREV_INSTALL_VERSION);
|
||||||
|
return jsonObject;
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error exporting settings", e);
|
||||||
|
}
|
||||||
return new JSONObject();
|
return new JSONObject();
|
||||||
}
|
});
|
||||||
try {
|
|
||||||
final JSONObject jsonObject = new JSONObject(allPrefs);
|
|
||||||
jsonObject.remove(Constants.COOKIE);
|
|
||||||
jsonObject.remove(Constants.DEVICE_UUID);
|
|
||||||
jsonObject.remove(Constants.PREV_INSTALL_VERSION);
|
|
||||||
return jsonObject;
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Error exporting settings", e);
|
|
||||||
}
|
|
||||||
return new JSONObject();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
private static ListenableFuture<JSONArray> getFavorites(final Context context) {
|
||||||
private static JSONArray getFavorites() {
|
final SettableFuture<JSONArray> future = SettableFuture.create();
|
||||||
if (Utils.dataBox == null) return new JSONArray();
|
final FavoriteRepository favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(context));
|
||||||
try {
|
favoriteRepository.getAllFavorites(new RepositoryCallback<List<Favorite>>() {
|
||||||
final List<DataBox.FavoriteModel> allFavorites = Utils.dataBox.getAllFavorites();
|
@Override
|
||||||
final JSONArray jsonArray = new JSONArray();
|
public void onSuccess(final List<Favorite> favorites) {
|
||||||
for (final DataBox.FavoriteModel favorite : allFavorites) {
|
final JSONArray jsonArray = new JSONArray();
|
||||||
final JSONObject jsonObject = new JSONObject();
|
try {
|
||||||
jsonObject.put("q", favorite.getQuery());
|
for (final Favorite favorite : favorites) {
|
||||||
jsonObject.put("type", favorite.getType().toString());
|
final JSONObject jsonObject = new JSONObject();
|
||||||
jsonObject.put("s", favorite.getDisplayName());
|
jsonObject.put("q", favorite.getQuery());
|
||||||
jsonObject.put("pic_url", favorite.getPicUrl());
|
jsonObject.put("type", favorite.getType().toString());
|
||||||
jsonObject.put("d", favorite.getDateAdded().getTime());
|
jsonObject.put("s", favorite.getDisplayName());
|
||||||
jsonArray.put(jsonObject);
|
jsonObject.put("pic_url", favorite.getPicUrl());
|
||||||
|
jsonObject.put("d", favorite.getDateAdded().getTime());
|
||||||
|
jsonArray.put(jsonObject);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (logCollector != null) {
|
||||||
|
logCollector.appendException(e, LogFile.UTILS_EXPORT, "getFavorites");
|
||||||
|
}
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.e(TAG, "Error exporting favorites", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
future.set(jsonArray);
|
||||||
}
|
}
|
||||||
return jsonArray;
|
|
||||||
} catch (final Exception e) {
|
@Override
|
||||||
if (logCollector != null) {
|
public void onDataNotAvailable() {
|
||||||
logCollector.appendException(e, LogFile.UTILS_EXPORT, "getFavorites");
|
future.set(new JSONArray());
|
||||||
}
|
}
|
||||||
if (BuildConfig.DEBUG) {
|
});
|
||||||
Log.e(TAG, "Error exporting favorites", e);
|
return future;
|
||||||
}
|
|
||||||
}
|
|
||||||
return new JSONArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
private static ListenableFuture<JSONArray> getCookies(final Context context) {
|
||||||
private static JSONArray getCookies() {
|
final SettableFuture<JSONArray> future = SettableFuture.create();
|
||||||
if (Utils.dataBox == null) return new JSONArray();
|
final AccountRepository accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(context));
|
||||||
try {
|
accountRepository.getAllAccounts(new RepositoryCallback<List<Account>>() {
|
||||||
final List<DataBox.CookieModel> allCookies = Utils.dataBox.getAllCookies();
|
@Override
|
||||||
final JSONArray jsonArray = new JSONArray();
|
public void onSuccess(final List<Account> accounts) {
|
||||||
for (final DataBox.CookieModel cookie : allCookies) {
|
final JSONArray jsonArray = new JSONArray();
|
||||||
final JSONObject jsonObject = new JSONObject();
|
try {
|
||||||
jsonObject.put("i", cookie.getUid());
|
for (final Account cookie : accounts) {
|
||||||
jsonObject.put("u", cookie.getUsername());
|
final JSONObject jsonObject = new JSONObject();
|
||||||
jsonObject.put("c", cookie.getCookie());
|
jsonObject.put("i", cookie.getUid());
|
||||||
jsonObject.put("full_name", cookie.getFullName());
|
jsonObject.put("u", cookie.getUsername());
|
||||||
jsonObject.put("profile_pic", cookie.getProfilePic());
|
jsonObject.put("c", cookie.getCookie());
|
||||||
jsonArray.put(jsonObject);
|
jsonObject.put("full_name", cookie.getFullName());
|
||||||
|
jsonObject.put("profile_pic", cookie.getProfilePic());
|
||||||
|
jsonArray.put(jsonObject);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (logCollector != null) {
|
||||||
|
logCollector.appendException(e, LogFile.UTILS_EXPORT, "getCookies");
|
||||||
|
}
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.e(TAG, "Error exporting accounts", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
future.set(jsonArray);
|
||||||
}
|
}
|
||||||
return jsonArray;
|
|
||||||
} catch (final Exception e) {
|
@Override
|
||||||
if (BuildConfig.DEBUG) {
|
public void onDataNotAvailable() {
|
||||||
Log.e(TAG, "Error exporting accounts", e);
|
future.set(new JSONArray());
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return new JSONArray();
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
@IntDef(value = {FLAG_COOKIES, FLAG_FAVORITES, FLAG_SETTINGS}, flag = true)
|
||||||
|
@interface ExportImportFlags {}
|
||||||
|
|
||||||
|
public interface OnExportStringCreatedCallback {
|
||||||
|
void onCreated(String exportString);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -47,7 +47,6 @@ public final class Utils {
|
|||||||
|
|
||||||
public static LogCollector logCollector;
|
public static LogCollector logCollector;
|
||||||
public static SettingsHelper settingsHelper;
|
public static SettingsHelper settingsHelper;
|
||||||
public static DataBox dataBox;
|
|
||||||
public static boolean sessionVolumeFull = false;
|
public static boolean sessionVolumeFull = false;
|
||||||
public static final MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
|
public static final MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
|
||||||
public static ClipboardManager clipboardManager;
|
public static ClipboardManager clipboardManager;
|
||||||
|
@ -5,12 +5,12 @@ import androidx.lifecycle.ViewModel;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.utils.DataBox;
|
import awais.instagrabber.db.entities.Favorite;
|
||||||
|
|
||||||
public class FavoritesViewModel extends ViewModel {
|
public class FavoritesViewModel extends ViewModel {
|
||||||
private MutableLiveData<List<DataBox.FavoriteModel>> list;
|
private MutableLiveData<List<Favorite>> list;
|
||||||
|
|
||||||
public MutableLiveData<List<DataBox.FavoriteModel>> getList() {
|
public MutableLiveData<List<Favorite>> getList() {
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
list = new MutableLiveData<>();
|
list = new MutableLiveData<>();
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
android:id="@+id/cookies"
|
android:id="@+id/cookies"
|
||||||
style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog"
|
style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/get_cookies" />
|
android:text="@string/get_cookies" />
|
||||||
|
|
||||||
@ -30,14 +30,15 @@
|
|||||||
android:id="@+id/refresh"
|
android:id="@+id/refresh"
|
||||||
style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog"
|
style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/refresh" />
|
android:text="@string/refresh" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatCheckBox
|
<androidx.appcompat.widget.AppCompatCheckBox
|
||||||
android:id="@+id/desktop_mode"
|
android:id="@+id/desktop_mode"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/desktop_2fa" />
|
android:text="@string/desktop_2fa" />
|
||||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
@ -101,7 +101,7 @@
|
|||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/fav_progress"
|
android:id="@+id/fav_progress"
|
||||||
style="@style/Widget.MaterialComponents.ProgressIndicator.Circular.Indeterminate"
|
style="@style/Widget.MaterialComponents.CircularProgressIndicator"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
@ -6,7 +6,7 @@ buildscript {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.1'
|
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||||
def nav_version = "2.3.0"
|
def nav_version = "2.3.2"
|
||||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
|
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user