mirror of
https://gitlab.shinice.net/pixeldroid/PixelDroid
synced 2025-01-30 23:34:48 +01:00
Dependency injection
Configure dependency injection for API and the database. Uses Dagger (dagger.dev) The API is held in a holder, so that it can be invalidated or recreated as needed. Big refactor of the feeds, this introduces a bit more duplication of code (some very similar methods that differ only in the types or minor details), but now the inheritance makes more sense and there is less "forcing" to make the inheritance work (for example: no more casting Int to String just to have the right type for the key) It should be easier to work with the feeds in the future, maybe we'll find better abstractions later on.
This commit is contained in:
parent
15d80da692
commit
21925e7af4
@ -6,7 +6,7 @@ apply plugin: 'jacoco'
|
||||
android {
|
||||
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.3"
|
||||
buildToolsVersion '30.0.1'
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
@ -56,12 +56,12 @@ dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.3.0'
|
||||
implementation 'androidx.core:core-ktx:1.3.1'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.2.2'
|
||||
implementation 'androidx.navigation:navigation-ui:2.2.2'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.7.2'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.3.0'
|
||||
implementation 'androidx.navigation:navigation-ui:2.3.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.8.0'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
|
||||
@ -78,9 +78,9 @@ dependencies {
|
||||
testImplementation "androidx.room:room-testing:$room_version"
|
||||
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.2.2'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
|
||||
|
||||
implementation 'info.androidhive:imagefilters:1.0.7'
|
||||
implementation 'com.github.yalantis:ucrop:2.2.5-native'
|
||||
@ -97,11 +97,11 @@ dependencies {
|
||||
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
testImplementation "com.github.tomakehurst:wiremock-jre8:2.26.3"
|
||||
testImplementation 'com.github.tomakehurst:wiremock-jre8:2.27.1'
|
||||
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
|
||||
testImplementation 'junit:junit:4.13'
|
||||
|
||||
androidTestImplementation('com.squareup.okhttp3:mockwebserver:4.7.2')
|
||||
androidTestImplementation('com.squareup.okhttp3:mockwebserver:4.8.0')
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test:rules:1.2.0'
|
||||
@ -126,24 +126,30 @@ dependencies {
|
||||
implementation "com.mikepenz:iconics-views:5.0.2"
|
||||
implementation 'com.mikepenz:google-material-typeface:3.0.1.4.original-kotlin@aar'
|
||||
|
||||
//Dagger (dependency injection)
|
||||
implementation 'com.google.dagger:dagger-android:2.28.3'
|
||||
implementation 'com.google.dagger:dagger-android-support:2.28.3'
|
||||
// if you use the support libraries
|
||||
kapt 'com.google.dagger:dagger-android-processor:2.28.3'
|
||||
kapt 'com.google.dagger:dagger-compiler:2.28.3'
|
||||
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test:rules:1.2.0'
|
||||
|
||||
def fragment_version = '1.2.4'
|
||||
def fragment_version = '1.2.5'
|
||||
debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
|
||||
|
||||
// Use the most recent version of CameraX
|
||||
def camerax_version = '1.0.0-beta04'
|
||||
def camerax_version = '1.0.0-beta07'
|
||||
implementation "androidx.camera:camera-core:${camerax_version}"
|
||||
implementation "androidx.camera:camera-camera2:${camerax_version}"
|
||||
// CameraX Lifecycle library
|
||||
implementation "androidx.camera:camera-lifecycle:$camerax_version"
|
||||
|
||||
// CameraX View class
|
||||
implementation 'androidx.camera:camera-view:1.0.0-alpha11'
|
||||
implementation 'androidx.camera:camera-view:1.0.0-alpha14'
|
||||
|
||||
implementation 'com.karumi:dexter:6.1.2'
|
||||
implementation 'com.karumi:dexter:6.2.1'
|
||||
|
||||
|
||||
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
|
||||
|
@ -16,6 +16,7 @@ import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.InstanceDatabaseEntity
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.testUtility.MockServer
|
||||
import com.h.pixeldroid.testUtility.initDB
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
@ -40,7 +41,7 @@ class DrawerMenuTest {
|
||||
val baseUrl = mockServer.getUrl()
|
||||
|
||||
context = ApplicationProvider.getApplicationContext()
|
||||
db = DBUtils.initDB(context)
|
||||
db = initDB(context)
|
||||
db.clearAllTables()
|
||||
db.instanceDao().insertInstance(
|
||||
InstanceDatabaseEntity(
|
||||
|
@ -6,7 +6,6 @@ import android.widget.TextView
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions.swipeDown
|
||||
import androidx.test.espresso.action.ViewActions.swipeUp
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition
|
||||
@ -17,7 +16,7 @@ import com.google.android.material.tabs.TabLayout
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.InstanceDatabaseEntity
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.fragments.feeds.PostViewHolder
|
||||
import com.h.pixeldroid.fragments.feeds.postFeeds.PostViewHolder
|
||||
import com.h.pixeldroid.testUtility.CustomMatchers.Companion.clickChildViewWithId
|
||||
import com.h.pixeldroid.testUtility.CustomMatchers.Companion.first
|
||||
import com.h.pixeldroid.testUtility.CustomMatchers.Companion.getText
|
||||
@ -25,6 +24,7 @@ import com.h.pixeldroid.testUtility.CustomMatchers.Companion.second
|
||||
import com.h.pixeldroid.testUtility.CustomMatchers.Companion.slowSwipeUp
|
||||
import com.h.pixeldroid.testUtility.CustomMatchers.Companion.typeTextInViewWithId
|
||||
import com.h.pixeldroid.testUtility.MockServer
|
||||
import com.h.pixeldroid.testUtility.initDB
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
@ -49,7 +49,7 @@ class HomeFeedTest {
|
||||
mockServer.start()
|
||||
val baseUrl = mockServer.getUrl()
|
||||
context = ApplicationProvider.getApplicationContext()
|
||||
db = DBUtils.initDB(context)
|
||||
db = initDB(context)
|
||||
db.clearAllTables()
|
||||
db.instanceDao().insertInstance(
|
||||
InstanceDatabaseEntity(
|
||||
|
@ -26,10 +26,11 @@ import androidx.test.rule.ActivityTestRule
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.InstanceDatabaseEntity
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.fragments.feeds.PostViewHolder
|
||||
import com.h.pixeldroid.fragments.feeds.postFeeds.PostViewHolder
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.objects.Account.Companion.ACCOUNT_TAG
|
||||
import com.h.pixeldroid.testUtility.MockServer
|
||||
import com.h.pixeldroid.testUtility.initDB
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import org.hamcrest.CoreMatchers
|
||||
import org.hamcrest.Matcher
|
||||
@ -64,7 +65,7 @@ class IntentTest {
|
||||
val baseUrl = mockServer.getUrl()
|
||||
|
||||
context = ApplicationProvider.getApplicationContext()
|
||||
db = DBUtils.initDB(context)
|
||||
db = initDB(context)
|
||||
db.clearAllTables()
|
||||
db.instanceDao().insertInstance(
|
||||
InstanceDatabaseEntity(
|
||||
|
@ -13,7 +13,7 @@ import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import androidx.test.uiautomator.UiSelector
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import com.h.pixeldroid.testUtility.initDB
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
@ -43,7 +43,7 @@ class LoginActivityOfflineTest {
|
||||
fun before() {
|
||||
switchAirplaneMode()
|
||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
db = DBUtils.initDB(context)
|
||||
db = initDB(context)
|
||||
db.clearAllTables()
|
||||
ActivityScenario.launch(LoginActivity::class.java)
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.InstanceDatabaseEntity
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.testUtility.MockServer
|
||||
import com.h.pixeldroid.testUtility.initDB
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
@ -45,7 +46,7 @@ class LoginActivityOnlineTest {
|
||||
context = ApplicationProvider.getApplicationContext()
|
||||
pref = context.getSharedPreferences("com.h.pixeldroid.pref", Context.MODE_PRIVATE)
|
||||
pref.edit().clear().apply()
|
||||
db = DBUtils.initDB(context)
|
||||
db = initDB(context)
|
||||
db.clearAllTables()
|
||||
db.close()
|
||||
}
|
||||
@ -97,7 +98,7 @@ class LoginActivityOnlineTest {
|
||||
@Test
|
||||
fun correctIntentReturnLoadsMainActivity() {
|
||||
context = ApplicationProvider.getApplicationContext()
|
||||
db = DBUtils.initDB(context)
|
||||
db = initDB(context)
|
||||
db.clearAllTables()
|
||||
|
||||
db.instanceDao().insertInstance(
|
||||
|
@ -16,10 +16,11 @@ import com.google.android.material.tabs.TabLayout
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.InstanceDatabaseEntity
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.fragments.feeds.PostViewHolder
|
||||
import com.h.pixeldroid.fragments.feeds.postFeeds.PostViewHolder
|
||||
import com.h.pixeldroid.testUtility.CustomMatchers.Companion.clickChildViewWithId
|
||||
import com.h.pixeldroid.testUtility.CustomMatchers.Companion.first
|
||||
import com.h.pixeldroid.testUtility.MockServer
|
||||
import com.h.pixeldroid.testUtility.initDB
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.censorColorMatrix
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.uncensorColorMatrix
|
||||
@ -46,7 +47,7 @@ class MockedServerTest {
|
||||
mockServer.start()
|
||||
val baseUrl = mockServer.getUrl()
|
||||
context = ApplicationProvider.getApplicationContext()
|
||||
db = DBUtils.initDB(context)
|
||||
db = initDB(context)
|
||||
db.clearAllTables()
|
||||
db.instanceDao().insertInstance(
|
||||
InstanceDatabaseEntity(
|
||||
|
@ -24,6 +24,7 @@ import com.h.pixeldroid.db.InstanceDatabaseEntity
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.testUtility.CustomMatchers
|
||||
import com.h.pixeldroid.testUtility.MockServer
|
||||
import com.h.pixeldroid.testUtility.initDB
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import kotlinx.android.synthetic.main.activity_post_creation.*
|
||||
import org.hamcrest.Matchers.not
|
||||
@ -60,7 +61,7 @@ class PostCreationActivityTest {
|
||||
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
mockServer.start()
|
||||
val baseUrl = mockServer.getUrl()
|
||||
db = DBUtils.initDB(context)
|
||||
db = initDB(context)
|
||||
db.clearAllTables()
|
||||
db.instanceDao().insertInstance(
|
||||
InstanceDatabaseEntity(
|
||||
|
@ -19,6 +19,7 @@ import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.InstanceDatabaseEntity
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.testUtility.MockServer
|
||||
import com.h.pixeldroid.testUtility.initDB
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import org.hamcrest.Matcher
|
||||
@ -73,7 +74,7 @@ class PostFragmentUITests {
|
||||
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
mockServer.start()
|
||||
val baseUrl = mockServer.getUrl()
|
||||
db = DBUtils.initDB(context)
|
||||
db = initDB(context)
|
||||
db.clearAllTables()
|
||||
db.instanceDao().insertInstance(
|
||||
InstanceDatabaseEntity(
|
||||
|
@ -27,6 +27,7 @@ import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.objects.Tag
|
||||
|
||||
import com.h.pixeldroid.testUtility.MockServer
|
||||
import com.h.pixeldroid.testUtility.initDB
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import org.hamcrest.Matcher
|
||||
import org.junit.*
|
||||
@ -49,7 +50,7 @@ class PostTest {
|
||||
val mockServer = MockServer()
|
||||
mockServer.start()
|
||||
val baseUrl = mockServer.getUrl()
|
||||
db = DBUtils.initDB(context)
|
||||
db = initDB(context)
|
||||
db.clearAllTables()
|
||||
db.instanceDao().insertInstance(
|
||||
InstanceDatabaseEntity(
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.h.pixeldroid.testUtility
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Room
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
|
||||
fun initDB(context: Context): AppDatabase {
|
||||
return Room.databaseBuilder(
|
||||
context,
|
||||
AppDatabase::class.java, "pixeldroid"
|
||||
).allowMainThreadQueries().build()
|
||||
}
|
@ -16,13 +16,14 @@
|
||||
|
||||
<application
|
||||
android:name=".Pixeldroid"
|
||||
android:allowBackup="true"
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
android:theme="@style/AppTheme"
|
||||
tools:replace="android:allowBackup">
|
||||
|
||||
<activity
|
||||
android:name=".PhotoEditActivity"
|
||||
|
@ -4,6 +4,8 @@ import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.di.PixelfedAPIHolder
|
||||
import com.h.pixeldroid.fragments.feeds.AccountListFragment
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.objects.Account.Companion.ACCOUNT_ID_TAG
|
||||
@ -12,28 +14,32 @@ import com.h.pixeldroid.utils.DBUtils
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
class FollowsActivity : AppCompatActivity() {
|
||||
private var followsFragment = AccountListFragment()
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
@Inject
|
||||
lateinit var apiHolder: PixelfedAPIHolder
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_followers)
|
||||
(this.application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
|
||||
// Get account id
|
||||
val id = intent.getSerializableExtra(ACCOUNT_ID_TAG) as String?
|
||||
val following = intent.getSerializableExtra(FOLLOWING_TAG) as Boolean
|
||||
|
||||
if(id == null) {
|
||||
val db = DBUtils.initDB(applicationContext)
|
||||
|
||||
val user = db.userDao().getActiveUser()
|
||||
|
||||
val domain = user?.instance_uri.orEmpty()
|
||||
val accessToken = user?.accessToken.orEmpty()
|
||||
db.close()
|
||||
|
||||
val pixelfedAPI = PixelfedAPI.create(domain)
|
||||
val pixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
|
||||
pixelfedAPI.verifyCredentials("Bearer $accessToken").enqueue(object :
|
||||
Callback<Account> {
|
||||
|
@ -4,7 +4,6 @@ import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
@ -13,6 +12,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.di.PixelfedAPIHolder
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.objects.Application
|
||||
import com.h.pixeldroid.objects.Instance
|
||||
@ -26,6 +26,7 @@ import okhttp3.HttpUrl
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class LoginActivity : AppCompatActivity() {
|
||||
@ -38,7 +39,12 @@ class LoginActivity : AppCompatActivity() {
|
||||
private lateinit var oauthScheme: String
|
||||
private lateinit var appName: String
|
||||
private lateinit var preferences: SharedPreferences
|
||||
private lateinit var db: AppDatabase
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
|
||||
@Inject
|
||||
lateinit var apiHolder: PixelfedAPIHolder
|
||||
|
||||
private lateinit var pixelfedAPI: PixelfedAPI
|
||||
private var inputVisibility: Int = View.GONE
|
||||
|
||||
@ -46,11 +52,11 @@ class LoginActivity : AppCompatActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_login)
|
||||
|
||||
(application as Pixeldroid).getAppComponent().inject(this)
|
||||
loadingAnimation(true)
|
||||
appName = getString(R.string.app_name)
|
||||
oauthScheme = getString(R.string.auth_scheme)
|
||||
preferences = getSharedPreferences("$PACKAGE_ID.pref", Context.MODE_PRIVATE)
|
||||
db = DBUtils.initDB(applicationContext)
|
||||
|
||||
if (Utils.hasInternet(applicationContext)) {
|
||||
connect_instance_button.setOnClickListener {
|
||||
@ -61,8 +67,8 @@ class LoginActivity : AppCompatActivity() {
|
||||
} else {
|
||||
login_activity_connection_required.visibility = View.VISIBLE
|
||||
login_activity_connection_required_button.setOnClickListener {
|
||||
finish();
|
||||
startActivity(intent);
|
||||
finish()
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
loadingAnimation(false)
|
||||
@ -113,7 +119,7 @@ class LoginActivity : AppCompatActivity() {
|
||||
hideKeyboard()
|
||||
loadingAnimation(true)
|
||||
|
||||
PixelfedAPI.create(normalizedDomain).registerApplication(
|
||||
apiHolder.setDomain(normalizedDomain).registerApplication(
|
||||
appName,"$oauthScheme://$PACKAGE_ID", SCOPE
|
||||
).enqueue(object : Callback<Application> {
|
||||
override fun onResponse(call: Call<Application>, response: Response<Application>) {
|
||||
@ -185,7 +191,7 @@ class LoginActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
pixelfedAPI = PixelfedAPI.create(domain)
|
||||
pixelfedAPI = apiHolder.setDomain(domain)
|
||||
pixelfedAPI.obtainToken(
|
||||
clientId, clientSecret, "$oauthScheme://$PACKAGE_ID", SCOPE, code,
|
||||
"authorization_code"
|
||||
@ -242,7 +248,7 @@ class LoginActivity : AppCompatActivity() {
|
||||
.enqueue(object : Callback<Account> {
|
||||
override fun onResponse(call: Call<Account>, response: Response<Account>) {
|
||||
if (response.body() != null && response.isSuccessful) {
|
||||
db.userDao().deActivateActiveUser()
|
||||
db.userDao().deActivateActiveUsers()
|
||||
val user = response.body() as Account
|
||||
DBUtils.addUser(
|
||||
db,
|
||||
@ -251,7 +257,7 @@ class LoginActivity : AppCompatActivity() {
|
||||
activeUser = true,
|
||||
accessToken = accessToken
|
||||
)
|
||||
db.close()
|
||||
apiHolder.setDomainToCurrentUser(db)
|
||||
val intent = Intent(this@LoginActivity, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
|
@ -14,15 +14,15 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.di.PixelfedAPIHolder
|
||||
import com.h.pixeldroid.fragments.CameraFragment
|
||||
import com.h.pixeldroid.fragments.SearchDiscoverFragment
|
||||
import com.h.pixeldroid.fragments.feeds.NotificationsFragment
|
||||
import com.h.pixeldroid.fragments.feeds.OfflineFeedFragment
|
||||
import com.h.pixeldroid.fragments.feeds.PostsFeedFragment
|
||||
import com.h.pixeldroid.fragments.feeds.PublicTimelineFragment
|
||||
import com.h.pixeldroid.fragments.feeds.postFeeds.HomeTimelineFragment
|
||||
import com.h.pixeldroid.fragments.feeds.postFeeds.PublicTimelineFragment
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import com.h.pixeldroid.utils.Utils.Companion.hasInternet
|
||||
@ -39,11 +39,16 @@ import kotlinx.android.synthetic.main.activity_main.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private val searchDiscoverFragment: SearchDiscoverFragment = SearchDiscoverFragment()
|
||||
private lateinit var db: AppDatabase
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
@Inject
|
||||
lateinit var apiHolder: PixelfedAPIHolder
|
||||
|
||||
private lateinit var header: AccountHeaderView
|
||||
private var user: UserDatabaseEntity? = null
|
||||
|
||||
@ -56,7 +61,7 @@ class MainActivity : AppCompatActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
db = DBUtils.initDB(applicationContext)
|
||||
(this.application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
//get the currently active user
|
||||
user = db.userDao().getActiveUser()
|
||||
@ -67,7 +72,7 @@ class MainActivity : AppCompatActivity() {
|
||||
} else {
|
||||
setupDrawer()
|
||||
val tabs = arrayOf(
|
||||
if (hasInternet(applicationContext)) PostsFeedFragment()
|
||||
if (hasInternet(applicationContext)) HomeTimelineFragment()
|
||||
else OfflineFeedFragment(),
|
||||
searchDiscoverFragment,
|
||||
CameraFragment(),
|
||||
@ -163,14 +168,17 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
|
||||
}
|
||||
private fun getUpdatedAccount(){
|
||||
private fun getUpdatedAccount() {
|
||||
if (hasInternet(applicationContext)) {
|
||||
val domain = user?.instance_uri.orEmpty()
|
||||
val accessToken = user?.accessToken.orEmpty()
|
||||
val pixelfedAPI = PixelfedAPI.create(domain)
|
||||
pixelfedAPI.verifyCredentials("Bearer $accessToken")
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
api.verifyCredentials("Bearer $accessToken")
|
||||
.enqueue(object : Callback<Account> {
|
||||
override fun onResponse(call: Call<Account>, response: Response<Account>) {
|
||||
override fun onResponse(
|
||||
call: Call<Account>,
|
||||
response: Response<Account>
|
||||
) {
|
||||
if (response.body() != null && response.isSuccessful) {
|
||||
val account = response.body() as Account
|
||||
DBUtils.addUser(db, account, domain, accessToken = accessToken)
|
||||
@ -197,9 +205,9 @@ class MainActivity : AppCompatActivity() {
|
||||
return false
|
||||
}
|
||||
|
||||
db.userDao().deActivateActiveUser()
|
||||
db.userDao().deActivateActiveUsers()
|
||||
db.userDao().activateUser(profile.identifier.toString())
|
||||
|
||||
apiHolder.setDomainToCurrentUser(db)
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
@ -271,9 +279,9 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
Launches the given activity and put it as the current one
|
||||
Setting argument firstTime to true means the task history will be reset (as if the app were launched anew into
|
||||
this activity)
|
||||
* Launches the given activity and put it as the current one
|
||||
* @param firstTime to true means the task history will be reset (as if the app were
|
||||
* launched anew into this activity)
|
||||
*/
|
||||
private fun launchActivity(activity: AppCompatActivity, firstTime: Boolean = false) {
|
||||
val intent = Intent(this, activity::class.java)
|
||||
@ -285,7 +293,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
Closes the drawer if it is open, when we press the back button
|
||||
* Closes the drawer if it is open, when we press the back button
|
||||
*/
|
||||
override fun onBackPressed() {
|
||||
if(drawer_layout.isDrawerOpen(GravityCompat.START)){
|
||||
|
@ -2,13 +2,29 @@ package com.h.pixeldroid
|
||||
|
||||
import android.app.Application
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.h.pixeldroid.di.*
|
||||
import com.h.pixeldroid.utils.ThemeUtils
|
||||
|
||||
|
||||
class Pixeldroid: Application() {
|
||||
|
||||
private lateinit var mApplicationComponent: ApplicationComponent
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
val sharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
ThemeUtils.setThemeFromPreferences(sharedPreferences, resources)
|
||||
mApplicationComponent = DaggerApplicationComponent
|
||||
.builder()
|
||||
.applicationModule(ApplicationModule(this))
|
||||
.databaseModule(DatabaseModule(applicationContext))
|
||||
.aPIModule(APIModule())
|
||||
.build()
|
||||
mApplicationComponent.inject(this);
|
||||
}
|
||||
|
||||
fun getAppComponent(): ApplicationComponent {
|
||||
return mApplicationComponent
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@ import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.di.PixelfedAPIHolder
|
||||
import com.h.pixeldroid.fragments.PostFragment
|
||||
import com.h.pixeldroid.objects.DiscoverPost
|
||||
import com.h.pixeldroid.objects.Status
|
||||
@ -16,25 +18,32 @@ import kotlinx.android.synthetic.main.activity_post.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
class PostActivity : AppCompatActivity() {
|
||||
private lateinit var postFragment : PostFragment
|
||||
lateinit var domain : String
|
||||
private lateinit var accessToken : String
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
@Inject
|
||||
lateinit var apiHolder: PixelfedAPIHolder
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_post)
|
||||
|
||||
(this.application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
|
||||
val status = intent.getSerializableExtra(POST_TAG) as Status?
|
||||
val discoverPost: DiscoverPost? = intent.getSerializableExtra(DISCOVER_TAG) as DiscoverPost?
|
||||
val db = DBUtils.initDB(applicationContext)
|
||||
|
||||
val user = db.userDao().getActiveUser()
|
||||
|
||||
domain = user?.instance_uri.orEmpty()
|
||||
accessToken = user?.accessToken.orEmpty()
|
||||
db.close()
|
||||
|
||||
postFragment = PostFragment()
|
||||
val arguments = Bundle()
|
||||
@ -52,7 +61,7 @@ class PostActivity : AppCompatActivity() {
|
||||
arguments: Bundle,
|
||||
discoverPost: DiscoverPost
|
||||
) {
|
||||
val api = PixelfedAPI.create(domain)
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
val id = discoverPost.url?.substringAfterLast('/') ?: ""
|
||||
api.getStatus("Bearer $accessToken", id).enqueue(object : Callback<Status> {
|
||||
|
||||
|
@ -19,7 +19,9 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.di.PixelfedAPIHolder
|
||||
import com.h.pixeldroid.interfaces.PostCreationListener
|
||||
import com.h.pixeldroid.objects.Attachment
|
||||
import com.h.pixeldroid.objects.Instance
|
||||
@ -35,6 +37,7 @@ import okhttp3.MultipartBody
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
||||
|
||||
@ -58,22 +61,28 @@ class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
||||
private var maxLength: Int = Instance.DEFAULT_MAX_TOOT_CHARS
|
||||
|
||||
private var description: String = ""
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
|
||||
@Inject
|
||||
lateinit var apiHolder: PixelfedAPIHolder
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_post_creation)
|
||||
|
||||
(this.application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
// load images
|
||||
posts = intent.getStringArrayListExtra("pictures_uri")!!
|
||||
|
||||
progressList = posts.map { 0 } as ArrayList<Int>
|
||||
muListOfIds = posts.map { "" }.toMutableList()
|
||||
|
||||
val db = DBUtils.initDB(applicationContext)
|
||||
user = db.userDao().getActiveUser()
|
||||
|
||||
val instances = db.instanceDao().getAll()
|
||||
db.close()
|
||||
maxLength = if (user!=null){
|
||||
val thisInstances =
|
||||
instances.filter { instanceDatabaseEntity ->
|
||||
@ -84,9 +93,8 @@ class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
||||
Instance.DEFAULT_MAX_TOOT_CHARS
|
||||
}
|
||||
|
||||
val domain = user?.instance_uri.orEmpty()
|
||||
accessToken = user?.accessToken.orEmpty()
|
||||
pixelfedAPI = PixelfedAPI.create(domain)
|
||||
pixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
|
||||
// check if the pictures are alright
|
||||
// TODO
|
||||
|
@ -16,6 +16,8 @@ import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.h.pixeldroid.adapters.ProfilePostsRecyclerViewAdapter
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.di.PixelfedAPIHolder
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.objects.Account.Companion.ACCOUNT_TAG
|
||||
import com.h.pixeldroid.objects.Relationship
|
||||
@ -26,6 +28,7 @@ import com.h.pixeldroid.utils.ImageConverter
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
class ProfileActivity : AppCompatActivity() {
|
||||
private lateinit var pixelfedAPI : PixelfedAPI
|
||||
@ -34,19 +37,24 @@ class ProfileActivity : AppCompatActivity() {
|
||||
private lateinit var accessToken : String
|
||||
private lateinit var domain : String
|
||||
private var account: Account? = null
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
|
||||
@Inject
|
||||
lateinit var apiHolder: PixelfedAPIHolder
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_profile)
|
||||
|
||||
val db = DBUtils.initDB(applicationContext)
|
||||
(this.application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
val user = db.userDao().getActiveUser()
|
||||
|
||||
domain = user?.instance_uri.orEmpty()
|
||||
pixelfedAPI = PixelfedAPI.create(domain)
|
||||
pixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
accessToken = user?.accessToken.orEmpty()
|
||||
db.close()
|
||||
|
||||
// Set posts RecyclerView as a grid with 3 columns
|
||||
recycler = findViewById(R.id.profilePostsRecyclerView)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.h.pixeldroid.api
|
||||
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.objects.*
|
||||
import io.reactivex.Observable
|
||||
import okhttp3.MultipartBody
|
||||
@ -9,6 +10,8 @@ import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.http.*
|
||||
import retrofit2.http.Field
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
|
||||
/*
|
||||
@ -246,4 +249,4 @@ interface PixelfedAPI {
|
||||
fun discover(
|
||||
@Header("Authorization") authorization: String
|
||||
) : Call<DiscoverPosts>
|
||||
}
|
||||
}
|
@ -16,8 +16,8 @@ interface UserDao {
|
||||
@Query("SELECT * FROM users WHERE isActive=1 LIMIT 1")
|
||||
fun getActiveUser(): UserDatabaseEntity?
|
||||
|
||||
@Query("UPDATE users SET isActive=0 WHERE isActive=1")
|
||||
fun deActivateActiveUser()
|
||||
@Query("UPDATE users SET isActive=0")
|
||||
fun deActivateActiveUsers()
|
||||
|
||||
@Query("UPDATE users SET isActive=1 WHERE user_id=:id")
|
||||
fun activateUser(id: String)
|
||||
|
41
app/src/main/java/com/h/pixeldroid/di/APIModule.kt
Normal file
41
app/src/main/java/com/h/pixeldroid/di/APIModule.kt
Normal file
@ -0,0 +1,41 @@
|
||||
package com.h.pixeldroid.di
|
||||
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
class APIModule{
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesAPIHolder(db: AppDatabase): PixelfedAPIHolder {
|
||||
return PixelfedAPIHolder(db.userDao().getActiveUser()?.instance_uri)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class PixelfedAPIHolder(domain: String?){
|
||||
private val intermediate: Retrofit.Builder = Retrofit.Builder()
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
var api: PixelfedAPI? = if (domain != null) setDomain(domain) else null
|
||||
|
||||
fun setDomainToCurrentUser(db: AppDatabase): PixelfedAPI {
|
||||
return setDomain(db.userDao().getActiveUser()!!.instance_uri)
|
||||
}
|
||||
|
||||
fun setDomain(domain: String): PixelfedAPI {
|
||||
val newAPI = intermediate
|
||||
.baseUrl(domain)
|
||||
.build().create(PixelfedAPI::class.java)
|
||||
api = newAPI
|
||||
return newAPI
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.h.pixeldroid.di
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import com.h.pixeldroid.*
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.fragments.PostFragment
|
||||
import com.h.pixeldroid.fragments.SearchDiscoverFragment
|
||||
import com.h.pixeldroid.fragments.feeds.FeedFragment
|
||||
import com.h.pixeldroid.fragments.feeds.OfflineFeedFragment
|
||||
import dagger.Component
|
||||
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
||||
@Singleton
|
||||
@Component(modules = [ApplicationModule::class, DatabaseModule::class, APIModule::class])
|
||||
interface ApplicationComponent {
|
||||
fun inject(application: Pixeldroid?)
|
||||
fun inject(activity: LoginActivity?)
|
||||
fun inject(feedFragment: FeedFragment)
|
||||
fun inject(activity: FollowsActivity?)
|
||||
fun inject(activity: PostActivity?)
|
||||
fun inject(activity: PostCreationActivity?)
|
||||
fun inject(activity: ProfileActivity?)
|
||||
fun inject(mainActivity: MainActivity?)
|
||||
fun inject(fragment: PostFragment)
|
||||
fun inject(fragment: SearchDiscoverFragment)
|
||||
fun inject(fragment: OfflineFeedFragment)
|
||||
|
||||
val context: Context?
|
||||
val application: Application?
|
||||
val database: AppDatabase
|
||||
}
|
27
app/src/main/java/com/h/pixeldroid/di/ApplicationModule.kt
Normal file
27
app/src/main/java/com/h/pixeldroid/di/ApplicationModule.kt
Normal file
@ -0,0 +1,27 @@
|
||||
package com.h.pixeldroid.di
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
||||
@Module
|
||||
class ApplicationModule(app: Application) {
|
||||
private val mApplication: Application = app
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideContext(): Context {
|
||||
return mApplication
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideApplication(): Application {
|
||||
return mApplication
|
||||
}
|
||||
|
||||
}
|
21
app/src/main/java/com/h/pixeldroid/di/DatabaseModule.kt
Normal file
21
app/src/main/java/com/h/pixeldroid/di/DatabaseModule.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package com.h.pixeldroid.di
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Room
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
class DatabaseModule(private val context: Context) {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesDatabase(): AppDatabase {
|
||||
return Room.databaseBuilder(
|
||||
context,
|
||||
AppDatabase::class.java, "pixeldroid"
|
||||
).allowMainThreadQueries().build()
|
||||
}
|
||||
}
|
@ -8,54 +8,67 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.bumptech.glide.Glide
|
||||
import com.h.pixeldroid.Pixeldroid
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.fragments.feeds.PostViewHolder
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.di.PixelfedAPIHolder
|
||||
import com.h.pixeldroid.fragments.feeds.postFeeds.PostViewHolder
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.objects.Status.Companion.DOMAIN_TAG
|
||||
import com.h.pixeldroid.objects.Status.Companion.POST_TAG
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class PostFragment : Fragment() {
|
||||
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
|
||||
@Inject
|
||||
lateinit var apiHolder: PixelfedAPIHolder
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val current_status = arguments?.getSerializable(POST_TAG) as Status?
|
||||
val currentStatus = arguments?.getSerializable(POST_TAG) as Status?
|
||||
val statusDomain = arguments?.getString(DOMAIN_TAG)!!
|
||||
val root: View = inflater.inflate(R.layout.post_fragment, container, false)
|
||||
val picRequest = Glide.with(this)
|
||||
.asDrawable().fitCenter()
|
||||
.placeholder(ColorDrawable(Color.GRAY))
|
||||
|
||||
current_status?.setupPost(root, picRequest, this, statusDomain, true)
|
||||
currentStatus?.setupPost(root, picRequest, this, statusDomain, true)
|
||||
|
||||
//Setup arguments needed for the onclicklisteners
|
||||
val holder = PostViewHolder(root, requireContext())
|
||||
val db = DBUtils.initDB(requireContext())
|
||||
val holder = PostViewHolder(
|
||||
root,
|
||||
requireContext()
|
||||
)
|
||||
|
||||
(requireActivity().application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
val user = db.userDao().getActiveUser()
|
||||
|
||||
val domain = user?.instance_uri.orEmpty()
|
||||
val accessToken = user?.accessToken.orEmpty()
|
||||
val api = PixelfedAPI.create(domain)
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
|
||||
current_status?.setDescription(root, api, "Bearer $accessToken")
|
||||
currentStatus?.setDescription(root, api, "Bearer $accessToken")
|
||||
|
||||
//Activate onclickListeners
|
||||
current_status?.activateLiker(holder, api, "Bearer $accessToken",
|
||||
current_status.favourited ?: false
|
||||
currentStatus?.activateLiker(holder, api, "Bearer $accessToken",
|
||||
currentStatus.favourited ?: false
|
||||
)
|
||||
current_status?.activateReblogger(holder, api, "Bearer $accessToken",
|
||||
current_status.reblogged ?: false
|
||||
currentStatus?.activateReblogger(holder, api, "Bearer $accessToken",
|
||||
currentStatus.reblogged ?: false
|
||||
)
|
||||
current_status?.activateCommenter(holder, api, "Bearer $accessToken")
|
||||
current_status?.showComments(holder, api, "Bearer $accessToken")
|
||||
currentStatus?.activateCommenter(holder, api, "Bearer $accessToken")
|
||||
currentStatus?.showComments(holder, api, "Bearer $accessToken")
|
||||
|
||||
//Activate double tap liking
|
||||
current_status?.activateDoubleTapLiker(holder, api, "Bearer $accessToken")
|
||||
currentStatus?.activateDoubleTapLiker(holder, api, "Bearer $accessToken")
|
||||
return root
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,13 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.h.pixeldroid.Pixeldroid
|
||||
import com.h.pixeldroid.PostActivity
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.SearchActivity
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.di.PixelfedAPIHolder
|
||||
import com.h.pixeldroid.objects.DiscoverPost
|
||||
import com.h.pixeldroid.objects.DiscoverPosts
|
||||
import com.h.pixeldroid.objects.Status
|
||||
@ -26,6 +29,7 @@ import com.h.pixeldroid.utils.ImageConverter
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* This fragment lets you search and use Pixelfed's Discover feature
|
||||
@ -38,6 +42,12 @@ class SearchDiscoverFragment : Fragment() {
|
||||
private lateinit var accessToken: String
|
||||
private lateinit var discoverProgressBar: ProgressBar
|
||||
private lateinit var discoverRefreshLayout: SwipeRefreshLayout
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
|
||||
@Inject
|
||||
lateinit var apiHolder: PixelfedAPIHolder
|
||||
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
@ -47,6 +57,9 @@ class SearchDiscoverFragment : Fragment() {
|
||||
val view = inflater.inflate(R.layout.fragment_search, container, false)
|
||||
val button = view.findViewById<Button>(R.id.searchButton)
|
||||
val search = view.findViewById<EditText>(R.id.searchEditText)
|
||||
|
||||
(requireActivity().application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
button.setOnClickListener {
|
||||
val intent = Intent(context, SearchActivity::class.java)
|
||||
intent.putExtra("searchFeed", search.text.toString())
|
||||
@ -64,13 +77,9 @@ class SearchDiscoverFragment : Fragment() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val db = DBUtils.initDB(requireContext())
|
||||
api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
|
||||
val user = db.userDao().getActiveUser()
|
||||
|
||||
val domain = user?.instance_uri.orEmpty()
|
||||
api = PixelfedAPI.create(domain)
|
||||
accessToken = user?.accessToken.orEmpty()
|
||||
accessToken = db.userDao().getActiveUser()?.accessToken.orEmpty()
|
||||
|
||||
discoverProgressBar = view.findViewById(R.id.discoverProgressBar)
|
||||
discoverRefreshLayout = view.findViewById(R.id.discoverRefreshLayout)
|
||||
|
@ -2,11 +2,13 @@ package com.h.pixeldroid.fragments.feeds
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.lifecycle.Observer
|
||||
@ -24,9 +26,14 @@ import com.h.pixeldroid.objects.Account.Companion.ACCOUNT_ID_TAG
|
||||
import com.h.pixeldroid.objects.Account.Companion.FOLLOWING_TAG
|
||||
import kotlinx.android.synthetic.main.account_list_entry.view.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
open class AccountListFragment : FeedFragment<Account, AccountListFragment.FollowsRecyclerViewAdapter.ViewHolder>() {
|
||||
open class AccountListFragment : FeedFragment() {
|
||||
lateinit var profilePicRequest: RequestBuilder<Drawable>
|
||||
protected lateinit var adapter : FeedsRecyclerViewAdapter<Account, AccountsRecyclerViewAdapter.ViewHolder>
|
||||
lateinit var factory: FeedDataSourceFactory<String, Account>
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
@ -39,13 +46,13 @@ open class AccountListFragment : FeedFragment<Account, AccountListFragment.Follo
|
||||
.asDrawable().apply(RequestOptions().circleCrop())
|
||||
.placeholder(R.drawable.ic_default_user)
|
||||
|
||||
adapter = FollowsRecyclerViewAdapter()
|
||||
adapter = AccountsRecyclerViewAdapter()
|
||||
list.adapter = adapter
|
||||
|
||||
//Make Glide be aware of the recyclerview and pre-load images
|
||||
val sizeProvider: ListPreloader.PreloadSizeProvider<Account> = ViewPreloadSizeProvider()
|
||||
val preloader: RecyclerViewPreloader<Account> = RecyclerViewPreloader(
|
||||
Glide.with(this), adapter as AccountListFragment.FollowsRecyclerViewAdapter, sizeProvider, 4
|
||||
Glide.with(this), adapter as AccountListFragment.AccountsRecyclerViewAdapter, sizeProvider, 4
|
||||
)
|
||||
list.addOnScrollListener(preloader)
|
||||
|
||||
@ -54,7 +61,7 @@ open class AccountListFragment : FeedFragment<Account, AccountListFragment.Follo
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
content = makeContent()
|
||||
val content = makeContent()
|
||||
|
||||
content.observe(viewLifecycleOwner,
|
||||
Observer { c ->
|
||||
@ -62,51 +69,86 @@ open class AccountListFragment : FeedFragment<Account, AccountListFragment.Follo
|
||||
//after a refresh is done we need to stop the pull to refresh spinner
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
})
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
//by invalidating data, loadInitial will be called again
|
||||
factory.liveData.value!!.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
internal open fun makeContent(): LiveData<PagedList<Account>> {
|
||||
val id = arguments?.getSerializable(ACCOUNT_ID_TAG) as String
|
||||
val following = arguments?.getSerializable(FOLLOWING_TAG) as Boolean
|
||||
|
||||
val (makeInitialCall, makeAfterCall)
|
||||
= makeCalls(following, id)
|
||||
|
||||
val config: PagedList.Config = PagedList.Config.Builder().setPageSize(10).build()
|
||||
val dataSource = FeedDataSource(makeInitialCall, makeAfterCall)
|
||||
val dataSource = AccountListDataSource(following, id)
|
||||
factory = FeedDataSourceFactory(dataSource)
|
||||
return LivePagedListBuilder(factory, config).build()
|
||||
}
|
||||
|
||||
private fun makeCalls(following: Boolean, id: String):
|
||||
Pair<(Int) -> Call<List<Account>>, (Int, String) -> Call<List<Account>>> {
|
||||
val makeInitialCall: (Int) -> Call<List<Account>> =
|
||||
if (following) { requestedLoadSize ->
|
||||
inner class AccountListDataSource(private val following: Boolean, private val id: String) :
|
||||
FeedDataSource<String, Account>() {
|
||||
|
||||
override fun newSource(): AccountListDataSource {
|
||||
return AccountListDataSource(following, id)
|
||||
}
|
||||
|
||||
//We use the id as the key
|
||||
override fun getKey(item: Account): String {
|
||||
return item.id
|
||||
}
|
||||
|
||||
override fun makeInitialCall(requestedLoadSize: Int): Call<List<Account>> {
|
||||
return if (following) {
|
||||
pixelfedAPI.followers(
|
||||
id, "Bearer $accessToken",
|
||||
limit = requestedLoadSize
|
||||
)
|
||||
} else { requestedLoadSize ->
|
||||
} else {
|
||||
pixelfedAPI.following(
|
||||
id, "Bearer $accessToken",
|
||||
limit = requestedLoadSize
|
||||
)
|
||||
}
|
||||
val makeAfterCall: (Int, String) -> Call<List<Account>> =
|
||||
if (following) { requestedLoadSize, key ->
|
||||
}
|
||||
|
||||
override fun makeAfterCall(requestedLoadSize: Int, key: String): Call<List<Account>> {
|
||||
return if (following) {
|
||||
pixelfedAPI.followers(
|
||||
id, "Bearer $accessToken",
|
||||
since_id = key, limit = requestedLoadSize
|
||||
)
|
||||
} else { requestedLoadSize, key ->
|
||||
} else {
|
||||
pixelfedAPI.following(
|
||||
id, "Bearer $accessToken",
|
||||
since_id = key, limit = requestedLoadSize
|
||||
)
|
||||
}
|
||||
return Pair(makeInitialCall, makeAfterCall)
|
||||
}
|
||||
|
||||
override fun enqueueCall(call: Call<List<Account>>, callback: LoadCallback<Account>){
|
||||
|
||||
call.enqueue(object : Callback<List<Account>> {
|
||||
override fun onResponse(call: Call<List<Account>>, response: Response<List<Account>>) {
|
||||
if (response.isSuccessful && response.body() != null) {
|
||||
val data = response.body()!!
|
||||
callback.onResult(data)
|
||||
} else{
|
||||
Toast.makeText(context, getString(R.string.loading_toast), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
loadingIndicator.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<Account>>, t: Throwable) {
|
||||
Toast.makeText(context, getString(R.string.feed_failed), Toast.LENGTH_SHORT).show()
|
||||
Log.e("AccountListFragment", t.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
inner class FollowsRecyclerViewAdapter : FeedsRecyclerViewAdapter<Account,FollowsRecyclerViewAdapter.ViewHolder>(),
|
||||
inner class AccountsRecyclerViewAdapter : FeedsRecyclerViewAdapter<Account, AccountsRecyclerViewAdapter.ViewHolder>(),
|
||||
ListPreloader.PreloadModelProvider<Account> {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
|
@ -1,52 +1,45 @@
|
||||
package com.h.pixeldroid.fragments.feeds
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.paging.DataSource
|
||||
import androidx.paging.ItemKeyedDataSource
|
||||
import androidx.paging.PagedList
|
||||
import androidx.paging.PagedListAdapter
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.h.pixeldroid.MainActivity
|
||||
import com.h.pixeldroid.Pixeldroid
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.di.PixelfedAPIHolder
|
||||
import com.h.pixeldroid.objects.FeedContent
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import com.h.pixeldroid.utils.Utils
|
||||
import kotlinx.android.synthetic.main.fragment_feed.view.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
open class FeedFragment<T: FeedContent, VH: RecyclerView.ViewHolder?>: Fragment() {
|
||||
|
||||
lateinit var content: LiveData<PagedList<T>>
|
||||
lateinit var factory: FeedDataSourceFactory<FeedDataSource>
|
||||
open class FeedFragment: Fragment() {
|
||||
|
||||
protected var accessToken: String? = null
|
||||
@Inject
|
||||
lateinit var apiHolder: PixelfedAPIHolder
|
||||
|
||||
protected lateinit var pixelfedAPI: PixelfedAPI
|
||||
|
||||
protected lateinit var list : RecyclerView
|
||||
protected lateinit var adapter : FeedsRecyclerViewAdapter<T, VH>
|
||||
protected lateinit var swipeRefreshLayout: SwipeRefreshLayout
|
||||
internal lateinit var loadingIndicator: ProgressBar
|
||||
private var user: UserDatabaseEntity? = null
|
||||
private lateinit var db: AppDatabase
|
||||
var user: UserDatabaseEntity? = null
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
|
||||
|
||||
|
||||
@ -57,101 +50,80 @@ open class FeedFragment<T: FeedContent, VH: RecyclerView.ViewHolder?>: Fragment(
|
||||
): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_feed, container, false)
|
||||
|
||||
(requireActivity().application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
//Initialize lateinit fields that are needed as soon as the view is created
|
||||
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout)
|
||||
loadingIndicator = view.findViewById(R.id.progressBar)
|
||||
list = swipeRefreshLayout.list
|
||||
list.layoutManager = LinearLayoutManager(context)
|
||||
db = DBUtils.initDB(requireContext())
|
||||
user = db.userDao().getActiveUser()
|
||||
pixelfedAPI = PixelfedAPI.create(user?.instance_uri.orEmpty())
|
||||
|
||||
pixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
accessToken = user?.accessToken.orEmpty()
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
open inner class FeedDataSourceFactory<ObjectId, APIObject: FeedContent>(
|
||||
private val dataSource: FeedDataSource<ObjectId, APIObject>
|
||||
): DataSource.Factory<ObjectId, APIObject>() {
|
||||
internal lateinit var liveData: MutableLiveData<FeedDataSource<ObjectId, APIObject>>
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
//by invalidating data, loadInitial will be called again
|
||||
if (Utils.hasInternet(requireContext())) {
|
||||
factory.liveData.value!!.invalidate()
|
||||
} else {
|
||||
startActivity(Intent(requireContext(), MainActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
open inner class FeedDataSource(private val makeInitialCall: ((Int) -> Call<List<T>>)?,
|
||||
private val makeAfterCall: ((Int, String) -> Call<List<T>>)?
|
||||
): ItemKeyedDataSource<String, T>() {
|
||||
|
||||
open fun newSource(): FeedDataSource {
|
||||
return FeedDataSource(makeInitialCall, makeAfterCall)
|
||||
}
|
||||
|
||||
//We use the id as the key
|
||||
override fun getKey(item: T): String {
|
||||
return item.id!!
|
||||
}
|
||||
//This is called to initialize the list, so we want some of the latest statuses
|
||||
override fun loadInitial(
|
||||
params: LoadInitialParams<String>,
|
||||
callback: LoadInitialCallback<T>
|
||||
) {
|
||||
enqueueCall(makeInitialCall!!(params.requestedLoadSize), callback)
|
||||
}
|
||||
|
||||
//This is called to when we get to the bottom of the loaded content, so we want statuses
|
||||
//older than the given key (params.key)
|
||||
override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<T>) {
|
||||
enqueueCall(makeAfterCall!!(params.requestedLoadSize, params.key), callback)
|
||||
}
|
||||
|
||||
override fun loadBefore(params: LoadParams<String>, callback: LoadCallback<T>) {
|
||||
//do nothing here, it is expected to pull to refresh to load newer notifications
|
||||
}
|
||||
|
||||
protected open fun enqueueCall(call: Call<List<T>>, callback: LoadCallback<T>){
|
||||
|
||||
call.enqueue(object : Callback<List<T>> {
|
||||
override fun onResponse(call: Call<List<T>>, response: Response<List<T>>) {
|
||||
if (response.isSuccessful && response.body() != null) {
|
||||
val notifications = response.body()!!
|
||||
callback.onResult(notifications)
|
||||
if(this@FeedDataSource.newSource() !is PublicTimelineFragment.SearchFeedDataSource) {
|
||||
DBUtils.storePosts(db, notifications, user!!)
|
||||
}
|
||||
} else{
|
||||
Toast.makeText(context, getString(R.string.loading_toast), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
loadingIndicator.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<T>>, t: Throwable) {
|
||||
Toast.makeText(context, getString(R.string.feed_failed), Toast.LENGTH_SHORT).show()
|
||||
Log.e("FeedFragment", t.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
open inner class FeedDataSourceFactory<DS: FeedDataSource>(
|
||||
private val dataSource: DS
|
||||
): DataSource.Factory<String, T>() {
|
||||
lateinit var liveData: MutableLiveData<DS>
|
||||
|
||||
override fun create(): DataSource<String, T> {
|
||||
override fun create(): DataSource<ObjectId, APIObject> {
|
||||
val dataSource = dataSource.newSource()
|
||||
liveData = MutableLiveData()
|
||||
liveData.postValue(dataSource as DS)
|
||||
liveData.postValue(dataSource)
|
||||
return dataSource
|
||||
}
|
||||
}
|
||||
abstract inner class FeedDataSource<ObjectId, APIObject: FeedContent>: ItemKeyedDataSource<ObjectId, APIObject>(){
|
||||
|
||||
/**
|
||||
* Used in the initial call to initialize the list [loadInitial].
|
||||
* @param requestedLoadSize number of objects requested in a call
|
||||
* @return [Call] that gets the list of [APIObject]
|
||||
*/
|
||||
abstract fun makeInitialCall(requestedLoadSize: Int): Call<List<APIObject>>
|
||||
|
||||
/**
|
||||
* Used in the subsequent calls to get more objects.
|
||||
* @param requestedLoadSize number of objects requested in a call
|
||||
* @param key of the last object we already have
|
||||
* @return [Call] that gets the list of [APIObject]
|
||||
*/
|
||||
abstract fun makeAfterCall(requestedLoadSize: Int, key: ObjectId): Call<List<APIObject>>
|
||||
|
||||
/**
|
||||
* This is called to initialize the list, so we want some of the most recent objects.
|
||||
* @param params holds the requestedLoadSize
|
||||
* @param callback to call after network request completes
|
||||
*/
|
||||
override fun loadInitial(
|
||||
params: LoadInitialParams<ObjectId>,
|
||||
callback: LoadInitialCallback<APIObject>
|
||||
) {
|
||||
enqueueCall(makeInitialCall(params.requestedLoadSize), callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called to when we get to the bottom of the loaded content, so we want objects
|
||||
* older than the given key (params.key).
|
||||
* @param params holds the requestedLoadSize
|
||||
* @param callback to call after network request completes
|
||||
*/
|
||||
override fun loadAfter(params: LoadParams<ObjectId>, callback: LoadCallback<APIObject>) {
|
||||
enqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing here, it is expected to pull to refresh to load newer notifications
|
||||
*/
|
||||
override fun loadBefore(params: LoadParams<ObjectId>, callback: LoadCallback<APIObject>) {}
|
||||
|
||||
abstract fun enqueueCall(call: Call<List<APIObject>>, callback: LoadCallback<APIObject>)
|
||||
|
||||
abstract fun newSource(): FeedDataSource<ObjectId, APIObject>
|
||||
|
||||
}
|
||||
}
|
||||
@ -167,7 +139,6 @@ abstract class FeedsRecyclerViewAdapter<T: FeedContent, VH : RecyclerView.ViewHo
|
||||
}
|
||||
}
|
||||
){
|
||||
|
||||
protected lateinit var context: Context
|
||||
}
|
||||
|
||||
|
@ -4,11 +4,13 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.paging.LivePagedListBuilder
|
||||
@ -29,14 +31,20 @@ import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.utils.HtmlUtils.Companion.parseHTMLText
|
||||
import kotlinx.android.synthetic.main.fragment_notifications.view.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
|
||||
/**
|
||||
* A fragment representing a list of Items.
|
||||
*/
|
||||
class NotificationsFragment : FeedFragment<Notification, NotificationsFragment.NotificationsRecyclerViewAdapter.ViewHolder>() {
|
||||
class NotificationsFragment : FeedFragment() {
|
||||
|
||||
lateinit var profilePicRequest: RequestBuilder<Drawable>
|
||||
protected lateinit var adapter : FeedsRecyclerViewAdapter<Notification, NotificationsRecyclerViewAdapter.ViewHolder>
|
||||
lateinit var factory: FeedDataSourceFactory<String, Notification>
|
||||
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
@ -67,7 +75,7 @@ class NotificationsFragment : FeedFragment<Notification, NotificationsFragment.N
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
content = makeContent()
|
||||
val content = makeContent()
|
||||
|
||||
content.observe(viewLifecycleOwner,
|
||||
Observer { c ->
|
||||
@ -75,22 +83,60 @@ class NotificationsFragment : FeedFragment<Notification, NotificationsFragment.N
|
||||
//after a refresh is done we need to stop the pull to refresh spinner
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
})
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
//by invalidating data, loadInitial will be called again
|
||||
factory.liveData.value!!.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeContent(): LiveData<PagedList<Notification>> {
|
||||
fun makeInitialCall(requestedLoadSize: Int): Call<List<Notification>> {
|
||||
val config: PagedList.Config = PagedList.Config.Builder().setPageSize(10).build()
|
||||
val dataSource = NotificationListDataSource()
|
||||
factory = FeedDataSourceFactory(dataSource)
|
||||
return LivePagedListBuilder(factory, config).build()
|
||||
}
|
||||
|
||||
inner class NotificationListDataSource: FeedDataSource<String, Notification>() {
|
||||
|
||||
override fun newSource(): NotificationListDataSource {
|
||||
return NotificationListDataSource()
|
||||
}
|
||||
|
||||
//We use the id as the key
|
||||
override fun getKey(item: Notification): String {
|
||||
return item.id
|
||||
}
|
||||
|
||||
override fun makeInitialCall(requestedLoadSize: Int): Call<List<Notification>> {
|
||||
return pixelfedAPI
|
||||
.notifications("Bearer $accessToken", limit="$requestedLoadSize")
|
||||
}
|
||||
fun makeAfterCall(requestedLoadSize: Int, key: String): Call<List<Notification>> {
|
||||
override fun makeAfterCall(requestedLoadSize: Int, key: String): Call<List<Notification>> {
|
||||
return pixelfedAPI
|
||||
.notifications("Bearer $accessToken", max_id=key, limit="$requestedLoadSize")
|
||||
}
|
||||
|
||||
val config: PagedList.Config = PagedList.Config.Builder().setPageSize(10).build()
|
||||
val dataSource = FeedDataSource(::makeInitialCall, ::makeAfterCall)
|
||||
factory = FeedDataSourceFactory(dataSource)
|
||||
return LivePagedListBuilder(factory, config).build()
|
||||
override fun enqueueCall(call: Call<List<Notification>>, callback: LoadCallback<Notification>){
|
||||
|
||||
call.enqueue(object : Callback<List<Notification>> {
|
||||
override fun onResponse(call: Call<List<Notification>>, response: Response<List<Notification>>) {
|
||||
if (response.isSuccessful && response.body() != null) {
|
||||
val data = response.body()!!
|
||||
callback.onResult(data)
|
||||
} else{
|
||||
Toast.makeText(context, getString(R.string.loading_toast), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
loadingIndicator.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<Notification>>, t: Throwable) {
|
||||
Toast.makeText(context, getString(R.string.feed_failed), Toast.LENGTH_SHORT).show()
|
||||
Log.e("NotificationsFragment", t.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,13 +20,16 @@ import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.RequestBuilder
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.h.pixeldroid.MainActivity
|
||||
import com.h.pixeldroid.Pixeldroid
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.PostDatabaseEntity
|
||||
import com.h.pixeldroid.fragments.ImageFragment
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.utils.*
|
||||
import kotlinx.android.synthetic.main.fragment_offline_feed.view.*
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.*
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class OfflineFeedFragment: Fragment() {
|
||||
@ -35,6 +38,9 @@ class OfflineFeedFragment: Fragment() {
|
||||
private lateinit var viewAdapter: RecyclerView.Adapter<*>
|
||||
private lateinit var viewManager: RecyclerView.LayoutManager
|
||||
lateinit var picRequest: RequestBuilder<Drawable>
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -53,7 +59,9 @@ class OfflineFeedFragment: Fragment() {
|
||||
picRequest = Glide.with(this)
|
||||
.asDrawable().fitCenter()
|
||||
.placeholder(ColorDrawable(Color.GRAY))
|
||||
val db = DBUtils.initDB(requireContext())
|
||||
|
||||
(requireActivity().application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
val user = db.userDao().getActiveUser()!!
|
||||
if (db.postDao().numberOfPosts(user.user_id, user.instance_uri) > 0) {
|
||||
val posts = db.postDao().getAll(user.user_id, user.instance_uri)
|
||||
|
@ -1,44 +0,0 @@
|
||||
package com.h.pixeldroid.fragments.feeds
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.paging.LivePagedListBuilder
|
||||
import androidx.paging.PagedList
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import retrofit2.Call
|
||||
|
||||
class PublicTimelineFragment: PostsFeedFragment() {
|
||||
|
||||
inner class SearchFeedDataSource : FeedDataSource(null, null){
|
||||
|
||||
override fun newSource(): SearchFeedDataSource {
|
||||
return SearchFeedDataSource()
|
||||
}
|
||||
|
||||
private fun makeInitialCall(requestedLoadSize: Int): Call<List<Status>> {
|
||||
return pixelfedAPI.timelinePublic(limit="$requestedLoadSize")
|
||||
}
|
||||
private fun makeAfterCall(requestedLoadSize: Int, key: String): Call<List<Status>> {
|
||||
return pixelfedAPI.timelinePublic( max_id=key, limit="$requestedLoadSize")
|
||||
}
|
||||
|
||||
override fun loadInitial(
|
||||
params: LoadInitialParams<String>,
|
||||
callback: LoadInitialCallback<Status>
|
||||
) {
|
||||
enqueueCall(makeInitialCall(params.requestedLoadSize), callback)
|
||||
}
|
||||
|
||||
//This is called to when we get to the bottom of the loaded content, so we want statuses
|
||||
//older than the given key (params.key)
|
||||
override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<Status>) {
|
||||
enqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
}
|
||||
}
|
||||
|
||||
override fun makeContent(): LiveData<PagedList<Status>> {
|
||||
val config: PagedList.Config = PagedList.Config.Builder().setPageSize(10).build()
|
||||
factory = FeedFragment<Status, PostViewHolder>()
|
||||
.FeedDataSourceFactory(SearchFeedDataSource())
|
||||
return LivePagedListBuilder(factory, config).build()
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package com.h.pixeldroid.fragments.feeds.postFeeds
|
||||
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.paging.LivePagedListBuilder
|
||||
import androidx.paging.PagedList
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
class HomeTimelineFragment: PostsFeedFragment() {
|
||||
|
||||
override fun makeContent(): LiveData<PagedList<Status>> {
|
||||
val config: PagedList.Config = PagedList.Config.Builder().setPageSize(10).build()
|
||||
val dataSource = PostFeedDataSource()
|
||||
factory = FeedDataSourceFactory(dataSource)
|
||||
return LivePagedListBuilder(factory, config).build()
|
||||
}
|
||||
|
||||
|
||||
inner class PostFeedDataSource: FeedDataSource<String, Status>() {
|
||||
|
||||
override fun newSource(): PostFeedDataSource {
|
||||
return PostFeedDataSource()
|
||||
}
|
||||
|
||||
override fun makeInitialCall(requestedLoadSize: Int): Call<List<Status>> {
|
||||
return pixelfedAPI
|
||||
.timelineHome("Bearer $accessToken", limit="$requestedLoadSize")
|
||||
}
|
||||
|
||||
override fun makeAfterCall(requestedLoadSize: Int, key: String): Call<List<Status>> {
|
||||
return pixelfedAPI
|
||||
.timelineHome("Bearer $accessToken", max_id=key,
|
||||
limit="$requestedLoadSize")
|
||||
}
|
||||
|
||||
//We use the id as the key
|
||||
override fun getKey(item: Status): String {
|
||||
return item.id!!
|
||||
}
|
||||
|
||||
override fun enqueueCall(call: Call<List<Status>>, callback: LoadCallback<Status>){
|
||||
|
||||
call.enqueue(object : Callback<List<Status>> {
|
||||
override fun onResponse(call: Call<List<Status>>, response: Response<List<Status>>) {
|
||||
if (response.isSuccessful && response.body() != null) {
|
||||
val notifications = response.body()!!
|
||||
callback.onResult(notifications)
|
||||
DBUtils.storePosts(db, notifications, user!!)
|
||||
} else{
|
||||
Toast.makeText(context, getString(R.string.loading_toast), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
loadingIndicator.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<Status>>, t: Throwable) {
|
||||
Toast.makeText(context, getString(R.string.feed_failed), Toast.LENGTH_SHORT).show()
|
||||
Log.e("PostsFeedFragment", t.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.h.pixeldroid.fragments.feeds
|
||||
package com.h.pixeldroid.fragments.feeds.postFeeds
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
@ -10,7 +10,6 @@ import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.paging.LivePagedListBuilder
|
||||
import androidx.paging.PagedList
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import at.connyduck.sparkbutton.SparkButton
|
||||
@ -20,24 +19,23 @@ import com.bumptech.glide.RequestBuilder
|
||||
import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader
|
||||
import com.bumptech.glide.util.ViewPreloadSizeProvider
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.db.UserDatabaseEntity
|
||||
import com.h.pixeldroid.fragments.feeds.FeedFragment
|
||||
import com.h.pixeldroid.fragments.feeds.FeedsRecyclerViewAdapter
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import retrofit2.Call
|
||||
|
||||
open class PostsFeedFragment : FeedFragment<Status, PostViewHolder>() {
|
||||
abstract class PostsFeedFragment : FeedFragment() {
|
||||
|
||||
lateinit var picRequest: RequestBuilder<Drawable>
|
||||
lateinit var domain : String
|
||||
private var user: UserDatabaseEntity? = null
|
||||
protected lateinit var adapter : FeedsRecyclerViewAdapter<Status, PostViewHolder>
|
||||
lateinit var factory: FeedDataSourceFactory<String, Status>
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val view = super.onCreateView(inflater, container, savedInstanceState)
|
||||
val db = DBUtils.initDB(requireContext())
|
||||
user = db.userDao().getActiveUser()
|
||||
|
||||
domain = user?.instance_uri.orEmpty()
|
||||
//RequestBuilder that is re-used for every image
|
||||
@ -45,14 +43,13 @@ open class PostsFeedFragment : FeedFragment<Status, PostViewHolder>() {
|
||||
.asDrawable().fitCenter()
|
||||
.placeholder(ColorDrawable(Color.GRAY))
|
||||
|
||||
adapter = PostsFeedRecyclerViewAdapter(this)
|
||||
adapter = PostsFeedRecyclerViewAdapter()
|
||||
list.adapter = adapter
|
||||
|
||||
|
||||
//Make Glide be aware of the recyclerview and pre-load images
|
||||
val sizeProvider: ListPreloader.PreloadSizeProvider<Status> = ViewPreloadSizeProvider()
|
||||
val preloader: RecyclerViewPreloader<Status> = RecyclerViewPreloader(
|
||||
Glide.with(this), adapter as PostsFeedFragment.PostsFeedRecyclerViewAdapter, sizeProvider, 4
|
||||
Glide.with(this), adapter as PostsFeedRecyclerViewAdapter, sizeProvider, 4
|
||||
)
|
||||
list.addOnScrollListener(preloader)
|
||||
|
||||
@ -61,35 +58,26 @@ open class PostsFeedFragment : FeedFragment<Status, PostViewHolder>() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
content = makeContent()
|
||||
val content = makeContent()
|
||||
content.observe(viewLifecycleOwner,
|
||||
Observer { c ->
|
||||
adapter.submitList(c)
|
||||
//after a refresh is done we need to stop the pull to refresh spinner
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
})
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
//by invalidating data, loadInitial will be called again
|
||||
factory.liveData.value!!.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
internal open fun makeContent(): LiveData<PagedList<Status>> {
|
||||
fun makeInitialCall(requestedLoadSize: Int): Call<List<Status>> {
|
||||
return pixelfedAPI
|
||||
.timelineHome("Bearer $accessToken", limit="$requestedLoadSize")
|
||||
}
|
||||
fun makeAfterCall(requestedLoadSize: Int, key: String): Call<List<Status>> {
|
||||
return pixelfedAPI
|
||||
.timelineHome("Bearer $accessToken", max_id=key,
|
||||
limit="$requestedLoadSize")
|
||||
}
|
||||
val config: PagedList.Config = PagedList.Config.Builder().setPageSize(10).build()
|
||||
val dataSource = FeedDataSource(::makeInitialCall, ::makeAfterCall)
|
||||
factory = FeedDataSourceFactory(dataSource)
|
||||
return LivePagedListBuilder(factory, config).build()
|
||||
}
|
||||
internal abstract fun makeContent(): LiveData<PagedList<Status>>
|
||||
|
||||
/**
|
||||
* [RecyclerView.Adapter] that can display a list of Statuses
|
||||
*/
|
||||
inner class PostsFeedRecyclerViewAdapter(private val postsFeedFragment: PostsFeedFragment)
|
||||
inner class PostsFeedRecyclerViewAdapter
|
||||
: FeedsRecyclerViewAdapter<Status, PostViewHolder>(),
|
||||
ListPreloader.PreloadModelProvider<Status> {
|
||||
private val api = pixelfedAPI
|
||||
@ -98,7 +86,10 @@ open class PostsFeedFragment : FeedFragment<Status, PostViewHolder>() {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.post_fragment, parent, false)
|
||||
context = view.context
|
||||
return PostViewHolder(view, context)
|
||||
return PostViewHolder(
|
||||
view,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
@ -0,0 +1,60 @@
|
||||
package com.h.pixeldroid.fragments.feeds.postFeeds
|
||||
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.paging.LivePagedListBuilder
|
||||
import androidx.paging.PagedList
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
class PublicTimelineFragment: PostsFeedFragment() {
|
||||
|
||||
inner class PublicFeedDataSource : FeedDataSource<String, Status>(){
|
||||
|
||||
override fun newSource(): PublicFeedDataSource {
|
||||
return PublicFeedDataSource()
|
||||
}
|
||||
|
||||
override fun makeInitialCall(requestedLoadSize: Int): Call<List<Status>> {
|
||||
return pixelfedAPI.timelinePublic(limit="$requestedLoadSize")
|
||||
}
|
||||
override fun makeAfterCall(requestedLoadSize: Int, key: String): Call<List<Status>> {
|
||||
return pixelfedAPI.timelinePublic( max_id=key, limit="$requestedLoadSize")
|
||||
}
|
||||
|
||||
override fun enqueueCall(call: Call<List<Status>>, callback: LoadCallback<Status>) {
|
||||
call.enqueue(object : Callback<List<Status>> {
|
||||
override fun onResponse(call: Call<List<Status>>, response: Response<List<Status>>) {
|
||||
if (response.isSuccessful && response.body() != null) {
|
||||
val notifications = response.body()!!
|
||||
callback.onResult(notifications)
|
||||
} else{
|
||||
Toast.makeText(context, getString(R.string.loading_toast), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
loadingIndicator.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<Status>>, t: Throwable) {
|
||||
Toast.makeText(context, getString(R.string.feed_failed), Toast.LENGTH_SHORT).show()
|
||||
Log.e("PublicTimelineFragment", t.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun getKey(item: Status): String {
|
||||
return item.id!!
|
||||
}
|
||||
}
|
||||
|
||||
override fun makeContent(): LiveData<PagedList<Status>> {
|
||||
val config: PagedList.Config = PagedList.Config.Builder().setPageSize(10).build()
|
||||
factory = FeedDataSourceFactory(PublicFeedDataSource())
|
||||
return LivePagedListBuilder(factory, config).build()
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import com.h.pixeldroid.fragments.feeds.AccountListFragment
|
||||
import com.h.pixeldroid.fragments.feeds.FeedFragment
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.objects.Results
|
||||
import com.h.pixeldroid.objects.Tag
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
@ -34,35 +35,38 @@ class SearchAccountFragment: AccountListFragment(){
|
||||
return view
|
||||
}
|
||||
|
||||
inner class SearchAccountListDataSource: FeedDataSource(null, null){
|
||||
inner class SearchAccountListDataSource: FeedDataSource<String, Account>(){
|
||||
|
||||
override fun newSource(): FeedDataSource {
|
||||
override fun newSource(): SearchAccountListDataSource {
|
||||
return SearchAccountListDataSource()
|
||||
}
|
||||
|
||||
private fun makeInitialCall(requestedLoadSize: Int): Call<Results> {
|
||||
override fun getKey(item: Account): String {
|
||||
return item.id
|
||||
}
|
||||
|
||||
private fun searchMakeInitialCall(requestedLoadSize: Int): Call<Results> {
|
||||
return pixelfedAPI
|
||||
.search("Bearer $accessToken",
|
||||
limit="$requestedLoadSize", q=query,
|
||||
type = Results.SearchType.accounts)
|
||||
}
|
||||
private fun makeAfterCall(requestedLoadSize: Int, key: String): Call<Results> {
|
||||
private fun searchMakeAfterCall(requestedLoadSize: Int, key: String): Call<Results> {
|
||||
return pixelfedAPI
|
||||
.search("Bearer $accessToken", max_id=key,
|
||||
limit="$requestedLoadSize", q = query,
|
||||
type = Results.SearchType.accounts)
|
||||
}
|
||||
|
||||
override fun loadInitial(
|
||||
params: LoadInitialParams<String>,
|
||||
callback: LoadInitialCallback<Account>
|
||||
) {
|
||||
searchEnqueueCall(makeInitialCall(params.requestedLoadSize), callback)
|
||||
searchEnqueueCall(searchMakeInitialCall(params.requestedLoadSize), callback)
|
||||
}
|
||||
|
||||
//This is called to when we get to the bottom of the loaded content, so we want statuses
|
||||
//older than the given key (params.key)
|
||||
override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<Account>) {
|
||||
searchEnqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
searchEnqueueCall(searchMakeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
}
|
||||
private fun searchEnqueueCall(call: Call<Results>, callback: LoadCallback<Account>) {
|
||||
|
||||
@ -86,16 +90,22 @@ class SearchAccountFragment: AccountListFragment(){
|
||||
})
|
||||
}
|
||||
|
||||
override fun makeInitialCall(requestedLoadSize: Int): Call<List<Account>> {
|
||||
throw NotImplementedError("Should not be called, reimplemented for Search fragment")
|
||||
}
|
||||
|
||||
override fun makeAfterCall(requestedLoadSize: Int, key: String): Call<List<Account>> {
|
||||
throw NotImplementedError("Should not be called, reimplemented for Search fragment")
|
||||
}
|
||||
|
||||
override fun enqueueCall(call: Call<List<Account>>, callback: LoadCallback<Account>) {
|
||||
throw NotImplementedError("Should not be called, reimplemented for Search fragment")
|
||||
}
|
||||
}
|
||||
|
||||
override fun makeContent(): LiveData<PagedList<Account>> {
|
||||
val config: PagedList.Config = PagedList.Config.Builder().setPageSize(10).build()
|
||||
factory =
|
||||
FeedFragment<Account, FollowsRecyclerViewAdapter.ViewHolder>()
|
||||
.FeedDataSourceFactory(
|
||||
SearchAccountListDataSource()
|
||||
)
|
||||
factory = FeedFragment().FeedDataSourceFactory(SearchAccountListDataSource())
|
||||
return LivePagedListBuilder(factory, config).build()
|
||||
}
|
||||
}
|
@ -14,8 +14,10 @@ import androidx.paging.LivePagedListBuilder
|
||||
import androidx.paging.PagedList
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.fragments.feeds.AccountListFragment
|
||||
import com.h.pixeldroid.fragments.feeds.FeedFragment
|
||||
import com.h.pixeldroid.fragments.feeds.FeedsRecyclerViewAdapter
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.objects.Results
|
||||
import com.h.pixeldroid.objects.Tag
|
||||
import kotlinx.android.synthetic.main.fragment_tags.view.*
|
||||
@ -23,9 +25,13 @@ import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
class SearchHashtagFragment: FeedFragment<Tag, SearchHashtagFragment.TagsRecyclerViewAdapter.ViewHolder>(){
|
||||
class SearchHashtagFragment: FeedFragment(){
|
||||
|
||||
private lateinit var query: String
|
||||
private lateinit var content: LiveData<PagedList<Tag>>
|
||||
protected lateinit var adapter : TagsRecyclerViewAdapter
|
||||
lateinit var factory: FeedDataSourceFactory<Int, Tag>
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
@ -51,43 +57,45 @@ class SearchHashtagFragment: FeedFragment<Tag, SearchHashtagFragment.TagsRecycle
|
||||
//after a refresh is done we need to stop the pull to refresh spinner
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
})
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
//by invalidating data, loadInitial will be called again
|
||||
factory.liveData.value!!.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
inner class SearchTagsListDataSource: FeedDataSource(null, null){
|
||||
inner class SearchTagsListDataSource: FeedDataSource<Int, Tag>(){
|
||||
|
||||
override fun newSource(): FeedDataSource {
|
||||
override fun newSource(): SearchTagsListDataSource {
|
||||
return SearchTagsListDataSource()
|
||||
}
|
||||
|
||||
private fun makeInitialCall(requestedLoadSize: Int): Call<Results> {
|
||||
private fun searchMakeInitialCall(requestedLoadSize: Int): Call<Results> {
|
||||
return pixelfedAPI
|
||||
.search("Bearer $accessToken",
|
||||
limit="$requestedLoadSize", q=query,
|
||||
type = Results.SearchType.hashtags)
|
||||
}
|
||||
private fun makeAfterCall(requestedLoadSize: Int, key: String): Call<Results> {
|
||||
private fun searchMakeAfterCall(requestedLoadSize: Int, key: Int): Call<Results> {
|
||||
return pixelfedAPI
|
||||
.search("Bearer $accessToken", offset=key.toInt(),
|
||||
.search("Bearer $accessToken", offset=key,
|
||||
limit="$requestedLoadSize", q = query,
|
||||
type = Results.SearchType.hashtags)
|
||||
}
|
||||
|
||||
override fun getKey(item: Tag): String {
|
||||
override fun getKey(item: Tag): Int {
|
||||
val value = content.value
|
||||
val count = value?.loadedCount ?: 0
|
||||
return count.toString()
|
||||
return value?.loadedCount ?: 0
|
||||
}
|
||||
override fun loadInitial(
|
||||
params: LoadInitialParams<String>,
|
||||
params: LoadInitialParams<Int>,
|
||||
callback: LoadInitialCallback<Tag>
|
||||
) {
|
||||
searchEnqueueCall(makeInitialCall(params.requestedLoadSize), callback)
|
||||
searchEnqueueCall(searchMakeInitialCall(params.requestedLoadSize), callback)
|
||||
}
|
||||
|
||||
//This is called to when we get to the bottom of the loaded content, so we want statuses
|
||||
//older than the given key (params.key)
|
||||
override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<Tag>) {
|
||||
searchEnqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Tag>) {
|
||||
searchEnqueueCall(searchMakeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
}
|
||||
|
||||
private fun searchEnqueueCall(call: Call<Results>, callback: LoadCallback<Tag>){
|
||||
@ -111,12 +119,24 @@ class SearchHashtagFragment: FeedFragment<Tag, SearchHashtagFragment.TagsRecycle
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun makeInitialCall(requestedLoadSize: Int): Call<List<Tag>> {
|
||||
throw NotImplementedError("Should not be called, reimplemented for Search fragment")
|
||||
}
|
||||
|
||||
override fun makeAfterCall(requestedLoadSize: Int, key: Int): Call<List<Tag>> {
|
||||
throw NotImplementedError("Should not be called, reimplemented for Search fragment")
|
||||
}
|
||||
|
||||
override fun enqueueCall(call: Call<List<Tag>>, callback: LoadCallback<Tag>) {
|
||||
throw NotImplementedError("Should not be called, reimplemented for Search fragment")
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeContent(): LiveData<PagedList<Tag>> {
|
||||
val config: PagedList.Config = PagedList.Config.Builder().setPageSize(10).build()
|
||||
factory =
|
||||
FeedFragment<Tag, TagsRecyclerViewAdapter.ViewHolder>()
|
||||
FeedFragment()
|
||||
.FeedDataSourceFactory(
|
||||
SearchTagsListDataSource()
|
||||
)
|
||||
|
@ -9,8 +9,7 @@ import androidx.lifecycle.LiveData
|
||||
import androidx.paging.LivePagedListBuilder
|
||||
import androidx.paging.PagedList
|
||||
import com.h.pixeldroid.fragments.feeds.FeedFragment
|
||||
import com.h.pixeldroid.fragments.feeds.PostViewHolder
|
||||
import com.h.pixeldroid.fragments.feeds.PostsFeedFragment
|
||||
import com.h.pixeldroid.fragments.feeds.postFeeds.PostsFeedFragment
|
||||
import com.h.pixeldroid.objects.Results
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import retrofit2.Call
|
||||
@ -33,19 +32,19 @@ class SearchPostsFragment: PostsFeedFragment(){
|
||||
return view
|
||||
}
|
||||
|
||||
inner class SearchFeedDataSource : FeedDataSource(null, null){
|
||||
inner class SearchFeedDataSource : FeedDataSource<String, Status>(){
|
||||
|
||||
override fun newSource(): FeedDataSource {
|
||||
override fun newSource(): SearchFeedDataSource {
|
||||
return SearchFeedDataSource()
|
||||
}
|
||||
|
||||
private fun makeInitialCall(requestedLoadSize: Int): Call<Results> {
|
||||
private fun searchMakeInitialCall(requestedLoadSize: Int): Call<Results> {
|
||||
return pixelfedAPI
|
||||
.search("Bearer $accessToken",
|
||||
limit="$requestedLoadSize", q=query,
|
||||
type = Results.SearchType.statuses)
|
||||
}
|
||||
private fun makeAfterCall(requestedLoadSize: Int, key: String): Call<Results> {
|
||||
private fun searchMakeAfterCall(requestedLoadSize: Int, key: String): Call<Results> {
|
||||
return pixelfedAPI
|
||||
.search("Bearer $accessToken", max_id=key,
|
||||
limit="$requestedLoadSize", q = query,
|
||||
@ -55,13 +54,11 @@ class SearchPostsFragment: PostsFeedFragment(){
|
||||
params: LoadInitialParams<String>,
|
||||
callback: LoadInitialCallback<Status>
|
||||
) {
|
||||
searchEnqueueCall(makeInitialCall(params.requestedLoadSize), callback)
|
||||
searchEnqueueCall(searchMakeInitialCall(params.requestedLoadSize), callback)
|
||||
}
|
||||
|
||||
//This is called to when we get to the bottom of the loaded content, so we want statuses
|
||||
//older than the given key (params.key)
|
||||
override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<Status>) {
|
||||
searchEnqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
searchEnqueueCall(searchMakeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
}
|
||||
|
||||
private fun searchEnqueueCall(call: Call<Results>, callback: LoadCallback<Status>){
|
||||
@ -84,13 +81,28 @@ class SearchPostsFragment: PostsFeedFragment(){
|
||||
}
|
||||
})
|
||||
}
|
||||
override fun makeInitialCall(requestedLoadSize: Int): Call<List<Status>> {
|
||||
throw NotImplementedError("Should not be called, reimplemented for Search fragment")
|
||||
}
|
||||
|
||||
override fun makeAfterCall(requestedLoadSize: Int, key: String): Call<List<Status>> {
|
||||
throw NotImplementedError("Should not be called, reimplemented for Search fragment")
|
||||
}
|
||||
|
||||
override fun enqueueCall(call: Call<List<Status>>, callback: LoadCallback<Status>) {
|
||||
throw NotImplementedError("Should not be called, reimplemented for Search fragment")
|
||||
}
|
||||
|
||||
override fun getKey(item: Status): String {
|
||||
return item.id!!
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun makeContent(): LiveData<PagedList<Status>> {
|
||||
val config: PagedList.Config = PagedList.Config.Builder().setPageSize(10).build()
|
||||
factory = FeedFragment<Status, PostViewHolder>()
|
||||
factory = FeedFragment()
|
||||
.FeedDataSourceFactory(SearchFeedDataSource())
|
||||
return LivePagedListBuilder(factory, config).build()
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.widget.*
|
||||
import androidx.core.text.toSpanned
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
@ -20,7 +19,7 @@ import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.fragments.ImageFragment
|
||||
import com.h.pixeldroid.fragments.feeds.PostViewHolder
|
||||
import com.h.pixeldroid.fragments.feeds.postFeeds.PostViewHolder
|
||||
import com.h.pixeldroid.utils.HtmlUtils.Companion.getDomain
|
||||
import com.h.pixeldroid.utils.HtmlUtils.Companion.parseHTMLText
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
|
@ -1,7 +1,5 @@
|
||||
package com.h.pixeldroid.utils
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Room
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.InstanceDatabaseEntity
|
||||
import com.h.pixeldroid.db.PostDatabaseEntity
|
||||
@ -15,12 +13,6 @@ class DBUtils {
|
||||
companion object {
|
||||
private const val MAX_NUMBER_OF_STORED_POSTS = 200
|
||||
|
||||
fun initDB(context: Context): AppDatabase {
|
||||
return Room.databaseBuilder(
|
||||
context,
|
||||
AppDatabase::class.java, "pixeldroid"
|
||||
).allowMainThreadQueries().build()
|
||||
}
|
||||
private fun normalizeOrNot(uri: String): String{
|
||||
return if(uri.startsWith("http://localhost")){
|
||||
uri
|
||||
|
@ -8,7 +8,7 @@ import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.fragments.feeds.PostViewHolder
|
||||
import com.h.pixeldroid.fragments.feeds.postFeeds.PostViewHolder
|
||||
import com.h.pixeldroid.objects.Context
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.utils.ImageConverter.Companion.setImageFromDrawable
|
||||
|
@ -7,7 +7,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.0'
|
||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Mon Jun 01 23:59:23 CEST 2020
|
||||
#Sun Jul 26 16:18:03 CEST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip
|
||||
|
Loading…
x
Reference in New Issue
Block a user