First use login flow (#44)
* transform profile activity into fragment * Implement swipeable tabs * Ask for login on first start, add API endpoints, change profile to show the user's profile * Add tests * delete test for now * Adapt test to changes (no more profile from drawer) * Add unit test for api * Add test for profile, refactor to allow testing, add exception to security policy to allow tests * Adapt test to new situation * Fix typo due to change * refactor somewhat * remove unused function * remove test dependent on network * update test * remove test Co-authored-by: Ulysse Widmer <ulysse.widmer@epfl.ch>
This commit is contained in:
parent
2d7020fd21
commit
20c5ff4ee0
|
@ -80,6 +80,7 @@ dependencies {
|
|||
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
|
||||
testImplementation 'junit:junit:4.13'
|
||||
|
||||
androidTestImplementation("com.squareup.okhttp3:mockwebserver:4.4.0")
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.2.0'
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class BottomMenuTest {
|
||||
@get:Rule
|
||||
var activityRule: ActivityScenarioRule<MainActivity>
|
||||
= ActivityScenarioRule(MainActivity::class.java)
|
||||
|
||||
@Test
|
||||
fun testFollowersTextView() {
|
||||
onView(withId(R.id.activity_main_account_btn)).perform(click())
|
||||
onView(withId(R.id.profile_main_container)).check(matches(isDisplayed()))
|
||||
}
|
||||
}
|
|
@ -59,27 +59,27 @@ class LoginInstrumentedTest {
|
|||
}
|
||||
}
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class LoginCheckIntent {
|
||||
@get:Rule
|
||||
val intentsTestRule = IntentsTestRule(LoginActivity::class.java)
|
||||
|
||||
@Test
|
||||
fun launchesIntent() {
|
||||
val expectedIntent: Matcher<Intent> = allOf(
|
||||
hasAction(ACTION_VIEW),
|
||||
hasDataString(containsString("pixelfed.social"))
|
||||
)
|
||||
|
||||
onView(withId(R.id.editText)).perform(ViewActions.replaceText("pixelfed.social"), ViewActions.closeSoftKeyboard())
|
||||
onView(withId(R.id.connect_instance_button)).perform(click())
|
||||
|
||||
Thread.sleep(5000)
|
||||
|
||||
intended(expectedIntent)
|
||||
|
||||
}
|
||||
}
|
||||
//@RunWith(AndroidJUnit4::class)
|
||||
//class LoginCheckIntent {
|
||||
// @get:Rule
|
||||
// val intentsTestRule = IntentsTestRule(LoginActivity::class.java)
|
||||
//
|
||||
// @Test
|
||||
// fun launchesIntent() {
|
||||
// val expectedIntent: Matcher<Intent> = allOf(
|
||||
// hasAction(ACTION_VIEW),
|
||||
// hasDataString(containsString("pixelfed.social"))
|
||||
// )
|
||||
//
|
||||
// onView(withId(R.id.editText)).perform(ViewActions.replaceText("pixelfed.social"), ViewActions.closeSoftKeyboard())
|
||||
// onView(withId(R.id.connect_instance_button)).perform(click())
|
||||
//
|
||||
// Thread.sleep(5000)
|
||||
//
|
||||
// intended(expectedIntent)
|
||||
//
|
||||
// }
|
||||
//}
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AfterIntent {
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.view.get
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.hamcrest.Matchers.not
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import okhttp3.mockwebserver.MockResponse
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
@ -16,18 +25,55 @@ import org.junit.runner.RunWith
|
|||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ProfileTest {
|
||||
private val accountJson = "{\n" +
|
||||
" \"id\": \"1450\",\n" +
|
||||
" \"username\": \"deerbard_photo\",\n" +
|
||||
" \"acct\": \"deerbard_photo\",\n" +
|
||||
" \"display_name\": \"deerbard photography\",\n" +
|
||||
" \"locked\": false,\n" +
|
||||
" \"created_at\": \"2018-08-01T12:58:21.000000Z\",\n" +
|
||||
" \"followers_count\": 68,\n" +
|
||||
" \"following_count\": 27,\n" +
|
||||
" \"statuses_count\": 72,\n" +
|
||||
" \"note\": \"\",\n" +
|
||||
" \"url\": \"https://pixelfed.social/deerbard_photo\",\n" +
|
||||
" \"avatar\": \"https://pixelfed.social/storage/avatars/000/000/001/450/SMSep5NoabDam1W8UDMh_avatar.png?v=4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a\",\n" +
|
||||
" \"avatar_static\": \"https://pixelfed.social/storage/avatars/000/000/001/450/SMSep5NoabDam1W8UDMh_avatar.png?v=4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a\",\n" +
|
||||
" \"header\": \"\",\n" +
|
||||
" \"header_static\": \"\",\n" +
|
||||
" \"emojis\": [],\n" +
|
||||
" \"moved\": null,\n" +
|
||||
" \"fields\": null,\n" +
|
||||
" \"bot\": false,\n" +
|
||||
" \"software\": \"pixelfed\",\n" +
|
||||
" \"is_admin\": false\n" +
|
||||
" }"
|
||||
@get:Rule
|
||||
var activityRule: ActivityScenarioRule<MainActivity>
|
||||
= ActivityScenarioRule(MainActivity::class.java)
|
||||
|
||||
@Before
|
||||
fun openProfileFragment() {
|
||||
onView(withId(R.id.activity_main_account_btn)).perform(click())
|
||||
}
|
||||
|
||||
@Before
|
||||
fun before(){
|
||||
val server = MockWebServer()
|
||||
server.enqueue(MockResponse().addHeader("Content-Type", "application/json; charset=utf-8").setBody(accountJson))
|
||||
server.start()
|
||||
val baseUrl = server.url("")
|
||||
val preferences = InstrumentationRegistry.getInstrumentation()
|
||||
.targetContext.getSharedPreferences("com.h.pixeldroid.pref", Context.MODE_PRIVATE)
|
||||
preferences.edit().putString("accessToken", "azerty").apply()
|
||||
preferences.edit().putString("domain", baseUrl.toString()).apply()
|
||||
ActivityScenario.launch(MainActivity::class.java)
|
||||
}
|
||||
@Test
|
||||
fun randomUsernameCorrectlyLoadedTest() {
|
||||
Thread.sleep(5000) // wait for the username to load (to modify once we know how)
|
||||
onView(withId(R.id.accountName)).check(matches(not(withText(R.string.no_username))))
|
||||
fun testFollowersTextView() {
|
||||
onView(withId(R.id.view_pager)).perform(ViewActions.swipeLeft()).perform(ViewActions.swipeLeft()).perform(
|
||||
ViewActions.swipeLeft()
|
||||
).perform(ViewActions.swipeLeft())
|
||||
Thread.sleep(1000)
|
||||
onView(withId(R.id.followers)).check(matches(withText("Followers")))
|
||||
onView(withId(R.id.accountName)).check(matches(withText("deerbard_photo")))
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,17 +1,22 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import android.content.Context
|
||||
import android.view.Gravity
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.contrib.DrawerActions
|
||||
import androidx.test.espresso.contrib.DrawerMatchers.isClosed
|
||||
import androidx.test.espresso.contrib.NavigationViewActions
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
|
@ -21,24 +26,27 @@ class SettingsTest {
|
|||
= ActivityScenarioRule(MainActivity::class.java)
|
||||
|
||||
@Before
|
||||
fun openDrawer() {
|
||||
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
fun before(){
|
||||
val preferences = InstrumentationRegistry.getInstrumentation()
|
||||
.targetContext.getSharedPreferences("com.h.pixeldroid.pref", Context.MODE_PRIVATE)
|
||||
preferences.edit().putString("accessToken", "azerty").apply()
|
||||
preferences.edit().putString("domain", "http://localhost").apply()
|
||||
ActivityScenario.launch(MainActivity::class.java)
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun myProfileButtonTest() {
|
||||
onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_account))
|
||||
onView(withId(R.id.profile_main_container)).check(matches(isDisplayed()))
|
||||
}
|
||||
fun testDrawerSettingsButton() {
|
||||
// Open Drawer to click on navigation.
|
||||
onView(withId(R.id.drawer_layout))
|
||||
.check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed.
|
||||
.perform(DrawerActions.open()); // Open Drawer
|
||||
|
||||
@Test
|
||||
fun settingsButtonTest() {
|
||||
// Start the screen of your activity.
|
||||
onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_settings))
|
||||
onView(withId(R.id.settings)).check(matches(isDisplayed()))
|
||||
|
||||
// Check that settings activity was opened.
|
||||
onView(withText(R.string.signature_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun accessibilityButtonTest() {
|
||||
// TODO if some accessibility view is added
|
||||
}
|
||||
}
|
|
@ -1,13 +1,18 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions.swipeLeft
|
||||
import androidx.test.espresso.action.ViewActions.swipeRight
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||
import androidx.test.rule.ActivityTestRule
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
@ -17,17 +22,19 @@ class SwipeTest {
|
|||
@get:Rule
|
||||
var activityRule: ActivityScenarioRule<MainActivity>
|
||||
= ActivityScenarioRule(MainActivity::class.java)
|
||||
@Before
|
||||
fun before(){
|
||||
val preferences = getInstrumentation()
|
||||
.targetContext.getSharedPreferences("com.h.pixeldroid.pref", Context.MODE_PRIVATE)
|
||||
preferences.edit().putString("accessToken", "azerty").apply()
|
||||
preferences.edit().putString("domain", "http://localhost").apply()
|
||||
ActivityScenario.launch(MainActivity::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun swipingRightOnHomepageShowsSettings() {
|
||||
onView(withId(R.id.main_linear_layout)).perform(swipeRight())
|
||||
onView(withId(R.id.nav_view)).check(matches(isDisplayed()))
|
||||
}
|
||||
onView(withId(R.id.view_pager)).perform(swipeLeft()).perform(swipeLeft()).perform(swipeLeft()).perform(swipeLeft())
|
||||
onView(withId(R.id.nbFollowers)).check(matches(isDisplayed()))
|
||||
|
||||
@Test
|
||||
fun swipeLeftOnHomePageShowsProfile() {
|
||||
// to modify when we add more tabs
|
||||
onView(withId(R.id.main_linear_layout)).perform(swipeLeft())
|
||||
onView(withId(R.id.profile_main_container)).check(matches(isDisplayed()))
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
|
|
|
@ -49,6 +49,9 @@ class LoginActivity : AppCompatActivity() {
|
|||
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
}
|
||||
|
||||
private fun onClickConnect() {
|
||||
|
||||
connect_instance_button.isEnabled = false
|
||||
|
@ -62,9 +65,9 @@ class LoginActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
preferences.edit()
|
||||
.putString("domain", normalizedDomain)
|
||||
.putString("domain", "https://$normalizedDomain")
|
||||
.apply()
|
||||
registerAppToServer(normalizedDomain)
|
||||
registerAppToServer("https://$normalizedDomain")
|
||||
|
||||
}
|
||||
|
||||
|
@ -97,14 +100,14 @@ class LoginActivity : AppCompatActivity() {
|
|||
return failedRegistration()
|
||||
}
|
||||
}
|
||||
PixelfedAPI.create("https://$normalizedDomain").registerApplication(
|
||||
PixelfedAPI.create(normalizedDomain).registerApplication(
|
||||
APP_NAME,"$OAUTH_SCHEME://$PACKAGE_ID", SCOPE
|
||||
).enqueue(callback)
|
||||
}
|
||||
|
||||
private fun promptOAuth(normalizedDomain: String, client_id: String) {
|
||||
|
||||
val url = "https://$normalizedDomain/oauth/authorize?" +
|
||||
val url = "$normalizedDomain/oauth/authorize?" +
|
||||
"client_id" + "=" + client_id + "&" +
|
||||
"redirect_uri" + "=" + "$OAUTH_SCHEME://$PACKAGE_ID" + "&" +
|
||||
"response_type=code" + "&" +
|
||||
|
@ -150,7 +153,7 @@ class LoginActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
PixelfedAPI.create("https://$domain")
|
||||
PixelfedAPI.create("$domain")
|
||||
.obtainToken(
|
||||
clientId, clientSecret, "$OAUTH_SCHEME://$PACKAGE_ID", SCOPE, code,
|
||||
"authorization_code"
|
||||
|
|
|
@ -1,40 +1,43 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.widget.Button
|
||||
import android.widget.ImageButton
|
||||
import android.widget.LinearLayout
|
||||
|
||||
import androidx.annotation.NonNull
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.h.pixeldroid.fragments.HomeFragment
|
||||
import com.h.pixeldroid.fragments.ProfileFragment
|
||||
import com.h.pixeldroid.motions.OnSwipeListener
|
||||
|
||||
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||
|
||||
private lateinit var drawerLayout: DrawerLayout
|
||||
private val newPostsActivityRequestCode = Activity.RESULT_OK
|
||||
private lateinit var viewPager: ViewPager2
|
||||
private lateinit var tabLayout: TabLayout
|
||||
private lateinit var preferences: SharedPreferences
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
val mainLinearLayout : LinearLayout = findViewById(R.id.main_linear_layout)
|
||||
val homepageButton : ImageButton = findViewById(R.id.activity_main_home_btn)
|
||||
val accountButton : ImageButton = findViewById(R.id.activity_main_account_btn)
|
||||
preferences = getSharedPreferences(
|
||||
"${BuildConfig.APPLICATION_ID}.pref", Context.MODE_PRIVATE
|
||||
)
|
||||
|
||||
homepageButton.setOnClickListener {
|
||||
launchFragment(HomeFragment())
|
||||
}
|
||||
accountButton.setOnClickListener {
|
||||
launchFragment(ProfileFragment())
|
||||
//Check if we have logged in and gotten an access token
|
||||
if(!preferences.contains("accessToken")){
|
||||
launchActivity(LoginActivity())
|
||||
}
|
||||
|
||||
// Setup the drawer
|
||||
|
@ -42,33 +45,31 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
val navigationView: NavigationView = findViewById(R.id.nav_view)
|
||||
navigationView.setNavigationItemSelectedListener(this)
|
||||
|
||||
val onSwipeListener = object: OnSwipeListener(this) {
|
||||
override fun onSwipeRight() = swipeRight()
|
||||
override fun onSwipeLeft() = swipeLeft()
|
||||
val tabs = arrayOf(HomeFragment(), Fragment(), Fragment(), Fragment(), ProfileFragment())
|
||||
setupTabs(tabs)
|
||||
}
|
||||
|
||||
private fun setupTabs(tabs: Array<Fragment>){
|
||||
viewPager = findViewById(R.id.view_pager)
|
||||
viewPager.adapter = object : FragmentStateAdapter(this) {
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
return tabs[position]
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return 5
|
||||
}
|
||||
}
|
||||
mainLinearLayout.setOnTouchListener(onSwipeListener)
|
||||
|
||||
// default fragment that displays when we open the app
|
||||
launchFragment(HomeFragment())
|
||||
}
|
||||
|
||||
private fun swipeRight() {
|
||||
// TODO: correctly switch between tabs
|
||||
drawerLayout.openDrawer(GravityCompat.START)
|
||||
}
|
||||
|
||||
private fun swipeLeft() {
|
||||
// TODO: correctly switch between tabs
|
||||
supportFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_from_right, R.anim.slide_to_left)
|
||||
.replace(R.id.fragment_container, ProfileFragment()).commit()
|
||||
}
|
||||
|
||||
/*
|
||||
Launches the given fragment and put it as the current "activity"
|
||||
*/
|
||||
private fun launchFragment(fragment: Fragment) {
|
||||
supportFragmentManager.beginTransaction().replace(R.id.fragment_container, fragment).commit()
|
||||
tabLayout = findViewById(R.id.tabs)
|
||||
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
|
||||
when(position){
|
||||
0 -> tab.icon = getDrawable(R.drawable.ic_home_white_24dp)
|
||||
1 -> tab.icon = getDrawable(R.drawable.ic_search_white_24dp)
|
||||
2 -> tab.icon = getDrawable(R.drawable.ic_photo_camera_white_24dp)
|
||||
3 -> tab.icon = getDrawable(R.drawable.ic_star_white_24dp)
|
||||
4 -> tab.icon = getDrawable(R.drawable.ic_person_white_24dp)
|
||||
}
|
||||
}.attach()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -77,7 +78,6 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
override fun onNavigationItemSelected(@NonNull item: MenuItem): Boolean {
|
||||
when (item.itemId){
|
||||
R.id.nav_settings -> launchActivity(SettingsActivity())
|
||||
R.id.nav_account -> launchFragment(ProfileFragment())
|
||||
}
|
||||
|
||||
drawerLayout.closeDrawer(GravityCompat.START)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.h.pixeldroid.api
|
||||
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.objects.Application
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.objects.Token
|
||||
|
@ -7,11 +8,7 @@ import retrofit2.Call
|
|||
import retrofit2.Retrofit
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.http.FormUrlEncoded
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Query
|
||||
import retrofit2.http.Field
|
||||
import retrofit2.http.*
|
||||
|
||||
|
||||
/*
|
||||
|
@ -53,6 +50,23 @@ interface PixelfedAPI {
|
|||
): Call<List<Status>>
|
||||
|
||||
|
||||
@GET("/api/v1/timelines/home")
|
||||
fun timelineHome(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Header("Authorization") authorization: String,
|
||||
@Query("max_id") max_id: String? = null,
|
||||
@Query("since_id") since_id: String? = null,
|
||||
@Query("min_id") min_id: String? = null,
|
||||
@Query("limit") limit: Int? = null,
|
||||
@Query("local") local: Boolean? = null
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("/api/v1/accounts/verify_credentials")
|
||||
fun verifyCredentials(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Header("Authorization") authorization: String
|
||||
): Call<Account>
|
||||
|
||||
companion object {
|
||||
fun create(baseUrl: String): PixelfedAPI {
|
||||
return Retrofit.Builder()
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
package com.h.pixeldroid.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import com.h.pixeldroid.LoginActivity
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.h.pixeldroid.R
|
||||
|
||||
|
||||
|
@ -19,11 +15,6 @@ class HomeFragment : Fragment() {
|
|||
): View? {
|
||||
val view: View = inflater.inflate(R.layout.fragment_home, container, false)
|
||||
|
||||
val loginButton: Button = view.findViewById(R.id.button_start_login)
|
||||
loginButton.setOnClickListener {
|
||||
startActivity(Intent(view.context, LoginActivity::class.java))
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.h.pixeldroid.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
|
@ -8,12 +10,10 @@ import androidx.fragment.app.Fragment
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.h.pixeldroid.LoginActivity
|
||||
|
||||
import com.h.pixeldroid.BuildConfig
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.objects.Account
|
||||
|
@ -22,47 +22,47 @@ import retrofit2.Call
|
|||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
const val BASE_URL = "https://pixelfed.de/"
|
||||
|
||||
class ProfileFragment : Fragment() {
|
||||
private lateinit var preferences: SharedPreferences
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val view: View = inflater.inflate(R.layout.fragment_profile, container, false)
|
||||
preferences = this.activity!!.getSharedPreferences(
|
||||
"${BuildConfig.APPLICATION_ID}.pref", Context.MODE_PRIVATE
|
||||
)
|
||||
return inflater.inflate(R.layout.fragment_profile, container, false)
|
||||
}
|
||||
|
||||
var statuses: ArrayList<Status>?
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val pixelfedAPI = PixelfedAPI.create(BASE_URL)
|
||||
val pixelfedAPI = PixelfedAPI.create("${preferences.getString("domain", "")}")
|
||||
val accessToken = preferences.getString("accessToken", "")
|
||||
|
||||
pixelfedAPI.timelinePublic(null, null, null, null, null)
|
||||
.enqueue(object : Callback<List<Status>> {
|
||||
override fun onResponse(call: Call<List<Status>>, response: Response<List<Status>>) {
|
||||
pixelfedAPI.verifyCredentials("Bearer $accessToken")
|
||||
.enqueue(object : Callback<Account> {
|
||||
override fun onResponse(call: Call<Account>, response: Response<Account>) {
|
||||
if (response.code() == 200) {
|
||||
statuses = response.body() as ArrayList<Status>?
|
||||
val account = response.body()!!
|
||||
|
||||
if(!statuses.isNullOrEmpty()) {
|
||||
setContent(view, account)
|
||||
|
||||
val account = statuses!![0].account
|
||||
|
||||
setContent(view, account)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<Status>>, t: Throwable) {
|
||||
Log.e("Ouch, not OK", t.toString())
|
||||
override fun onFailure(call: Call<Account>, t: Throwable) {
|
||||
Log.e("ProfileFragment:", t.toString())
|
||||
}
|
||||
})
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
private fun setContent(view: View, account: Account) {
|
||||
// ImageView : profile picture
|
||||
val profilePicture = view.findViewById<ImageView>(R.id.profilePicture)
|
||||
Glide.with(view.context.applicationContext).load(account.avatar).into(profilePicture)
|
||||
Glide.with(view.context).load(account.avatar).into(profilePicture)
|
||||
|
||||
|
||||
// TextView : description / bio
|
||||
val description = view.findViewById<TextView>(R.id.description)
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
package com.h.pixeldroid.motions
|
||||
|
||||
import android.content.Context
|
||||
import android.view.GestureDetector
|
||||
import android.view.GestureDetector.SimpleOnGestureListener
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.View.OnTouchListener
|
||||
import kotlin.math.abs
|
||||
|
||||
const val SWIPE_DISTANCE_THRESHOLD: Int = 100
|
||||
const val SWIPE_VELOCITY_THRESHOLD: Int = 100
|
||||
|
||||
/**
|
||||
* Detects left and right swipes across a view.
|
||||
*
|
||||
* inspired from https://stackoverflow.com/questions/4139288/android-how-to-handle-right-to-left-swipe-gestures
|
||||
*/
|
||||
open class OnSwipeListener(context: Context?) : OnTouchListener {
|
||||
|
||||
private val gestureDetector: GestureDetector = GestureDetector(context, GestureListener())
|
||||
|
||||
override fun onTouch(v: View?, event: MotionEvent?): Boolean =
|
||||
gestureDetector.onTouchEvent(event)
|
||||
|
||||
// redefining gesture listener to call our custom functions
|
||||
private inner class GestureListener : SimpleOnGestureListener() {
|
||||
|
||||
override fun onDown(e: MotionEvent): Boolean = true
|
||||
|
||||
override fun onFling(
|
||||
e1: MotionEvent,
|
||||
e2: MotionEvent,
|
||||
velocityX: Float,
|
||||
velocityY: Float
|
||||
): Boolean {
|
||||
val distanceX = e2.x - e1.x
|
||||
val distanceY = e2.y - e1.y
|
||||
if (abs(distanceX) > abs(distanceY) // swipe on the side and not up or down
|
||||
&& abs(distanceX) > SWIPE_DISTANCE_THRESHOLD
|
||||
&& abs(velocityX) > SWIPE_VELOCITY_THRESHOLD
|
||||
) {
|
||||
if (distanceX > 0) onSwipeRight() else onSwipeLeft()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
open fun onSwipeLeft() {}
|
||||
|
||||
open fun onSwipeRight() {}
|
||||
}
|
|
@ -12,69 +12,26 @@
|
|||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/main_linear_layout">
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/fragment_container"
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/colorPrimary"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/activity_main_home_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="10dp"
|
||||
app:srcCompat="@drawable/ic_home_white_24dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/activity_main_search_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:padding="10dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:srcCompat="@drawable/ic_search_white_24dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/activity_main_camera_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:padding="10dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:srcCompat="@drawable/ic_photo_camera_white_24dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/activity_main_favorite_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:padding="10dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:srcCompat="@drawable/ic_star_white_24dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/activity_main_account_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
app:srcCompat="@drawable/ic_person_white_24dp" />
|
||||
</LinearLayout>
|
||||
app:tabMode="fixed"
|
||||
app:tabBackground="@color/colorPrimary">
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
<com.google.android.material.navigation.NavigationView
|
||||
android:id="@+id/nav_view"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -9,15 +9,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_start_login"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/start_login" />
|
||||
|
||||
</LinearLayout>
|
||||
android:gravity="center"/>
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">localhost</domain>
|
||||
</domain-config>
|
||||
</network-security-config>
|
File diff suppressed because one or more lines are too long
|
@ -1,20 +0,0 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import com.h.pixeldroid.motions.OnSwipeListener
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class OnSwipeListenerUnitTest {
|
||||
|
||||
@Test
|
||||
fun undefinedSwipeRightDoesNothingTest() {
|
||||
val swipeListener = OnSwipeListener(null)
|
||||
assertEquals(Unit, swipeListener.onSwipeRight())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun undefinedSwipeLeftDoesNothingTest() {
|
||||
val swipeListener = OnSwipeListener(null)
|
||||
assertEquals(Unit, swipeListener.onSwipeLeft())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue