Ammar Githam
4 years ago
30 changed files with 1700 additions and 849 deletions
-
3app/src/main/AndroidManifest.xml
-
7app/src/main/java/awais/instagrabber/InstaGrabberApplication.java
-
3app/src/main/java/awais/instagrabber/activities/DirectDownload.java
-
18app/src/main/java/awais/instagrabber/adapters/AccountSwitcherAdapter.java
-
18app/src/main/java/awais/instagrabber/adapters/FavoritesAdapter.java
-
4app/src/main/java/awais/instagrabber/adapters/viewholder/FavoriteViewHolder.java
-
4app/src/main/java/awais/instagrabber/asyncs/NotificationsFetcher.java
-
3app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java
-
182app/src/main/java/awais/instagrabber/db/datasources/AccountDataSource.java
-
180app/src/main/java/awais/instagrabber/db/datasources/FavoriteDataSource.java
-
114app/src/main/java/awais/instagrabber/db/entities/Account.java
-
103app/src/main/java/awais/instagrabber/db/entities/Favorite.java
-
131app/src/main/java/awais/instagrabber/db/repositories/AccountRepository.java
-
92app/src/main/java/awais/instagrabber/db/repositories/FavoriteRepository.java
-
11app/src/main/java/awais/instagrabber/db/repositories/RepositoryCallback.java
-
55app/src/main/java/awais/instagrabber/dialogs/AccountSwitcherDialogFragment.java
-
5app/src/main/java/awais/instagrabber/dialogs/RestoreBackupDialogFragment.java
-
94app/src/main/java/awais/instagrabber/fragments/FavoritesFragment.java
-
77app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java
-
78app/src/main/java/awais/instagrabber/fragments/LocationFragment.java
-
6app/src/main/java/awais/instagrabber/fragments/NotificationsViewerFragment.java
-
99app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java
-
95app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java
-
87app/src/main/java/awais/instagrabber/utils/AppExecutors.java
-
25app/src/main/java/awais/instagrabber/utils/CookieUtils.java
-
502app/src/main/java/awais/instagrabber/utils/DataBox.java
-
175app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java
-
1app/src/main/java/awais/instagrabber/utils/Utils.java
-
6app/src/main/java/awais/instagrabber/viewmodels/FavoritesViewModel.java
-
9app/src/main/res/layout/activity_login.xml
@ -0,0 +1,182 @@ |
|||
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.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 AccountDataSource(@NonNull Context context) { |
|||
dataBox = DataBox.getInstance(context); |
|||
} |
|||
|
|||
public static synchronized AccountDataSource getInstance(@NonNull Context context) { |
|||
if (INSTANCE == null) { |
|||
INSTANCE = new AccountDataSource(context); |
|||
} |
|||
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; |
|||
} |
|||
|
|||
@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; |
|||
} |
|||
|
|||
// 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(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
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 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(); |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,180 @@ |
|||
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.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 FavoriteDataSource(@NonNull Context context) { |
|||
dataBox = DataBox.getInstance(context); |
|||
} |
|||
|
|||
public static synchronized FavoriteDataSource getInstance(@NonNull Context context) { |
|||
if (INSTANCE == null) { |
|||
INSTANCE = new FavoriteDataSource(context); |
|||
} |
|||
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; |
|||
} |
|||
|
|||
@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; |
|||
} |
|||
|
|||
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()); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
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(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,114 @@ |
|||
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 awais.instagrabber.utils.TextUtils; |
|||
|
|||
@Entity(tableName = "cookies") |
|||
public class Account { |
|||
|
|||
@PrimaryKey |
|||
@ColumnInfo(name = "id") |
|||
private final int id; |
|||
|
|||
@ColumnInfo(name = "uid") |
|||
private final String uid; |
|||
|
|||
@ColumnInfo(name = "username") |
|||
private final String username; |
|||
|
|||
@ColumnInfo(name = "cookie") |
|||
private final String cookie; |
|||
|
|||
@ColumnInfo(name = "full_name") |
|||
private final String fullName; |
|||
|
|||
@ColumnInfo(name = "profile_pic") |
|||
private final String profilePic; |
|||
|
|||
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 + |
|||
'}'; |
|||
} |
|||
} |
@ -0,0 +1,103 @@ |
|||
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 = "favorites") |
|||
public class Favorite { |
|||
|
|||
@PrimaryKey |
|||
@ColumnInfo(name = "id") |
|||
private final int id; |
|||
|
|||
@ColumnInfo(name = "query_text") |
|||
private final String query; |
|||
|
|||
@ColumnInfo(name = "type") |
|||
private final FavoriteType type; |
|||
|
|||
@ColumnInfo(name = "display_name") |
|||
private final String displayName; |
|||
|
|||
@ColumnInfo(name = "pic_url") |
|||
private final String picUrl; |
|||
|
|||
@ColumnInfo(name = "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 AppExecutors appExecutors, final AccountDataSource accountDataSource) { |
|||
if (instance == null) { |
|||
instance = new AccountRepository(appExecutors, 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,92 @@ |
|||
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 AppExecutors appExecutors, final FavoriteDataSource favoriteDataSource) { |
|||
if (instance == null) { |
|||
instance = new FavoriteRepository(appExecutors, 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<Favorite> callback) { |
|||
// request on the I/O thread |
|||
appExecutors.diskIO().execute(() -> { |
|||
final Favorite updated = favoriteDataSource.insertOrUpdateFavorite(favorite); |
|||
// notify on the main thread |
|||
appExecutors.mainThread().execute(() -> { |
|||
if (callback == null) return; |
|||
if (updated == null) { |
|||
callback.onDataNotAvailable(); |
|||
return; |
|||
} |
|||
callback.onSuccess(updated); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
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(); |
|||
} |
@ -0,0 +1,87 @@ |
|||
/* |
|||
* 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 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 AppExecutors() { |
|||
this(Executors.newSingleThreadExecutor(), |
|||
// Executors.newFixedThreadPool(THREAD_COUNT), |
|||
new MainThreadExecutor(), |
|||
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10))); |
|||
} |
|||
|
|||
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); |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue