Browse Source

Migrate to Room

renovate/org.robolectric-robolectric-4.x
Ammar Githam 4 years ago
parent
commit
6b8df5fee2
  1. 229
      app/src/main/java/awais/instagrabber/db/AppDatabase.java
  2. 33
      app/src/main/java/awais/instagrabber/db/Converters.java
  3. 34
      app/src/main/java/awais/instagrabber/db/dao/AccountDao.java
  4. 35
      app/src/main/java/awais/instagrabber/db/dao/FavoriteDao.java
  5. 162
      app/src/main/java/awais/instagrabber/db/datasources/AccountDataSource.java
  6. 164
      app/src/main/java/awais/instagrabber/db/datasources/FavoriteDataSource.java
  7. 28
      app/src/main/java/awais/instagrabber/db/entities/Account.java
  8. 25
      app/src/main/java/awais/instagrabber/db/entities/Favorite.java
  9. 4
      app/src/main/java/awais/instagrabber/db/repositories/AccountRepository.java
  10. 14
      app/src/main/java/awais/instagrabber/db/repositories/FavoriteRepository.java
  11. 5
      app/src/main/java/awais/instagrabber/dialogs/AccountSwitcherDialogFragment.java
  12. 11
      app/src/main/java/awais/instagrabber/fragments/FavoritesFragment.java
  13. 8
      app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java
  14. 7
      app/src/main/java/awais/instagrabber/fragments/LocationFragment.java
  15. 10
      app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java
  16. 3
      app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java
  17. 35
      app/src/main/java/awais/instagrabber/utils/AppExecutors.java
  18. 2
      app/src/main/java/awais/instagrabber/utils/CookieUtils.java
  19. 140
      app/src/main/java/awais/instagrabber/utils/DataBox.java
  20. 11
      app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java

229
app/src/main/java/awais/instagrabber/db/AppDatabase.java

@ -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

@ -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

@ -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

@ -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();
}

162
app/src/main/java/awais/instagrabber/db/datasources/AccountDataSource.java

