Merge branch 'db_fixes' into 'master'
Various fixes related to database See merge request pixeldroid/PixelDroid!383
This commit is contained in:
commit
002b1548e1
@ -123,6 +123,7 @@ dependencies {
|
||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||
implementation "androidx.activity:activity-ktx:1.3.1"
|
||||
implementation 'androidx.fragment:fragment-ktx:1.3.6'
|
||||
implementation "androidx.work:work-runtime-ktx:2.5.0"
|
||||
|
||||
// Use the most recent version of CameraX
|
||||
def cameraX_version = '1.0.1'
|
||||
@ -187,7 +188,7 @@ dependencies {
|
||||
implementation "com.mikepenz:iconics-core:5.3.0"
|
||||
implementation 'com.mikepenz:materialdrawer-iconics:8.4.2'
|
||||
implementation "com.mikepenz:iconics-views:5.3.0"
|
||||
implementation 'com.mikepenz:google-material-typeface:3.0.1.4.original-kotlin@aar'
|
||||
implementation 'com.mikepenz:google-material-typeface:4.0.0.1-kotlin@aar'
|
||||
|
||||
|
||||
implementation 'com.karumi:dexter:6.2.3'
|
||||
|
@ -515,6 +515,47 @@
|
||||
license: The Apache Software License, Version 2.0
|
||||
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
url: http://developer.android.com/tools/extras/support-library.html
|
||||
- artifact: androidx.constraintlayout:constraintlayout-core:+
|
||||
name: constraintlayout-core
|
||||
copyrightHolder: Google Inc.
|
||||
license: The Apache Software License, Version 2.0
|
||||
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
url: http://tools.android.com
|
||||
- artifact: androidx.databinding:databinding-ktx:+
|
||||
name: databinding-ktx
|
||||
copyrightHolder: Google Inc.
|
||||
license: The Apache Software License, Version 2.0
|
||||
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
- artifact: androidx.lifecycle:lifecycle-extensions:+
|
||||
name: lifecycle-extensions
|
||||
copyrightHolder: Google Inc.
|
||||
license: The Apache Software License, Version 2.0
|
||||
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
url: https://developer.android.com/topic/libraries/architecture/index.html
|
||||
- artifact: androidx.lifecycle:lifecycle-process:+
|
||||
name: lifecycle-process
|
||||
copyrightHolder: Google Inc.
|
||||
license: The Apache Software License, Version 2.0
|
||||
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
url: https://developer.android.com/topic/libraries/architecture/index.html
|
||||
- artifact: androidx.lifecycle:lifecycle-service:+
|
||||
name: lifecycle-service
|
||||
copyrightHolder: Google Inc.
|
||||
license: The Apache Software License, Version 2.0
|
||||
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
url: https://developer.android.com/topic/libraries/architecture/index.html
|
||||
- artifact: androidx.work:work-runtime-ktx:+
|
||||
name: work-runtime-ktx
|
||||
copyrightHolder: Google Inc.
|
||||
license: The Apache Software License, Version 2.0
|
||||
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
url: https://developer.android.com/jetpack/androidx/releases/work#2.5.0
|
||||
- artifact: androidx.work:work-runtime:+
|
||||
name: work-runtime
|
||||
copyrightHolder: Google Inc.
|
||||
license: The Apache Software License, Version 2.0
|
||||
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
url: https://developer.android.com/jetpack/androidx/releases/work#2.5.0
|
||||
- artifact: androidx.paging:paging-common:+
|
||||
name: paging-common
|
||||
copyrightHolder: Google Inc.
|
||||
@ -668,12 +709,6 @@
|
||||
license: The Apache License, Version 2.0
|
||||
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
url: https://kotlinlang.org/
|
||||
- artifact: androidx.constraintlayout:constraintlayout-solver:+
|
||||
name: constraintlayout-solver
|
||||
copyrightHolder: Google Inc.
|
||||
license: The Apache Software License, Version 2.0
|
||||
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
url: http://tools.android.com
|
||||
- artifact: com.google.guava:listenablefuture:+
|
||||
name: listenablefuture
|
||||
copyrightHolder: Google Inc.
|
||||
|
@ -72,8 +72,8 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
//Check if we have logged in and gotten an access token
|
||||
if (user == null) {
|
||||
launchActivity(LoginActivity(), firstTime = true)
|
||||
finish()
|
||||
launchActivity(LoginActivity(), firstTime = true)
|
||||
} else {
|
||||
sendTraceDroidStackTracesIfExist("contact@pixeldroid.org", this)
|
||||
|
||||
@ -172,6 +172,7 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private fun logOut(){
|
||||
finish()
|
||||
db.runInTransaction {
|
||||
db.userDao().deleteActiveUsers()
|
||||
|
||||
@ -229,6 +230,8 @@ class MainActivity : BaseActivity() {
|
||||
apiHolder.setToCurrentUser()
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
|
||||
finish()
|
||||
startActivity(intent)
|
||||
|
||||
return false
|
||||
|
@ -36,7 +36,7 @@ class ThumbnailAdapter (private val context: Context,
|
||||
holder.thumbnail.setImageBitmap(tbItem.image)
|
||||
holder.thumbnail.setOnClickListener {
|
||||
listener.onFilterSelected(tbItem.filter)
|
||||
selectedIndex = position
|
||||
selectedIndex = holder.bindingAdapterPosition
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,8 @@ class PostActivity : BaseActivity() {
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
status = intent.getSerializableExtra(POST_TAG) as Status
|
||||
val viewComments: Boolean = (intent.getSerializableExtra(VIEW_COMMENTS_TAG) ?: false) as Boolean
|
||||
val postComment: Boolean = (intent.getSerializableExtra(POST_COMMENT_TAG) ?: false) as Boolean
|
||||
val viewComments: Boolean = intent.getBooleanExtra(VIEW_COMMENTS_TAG, false)
|
||||
val postComment: Boolean = intent.getBooleanExtra(POST_COMMENT_TAG, false)
|
||||
|
||||
val user = db.userDao().getActiveUser()
|
||||
|
||||
|
@ -87,7 +87,8 @@ class NotificationsFragment : CachedFeedFragment<Notification>() {
|
||||
val intent: Intent =
|
||||
when (type) {
|
||||
Notification.NotificationType.mention, Notification.NotificationType.favourite,
|
||||
Notification.NotificationType.poll, Notification.NotificationType.reblog -> {
|
||||
Notification.NotificationType.poll, Notification.NotificationType.reblog,
|
||||
Notification.NotificationType.comment -> {
|
||||
openPostFromNotification()
|
||||
}
|
||||
Notification.NotificationType.follow -> {
|
||||
@ -113,39 +114,38 @@ class NotificationsFragment : CachedFeedFragment<Notification>() {
|
||||
) {
|
||||
val context = textView.context
|
||||
val (format: String, drawable: Drawable?) = when (type) {
|
||||
Notification.NotificationType.follow -> {
|
||||
Notification.NotificationType.follow ->
|
||||
getStringAndDrawable(
|
||||
context,
|
||||
R.string.followed_notification,
|
||||
R.drawable.ic_follow
|
||||
)
|
||||
}
|
||||
Notification.NotificationType.mention -> {
|
||||
Notification.NotificationType.mention ->
|
||||
getStringAndDrawable(
|
||||
context,
|
||||
R.string.mention_notification,
|
||||
R.drawable.mention_at_24dp
|
||||
)
|
||||
}
|
||||
|
||||
Notification.NotificationType.reblog -> {
|
||||
Notification.NotificationType.comment ->
|
||||
getStringAndDrawable(
|
||||
context,
|
||||
R.string.comment_notification,
|
||||
R.drawable.ic_comment_empty
|
||||
)
|
||||
Notification.NotificationType.reblog ->
|
||||
getStringAndDrawable(
|
||||
context,
|
||||
R.string.shared_notification,
|
||||
R.drawable.ic_reblog_blue
|
||||
)
|
||||
}
|
||||
|
||||
Notification.NotificationType.favourite -> {
|
||||
Notification.NotificationType.favourite ->
|
||||
getStringAndDrawable(
|
||||
context,
|
||||
R.string.liked_notification,
|
||||
R.drawable.ic_like_full
|
||||
)
|
||||
}
|
||||
Notification.NotificationType.poll -> {
|
||||
Notification.NotificationType.poll ->
|
||||
getStringAndDrawable(context, R.string.poll_notification, R.drawable.poll)
|
||||
}
|
||||
}
|
||||
textView.text = format.format(username)
|
||||
textView.setCompoundDrawablesWithIntrinsicBounds(
|
||||
@ -249,7 +249,7 @@ class NotificationsFragment : CachedFeedFragment<Notification>() {
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val uiModel = getItem(position)
|
||||
uiModel.let {
|
||||
uiModel?.let {
|
||||
(holder as NotificationViewHolder).bind(
|
||||
it,
|
||||
apiHolder,
|
||||
|
@ -73,7 +73,7 @@ class NotificationsRemoteMediator @Inject constructor(
|
||||
db.withTransaction {
|
||||
// clear table in the database
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
db.notificationDao().clearFeedContent()
|
||||
db.notificationDao().clearFeedContent(user.user_id, user.instance_uri)
|
||||
}
|
||||
db.notificationDao().insertAll(apiResponse)
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ class HomeFeedRemoteMediator @Inject constructor(
|
||||
db.withTransaction {
|
||||
// clear table in the database
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
db.homePostDao().clearFeedContent()
|
||||
db.homePostDao().clearFeedContent(user.user_id, user.instance_uri)
|
||||
}
|
||||
db.homePostDao().insertAll(dbObjects)
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ class PublicFeedRemoteMediator @Inject constructor(
|
||||
db.withTransaction {
|
||||
// clear table in the database
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
db.publicPostDao().clearFeedContent()
|
||||
db.publicPostDao().clearFeedContent(user.user_id, user.instance_uri)
|
||||
}
|
||||
db.publicPostDao().insertAll(dbObjects)
|
||||
}
|
||||
|
@ -3,6 +3,11 @@ package org.pixeldroid.app.utils.api
|
||||
import org.pixeldroid.app.utils.api.objects.*
|
||||
import io.reactivex.Observable
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.OkHttpClient
|
||||
import org.pixeldroid.app.utils.db.AppDatabase
|
||||
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
||||
import org.pixeldroid.app.utils.di.PixelfedAPIHolder
|
||||
import org.pixeldroid.app.utils.di.TokenAuthenticator
|
||||
import retrofit2.Response
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
||||
@ -28,6 +33,30 @@ interface PixelfedAPI {
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
.build().create(PixelfedAPI::class.java)
|
||||
}
|
||||
|
||||
private val intermediate: Retrofit.Builder = Retrofit.Builder()
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
|
||||
|
||||
fun apiForUser(
|
||||
user: UserDatabaseEntity,
|
||||
db: AppDatabase,
|
||||
pixelfedAPIHolder: PixelfedAPIHolder
|
||||
): PixelfedAPI =
|
||||
intermediate
|
||||
.baseUrl(user.instance_uri)
|
||||
.client(
|
||||
OkHttpClient().newBuilder().authenticator(TokenAuthenticator(user, db, pixelfedAPIHolder))
|
||||
.addInterceptor {
|
||||
it.request().newBuilder().run {
|
||||
header("Accept", "application/json")
|
||||
header("Authorization", "Bearer ${user.accessToken}")
|
||||
it.proceed(build())
|
||||
}
|
||||
}.build()
|
||||
)
|
||||
.build().create(PixelfedAPI::class.java)
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,6 +38,6 @@ data class Notification(
|
||||
override var instance_uri: String,
|
||||
): FeedContent, FeedContentDatabase {
|
||||
enum class NotificationType: Serializable {
|
||||
follow, mention, reblog, favourite, poll
|
||||
follow, mention, reblog, favourite, poll, comment
|
||||
}
|
||||
}
|
@ -3,6 +3,8 @@ package org.pixeldroid.app.utils.db
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import org.pixeldroid.app.utils.db.dao.*
|
||||
import org.pixeldroid.app.utils.db.dao.feedContent.NotificationDao
|
||||
import org.pixeldroid.app.utils.db.dao.feedContent.posts.HomePostDao
|
||||
@ -29,4 +31,12 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun homePostDao(): HomePostDao
|
||||
abstract fun publicPostDao(): PublicPostDao
|
||||
abstract fun notificationDao(): NotificationDao
|
||||
}
|
||||
|
||||
val MIGRATION_3_4 = object : Migration(3, 4) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DELETE FROM homePosts")
|
||||
database.execSQL("DELETE FROM publicPosts")
|
||||
database.execSQL("DELETE FROM notifications")
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ import java.lang.IllegalArgumentException
|
||||
|
||||
fun addUser(db: AppDatabase, account: Account, instance_uri: String, activeUser: Boolean = true,
|
||||
accessToken: String, refreshToken: String?, clientId: String, clientSecret: String) {
|
||||
db.userDao().insertUser(
|
||||
db.userDao().insertOrUpdate(
|
||||
UserDatabaseEntity(
|
||||
user_id = account.id!!,
|
||||
instance_uri = normalizeDomain(instance_uri),
|
||||
|
@ -5,8 +5,21 @@ import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
||||
|
||||
@Dao
|
||||
interface UserDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertUser(user: UserDatabaseEntity)
|
||||
/**
|
||||
* Insert a user, if it already exists return -1
|
||||
*/
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
fun insertUser(user: UserDatabaseEntity): Long
|
||||
|
||||
@Transaction
|
||||
fun insertOrUpdate(user: UserDatabaseEntity) {
|
||||
if (insertUser(user) == -1L) {
|
||||
updateUser(user)
|
||||
}
|
||||
}
|
||||
|
||||
@Update
|
||||
fun updateUser(user: UserDatabaseEntity)
|
||||
|
||||
@Query("UPDATE users SET accessToken = :accessToken, refreshToken = :refreshToken WHERE user_id = :id and instance_uri = :instance_uri")
|
||||
fun updateAccessToken(accessToken: String, refreshToken: String, id: String, instance_uri: String)
|
||||
|
@ -9,7 +9,7 @@ interface FeedContentDao<T: FeedContentDatabase>{
|
||||
|
||||
fun feedContent(userId: String, instanceUri: String): PagingSource<Int, T>
|
||||
|
||||
suspend fun clearFeedContent()
|
||||
suspend fun clearFeedContent(userId: String, instanceUri: String)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertAll(feedContent: List<T>)
|
||||
|
@ -8,8 +8,8 @@ import org.pixeldroid.app.utils.api.objects.Notification
|
||||
@Dao
|
||||
interface NotificationDao: FeedContentDao<Notification> {
|
||||
|
||||
@Query("DELETE FROM notifications")
|
||||
override suspend fun clearFeedContent()
|
||||
@Query("DELETE FROM notifications WHERE user_id=:userId AND instance_uri=:instanceUri")
|
||||
override suspend fun clearFeedContent(userId: String, instanceUri: String)
|
||||
|
||||
@Query("""SELECT * FROM notifications WHERE user_id=:userId AND instance_uri=:instanceUri
|
||||
ORDER BY CAST(created_at AS FLOAT) DESC""")
|
||||
|
@ -12,8 +12,8 @@ interface HomePostDao: FeedContentDao<HomeStatusDatabaseEntity> {
|
||||
ORDER BY CAST(created_at AS FLOAT)""")
|
||||
override fun feedContent(userId: String, instanceUri: String): PagingSource<Int, HomeStatusDatabaseEntity>
|
||||
|
||||
@Query("DELETE FROM homePosts")
|
||||
override suspend fun clearFeedContent()
|
||||
@Query("DELETE FROM homePosts WHERE user_id=:userId AND instance_uri=:instanceUri")
|
||||
override suspend fun clearFeedContent(userId: String, instanceUri: String)
|
||||
|
||||
@Query("DELETE FROM homePosts WHERE user_id=:userId AND instance_uri=:instanceUri AND id=:id")
|
||||
override suspend fun delete(id: String, userId: String, instanceUri: String)
|
||||
|
@ -12,8 +12,8 @@ interface PublicPostDao: FeedContentDao<PublicFeedStatusDatabaseEntity> {
|
||||
ORDER BY CAST(created_at AS FLOAT)""")
|
||||
override fun feedContent(userId: String, instanceUri: String): PagingSource<Int, PublicFeedStatusDatabaseEntity>
|
||||
|
||||
@Query("DELETE FROM publicPosts")
|
||||
override suspend fun clearFeedContent()
|
||||
@Query("DELETE FROM publicPosts WHERE user_id=:userId AND instance_uri=:instanceUri")
|
||||
override suspend fun clearFeedContent(userId: String, instanceUri: String)
|
||||
|
||||
@Query("DELETE FROM publicPosts WHERE user_id=:userId AND instance_uri=:instanceUri AND id=:id")
|
||||
override suspend fun delete(id: String, userId: String, instanceUri: String)
|
||||
|
@ -8,9 +8,7 @@ import dagger.Module
|
||||
import dagger.Provides
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.*
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import org.pixeldroid.app.utils.api.PixelfedAPI.Companion.apiForUser
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@ -78,9 +76,6 @@ class TokenAuthenticator(val user: UserDatabaseEntity, val db: AppDatabase, val
|
||||
}
|
||||
|
||||
class PixelfedAPIHolder(private val db: AppDatabase){
|
||||
private val intermediate: Retrofit.Builder = Retrofit.Builder()
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
|
||||
var api: PixelfedAPI? =
|
||||
db.userDao().getActiveUser()?.let {
|
||||
@ -90,21 +85,8 @@ class PixelfedAPIHolder(private val db: AppDatabase){
|
||||
fun setToCurrentUser(
|
||||
user: UserDatabaseEntity = db.userDao().getActiveUser()!!
|
||||
): PixelfedAPI {
|
||||
val newAPI = intermediate
|
||||
.baseUrl(user.instance_uri)
|
||||
.client(
|
||||
OkHttpClient().newBuilder().authenticator(TokenAuthenticator(user, db, this))
|
||||
.addInterceptor {
|
||||
it.request().newBuilder().run {
|
||||
header("Accept", "application/json")
|
||||
header("Authorization", "Bearer ${user.accessToken}")
|
||||
it.proceed(build())
|
||||
}
|
||||
}.build()
|
||||
)
|
||||
.build().create(PixelfedAPI::class.java)
|
||||
val newAPI = apiForUser(user, db, this)
|
||||
api = newAPI
|
||||
return newAPI
|
||||
}
|
||||
|
||||
}
|
@ -5,6 +5,7 @@ import androidx.room.Room
|
||||
import org.pixeldroid.app.utils.db.AppDatabase
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import org.pixeldroid.app.utils.db.MIGRATION_3_4
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@ -16,6 +17,6 @@ class DatabaseModule(private val context: Context) {
|
||||
return Room.databaseBuilder(
|
||||
context,
|
||||
AppDatabase::class.java, "pixeldroid"
|
||||
).allowMainThreadQueries().build()
|
||||
).addMigrations(MIGRATION_3_4).allowMainThreadQueries().build()
|
||||
}
|
||||
}
|
@ -50,6 +50,12 @@
|
||||
<!-- Notifications: end of poll notification -->
|
||||
<string name="poll_notification">"%1$s's poll has ended"</string>
|
||||
|
||||
<!-- Notifications: comment notification -->
|
||||
<string name="comment_notification">%1$s commented on your post</string>
|
||||
|
||||
<!-- Notifications: other notification -->
|
||||
<string name="other_notification">"Notification from %1$s"</string>
|
||||
|
||||
<!-- Login page -->
|
||||
<string name="whats_an_instance">"What's an instance?"</string>
|
||||
<string name="whats_an_instance_explanation">"You might be confused by the text field asking for the domain of your 'instance'.
|
||||
|
Loading…
x
Reference in New Issue
Block a user