@ -1,182 +1,68 @@
package awais.instagrabber.db.datasources;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import awais.instagrabber.BuildConfig;
import awais.instagrabber.db.AppDatabase;
import awais.instagrabber.db.dao.AccountDao;
import awais.instagrabber.db.entities.Account;
import awais.instagrabber.utils.DataBox;
import awais.instagrabber.utils.TextUtils;
import static awais.instagrabber.utils.DataBox.KEY_COOKIE;
import static awais.instagrabber.utils.DataBox.KEY_FULL_NAME;
import static awais.instagrabber.utils.DataBox.KEY_ID;
import static awais.instagrabber.utils.DataBox.KEY_PROFILE_PIC;
import static awais.instagrabber.utils.DataBox.KEY_UID;
import static awais.instagrabber.utils.DataBox.KEY_USERNAME;
import static awais.instagrabber.utils.DataBox.TABLE_COOKIES;
public class AccountDataSource {
private static final String TAG = AccountDataSource.class.getSimpleName();
private static AccountDataSource INSTANCE;
private final DataBox dataBox;
private final AccountDao accountDao;
private AccountDataSource(@NonNull Context context) {
dataBox = DataBox.getInstance(context);
private AccountDataSource(final AccountDao accountDao) {
this.accountDao = accountDao;
}
public static synchronized AccountDataSource getInstance(@NonNull Context context) {
public static AccountDataSource getInstance(@NonNull Context context) {
if (INSTANCE == null) {
INSTANCE = new AccountDataSource(context);
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) {
Account cookie = null;
try (final SQLiteDatabase db = dataBox.getReadableDatabase();
final Cursor cursor = db.query(TABLE_COOKIES,
new String[]{
KEY_ID,
KEY_UID,
KEY_USERNAME,
KEY_COOKIE,
KEY_FULL_NAME,
KEY_PROFILE_PIC
},
KEY_UID + "=?",
new String[]{uid},
null,
null,
null)) {
if (cursor != null && cursor.moveToFirst())
cookie = new Account(
cursor.getInt(cursor.getColumnIndex(KEY_ID)),
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;
return accountDao.findAccountByUid(uid);
}
@NonNull
public final List<Account> getAllAccounts() {
final List<Account> cookies = new ArrayList<>();
try (final SQLiteDatabase db = dataBox.getReadableDatabase();
final Cursor cursor = db.query(TABLE_COOKIES,
new String[]{
KEY_ID,
KEY_UID,
KEY_USERNAME,
KEY_COOKIE,
KEY_FULL_NAME,
KEY_PROFILE_PIC
},
null,
null,
null,
null,
null)) {
if (cursor != null && cursor.moveToFirst()) {
do {
cookies.add(new Account(
cursor.getInt(cursor.getColumnIndex(KEY_ID)),
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;
return accountDao.getAllAccounts();
}
// public final void insertOrUpdateAccount(@NonNull final Account account) {
// insertOrUpdateAccount(
// account.getUid(),
// account.getUsername(),
// account.getCookie(),
// account.getFullName(),
// account.getProfilePic()
// );
// }
public final void insertOrUpdateAccount(final String uid,
final String username,
final String cookie,
final String fullName,
final String profilePicUrl) {
if (TextUtils.isEmpty(uid)) return;
try (final SQLiteDatabase db = dataBox.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.insert(TABLE_COOKIES, null, values);
}
db.setTransactionSuccessful();
} catch (final Exception e) {
if (BuildConfig.DEBUG) Log.e(TAG, "Error", e);
} finally {
db.endTransaction();
}
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 synchronized void deleteAccount(@NonNull final Account account) {
final String cookieModelUid = account.getUid();
if (!TextUtils.isEmpty(cookieModelUid)) {
try (final SQLiteDatabase db = dataBox.getWritableDatabase()) {
db.beginTransaction();
try {
final int rowsDeleted = db.delete(TABLE_COOKIES, KEY_UID + "=? AND " + KEY_USERNAME + "=? AND " + KEY_COOKIE + "=?",
new String[]{cookieModelUid, account.getUsername(), account.getCookie()});
if (rowsDeleted > 0) db.setTransactionSuccessful();
} catch (final Exception e) {
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
} finally {
db.endTransaction();
}
}
}
public final void deleteAccount(@NonNull final Account account) {
accountDao.deleteAccounts(account);
}
public final synchronized void deleteAllAccounts() {
try (final SQLiteDatabase db = dataBox.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();
}
}
public final void deleteAllAccounts() {
accountDao.deleteAllAccounts();
}
}

164
app/src/main/java/awais/instagrabber/db/datasources/FavoriteDataSource.java

@ -1,180 +1,62 @@
package awais.instagrabber.db.datasources;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import awais.instagrabber.BuildConfig;
import awais.instagrabber.db.AppDatabase;
import awais.instagrabber.db.dao.FavoriteDao;
import awais.instagrabber.db.entities.Favorite;
import awais.instagrabber.models.enums.FavoriteType;
import awais.instagrabber.utils.DataBox;
import awais.instagrabber.utils.TextUtils;
import awaisomereport.LogCollector;
import static awais.instagrabber.utils.DataBox.FAV_COL_DATE_ADDED;
import static awais.instagrabber.utils.DataBox.FAV_COL_DISPLAY_NAME;
import static awais.instagrabber.utils.DataBox.FAV_COL_ID;
import static awais.instagrabber.utils.DataBox.FAV_COL_PIC_URL;
import static awais.instagrabber.utils.DataBox.FAV_COL_QUERY;
import static awais.instagrabber.utils.DataBox.FAV_COL_TYPE;
import static awais.instagrabber.utils.DataBox.TABLE_FAVORITES;
import static awais.instagrabber.utils.Utils.logCollector;
public class FavoriteDataSource {
private static final String TAG = FavoriteDataSource.class.getSimpleName();
private static FavoriteDataSource INSTANCE;
private final DataBox dataBox;
private final FavoriteDao favoriteDao;
private FavoriteDataSource(@NonNull Context context) {
dataBox = DataBox.getInstance(context);
private FavoriteDataSource(final FavoriteDao favoriteDao) {
this.favoriteDao = favoriteDao;
}
public static synchronized FavoriteDataSource getInstance(@NonNull Context context) {
if (INSTANCE == null) {
INSTANCE = new FavoriteDataSource(context);
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) {
try (final SQLiteDatabase db = dataBox.getReadableDatabase();
final Cursor cursor = db.query(TABLE_FAVORITES,
new String[]{
FAV_COL_ID,
FAV_COL_QUERY,
FAV_COL_TYPE,
FAV_COL_DISPLAY_NAME,
FAV_COL_PIC_URL,
FAV_COL_DATE_ADDED
},
FAV_COL_QUERY + "=?" + " AND " + FAV_COL_TYPE + "=?",
new String[]{
query,
type.toString()
},
null,
null,
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 Favorite(
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;
return favoriteDao.findFavoriteByQueryAndType(query, type);
}
@NonNull
public final List<Favorite> getAllFavorites() {
final List<Favorite> favorites = new ArrayList<>();
try (final SQLiteDatabase db = dataBox.getWritableDatabase()) {
try (final Cursor cursor = db.query(TABLE_FAVORITES,
new String[]{
FAV_COL_ID,
FAV_COL_QUERY,
FAV_COL_TYPE,
FAV_COL_DISPLAY_NAME,
FAV_COL_PIC_URL,
FAV_COL_DATE_ADDED
},
null,
null,
null,
null,
null)) {
if (cursor != null && cursor.moveToFirst()) {
db.beginTransaction();
Favorite tempFav;
do {
FavoriteType type = null;
try {
type = FavoriteType.valueOf(cursor.getString(cursor.getColumnIndex(FAV_COL_TYPE)));
} catch (IllegalArgumentException ignored) {}
tempFav = new Favorite(
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;
return favoriteDao.getAllFavorites();
}
public final synchronized Favorite insertOrUpdateFavorite(@NonNull final Favorite model) {
final String query = model.getQuery();
if (!TextUtils.isEmpty(query)) {
try (final SQLiteDatabase db = dataBox.getWritableDatabase()) {
db.beginTransaction();
try {
dataBox.insertOrUpdateFavorite(db, model);
db.setTransactionSuccessful();
} catch (Exception e) {
if (logCollector != null) {
logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "insertOrUpdateFavorite");
}
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error adding/updating favorite", e);
}
} finally {
db.endTransaction();
}
}
return getFavorite(model.getQuery(), model.getType());
public final void insertOrUpdateFavorite(@NonNull final Favorite favorite) {
if (favorite.getId() > 0) {
favoriteDao.updateFavorites(favorite);
return;
}
return null;
favoriteDao.insertFavorites(favorite);
}
public final synchronized void deleteFavorite(@NonNull final String query, @NonNull final FavoriteType type) {
if (!TextUtils.isEmpty(query)) {
try (final SQLiteDatabase db = dataBox.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();
}
}
}
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);
}
}

28
app/src/main/java/awais/instagrabber/db/entities/Account.java

@ -4,32 +4,42 @@ 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 = "cookies")
@Entity(tableName = Account.TABLE_NAME)
public class Account {
@PrimaryKey
@ColumnInfo(name = "id")
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 = "uid")
@ColumnInfo(name = COL_UID)
private final String uid;
@ColumnInfo(name = "username")
@ColumnInfo(name = COL_USERNAME)
private final String username;
@ColumnInfo(name = "cookie")
@ColumnInfo(name = COL_COOKIE)
private final String cookie;
@ColumnInfo(name = "full_name")
@ColumnInfo(name = COL_FULL_NAME)
private final String fullName;
@ColumnInfo(name = "profile_pic")
@ColumnInfo(name = COL_PROFILE_PIC)
private final String profilePic;
@Ignore
private boolean selected;
public Account(final int id,

25
app/src/main/java/awais/instagrabber/db/entities/Favorite.java

@ -10,26 +10,33 @@ import java.util.Date;
import awais.instagrabber.models.enums.FavoriteType;
@Entity(tableName = "favorites")
@Entity(tableName = Favorite.TABLE_NAME)
public class Favorite {
@PrimaryKey
@ColumnInfo(name = "id")
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 = "query_text")
@ColumnInfo(name = COL_QUERY)
private final String query;
@ColumnInfo(name = "type")
@ColumnInfo(name = COL_TYPE)
private final FavoriteType type;
@ColumnInfo(name = "display_name")
@ColumnInfo(name = COL_DISPLAY_NAME)
private final String displayName;
@ColumnInfo(name = "pic_url")
@ColumnInfo(name = COL_PIC_URL)
private final String picUrl;
@ColumnInfo(name = "date_added")
@ColumnInfo(name = COL_DATE_ADDED)
private final Date dateAdded;
public Favorite(final int id,

4
app/src/main/java/awais/instagrabber/db/repositories/AccountRepository.java

@ -21,9 +21,9 @@ public class AccountRepository {
this.accountDataSource = accountDataSource;
}
public static AccountRepository getInstance(final AppExecutors appExecutors, final AccountDataSource accountDataSource) {
public static AccountRepository getInstance(final AccountDataSource accountDataSource) {
if (instance == null) {
instance = new AccountRepository(appExecutors, accountDataSource);
instance = new AccountRepository(AppExecutors.getInstance(), accountDataSource);
}
return instance;
}

14
app/src/main/java/awais/instagrabber/db/repositories/FavoriteRepository.java

@ -20,9 +20,9 @@ public class FavoriteRepository {
this.favoriteDataSource = favoriteDataSource;
}
public static FavoriteRepository getInstance(final AppExecutors appExecutors, final FavoriteDataSource favoriteDataSource) {
public static FavoriteRepository getInstance(final FavoriteDataSource favoriteDataSource) {
if (instance == null) {
instance = new FavoriteRepository(appExecutors, favoriteDataSource);
instance = new FavoriteRepository(AppExecutors.getInstance(), favoriteDataSource);
}
return instance;
}
@ -60,18 +60,14 @@ public class FavoriteRepository {
}
public void insertOrUpdateFavorite(final Favorite favorite,
final RepositoryCallback<Favorite> callback) {
final RepositoryCallback<Void> callback) {
// request on the I/O thread
appExecutors.diskIO().execute(() -> {
final Favorite updated = favoriteDataSource.insertOrUpdateFavorite(favorite);
favoriteDataSource.insertOrUpdateFavorite(favorite);
// notify on the main thread
appExecutors.mainThread().execute(() -> {
if (callback == null) return;
if (updated == null) {
callback.onDataNotAvailable();
return;
}
callback.onSuccess(updated);
callback.onSuccess(null);
});
});
}

5
app/src/main/java/awais/instagrabber/dialogs/AccountSwitcherDialogFragment.java

@ -25,7 +25,6 @@ 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.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.TextUtils;
@ -41,12 +40,12 @@ public class AccountSwitcherDialogFragment extends DialogFragment {
private DialogAccountSwitcherBinding binding;
public AccountSwitcherDialogFragment() {
accountRepository = AccountRepository.getInstance(new AppExecutors(), AccountDataSource.getInstance(getContext()));
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext()));
}
public AccountSwitcherDialogFragment(final OnAddAccountClickListener onAddAccountClickListener) {
this.onAddAccountClickListener = onAddAccountClickListener;
accountRepository = AccountRepository.getInstance(new AppExecutors(), AccountDataSource.getInstance(getContext()));
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext()));
}
private final AccountSwitcherAdapter.OnAccountClickListener accountClickListener = (model, isCurrent) -> {

11
app/src/main/java/awais/instagrabber/fragments/FavoritesFragment.java

@ -32,7 +32,6 @@ 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.AppExecutors;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.viewmodels.FavoritesViewModel;
@ -49,7 +48,7 @@ public class FavoritesFragment extends Fragment {
@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
favoriteRepository = FavoriteRepository.getInstance(new AppExecutors(), FavoriteDataSource.getInstance(getContext()));
favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext()));
}
@NonNull
@ -186,9 +185,9 @@ public class FavoritesFragment extends Fragment {
result.getSdProfilePic(),
model.getDateAdded()
);
favoriteRepository.insertOrUpdateFavorite(updated, new RepositoryCallback<Favorite>() {
favoriteRepository.insertOrUpdateFavorite(updated, new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Favorite result) {
public void onSuccess(final Void result) {
updatedList.add(i, updated);
try {
cyclicBarrier.await();
@ -225,9 +224,9 @@ public class FavoritesFragment extends Fragment {
result.getSdProfilePic(),
model.getDateAdded()
);
favoriteRepository.insertOrUpdateFavorite(updated, new RepositoryCallback<Favorite>() {
favoriteRepository.insertOrUpdateFavorite(updated, new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Favorite result) {
public void onSuccess(final Void result) {
try {
cyclicBarrier.await();
} catch (BrokenBarrierException | InterruptedException e) {

8
app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java

@ -59,7 +59,6 @@ import awais.instagrabber.models.HashtagModel;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.StoryModel;
import awais.instagrabber.models.enums.FavoriteType;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.DownloadUtils;
@ -459,8 +458,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
hashtagDetailsBinding.btnFollowTag.setVisibility(View.GONE);
}
hashtagDetailsBinding.favChip.setVisibility(View.VISIBLE);
final FavoriteRepository favoriteRepository = FavoriteRepository
.getInstance(new AppExecutors(), FavoriteDataSource.getInstance(getContext()));
final FavoriteRepository favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext()));
favoriteRepository.getFavorite(hashtag.substring(1), FavoriteType.HASHTAG, new RepositoryCallback<Favorite>() {
@Override
public void onSuccess(final Favorite result) {
@ -500,9 +498,9 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
hashtagModel.getName(),
null,
new Date()
), new RepositoryCallback<Favorite>() {
), new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Favorite result) {
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));

7
app/src/main/java/awais/instagrabber/fragments/LocationFragment.java

@ -62,7 +62,6 @@ import awais.instagrabber.models.LocationModel;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.StoryModel;
import awais.instagrabber.models.enums.FavoriteType;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.DownloadUtils;
@ -448,7 +447,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
locationDetailsBinding.locationUrl.setText(TextUtils.getSpannableUrl(url));
}
final FavoriteDataSource dataSource = FavoriteDataSource.getInstance(getContext());
final FavoriteRepository favoriteRepository = FavoriteRepository.getInstance(new AppExecutors(), dataSource);
final FavoriteRepository favoriteRepository = FavoriteRepository.getInstance(dataSource);
locationDetailsBinding.favChip.setVisibility(View.VISIBLE);
favoriteRepository.getFavorite(locationId, FavoriteType.LOCATION, new RepositoryCallback<Favorite>() {
@Override
@ -491,9 +490,9 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
locationModel.getName(),
locationModel.getSdProfilePic(),
new Date()
), new RepositoryCallback<Favorite>() {
), new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Favorite result) {
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));

10
app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java

@ -82,7 +82,6 @@ import awais.instagrabber.models.enums.FavoriteType;
import awais.instagrabber.models.enums.PostItemType;
import awais.instagrabber.repositories.responses.FriendshipRepoChangeRootResponse;
import awais.instagrabber.repositories.responses.FriendshipRepoRestrictRootResponse;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.DownloadUtils;
@ -299,9 +298,8 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
fragmentActivity = (MainActivity) requireActivity();
friendshipService = FriendshipService.getInstance();
storiesService = StoriesService.getInstance();
final AppExecutors appExecutors = new AppExecutors();
accountRepository = AccountRepository.getInstance(appExecutors, AccountDataSource.getInstance(getContext()));
favoriteRepository = FavoriteRepository.getInstance(appExecutors, FavoriteDataSource.getInstance(getContext()));
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext()));
favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext()));
setHasOptionsMenu(true);
}
@ -907,9 +905,9 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
profileModel.getSdProfilePic(),
new Date()
);
favoriteRepository.insertOrUpdateFavorite(model, new RepositoryCallback<Favorite>() {
favoriteRepository.insertOrUpdateFavorite(model, new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Favorite result) {
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);

3
app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java

@ -33,7 +33,6 @@ import awais.instagrabber.db.repositories.AccountRepository;
import awais.instagrabber.db.repositories.RepositoryCallback;
import awais.instagrabber.dialogs.AccountSwitcherDialogFragment;
import awais.instagrabber.repositories.responses.UserInfo;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.FlavorTown;
@ -49,7 +48,7 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
private final AccountRepository accountRepository;
public MorePreferencesFragment() {
accountRepository = AccountRepository.getInstance(new AppExecutors(), AccountDataSource.getInstance(getContext()));
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext()));
}
@Override

35
app/src/main/java/awais/instagrabber/utils/AppExecutors.java

@ -35,37 +35,48 @@ import java.util.concurrent.Executors;
*/
public class AppExecutors {
// private static final int THREAD_COUNT = 3;
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 networkIO;
private final Executor mainThread;
private final ListeningExecutorService tasksThread;
private AppExecutors(Executor diskIO,
// Executor networkIO,
Executor networkIO,
Executor mainThread,
ListeningExecutorService tasksThread) {
this.diskIO = diskIO;
// this.networkIO = networkIO;
this.networkIO = networkIO;
this.mainThread = mainThread;
this.tasksThread = tasksThread;
}
public AppExecutors() {
this(Executors.newSingleThreadExecutor(),
// Executors.newFixedThreadPool(THREAD_COUNT),
new MainThreadExecutor(),
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)));
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 Executor networkIO() {
return networkIO;
}
public ListeningExecutorService tasksThread() {

2
app/src/main/java/awais/instagrabber/utils/CookieUtils.java

@ -63,7 +63,7 @@ public final class CookieUtils {
if (cookieStore == null) return;
cookieStore.removeAll();
try {
AccountRepository.getInstance(new AppExecutors(), AccountDataSource.getInstance(context))
AccountRepository.getInstance(AccountDataSource.getInstance(context))
.deleteAllAccounts(callback);
} catch (Exception e) {
Log.e(TAG, "setupCookies", e);

140
app/src/main/java/awais/instagrabber/utils/DataBox.java

@ -1,45 +1,19 @@
package awais.instagrabber.utils;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import awais.instagrabber.db.entities.Favorite;
import awais.instagrabber.models.enums.FavoriteType;
public final class DataBox extends SQLiteOpenHelper {
private static final String TAG = "DataBox";
private static DataBox sInstance;
private final static int VERSION = 3;
public final static String TABLE_COOKIES = "cookies";
public final static String TABLE_FAVORITES = "favorites";
public final static String KEY_ID = "id";
public final static String KEY_USERNAME = Constants.EXTRAS_USERNAME;
public final static String KEY_COOKIE = "cookie";
public final static String KEY_UID = "uid";
public final static String KEY_FULL_NAME = "full_name";
public final static String KEY_PROFILE_PIC = "profile_pic";
public final static String FAV_COL_ID = "id";
public final static String FAV_COL_QUERY = "query_text";
public final static String FAV_COL_TYPE = "type";
public final static String FAV_COL_DISPLAY_NAME = "display_name";
public final static String FAV_COL_PIC_URL = "pic_url";
public final static String FAV_COL_DATE_ADDED = "date_added";
public static synchronized DataBox getInstance(final Context context) {
if (sInstance == null) sInstance = new DataBox(context.getApplicationContext());
@ -53,21 +27,6 @@ public final class DataBox extends SQLiteOpenHelper {
@Override
public void onCreate(@NonNull final SQLiteDatabase db) {
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!");
}
@ -77,107 +36,8 @@ public final class DataBox extends SQLiteOpenHelper {
// switch without break, so that all migrations from a previous version to new are run
switch (oldVersion) {
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:
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 " + 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 Favorite oldFavorite : oldFavorites) {
insertOrUpdateFavorite(db, oldFavorite);
}
}
Log.i(TAG, String.format("DB update from v%d to v%d completed!", oldVersion, newVersion));
}
public synchronized void insertOrUpdateFavorite(@NonNull final SQLiteDatabase db, @NonNull final Favorite 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.insert(TABLE_FAVORITES, null, values);
}
}
@NonNull
private List<Favorite> 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<Favorite> 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 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;
}
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;
}
}

11
app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java

@ -198,7 +198,7 @@ public final class ExportImportUtils {
: favsObject.optString("pic_url"),
new Date(favsObject.getLong("d")));
// Log.d(TAG, "importJson: favoriteModel: " + favoriteModel);
FavoriteRepository.getInstance(new AppExecutors(), FavoriteDataSource.getInstance(context))
FavoriteRepository.getInstance(FavoriteDataSource.getInstance(context))
.insertOrUpdateFavorite(favorite, null);
}
}
@ -225,7 +225,7 @@ public final class ExportImportUtils {
Log.e(TAG, "importAccounts: Error parsing json", e);
return;
}
AccountRepository.getInstance(new AppExecutors(), AccountDataSource.getInstance(context))
AccountRepository.getInstance(AccountDataSource.getInstance(context))
.insertOrUpdateAccounts(accounts, null);
}
@ -266,9 +266,8 @@ public final class ExportImportUtils {
private static void getExportString(@ExportImportFlags final int flags,
@NonNull final Context context,
final OnExportStringCreatedCallback callback) {
final AppExecutors appExecutors = new AppExecutors();
final Handler innerHandler = new Handler();
appExecutors.tasksThread().execute(() -> {
AppExecutors.getInstance().tasksThread().execute(() -> {
final CountDownLatch responseWaiter = new CountDownLatch(3);
try {
final JSONObject jsonObject = new JSONObject();
@ -341,7 +340,7 @@ public final class ExportImportUtils {
private static void getFavorites(final Context context, final OnFavoritesJsonLoadedCallback callback) {
final FavoriteDataSource dataSource = FavoriteDataSource.getInstance(context);
final FavoriteRepository favoriteRepository = FavoriteRepository.getInstance(new AppExecutors(), dataSource);
final FavoriteRepository favoriteRepository = FavoriteRepository.getInstance(dataSource);
try {
favoriteRepository.getAllFavorites(new RepositoryCallback<List<Favorite>>() {
@Override
@ -379,7 +378,7 @@ public final class ExportImportUtils {
}
private static void getCookies(final Context context, final OnAccountJsonLoadedCallback callback) {
final AccountRepository accountRepository = AccountRepository.getInstance(new AppExecutors(), AccountDataSource.getInstance(context));
final AccountRepository accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(context));
accountRepository.getAllAccounts(new RepositoryCallback<List<Account>>() {
@Override
public void onSuccess(final List<Account> accounts) {

Loading…
Cancel
Save