Merge with master
This commit is contained in:
commit
e1a1e88e65
@ -1,4 +1,5 @@
|
||||
# PixelDroid
|
||||
Software Development Project course, EPFL, Spring 2020
|
||||

|
||||
Free (as in freedom) Android client for Pixelfed, the federated image sharing platform.
|
||||
|
||||
[](https://gitlab.com/Matttter/PixelDroid/pipelines) [](https://codeclimate.com/github/H-PixelDroid/PixelDroid/maintainability) [](https://codeclimate.com/github/H-PixelDroid/PixelDroid/test_coverage)
|
||||
[](https://gitlab.com/Matttter/PixelDroid/pipelines) [](https://codeclimate.com/github/H-PixelDroid/PixelDroid/maintainability) [](https://codeclimate.com/github/H-PixelDroid/PixelDroid/test_coverage) [](https://weblate.pixeldroid.org/engage/pixeldroid/?utm_source=widget)
|
||||
|
@ -105,7 +105,6 @@ dependencies {
|
||||
def fragment_version = '1.2.4'
|
||||
debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
|
||||
|
||||
|
||||
}
|
||||
|
||||
tasks.withType(Test) {
|
||||
|
@ -76,6 +76,17 @@ class MockedServerTest {
|
||||
Thread.sleep(3000)
|
||||
onView(first(withId(R.id.tag_name))).check(matches(withText("#caturday")))
|
||||
|
||||
}
|
||||
@Test
|
||||
fun openDiscoverPost(){
|
||||
activityScenario.onActivity{
|
||||
a -> a.findViewById<TabLayout>(R.id.tabs).getTabAt(1)?.select()
|
||||
}
|
||||
Thread.sleep(1000)
|
||||
onView(withId(R.id.discoverList)).perform(click())
|
||||
Thread.sleep(1000)
|
||||
onView(withId(R.id.username)).check(matches(withText("machintuck")))
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -201,18 +212,23 @@ class MockedServerTest {
|
||||
Thread.sleep(10000)
|
||||
onView(withText("Dante")).check(matches(withId(R.id.accountNameTextView)))
|
||||
}
|
||||
/*
|
||||
|
||||
@Test
|
||||
fun swipingLeftStopsAtProfile() {
|
||||
onView(withId(R.id.main_activity_main_linear_layout))
|
||||
.perform(ViewActions.swipeLeft()) // search
|
||||
.perform(ViewActions.swipeLeft()) // camera
|
||||
.perform(ViewActions.swipeLeft()) // notifications
|
||||
.perform(ViewActions.swipeLeft()) // profile
|
||||
.perform(ViewActions.swipeLeft()) // should stop at profile
|
||||
onView(withId(R.id.nbFollowersTextView)).check(matches(isDisplayed()))
|
||||
fun clickNotificationRePost() {
|
||||
ActivityScenario.launch(MainActivity::class.java).onActivity{
|
||||
a -> a.findViewById<TabLayout>(R.id.tabs).getTabAt(3)?.select()
|
||||
}
|
||||
Thread.sleep(1000)
|
||||
|
||||
onView(withId(R.id.view_pager)).perform(ViewActions.swipeUp()).perform(ViewActions.swipeDown())
|
||||
Thread.sleep(1000)
|
||||
|
||||
onView(withText("Clement shared your post")).perform(ViewActions.click())
|
||||
Thread.sleep(1000)
|
||||
|
||||
onView(first(withText("Clement"))).check(matches(withId(R.id.username)))
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
fun swipingRightStopsAtHomepage() {
|
||||
activityScenario.onActivity {
|
||||
@ -229,6 +245,38 @@ class MockedServerTest {
|
||||
onView(withId(R.id.list)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun swipingLeftStopsAtPublicTimeline() {
|
||||
activityScenario.onActivity {
|
||||
a -> a.findViewById<TabLayout>(R.id.tabs).getTabAt(0)?.select()
|
||||
}
|
||||
|
||||
Thread.sleep(1000)
|
||||
onView(withId(R.id.main_activity_main_linear_layout))
|
||||
.perform(ViewActions.swipeLeft()) // notifications
|
||||
.perform(ViewActions.swipeLeft()) // camera
|
||||
.perform(ViewActions.swipeLeft()) // search
|
||||
.perform(ViewActions.swipeLeft()) // homepage
|
||||
.perform(ViewActions.swipeLeft()) // should stop at homepage
|
||||
onView(withId(R.id.list)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun swipingPublicTimelineWorks() {
|
||||
activityScenario.onActivity {
|
||||
a -> a.findViewById<TabLayout>(R.id.tabs).getTabAt(4)?.select()
|
||||
} // go to the last tab
|
||||
|
||||
Thread.sleep(1000)
|
||||
onView(withId(R.id.main_activity_main_linear_layout))
|
||||
.perform(ViewActions.swipeUp()) // notifications
|
||||
.perform(ViewActions.swipeUp()) // camera
|
||||
.perform(ViewActions.swipeUp()) // search
|
||||
.perform(ViewActions.swipeUp()) // homepage
|
||||
.perform(ViewActions.swipeUp()) // should stop at homepage
|
||||
onView(withId(R.id.list)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clickingTabOnAlbumShowsNextPhoto() {
|
||||
ActivityScenario.launch(MainActivity::class.java).onActivity {
|
||||
|
174
app/src/androidTest/java/com/h/pixeldroid/PostTest.kt
Normal file
174
app/src/androidTest/java/com/h/pixeldroid/PostTest.kt
Normal file
@ -0,0 +1,174 @@
|
||||
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
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.action.ViewActions.longClick
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.intent.Intents
|
||||
import androidx.test.espresso.intent.matcher.IntentMatchers
|
||||
import androidx.test.espresso.intent.rule.IntentsTestRule
|
||||
import androidx.test.espresso.matcher.RootMatchers
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.objects.Attachment
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.testUtility.MockServer
|
||||
import org.hamcrest.CoreMatchers
|
||||
import org.hamcrest.Matcher
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.Timeout
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class PostTest {
|
||||
|
||||
private lateinit var context: Context
|
||||
|
||||
@get:Rule
|
||||
var globalTimeout: Timeout = Timeout.seconds(100)
|
||||
|
||||
@Before
|
||||
fun before(){
|
||||
context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
val mockServer = MockServer()
|
||||
mockServer.start()
|
||||
val baseUrl = mockServer.getUrl()
|
||||
val preferences = context.getSharedPreferences(
|
||||
"com.h.pixeldroid.pref",
|
||||
Context.MODE_PRIVATE)
|
||||
preferences.edit().putString("accessToken", "azerty").apply()
|
||||
preferences.edit().putString("domain", baseUrl.toString()).apply()
|
||||
Intents.init()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun saveToGalleryTestSimplePost() {
|
||||
val attachment = Attachment(
|
||||
id = "12",
|
||||
url = "https://wiki.gnugen.ch/lib/tpl/gnugen/images/logo_web.png"
|
||||
)
|
||||
val post = Status(
|
||||
id = "12",
|
||||
account = Account(
|
||||
id = "12",
|
||||
username = "douze",
|
||||
url = "https://pixelfed.de/douze"
|
||||
),
|
||||
media_attachments = listOf(attachment)
|
||||
)
|
||||
val intent = Intent(context, PostActivity::class.java)
|
||||
intent.putExtra(Status.POST_TAG, post)
|
||||
ActivityScenario.launch<PostActivity>(intent)
|
||||
onView(withId(R.id.postPicture)).perform(longClick())
|
||||
onView(withText(R.string.save_to_gallery)).inRoot(RootMatchers.isPlatformPopup()).perform(click())
|
||||
Thread.sleep(300)
|
||||
onView(withText(R.string.image_download_downloading)).inRoot(
|
||||
RootMatchers.hasWindowLayoutParams()
|
||||
).check(matches(isDisplayed()))
|
||||
Thread.sleep(5000)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun saveToGalleryTestAlbum() {
|
||||
val attachment1 = Attachment(
|
||||
id = "12",
|
||||
url = "https://wiki.gnugen.ch/lib/tpl/gnugen/images/logo_web.png"
|
||||
)
|
||||
val attachment2 = Attachment(
|
||||
id = "13",
|
||||
url = "https://wiki.gnugen.ch/lib/tpl/gnugen/images/logo_web.png"
|
||||
)
|
||||
val post = Status(
|
||||
id = "12",
|
||||
account = Account(
|
||||
id = "12",
|
||||
username = "douze",
|
||||
url = "https://pixelfed.de/douze"
|
||||
),
|
||||
media_attachments = listOf(attachment1, attachment2)
|
||||
)
|
||||
val intent = Intent(context, PostActivity::class.java)
|
||||
intent.putExtra(Status.POST_TAG, post)
|
||||
ActivityScenario.launch<PostActivity>(intent)
|
||||
onView(withId(R.id.imageImageView)).perform(longClick())
|
||||
onView(withText(R.string.save_to_gallery)).inRoot(RootMatchers.isPlatformPopup()).perform(click())
|
||||
Thread.sleep(300)
|
||||
onView(withText(R.string.image_download_downloading)).inRoot(
|
||||
RootMatchers.hasWindowLayoutParams()
|
||||
).check(matches(isDisplayed()))
|
||||
Thread.sleep(5000)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shareTestSimplePost() {
|
||||
val expectedIntent: Matcher<Intent> = IntentMatchers.hasAction(Intent.ACTION_CHOOSER)
|
||||
val attachment = Attachment(
|
||||
id = "12",
|
||||
url = "https://wiki.gnugen.ch/lib/tpl/gnugen/images/logo_web.png"
|
||||
)
|
||||
val post = Status(
|
||||
id = "12",
|
||||
account = Account(
|
||||
id = "12",
|
||||
username = "douze",
|
||||
url = "https://pixelfed.de/douze"
|
||||
),
|
||||
media_attachments = listOf(attachment)
|
||||
)
|
||||
val intent = Intent(context, PostActivity::class.java)
|
||||
intent.putExtra(Status.POST_TAG, post)
|
||||
ActivityScenario.launch<PostActivity>(intent)
|
||||
onView(withId(R.id.postPicture)).perform(longClick())
|
||||
onView(withText(R.string.share_picture)).inRoot(RootMatchers.isPlatformPopup()).perform(click())
|
||||
Thread.sleep(2000)
|
||||
Intents.intended(expectedIntent)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shareIntentAlbumTest() {
|
||||
val expectedIntent: Matcher<Intent> = IntentMatchers.hasAction(Intent.ACTION_CHOOSER)
|
||||
val attachment1 = Attachment(
|
||||
id = "12",
|
||||
url = "https://wiki.gnugen.ch/lib/tpl/gnugen/images/logo_web.png"
|
||||
)
|
||||
val attachment2 = Attachment(
|
||||
id = "13",
|
||||
url = "https://wiki.gnugen.ch/lib/tpl/gnugen/images/logo_web.png"
|
||||
)
|
||||
val post = Status(
|
||||
id = "12",
|
||||
account = Account(
|
||||
id = "12",
|
||||
username = "douze",
|
||||
url = "https://pixelfed.de/douze"
|
||||
),
|
||||
media_attachments = listOf(attachment1, attachment2)
|
||||
)
|
||||
val intent = Intent(context, PostActivity::class.java)
|
||||
intent.putExtra(Status.POST_TAG, post)
|
||||
ActivityScenario.launch<PostActivity>(intent)
|
||||
onView(withId(R.id.imageImageView)).perform(longClick())
|
||||
onView(withText(R.string.share_picture)).inRoot(RootMatchers.isPlatformPopup()).perform(click())
|
||||
Thread.sleep(2000)
|
||||
Intents.intended(expectedIntent)
|
||||
}
|
||||
|
||||
@After
|
||||
fun after() {
|
||||
Intents.release()
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.h.pixeldroid">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
@ -19,20 +20,32 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".PostCreationActivity" />
|
||||
<activity android:name=".FollowsActivity" />
|
||||
<activity android:name=".PostActivity" />
|
||||
<activity android:name=".ProfileActivity" />
|
||||
<activity android:name=".PostCreationActivity"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity" />
|
||||
<activity android:name=".FollowsActivity"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity"/>
|
||||
<activity android:name=".PostActivity"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity"/>
|
||||
<activity android:name=".ProfileActivity"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity"/>
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:label="@string/title_activity_settings2">
|
||||
android:label="@string/title_activity_settings2"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MainActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:theme="@style/AppTheme.Launcher">
|
||||
android:theme="@style/AppTheme.Launcher"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
@ -41,7 +54,9 @@
|
||||
<activity
|
||||
android:name=".LoginActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
@ -55,9 +70,13 @@
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".SearchActivity"
|
||||
android:launchMode="singleTop">
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEARCH" />
|
||||
<action android:name="android.intent.action.SEARCH"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity"/>
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.searchable"
|
||||
|
@ -8,10 +8,13 @@ import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.PopupMenu
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.RequestBuilder
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
import com.h.pixeldroid.utils.ImageUtils
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.*
|
||||
import java.io.Serializable
|
||||
|
||||
@ -38,9 +41,30 @@ class ImageFragment : Fragment() {
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_image, container, false)
|
||||
|
||||
view.findViewById<ImageView>(R.id.imageImageView).setOnLongClickListener {
|
||||
PopupMenu(view.context, it).apply {
|
||||
setOnMenuItemClickListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.image_popup_menu_save_to_gallery -> {
|
||||
ImageUtils.downloadImage(requireActivity(), view.context, imgUrl)
|
||||
true
|
||||
}
|
||||
R.id.image_popup_menu_share_picture -> {
|
||||
ImageUtils.downloadImage(requireActivity(), view.context, imgUrl, share = true)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
inflate(R.menu.image_popup_menu)
|
||||
show()
|
||||
}
|
||||
true
|
||||
}
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_image, container, false)
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@ -52,6 +76,7 @@ class ImageFragment : Fragment() {
|
||||
.placeholder(ColorDrawable(Color.GRAY))
|
||||
|
||||
picRequest.load(imgUrl).into(imageView)
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -24,6 +24,7 @@ import com.h.pixeldroid.fragments.NewPostFragment
|
||||
import com.h.pixeldroid.fragments.SearchDiscoverFragment
|
||||
import com.h.pixeldroid.fragments.feeds.PostsFeedFragment
|
||||
import com.h.pixeldroid.fragments.feeds.NotificationsFragment
|
||||
import com.h.pixeldroid.fragments.feeds.PublicTimelineFragment
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
import retrofit2.Call
|
||||
@ -53,7 +54,16 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||
launchActivity(LoginActivity())
|
||||
} else {
|
||||
setupDrawer()
|
||||
setupTabs()
|
||||
|
||||
val tabs = arrayOf(
|
||||
PostsFeedFragment(),
|
||||
searchDiscoverFragment,
|
||||
NewPostFragment(),
|
||||
NotificationsFragment(),
|
||||
PublicTimelineFragment()
|
||||
)
|
||||
|
||||
setupTabs(tabs)
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,19 +98,13 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<Account>, t: Throwable) {
|
||||
Log.e("ProfileActivity:", t.toString())
|
||||
Log.e("DRAWER ACCOUNT:", t.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setupTabs(){
|
||||
val tabs = arrayOf(
|
||||
PostsFeedFragment(),
|
||||
searchDiscoverFragment,
|
||||
NewPostFragment(),
|
||||
NotificationsFragment(),
|
||||
Fragment()
|
||||
)
|
||||
|
||||
private fun setupTabs(tabs: Array<Fragment>){
|
||||
|
||||
viewPager = findViewById(R.id.view_pager)
|
||||
viewPager.adapter = object : FragmentStateAdapter(this) {
|
||||
@ -119,7 +123,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||
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_heart)
|
||||
4 -> tab.icon = getDrawable(R.drawable.ic_person_white_24dp)
|
||||
4 -> tab.icon = getDrawable(R.drawable.ic_filter_black_24dp)
|
||||
}
|
||||
}.attach()
|
||||
}
|
||||
|
@ -1,28 +1,80 @@
|
||||
package com.h.pixeldroid
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.fragments.PostFragment
|
||||
import com.h.pixeldroid.objects.DiscoverPost
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.objects.Status.Companion.DISCOVER_TAG
|
||||
import com.h.pixeldroid.objects.Status.Companion.DOMAIN_TAG
|
||||
import com.h.pixeldroid.objects.Status.Companion.POST_TAG
|
||||
|
||||
|
||||
import kotlinx.android.synthetic.main.activity_post.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
class PostActivity : AppCompatActivity() {
|
||||
private lateinit var preferences: SharedPreferences
|
||||
lateinit var postFragment : PostFragment
|
||||
lateinit var domain : String
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_post)
|
||||
|
||||
val status = intent.getSerializableExtra(POST_TAG) as Status?
|
||||
val discoverPost: DiscoverPost? = intent.getSerializableExtra(DISCOVER_TAG) as DiscoverPost?
|
||||
|
||||
preferences = getSharedPreferences(
|
||||
"${BuildConfig.APPLICATION_ID}.pref", Context.MODE_PRIVATE
|
||||
)
|
||||
domain = preferences.getString("domain", "")!!
|
||||
|
||||
postFragment = PostFragment()
|
||||
val arguments = Bundle()
|
||||
arguments.putString(DOMAIN_TAG, domain)
|
||||
|
||||
if (discoverPost != null) {
|
||||
postProgressBar.visibility = View.VISIBLE
|
||||
getDiscoverPost(arguments, discoverPost)
|
||||
} else {
|
||||
initializeFragment(arguments, status)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDiscoverPost(
|
||||
arguments: Bundle,
|
||||
discoverPost: DiscoverPost
|
||||
) {
|
||||
val api = PixelfedAPI.create(domain)
|
||||
val accessToken = preferences.getString("accessToken", "") ?: ""
|
||||
val id = discoverPost.url?.substringAfterLast('/') ?: ""
|
||||
api.getStatus("Bearer $accessToken", id).enqueue(object : Callback<Status> {
|
||||
|
||||
override fun onFailure(call: Call<Status>, t: Throwable) {
|
||||
Log.e("PostActivity:", t.toString())
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call<Status>, response: Response<Status>) {
|
||||
if(response.code() == 200) {
|
||||
val status = response.body()!!
|
||||
postProgressBar.visibility = View.GONE
|
||||
initializeFragment(arguments, status)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun initializeFragment(arguments: Bundle, status: Status?){
|
||||
arguments.putSerializable(POST_TAG, status)
|
||||
postFragment.arguments = arguments
|
||||
|
||||
supportFragmentManager.beginTransaction()
|
||||
.add(R.id.postFragmentSingle, postFragment).commit()
|
||||
postFragmentSingle.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.fragments.ProfileBookmarkFragment
|
||||
import com.h.pixeldroid.fragments.ProfilePostFragment
|
||||
import com.h.pixeldroid.fragments.ProfileTabsFragment
|
||||
import com.h.pixeldroid.objects.Account
|
||||
import com.h.pixeldroid.objects.Account.Companion.ACCOUNT_TAG
|
||||
import com.h.pixeldroid.objects.Relationship
|
||||
@ -52,7 +51,13 @@ class ProfileActivity : AppCompatActivity() {
|
||||
// Set profile according to given account
|
||||
account = intent.getSerializableExtra(ACCOUNT_TAG) as Account?
|
||||
|
||||
if (account == null) {
|
||||
account?.let {
|
||||
setViews()
|
||||
activateFollow()
|
||||
|
||||
val tabs = arrayOf(ProfilePostFragment(), Fragment())
|
||||
setTabs(tabs)
|
||||
} ?: run {
|
||||
pixelfedAPI.verifyCredentials("Bearer $accessToken")
|
||||
.enqueue(object : Callback<Account> {
|
||||
override fun onResponse(call: Call<Account>, response: Response<Account>) {
|
||||
@ -73,14 +78,7 @@ class ProfileActivity : AppCompatActivity() {
|
||||
// Edit button redirects to Pixelfed's "edit account" page
|
||||
val editButton = findViewById<Button>(R.id.editButton)
|
||||
editButton.visibility = View.VISIBLE
|
||||
editButton.setOnClickListener { onClickEditButton() }
|
||||
|
||||
} else {
|
||||
setViews()
|
||||
activateFollow()
|
||||
|
||||
val tabs = arrayOf(ProfilePostFragment(), Fragment())
|
||||
setTabs(tabs)
|
||||
editButton.setOnClickListener{ onClickEditButton() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,17 @@ import retrofit2.http.Field
|
||||
|
||||
interface PixelfedAPI {
|
||||
|
||||
companion object {
|
||||
fun create(baseUrl: String): PixelfedAPI {
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(baseUrl)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
.build().create(PixelfedAPI::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v1/apps")
|
||||
fun registerApplication(
|
||||
@ -231,15 +242,11 @@ interface PixelfedAPI {
|
||||
@Path("id") accountId : String
|
||||
): Call<Account>
|
||||
|
||||
companion object {
|
||||
fun create(baseUrl: String): PixelfedAPI {
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(baseUrl)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
.build().create(PixelfedAPI::class.java)
|
||||
}
|
||||
}
|
||||
@GET("/api/v1/statuses/{id}")
|
||||
fun getStatus(
|
||||
@Header("Authorization") authorization: String,
|
||||
@Path("id") accountId : String
|
||||
): Call<Status>
|
||||
|
||||
@Multipart
|
||||
@POST("/api/v1/media")
|
||||
@ -252,5 +259,11 @@ interface PixelfedAPI {
|
||||
// get instance configuration
|
||||
@GET("/api/v1/instance")
|
||||
fun instance() : Call<Instance>
|
||||
|
||||
// get discover
|
||||
@GET("/api/v2/discover/posts")
|
||||
fun discover(
|
||||
@Header("Authorization") authorization: String
|
||||
) : Call<DiscoverPosts>
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.fragments.feeds.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
|
||||
|
||||
|
||||
@ -24,12 +25,13 @@ class PostFragment : Fragment() {
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val status = arguments?.getSerializable(POST_TAG) as Status?
|
||||
val domain = arguments?.getString(DOMAIN_TAG)!!
|
||||
val root = inflater.inflate(R.layout.post_fragment, container, false)
|
||||
val picRequest = Glide.with(this)
|
||||
.asDrawable().fitCenter()
|
||||
.placeholder(ColorDrawable(Color.GRAY))
|
||||
|
||||
status?.setupPost(root, picRequest, this)
|
||||
status?.setupPost(root, picRequest, this, domain, true)
|
||||
|
||||
//Setup arguments needed for the onclicklisteners
|
||||
val holder = PostViewHolder(root, requireContext())
|
||||
|
@ -32,9 +32,9 @@ class ProfilePostsRecyclerViewAdapter(
|
||||
setSquareImageFromURL(holder.postView, post.getPostPreviewURL(), holder.postPreview)
|
||||
|
||||
holder.postPreview.setOnClickListener {
|
||||
val intent = Intent(context, PostActivity::class.java)
|
||||
val intent = Intent(holder.postPreview.context, PostActivity::class.java)
|
||||
intent.putExtra(Status.POST_TAG, post)
|
||||
context.startActivity(intent)
|
||||
holder.postPreview.context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,25 +4,44 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.ProgressBar
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.h.pixeldroid.BuildConfig
|
||||
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.objects.DiscoverPost
|
||||
import com.h.pixeldroid.objects.DiscoverPosts
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
/**
|
||||
* This fragment lets you search and use PixelFed's Discover feature
|
||||
* This fragment lets you search and use Pixelfed's Discover feature
|
||||
*/
|
||||
|
||||
class SearchDiscoverFragment : Fragment() {
|
||||
lateinit var api: PixelfedAPI
|
||||
private lateinit var api: PixelfedAPI
|
||||
private lateinit var preferences: SharedPreferences
|
||||
private lateinit var recycler : RecyclerView
|
||||
private lateinit var adapter : DiscoverRecyclerViewAdapter
|
||||
private lateinit var accessToken: String
|
||||
private lateinit var discoverProgressBar: ProgressBar
|
||||
private lateinit var discoverRefreshLayout: SwipeRefreshLayout
|
||||
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
@ -37,6 +56,11 @@ class SearchDiscoverFragment : Fragment() {
|
||||
intent.putExtra("searchFeed", search.text.toString())
|
||||
startActivity(intent)
|
||||
}
|
||||
// Set posts RecyclerView as a grid with 3 columns
|
||||
recycler = view.findViewById(R.id.discoverList)
|
||||
recycler.layoutManager = GridLayoutManager(requireContext(), 3)
|
||||
adapter = DiscoverRecyclerViewAdapter()
|
||||
recycler.adapter = adapter
|
||||
|
||||
return view
|
||||
}
|
||||
@ -49,5 +73,67 @@ class SearchDiscoverFragment : Fragment() {
|
||||
api = PixelfedAPI.create("${preferences.getString("domain", "")}")
|
||||
accessToken = preferences.getString("accessToken", "") ?: ""
|
||||
|
||||
discoverProgressBar = view.findViewById(R.id.discoverProgressBar)
|
||||
discoverRefreshLayout = view.findViewById(R.id.discoverRefreshLayout)
|
||||
|
||||
getDiscover()
|
||||
|
||||
discoverRefreshLayout.setOnRefreshListener {
|
||||
getDiscover()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDiscover() {
|
||||
|
||||
api.discover("Bearer $accessToken")
|
||||
.enqueue(object : Callback<DiscoverPosts> {
|
||||
|
||||
override fun onFailure(call: Call<DiscoverPosts>, t: Throwable) {
|
||||
Log.e("SearchDiscoverFragment:", t.toString())
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call<DiscoverPosts>, response: Response<DiscoverPosts>) {
|
||||
if(response.code() == 200) {
|
||||
val discoverPosts = response.body()!!
|
||||
adapter.addPosts(discoverPosts.posts)
|
||||
discoverProgressBar.visibility = View.GONE
|
||||
discoverRefreshLayout.isRefreshing = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* [RecyclerView.Adapter] that can display a list of [DiscoverPost]s
|
||||
*/
|
||||
class DiscoverRecyclerViewAdapter: RecyclerView.Adapter<DiscoverRecyclerViewAdapter.ViewHolder>() {
|
||||
private val posts: ArrayList<DiscoverPost> = ArrayList()
|
||||
|
||||
fun addPosts(newPosts : List<DiscoverPost>) {
|
||||
posts.clear()
|
||||
posts.addAll(newPosts)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.fragment_profile_posts, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val post = posts[position]
|
||||
ImageConverter.setSquareImageFromURL(holder.postView, post.thumb, holder.postPreview)
|
||||
holder.postPreview.setOnClickListener {
|
||||
val intent = Intent(holder.postView.context, PostActivity::class.java)
|
||||
intent.putExtra(Status.DISCOVER_TAG, post)
|
||||
holder.postView.context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = posts.size
|
||||
|
||||
inner class ViewHolder(val postView: View) : RecyclerView.ViewHolder(postView) {
|
||||
val postPreview: ImageView = postView.findViewById(R.id.postPreview)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,12 +20,10 @@ import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.bumptech.glide.ListPreloader.PreloadModelProvider
|
||||
import com.h.pixeldroid.BuildConfig
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.objects.FeedContent
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import kotlinx.android.synthetic.main.fragment_feed.view.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
@ -106,7 +104,7 @@ open class FeedFragment<T: FeedContent, VH: RecyclerView.ViewHolder?>: Fragment(
|
||||
//do nothing here, it is expected to pull to refresh to load newer notifications
|
||||
}
|
||||
|
||||
private fun enqueueCall(call: Call<List<T>>, callback: LoadCallback<T>){
|
||||
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>>) {
|
||||
|
@ -108,16 +108,21 @@ class NotificationsFragment : FeedFragment<Notification, NotificationsFragment.N
|
||||
openActivity(notification)
|
||||
}
|
||||
}
|
||||
|
||||
private fun openPostFromNotifcation(notification: Notification) : Intent {
|
||||
val intent = Intent(context, PostActivity::class.java)
|
||||
intent.putExtra(Status.POST_TAG, notification.status)
|
||||
return intent
|
||||
}
|
||||
|
||||
private fun openActivity(notification: Notification){
|
||||
val intent: Intent
|
||||
when (notification.type){
|
||||
Notification.NotificationType.mention, Notification.NotificationType.favourite-> {
|
||||
intent = Intent(context, PostActivity::class.java)
|
||||
intent.putExtra(Status.POST_TAG, notification.status)
|
||||
intent = openPostFromNotifcation(notification)
|
||||
}
|
||||
Notification.NotificationType.reblog-> {
|
||||
Toast.makeText(context,"Can't see shares yet, sorry!", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
intent = openPostFromNotifcation(notification)
|
||||
}
|
||||
Notification.NotificationType.follow -> {
|
||||
intent = Intent(context, ProfileActivity::class.java)
|
||||
|
@ -4,6 +4,7 @@ import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
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
|
||||
@ -23,17 +24,17 @@ import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import retrofit2.Call
|
||||
|
||||
|
||||
open class PostsFeedFragment : FeedFragment<Status, PostViewHolder>() {
|
||||
|
||||
lateinit var picRequest: RequestBuilder<Drawable>
|
||||
lateinit var domain : String
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val view = super.onCreateView(inflater, container, savedInstanceState)
|
||||
|
||||
domain = preferences.getString("domain", "")!!
|
||||
//RequestBuilder that is re-used for every image
|
||||
picRequest = Glide.with(this)
|
||||
.asDrawable().fitCenter()
|
||||
@ -106,7 +107,7 @@ open class PostsFeedFragment : FeedFragment<Status, PostViewHolder>() {
|
||||
holder.postPic.maxHeight = metrics.heightPixels
|
||||
|
||||
//Setup the post layout
|
||||
post.setupPost(holder.postView, picRequest, postsFeedFragment)
|
||||
post.setupPost(holder.postView, picRequest, this@PostsFeedFragment, domain, false)
|
||||
|
||||
//Set the special HTML text
|
||||
post.setDescription(holder.postView, api, credential)
|
||||
@ -157,4 +158,6 @@ class PostViewHolder(val postView: View, val context: android.content.Context) :
|
||||
val commentCont : LinearLayout = postView.findViewById(R.id.commentContainer)
|
||||
val commentIn : LinearLayout = postView.findViewById(R.id.commentIn)
|
||||
val viewComment : TextView = postView.findViewById(R.id.ViewComments)
|
||||
val postDate : TextView = postView.findViewById(R.id.postDate)
|
||||
val postDomain : TextView = postView.findViewById(R.id.postDomain)
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
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(): FeedDataSource {
|
||||
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()
|
||||
}
|
||||
}
|
@ -55,15 +55,15 @@ class SearchAccountFragment: AccountListFragment(){
|
||||
params: LoadInitialParams<String>,
|
||||
callback: LoadInitialCallback<Account>
|
||||
) {
|
||||
enqueueCall(makeInitialCall(params.requestedLoadSize), callback)
|
||||
searchEnqueueCall(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<Account>) {
|
||||
enqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
searchEnqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
}
|
||||
private fun enqueueCall(call: Call<Results>, callback: LoadCallback<Account>){
|
||||
private fun searchEnqueueCall(call: Call<Results>, callback: LoadCallback<Account>) {
|
||||
|
||||
call.enqueue(object : Callback<Results> {
|
||||
override fun onResponse(call: Call<Results>, response: Response<Results>) {
|
||||
|
@ -92,16 +92,16 @@ class SearchHashtagFragment: FeedFragment<Tag, SearchHashtagFragment.TagsRecycle
|
||||
params: LoadInitialParams<String>,
|
||||
callback: LoadInitialCallback<Tag>
|
||||
) {
|
||||
enqueueCall(makeInitialCall(params.requestedLoadSize), callback)
|
||||
searchEnqueueCall(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<Tag>) {
|
||||
enqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
searchEnqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
}
|
||||
|
||||
private fun enqueueCall(call: Call<Results>, callback: LoadCallback<Tag>){
|
||||
private fun searchEnqueueCall(call: Call<Results>, callback: LoadCallback<Tag>){
|
||||
|
||||
call.enqueue(object : Callback<Results> {
|
||||
override fun onResponse(call: Call<Results>, response: Response<Results>) {
|
||||
|
@ -57,16 +57,16 @@ class SearchPostsFragment: PostsFeedFragment(){
|
||||
params: LoadInitialParams<String>,
|
||||
callback: LoadInitialCallback<Status>
|
||||
) {
|
||||
enqueueCall(makeInitialCall(params.requestedLoadSize), callback)
|
||||
searchEnqueueCall(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)
|
||||
searchEnqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback)
|
||||
}
|
||||
|
||||
private fun enqueueCall(call: Call<Results>, callback: LoadCallback<Status>){
|
||||
private fun searchEnqueueCall(call: Call<Results>, callback: LoadCallback<Status>){
|
||||
|
||||
call.enqueue(object : Callback<Results> {
|
||||
override fun onResponse(call: Call<Results>, response: Response<Results>) {
|
||||
|
@ -20,23 +20,23 @@ data class Account(
|
||||
//Base attributes
|
||||
override val id: String,
|
||||
val username: String,
|
||||
val acct: String,
|
||||
val url: String, //HTTPS URL
|
||||
val acct: String = "",
|
||||
val url: String = "", //HTTPS URL
|
||||
//Display attributes
|
||||
val display_name: String?,
|
||||
val note: String, //HTML
|
||||
val avatar: String, //URL
|
||||
val avatar_static: String, //URL
|
||||
val header: String, //URL
|
||||
val header_static: String, //URL
|
||||
val locked: Boolean,
|
||||
val emojis: List<Emoji>,
|
||||
val discoverable: Boolean,
|
||||
val display_name: String? = null,
|
||||
val note: String = "", //HTML
|
||||
val avatar: String = "", //URL
|
||||
val avatar_static: String = "", //URL
|
||||
val header: String = "", //URL
|
||||
val header_static: String = "", //URL
|
||||
val locked: Boolean = false,
|
||||
val emojis: List<Emoji>? = null,
|
||||
val discoverable: Boolean = true,
|
||||
//Statistical attributes
|
||||
val created_at: String, //ISO 8601 Datetime (maybe can use a date type)
|
||||
val statuses_count: Int,
|
||||
val followers_count: Int,
|
||||
val following_count: Int,
|
||||
val created_at: String = "", //ISO 8601 Datetime (maybe can use a date type)
|
||||
val statuses_count: Int = 0,
|
||||
val followers_count: Int = 0,
|
||||
val following_count: Int = 0,
|
||||
//Optional attributes
|
||||
val moved: Account? = null,
|
||||
val fields: List<Field>? = emptyList(),
|
||||
|
@ -5,9 +5,9 @@ import java.io.Serializable
|
||||
data class Attachment(
|
||||
//Required attributes
|
||||
val id: String,
|
||||
val type: AttachmentType,
|
||||
val type: AttachmentType = AttachmentType.image,
|
||||
val url: String, //URL
|
||||
val preview_url: String, //URL
|
||||
val preview_url: String = "", //URL
|
||||
//Optional attributes
|
||||
val remote_url: String? = null, //URL
|
||||
val text_url: String? = null, //URL
|
||||
|
13
app/src/main/java/com/h/pixeldroid/objects/DiscoverPost.kt
Normal file
13
app/src/main/java/com/h/pixeldroid/objects/DiscoverPost.kt
Normal file
@ -0,0 +1,13 @@
|
||||
package com.h.pixeldroid.objects
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
/*
|
||||
NOT DOCUMENTED, USE WITH CAUTION
|
||||
*/
|
||||
|
||||
data class DiscoverPost(
|
||||
val type: String?, //This is probably an enum, with these values: https://github.com/pixelfed/pixelfed/blob/700c7805cecc364b68b9cfe20df00608e0f6c465/app/Status.php#L31
|
||||
val url: String?, //URL to post
|
||||
val thumb: String? //URL to thumbnail
|
||||
) : Serializable
|
@ -0,0 +1,8 @@
|
||||
package com.h.pixeldroid.objects
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
data class DiscoverPosts(
|
||||
//Required attributes
|
||||
val posts: List<DiscoverPost>
|
||||
) : Serializable
|
@ -9,11 +9,15 @@ import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.text.toSpanned
|
||||
import android.widget.TextView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.ImageView
|
||||
import android.widget.FrameLayout
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import com.bumptech.glide.RequestBuilder
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
@ -21,8 +25,10 @@ import com.h.pixeldroid.ImageFragment
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.fragments.feeds.PostViewHolder
|
||||
import com.h.pixeldroid.utils.HtmlUtils.Companion.getDomain
|
||||
import com.h.pixeldroid.utils.HtmlUtils.Companion.parseHTMLText
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
import com.h.pixeldroid.utils.ImageUtils.Companion.downloadImage
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.likePostCall
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.postComment
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.reblogPost
|
||||
@ -30,10 +36,17 @@ import com.h.pixeldroid.utils.PostUtils.Companion.retrieveComments
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.toggleCommentInput
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.unLikePostCall
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.undoReblogPost
|
||||
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.*
|
||||
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.postDate
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.postDomain
|
||||
import java.io.Serializable
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.postPager
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.postPicture
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.postTabs
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.profilePic
|
||||
|
||||
/*
|
||||
Represents a status posted by an account.
|
||||
@ -42,44 +55,46 @@ https://docs.joinmastodon.org/entities/status/
|
||||
data class Status(
|
||||
//Base attributes
|
||||
override val id: String,
|
||||
val uri: String,
|
||||
val created_at: String, //ISO 8601 Datetime (maybe can use a date type)
|
||||
val uri: String = "",
|
||||
val created_at: String = "", //ISO 8601 Datetime (maybe can use a date type)
|
||||
val account: Account,
|
||||
val content: String, //HTML
|
||||
val visibility: Visibility,
|
||||
val sensitive: Boolean,
|
||||
val spoiler_text: String,
|
||||
val media_attachments: List<Attachment>?,
|
||||
val application: Application,
|
||||
val content: String = "", //HTML
|
||||
val visibility: Visibility = Visibility.public,
|
||||
val sensitive: Boolean = false,
|
||||
val spoiler_text: String = "",
|
||||
val media_attachments: List<Attachment>? = null,
|
||||
val application: Application? = null,
|
||||
//Rendering attributes
|
||||
val mentions: List<Mention>,
|
||||
val tags: List<Tag>,
|
||||
val emojis: List<Emoji>,
|
||||
val mentions: List<Mention>? = null,
|
||||
val tags: List<Tag>? = null,
|
||||
val emojis: List<Emoji>? = null,
|
||||
//Informational attributes
|
||||
val reblogs_count: Int,
|
||||
val favourites_count: Int,
|
||||
val replies_count: Int,
|
||||
val reblogs_count: Int = 0,
|
||||
val favourites_count: Int = 0,
|
||||
val replies_count: Int = 0,
|
||||
//Nullable attributes
|
||||
val url: String?, //URL
|
||||
val in_reply_to_id: String?,
|
||||
val in_reply_to_account: String?,
|
||||
val reblog: Status?,
|
||||
val poll: Poll?,
|
||||
val card: Card?,
|
||||
val language: String?, //ISO 639 Part 1 two-letter language code
|
||||
val text: String?,
|
||||
val url: String? = null, //URL
|
||||
val in_reply_to_id: String? = null,
|
||||
val in_reply_to_account: String? = null,
|
||||
val reblog: Status? = null,
|
||||
val poll: Poll? = null,
|
||||
val card: Card? = null,
|
||||
val language: String? = null, //ISO 639 Part 1 two-letter language code
|
||||
val text: String? = null,
|
||||
//Authorized user attributes
|
||||
val favourited: Boolean,
|
||||
val reblogged: Boolean,
|
||||
val muted: Boolean,
|
||||
val bookmarked: Boolean,
|
||||
val pinned: Boolean
|
||||
val favourited: Boolean = false,
|
||||
val reblogged: Boolean = false,
|
||||
val muted: Boolean = false,
|
||||
val bookmarked: Boolean = false,
|
||||
val pinned: Boolean = false
|
||||
) : Serializable, FeedContent()
|
||||
{
|
||||
|
||||
companion object {
|
||||
const val POST_TAG = "postTag"
|
||||
const val POST_FRAG_TAG = "postFragTag"
|
||||
const val DOMAIN_TAG = "domainTag"
|
||||
const val DISCOVER_TAG = "discoverTag"
|
||||
}
|
||||
|
||||
fun getPostUrl() : String? = media_attachments?.getOrNull(0)?.url
|
||||
@ -100,8 +115,8 @@ data class Status(
|
||||
|
||||
fun getUsername() : CharSequence {
|
||||
var name = account.username
|
||||
if (name.isEmpty()) {
|
||||
name = account.display_name!!
|
||||
if (name.isNullOrEmpty()) {
|
||||
name = account.display_name?: "NoName"
|
||||
}
|
||||
return name
|
||||
}
|
||||
@ -116,6 +131,36 @@ data class Status(
|
||||
return "$nShares Shares"
|
||||
}
|
||||
|
||||
private fun ISO8601toDate(dateString : String, textView: TextView, isActivity: Boolean) {
|
||||
var format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.hhmmss'Z'")
|
||||
if(dateString.matches("[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{6}Z".toRegex())) {
|
||||
format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.hhmmss'Z'")
|
||||
} else if(dateString.matches("[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}+[0-9]{2}:[0-9]{2}".toRegex())) {
|
||||
format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss+hh:mm")
|
||||
}
|
||||
val now = Date().time
|
||||
|
||||
try {
|
||||
val date: Date = format.parse(dateString)!!
|
||||
val then = date.time
|
||||
val formattedDate = android.text.format.DateUtils
|
||||
.getRelativeTimeSpanString(then, now,
|
||||
android.text.format.DateUtils.SECOND_IN_MILLIS,
|
||||
android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE)
|
||||
textView.text = if(isActivity) "Posted on $date"
|
||||
else "$formattedDate"
|
||||
} catch (e: ParseException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStatusDomain(domain : String) : String {
|
||||
val accountDomain = getDomain(account.url)
|
||||
return if(getDomain(domain) == accountDomain) ""
|
||||
else " from $accountDomain"
|
||||
|
||||
}
|
||||
|
||||
private fun setupPostPics(rootView: View, request: RequestBuilder<Drawable>, homeFragment: Fragment) {
|
||||
//Check whether or not we need to activate the viewPager
|
||||
if(media_attachments?.size == 1) {
|
||||
@ -158,7 +203,9 @@ data class Status(
|
||||
fun setupPost(
|
||||
rootView: View,
|
||||
request: RequestBuilder<Drawable>,
|
||||
homeFragment: Fragment
|
||||
homeFragment: Fragment,
|
||||
domain : String,
|
||||
isActivity : Boolean
|
||||
) {
|
||||
//Setup username as a button that opens the profile
|
||||
val username = rootView.findViewById<TextView>(R.id.username)
|
||||
@ -178,6 +225,11 @@ data class Status(
|
||||
nshares.text = this.getNShares()
|
||||
nshares.setTypeface(null, Typeface.BOLD)
|
||||
|
||||
//Convert the date to a readable string
|
||||
ISO8601toDate(created_at, rootView.postDate, isActivity)
|
||||
|
||||
rootView.postDomain.text = getStatusDomain(domain)
|
||||
|
||||
//Setup images
|
||||
ImageConverter.setRoundImageFromURL(
|
||||
rootView,
|
||||
@ -194,6 +246,8 @@ data class Status(
|
||||
|
||||
//Set comment initial visibility
|
||||
rootView.findViewById<LinearLayout>(R.id.commentIn).visibility = View.GONE
|
||||
|
||||
imagePopUpMenu(rootView, homeFragment.requireActivity())
|
||||
}
|
||||
|
||||
fun setDescription(rootView: View, api : PixelfedAPI, credential: String) {
|
||||
@ -292,4 +346,31 @@ data class Status(
|
||||
enum class Visibility : Serializable {
|
||||
public, unlisted, private, direct
|
||||
}
|
||||
|
||||
|
||||
fun imagePopUpMenu(view: View, activity: FragmentActivity) {
|
||||
val anchor = view.findViewById<FrameLayout>(R.id.post_fragment_image_popup_menu_anchor)
|
||||
if (!media_attachments.isNullOrEmpty() && media_attachments.size == 1) {
|
||||
view.findViewById<ImageView>(R.id.postPicture).setOnLongClickListener {
|
||||
PopupMenu(view.context, anchor).apply {
|
||||
setOnMenuItemClickListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.image_popup_menu_save_to_gallery -> {
|
||||
downloadImage(activity, view.context, getPostUrl()!!)
|
||||
true
|
||||
}
|
||||
R.id.image_popup_menu_share_picture -> {
|
||||
downloadImage(activity, view.context, getPostUrl()!!, share = true)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
inflate(R.menu.image_popup_menu)
|
||||
show()
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ class HtmlUtils {
|
||||
return result.trim().toSpanned()
|
||||
}
|
||||
|
||||
private fun getDomain(urlString: String?): String {
|
||||
public fun getDomain(urlString: String?): String {
|
||||
val uri: URI
|
||||
try {
|
||||
uri = URI(urlString!!)
|
||||
|
98
app/src/main/java/com/h/pixeldroid/utils/ImageUtils.kt
Normal file
98
app/src/main/java/com/h/pixeldroid/utils/ImageUtils.kt
Normal file
@ -0,0 +1,98 @@
|
||||
package com.h.pixeldroid.utils
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.provider.MediaStore.Images
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.h.pixeldroid.R
|
||||
import java.io.File
|
||||
|
||||
|
||||
class ImageUtils {
|
||||
companion object {
|
||||
fun downloadImage(activity: FragmentActivity, context: Context, url: String, share: Boolean = false) {
|
||||
var msg = ""
|
||||
var lastMsg = ""
|
||||
val directory = File(Environment.DIRECTORY_PICTURES)
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs()
|
||||
}
|
||||
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE)
|
||||
as DownloadManager
|
||||
val downloadUri = Uri.parse(url)
|
||||
val title = url.substring(url.lastIndexOf("/") + 1)
|
||||
val ext = url.substring(url.lastIndexOf("."))
|
||||
val request = DownloadManager.Request(downloadUri).apply {
|
||||
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI
|
||||
or DownloadManager.Request.NETWORK_MOBILE)
|
||||
setTitle(title)
|
||||
setDestinationInExternalPublicDir(directory.toString(), title)
|
||||
}
|
||||
val downloadId = downloadManager.enqueue(request)
|
||||
val query = DownloadManager.Query().setFilterById(downloadId)
|
||||
|
||||
Thread(Runnable {
|
||||
var downloading = true
|
||||
while (downloading) {
|
||||
val cursor: Cursor = downloadManager.query(query)
|
||||
cursor.moveToFirst()
|
||||
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
|
||||
== DownloadManager.STATUS_SUCCESSFUL) {
|
||||
downloading = false
|
||||
}
|
||||
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
|
||||
if(!share) {
|
||||
msg = when (status) {
|
||||
DownloadManager.STATUS_FAILED ->
|
||||
context.getString(R.string.image_download_failed)
|
||||
DownloadManager.STATUS_RUNNING ->
|
||||
context.getString(R.string.image_download_downloading)
|
||||
DownloadManager.STATUS_SUCCESSFUL ->
|
||||
context.getString(R.string.image_download_success)
|
||||
else -> ""
|
||||
}
|
||||
if (msg != lastMsg && msg != "") {
|
||||
activity.runOnUiThread {
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
lastMsg = msg
|
||||
}
|
||||
} else if (status == DownloadManager.STATUS_SUCCESSFUL) {
|
||||
val icon: Bitmap = BitmapFactory.decodeFile(
|
||||
Uri.parse(cursor.getString(
|
||||
cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)
|
||||
)).path
|
||||
)
|
||||
val intentShare = Intent(Intent.ACTION_SEND)
|
||||
intentShare.type = "image/$ext"
|
||||
val values = ContentValues()
|
||||
values.put(Images.Media.TITLE, title)
|
||||
values.put(Images.Media.MIME_TYPE, "image/$ext")
|
||||
val uri: Uri = context.contentResolver.insert(
|
||||
Images.Media.EXTERNAL_CONTENT_URI,
|
||||
values
|
||||
)!!
|
||||
try {
|
||||
val outstream = context.contentResolver.openOutputStream(uri)!!
|
||||
icon.compress(Bitmap.CompressFormat.JPEG, 100, outstream)
|
||||
outstream.close()
|
||||
} catch(e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
intentShare.putExtra(Intent.EXTRA_STREAM, uri)
|
||||
context.startActivity(Intent.createChooser(intentShare, "Share Image"))
|
||||
}
|
||||
cursor.close()
|
||||
}
|
||||
}).start()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:fromXDelta="-100%p"
|
||||
android:toXDelta="0"
|
||||
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
|
||||
android:duration="@integer/swipe_animation_duration"/>
|
||||
</set>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:fromXDelta="100%p"
|
||||
android:toXDelta="0"
|
||||
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
|
||||
android:duration="@integer/swipe_animation_duration"/>
|
||||
</set>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:fromXDelta="0"
|
||||
android:toXDelta="-100%p"
|
||||
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
|
||||
android:duration="@integer/swipe_animation_duration"/>
|
||||
</set>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:fromXDelta="0"
|
||||
android:toXDelta="100%p"
|
||||
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
|
||||
android:duration="@integer/swipe_animation_duration"/>
|
||||
</set>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 11,14.41L11,22h1l5.71,-5.71 -4.3,-4.29 4.3,-4.29zM13,5.83l1.88,1.88L13,9.59L13,5.83zM14.88,16.29L13,18.17v-3.76l1.88,1.88z"/>
|
||||
</vector>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M20,2H4c-1.1,0 -2,0.9 -2,2v18l4,-4h14c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
@ -1,5 +0,0 @@
|
||||
<vector android:height="24dp" android:tint="#003DFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#010101" android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"/>
|
||||
</vector>
|
@ -5,5 +5,5 @@
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||
android:pathData="M15.96,10.29l-2.75,3.54 -1.96,-2.36L8.5,15h11l-3.54,-4.71zM3,5L1,5v16c0,1.1 0.9,2 2,2h16v-2L3,21L3,5zM21,1L7,1c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L23,3c0,-1.1 -0.9,-2 -2,-2zM21,17L7,17L7,3h14v14z"/>
|
||||
</vector>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M2.5,4v3h5v12h3L10.5,7h5L15.5,4h-13zM21.5,9h-9v3h3v7h3v-7h3L21.5,9z"/>
|
||||
</vector>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M7.58,4.08L6.15,2.65C3.75,4.48 2.17,7.3 2.03,10.5h2c0.15,-2.65 1.51,-4.97 3.55,-6.42zM19.97,10.5h2c-0.15,-3.2 -1.73,-6.02 -4.12,-7.85l-1.42,1.43c2.02,1.45 3.39,3.77 3.54,6.42zM18,11c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2v-5zM12,22c0.14,0 0.27,-0.01 0.4,-0.04 0.65,-0.14 1.18,-0.58 1.44,-1.18 0.1,-0.24 0.15,-0.5 0.15,-0.78h-4c0.01,1.1 0.9,2 2.01,2z"/>
|
||||
</vector>
|
@ -1,5 +0,0 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
|
||||
</vector>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
|
||||
</vector>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12.87,15.07l-2.54,-2.51 0.03,-0.03c1.74,-1.94 2.98,-4.17 3.71,-6.53L17,6L17,4h-7L10,2L8,2v2L1,4v1.99h11.17C11.5,7.92 10.44,9.75 9,11.35 8.07,10.32 7.3,9.19 6.69,8h-2c0.73,1.63 1.73,3.17 2.98,4.56l-5.09,5.02L4,19l5,-5 3.11,3.11 0.76,-2.04zM18.5,10h-2L12,22h2l1.12,-3h4.75L21,22h2l-4.5,-12zM15.88,17l1.62,-4.33L19.12,17h-3.24z"/>
|
||||
</vector>
|
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/camera_fragment_main_linear_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragments.NewPostFragment">
|
||||
|
||||
<TextureView
|
||||
android:id="@+id/textureView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/takePictureButton"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_margin="15dp"
|
||||
android:layout_marginStart="14dp"
|
||||
android:background="?android:attr/listChoiceIndicatorSingle"
|
||||
android:gravity="center"
|
||||
android:padding="15dp"
|
||||
android:textColor="@color/cardview_light_background"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.517"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
tools:ignore="MissingConstraints,PrivateResource" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/uploadedPictureView"
|
||||
android:layout_width="366dp"
|
||||
android:layout_height="532dp"
|
||||
android:layout_margin="15dp"
|
||||
android:layout_marginStart="14dp"
|
||||
android:layout_marginEnd="14dp"
|
||||
android:contentDescription="@string/upload_a_picture"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/textureView"
|
||||
app:layout_constraintHorizontal_bias="0.501"
|
||||
app:layout_constraintStart_toEndOf="@+id/textureView"
|
||||
app:layout_constraintTop_toTopOf="@+id/textureView"
|
||||
app:layout_constraintVertical_bias="0.147"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:srcCompat="@tools:sample/avatars" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/followsFragment"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -20,7 +20,6 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="20dp"
|
||||
|
@ -6,12 +6,26 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".PostActivity">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/postFragmentSingle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
<ProgressBar
|
||||
android:id="@+id/postProgressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/postFragmentSingle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" >
|
||||
|
||||
</androidx.fragment.app.FragmentContainerView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:tools="http://schemas.android.com/tools"
|
||||
<merge xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
@ -18,7 +18,6 @@
|
||||
android:background="#88000000">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/new_post_description_input_layout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
@ -52,4 +51,4 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
</merge>
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/feedList"
|
||||
android:name="com.h.pixeldroid.FeedFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
app:layoutManager="LinearLayoutManager"
|
||||
tools:listitem="@layout/post_fragment" />
|
@ -7,7 +7,6 @@
|
||||
android:layout_margin="5dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/notification"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp">
|
||||
|
@ -10,12 +10,13 @@
|
||||
android:id="@+id/search"
|
||||
android:layout_width="250dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
android:gravity="center"
|
||||
android:hint="Search"
|
||||
app:errorEnabled="true"
|
||||
app:layout_constraintEnd_toStartOf="@+id/searchButton"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" >
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/searchEditText"
|
||||
@ -27,24 +28,45 @@
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/searchProgressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/search" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/searchButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:text="Search"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/search"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/search" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/discoverProgressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/search" />
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/discoverRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/search">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/discoverList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
app:layoutManager="LinearLayoutManager"
|
||||
app:layout_constraintTop_toBottomOf="@+id/search" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -28,20 +28,30 @@
|
||||
android:id="@+id/profilePic"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/ic_default_user"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/username"
|
||||
android:id="@+id/username"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/profilePic"
|
||||
app:layout_constraintStart_toEndOf="@+id/profilePic"
|
||||
app:layout_constraintTop_toTopOf="@+id/profilePic"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/postDomain"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:textColor="#b3b3b3"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/profilePic"
|
||||
app:layout_constraintStart_toEndOf="@+id/profilePic"
|
||||
app:layout_constraintTop_toTopOf="@+id/profilePic"
|
||||
tools:text="Account" />
|
||||
app:layout_constraintStart_toEndOf="@+id/username"
|
||||
app:layout_constraintTop_toTopOf="@+id/profilePic"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/postConstraint"
|
||||
@ -78,7 +88,19 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@color/browser_actions_bg_grey"/>
|
||||
tools:src="@color/browser_actions_bg_grey"
|
||||
android:longClickable="true"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/post_fragment_image_popup_menu_anchor"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="1dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/postPicture"
|
||||
app:layout_constraintEnd_toEndOf="@+id/postPicture"
|
||||
app:layout_constraintHorizontal_bias="0.1"
|
||||
app:layout_constraintStart_toStartOf="@+id/postPicture"
|
||||
app:layout_constraintTop_toTopOf="@+id/postPicture"
|
||||
app:layout_constraintVertical_bias="0.1" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@ -166,17 +188,27 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hyphenationFrequency="full"
|
||||
app:layout_constraintStart_toStartOf="@+id/usernameDesc"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/usernameDesc"
|
||||
app:layout_constraintTop_toBottomOf="@+id/usernameDesc"
|
||||
tools:text="This is a description, describing stuff.\nIt contains multiple lines, and that's okay. It's also got some really long lines, and we love it for it." />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/postDate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
android:textColor="#b3b3b3"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/description"
|
||||
tools:text="time" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/commentIn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintTop_toBottomOf="@+id/description"
|
||||
app:layout_constraintTop_toBottomOf="@+id/postDate"
|
||||
tools:layout_editor_absoluteX="10dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
|
7
app/src/main/res/menu/image_popup_menu.xml
Normal file
7
app/src/main/res/menu/image_popup_menu.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/image_popup_menu_save_to_gallery"
|
||||
android:title="@string/save_to_gallery"/>
|
||||
<item android:id="@+id/image_popup_menu_share_picture"
|
||||
android:title="@string/share_picture"/>
|
||||
</menu>
|
2
app/src/main/res/values-de/strings.xml
Normal file
2
app/src/main/res/values-de/strings.xml
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
2
app/src/main/res/values-es/strings.xml
Normal file
2
app/src/main/res/values-es/strings.xml
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
2
app/src/main/res/values-fr/strings.xml
Normal file
2
app/src/main/res/values-fr/strings.xml
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
2
app/src/main/res/values-nl/strings.xml
Normal file
2
app/src/main/res/values-nl/strings.xml
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
@ -4,7 +4,5 @@
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<dimen name="nav_header_vertical_spacing">8dp</dimen>
|
||||
<dimen name="nav_header_height">176dp</dimen>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
|
||||
<dimen name="text_margin">16dp</dimen>
|
||||
</resources>
|
||||
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<integer name="swipe_animation_duration">300</integer>
|
||||
</resources>
|
@ -1,80 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">PixelDroid</string>
|
||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
|
||||
<string name="menu_slideshow">Account name</string>
|
||||
<string name="menu_subtitle">Account informations</string>
|
||||
|
||||
<string name="menu_account">My Profile</string>
|
||||
<string name="menu_settings">Settings</string>
|
||||
<string name="menu_accessibility">Accessibility</string>
|
||||
|
||||
<string-array name="list_languages">
|
||||
<item>English</item>
|
||||
<item>Français</item>
|
||||
<item>日本人</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="list_font_size">
|
||||
<item>Small</item>
|
||||
<item>Medium</item>
|
||||
<item>Big</item>
|
||||
</string-array>
|
||||
|
||||
<string name="title_activity_login">Sign in</string>
|
||||
<string name="prompt_email">Email</string>
|
||||
<string name="prompt_password">Password</string>
|
||||
<string name="action_sign_in">Sign in or register</string>
|
||||
<string name="action_sign_in_short">Sign in</string>
|
||||
<string name="welcome">"Welcome !"</string>
|
||||
<string name="invalid_username">Not a valid username</string>
|
||||
<string name="invalid_password">Password must be >5 characters</string>
|
||||
<string name="login_failed">"Login failed"</string>
|
||||
<string name="invalid_domain">"Invalid domain"</string>
|
||||
<string name="registration_failed">"Could not register the application with this server"</string>
|
||||
<string name="browser_launch_failed">"Could not launch a browser, do you have one?"</string>
|
||||
<string name="auth_failed">"Could not authenticate"</string>
|
||||
<string name="token_error">"Error getting token"</string>
|
||||
<string name="title_activity_settings2">Settings</string>
|
||||
|
||||
<!-- Preference Titles -->
|
||||
<string name="messages_header">Messages</string>
|
||||
<string name="sync_header">Sync</string>
|
||||
|
||||
<!-- Messages Preferences -->
|
||||
<string name="signature_title">Your signature</string>
|
||||
<string name="reply_title">Default reply action</string>
|
||||
|
||||
<!-- Sync Preferences -->
|
||||
<string name="sync_title">Sync email periodically</string>
|
||||
<string name="attachment_title">Download incoming attachments</string>
|
||||
<string name="attachment_summary_on">Automatically download attachments for incoming emails
|
||||
</string>
|
||||
<string name="attachment_summary_off">Only download attachments when manually requested</string>
|
||||
|
||||
<string name="start_login">Start Login</string>
|
||||
<string name="no_username">No Username</string>
|
||||
<string name="followed_notification">%1$s followed you</string>
|
||||
<string name="mention_notification">%1$s mentioned you</string>
|
||||
<string name="shared_notification">%1$s shared your post</string>
|
||||
<string name="liked_notification">%1$s liked your post</string>
|
||||
|
||||
<string name="create_a_new_post">Create a new post!</string>
|
||||
<string name="take_a_picture">Take a picture</string>
|
||||
<string name="upload_a_picture">Upload a picture</string>
|
||||
<string name="or">or</string>
|
||||
|
||||
<string name="description">Description…</string>
|
||||
<string name="upload">upload</string>
|
||||
<string name="send">send</string>
|
||||
<string name="reconnect">Reconnect</string>
|
||||
|
||||
<string name="whats_an_instance">What\'s an instance?</string>
|
||||
<string name="whats_an_instance">"What's an instance?"</string>
|
||||
<string name="logout">Logout</string>
|
||||
|
||||
<!-- TODO: Remove or change this placeholder text -->
|
||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||
|
||||
<string name="save_to_gallery">Save to Gallery…</string>
|
||||
<string name="image_download_failed">Download has been failed, please try again</string>
|
||||
<string name="image_download_downloading">Downloading…</string>
|
||||
<string name="image_download_success">Image downloaded successfully</string>
|
||||
<string name="share_picture">Share picture…</string>
|
||||
</resources>
|
||||
|
@ -15,16 +15,4 @@
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
<style name="posts_title">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_marginBottom">8dp</item>
|
||||
<item name="android:paddingLeft">8dp</item>
|
||||
<item name="android:background">@android:color/holo_orange_light</item>
|
||||
<item name="android:textAppearance">@android:style/TextAppearance.Large</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -215,9 +215,9 @@ fun assertStatusEqualsToReference(actual: Status){
|
||||
assert(attchmnt.id == "15888" && attchmnt.type == Attachment.AttachmentType.image && attchmnt.url=="https://pixelfed.de/storage/m/113a3e2124a33b1f5511e531953f5ee48456e0c7/34dd6d9fb1762dac8c7ddeeaf789d2d8fa083c9f/JtjO0eAbELpgO1UZqF5ydrKbCKRVyJUM1WAaqIeB.jpeg" &&
|
||||
attchmnt.preview_url =="https://pixelfed.de/storage/m/113a3e2124a33b1f5511e531953f5ee48456e0c7/34dd6d9fb1762dac8c7ddeeaf789d2d8fa083c9f/JtjO0eAbELpgO1UZqF5ydrKbCKRVyJUM1WAaqIeB_thumb.jpeg" &&
|
||||
attchmnt.remote_url ==null && attchmnt.text_url==null && attchmnt.description==null && attchmnt.blurhash==null )
|
||||
assert( actual.application.name=="web" && actual.application.website==null && actual.application.vapid_key==null && actual.mentions==emptyList<Mention>())
|
||||
assert( actual.application!!.name=="web" && actual.application!!.website==null && actual.application!!.vapid_key==null && actual.mentions==emptyList<Mention>())
|
||||
|
||||
val firstTag =actual.tags[0]
|
||||
val firstTag =actual.tags!![0]
|
||||
|
||||
assert(firstTag.name=="hiking" && firstTag.url=="https://pixelfed.de/discover/tags/hiking" && firstTag.history==null &&
|
||||
actual.emojis== emptyList<Emoji>() && actual.reblogs_count==0 && actual.favourites_count==0&& actual.replies_count==0 && actual.url=="https://pixelfed.de/p/Miike/140364967936397312")
|
||||
|
BIN
pixeldroid_logo.png
Normal file
BIN
pixeldroid_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
546
pixeldroid_logo.svg
Normal file
546
pixeldroid_logo.svg
Normal file
@ -0,0 +1,546 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
style="enable-background:new"
|
||||
id="svg102"
|
||||
version="1.1"
|
||||
height="49.582283"
|
||||
width="49.688999">
|
||||
<metadata
|
||||
id="metadata106">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs56">
|
||||
<linearGradient
|
||||
id="g1"
|
||||
y2="0.60117739"
|
||||
x2="0"
|
||||
y1="0.55806792"
|
||||
x1="1">
|
||||
<stop
|
||||
id="stop2"
|
||||
offset="0"
|
||||
stop-color="#FF5C34" />
|
||||
<stop
|
||||
id="stop4"
|
||||
offset="1"
|
||||
stop-color="#EB0256" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="g2"
|
||||
y2="0"
|
||||
x2="0.30560157"
|
||||
y1="1.1191301"
|
||||
x1="0.5">
|
||||
<stop
|
||||
id="stop7"
|
||||
offset="0"
|
||||
stop-color="#FFB000" />
|
||||
<stop
|
||||
id="stop9"
|
||||
offset="1"
|
||||
stop-color="#FF7725" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#g4"
|
||||
id="g3"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="scale(0.85441985,1.1703848)"
|
||||
x1="38.66045"
|
||||
y1="42.313534"
|
||||
x2="29.417906"
|
||||
y2="17.769199" />
|
||||
<linearGradient
|
||||
x1="38.66045"
|
||||
y1="42.313534"
|
||||
x2="29.417906"
|
||||
y2="17.769199"
|
||||
id="g4"
|
||||
gradientTransform="scale(0.85441985,1.1703848)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
id="stop20"
|
||||
stop-color="#21EFE3"
|
||||
offset="0%" />
|
||||
<stop
|
||||
id="stop22"
|
||||
stop-color="#2598FF"
|
||||
offset="100%" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="32.778084"
|
||||
y1="31.292349"
|
||||
x2="-5.737164"
|
||||
y2="34.564075"
|
||||
id="g5"
|
||||
gradientTransform="scale(0.85441985,1.1703848)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
id="stop25"
|
||||
stop-color="#A63FDB"
|
||||
offset="0%" />
|
||||
<stop
|
||||
id="stop27"
|
||||
stop-color="#FF257E"
|
||||
offset="100%" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#g1"
|
||||
id="g6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="scale(0.85441985,1.1703848)"
|
||||
x1="26.799479"
|
||||
y1="19.639755"
|
||||
x2="6.4907837"
|
||||
y2="20.515251" />
|
||||
<linearGradient
|
||||
xlink:href="#g1"
|
||||
id="g7"
|
||||
x1="26.799479"
|
||||
y1="19.639755"
|
||||
x2="6.4907837"
|
||||
y2="20.515251"
|
||||
gradientTransform="matrix(0.73238181,-0.44005875,0.60279359,1.0032156,7.0612668,16.678016)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
xlink:href="#g2"
|
||||
id="g8"
|
||||
x1="15.185128"
|
||||
y1="33.220253"
|
||||
x2="9.5916662"
|
||||
y2="1.0193164"
|
||||
gradientTransform="matrix(0.87275201,0.73232484,-0.56419841,0.67238452,33.373061,2.1802866)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
xlink:href="#g10"
|
||||
id="g9"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="scale(0.85441984,1.1703848)"
|
||||
x1="16.690788"
|
||||
y1="19.195547"
|
||||
x2="57.873302"
|
||||
y2="21.720842" />
|
||||
<linearGradient
|
||||
x1="16.690788"
|
||||
y1="19.195547"
|
||||
x2="57.873302"
|
||||
y2="21.720842"
|
||||
id="g10"
|
||||
gradientTransform="scale(0.85441984,1.1703848)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
id="stop34"
|
||||
stop-color="#9EE85D"
|
||||
offset="0%" />
|
||||
<stop
|
||||
id="stop36"
|
||||
stop-color="#0ED061"
|
||||
offset="100%" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="40.01442"
|
||||
y1="3.0503507"
|
||||
x2="21.610674"
|
||||
y2="22.693472"
|
||||
id="g11"
|
||||
gradientTransform="matrix(0.8028135,0.67363955,-0.61334952,0.73096044,33.373061,2.1802866)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
id="stop39"
|
||||
stop-color="#17C934"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop41"
|
||||
stop-color="#03FF6E"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="31.906258"
|
||||
y1="22.861416"
|
||||
x2="56.143276"
|
||||
y2="28.198187"
|
||||
id="g12"
|
||||
gradientTransform="matrix(0.67306192,0.5647652,-0.7315899,0.87187364,33.373061,2.1802866)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
id="stop44"
|
||||
stop-color="#00FFF0"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop46"
|
||||
stop-color="#0087FF"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="18.604218"
|
||||
y1="60.088772"
|
||||
x2="29.551889"
|
||||
y2="34.263325"
|
||||
id="g13"
|
||||
gradientTransform="matrix(0.93316856,0.78302028,-0.52767025,0.62885203,33.373061,2.1802866)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
id="stop49"
|
||||
stop-color="#A63FDB"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop51"
|
||||
stop-color="#FF257E"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#g1"
|
||||
id="g14"
|
||||
x1="30.973358"
|
||||
y1="27.509178"
|
||||
x2="1.1089396"
|
||||
y2="28.796618"
|
||||
gradientTransform="matrix(0.64006516,0.53707767,-0.76930493,0.9168206,33.373061,2.1802866)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
xlink:href="#g2"
|
||||
id="g15"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.87275201,0.73232484,-0.56419841,0.67238452,33.373061,2.1802866)"
|
||||
x1="15.185128"
|
||||
y1="33.220253"
|
||||
x2="9.5916662"
|
||||
y2="1.0193164" />
|
||||
<linearGradient
|
||||
y2="85.349998"
|
||||
x2="519.52002"
|
||||
y1="832.48999"
|
||||
x1="519.52002"
|
||||
gradientTransform="matrix(-0.09058464,0,0,0.09058464,281.81967,-8.9318819)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient887"
|
||||
xlink:href="#a26385e9-dbb5-4257-86ba-bfe3022541ed" />
|
||||
<linearGradient
|
||||
id="a26385e9-dbb5-4257-86ba-bfe3022541ed"
|
||||
x1="519.52002"
|
||||
y1="832.48999"
|
||||
x2="519.52002"
|
||||
y2="85.349998"
|
||||
gradientTransform="matrix(-1,0,0,1,1096.85,0)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="gray"
|
||||
stop-opacity="0.25"
|
||||
id="stop2-3" />
|
||||
<stop
|
||||
offset="0.54"
|
||||
stop-color="gray"
|
||||
stop-opacity="0.12"
|
||||
id="stop4-6" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="gray"
|
||||
stop-opacity="0.1"
|
||||
id="stop6" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
id="filter447"
|
||||
style="color-interpolation-filters:sRGB">
|
||||
<feBlend
|
||||
id="feBlend449"
|
||||
in2="BackgroundImage"
|
||||
mode="overlay" />
|
||||
</filter>
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(-12.5,-12.917718)"
|
||||
style="opacity:1;filter:url(#filter447)"
|
||||
id="layer4">
|
||||
<path
|
||||
id="path58"
|
||||
d="M 37.344501,37.708859 C 33.27843,32.146166 25.502814,30.871306 19.977177,34.86138 14.451539,38.851453 13.268326,46.5955 17.334396,52.158194 l 0.307623,0.420851 C 11.011178,43.906438 10.684942,31.740724 17.295264,22.825752 l 0.117697,-0.1564 c 4.095389,-5.4421 11.877186,-6.487086 17.381128,-2.33404 5.503943,4.153045 6.6458,11.931447 2.550412,17.373547 z"
|
||||
style="fill:url(#g14)" />
|
||||
<path
|
||||
id="path60"
|
||||
d="m 37.344501,37.708859 c -6.472999,2.189353 -9.877881,9.222288 -7.605018,15.708503 2.272862,6.486214 9.362782,9.969509 15.835779,7.780157 l 0.428828,-0.145041 c -8.049827,2.880268 -17.427966,1.494994 -24.513119,-4.450146 -1.457037,-1.222598 -2.741004,-2.57418 -3.848952,-4.023287 L 17.334396,52.158194 C 13.268326,46.5955 14.451539,38.851453 19.977177,34.86138 25.502814,30.871306 33.27843,32.146166 37.344501,37.708859 Z"
|
||||
style="fill:url(#g13)" />
|
||||
<path
|
||||
id="path62"
|
||||
d="m 37.344501,37.708859 c 0.04163,6.84562 5.636761,12.42884 12.497071,12.470471 6.860311,0.04163 12.387942,-5.47409 12.346311,-12.319709 l -9.53e-4,-0.156747 c 0.07327,5.679151 -1.798009,11.388946 -5.714387,16.056296 -2.883411,3.436311 -6.515801,5.879029 -10.468453,7.293308 l -0.428828,0.145041 C 39.102265,63.386871 32.012345,59.903576 29.739483,53.417362 27.46662,46.931147 30.871502,39.898212 37.344501,37.708859 Z"
|
||||
style="fill:url(#g12)" />
|
||||
<path
|
||||
id="path64"
|
||||
d="M 37.344501,37.708859 C 43.881909,39.863866 50.867988,36.343413 52.948347,29.845706 55.028706,23.348 51.415553,16.33359 44.878144,14.178584 l -0.535192,-0.176422 c 3.149862,0.958982 6.167442,2.558035 8.855077,4.813224 5.838829,4.899353 8.898368,11.870026 8.988901,18.887488 l 9.53e-4,0.156747 c 0.04163,6.845619 -5.486,12.361341 -12.346311,12.319709 -6.86031,-0.04163 -12.45544,-5.624851 -12.497071,-12.470471 z"
|
||||
style="fill:url(#g11)" />
|
||||
<path
|
||||
id="path66"
|
||||
style="fill:url(#g15)"
|
||||
d="m 37.344501,37.708859 c 4.095388,-5.4421 2.953531,-13.220502 -2.550412,-17.373547 -5.503942,-4.153046 -13.285739,-3.10806 -17.381128,2.33404 l -0.117698,0.156401 c 0.293382,-0.395668 0.600429,-0.784933 0.921193,-1.167205 6.528123,-7.779903 16.895374,-10.466821 26.126496,-7.656386 l 0.535192,0.176422 c 6.537409,2.155006 10.150562,9.169416 8.070203,15.667122 -2.080359,6.497707 -9.066438,10.01816 -15.603846,7.863153 z" />
|
||||
<g
|
||||
id="g72"
|
||||
style="opacity:0.54425222;fill:none"
|
||||
transform="matrix(-0.37460713,0.92718385,-0.92718518,-0.37460659,81.342244,14.622857)">
|
||||
<path
|
||||
id="path68"
|
||||
d="m 28.379451,9.2701483 0.186983,-0.07462 c 6.393149,-2.551328 13.669757,0.4995351 16.252757,6.8142937 2.583,6.314759 -0.505736,13.502142 -6.898886,16.05347 -0.05343,-1.007011 -0.227732,-1.979458 -0.50829,-2.904343 3.429966,-1.856689 5.75552,-5.45605 5.75552,-9.591913 0,-6.036745 -4.954499,-10.9304939 -11.066184,-10.9304939 -1.305803,0 -2.558782,0.223396 -3.7219,0.6336062 z"
|
||||
style="fill:url(#g9)" />
|
||||
<path
|
||||
id="path70"
|
||||
d="m 28.379451,9.2701483 0.186983,-0.07462 c 6.393149,-2.551328 13.669757,0.4995351 16.252757,6.8142937 2.583,6.314759 -0.505736,13.502142 -6.898886,16.05347 -0.05343,-1.007011 -0.227732,-1.979458 -0.50829,-2.904343 3.429966,-1.856689 5.75552,-5.45605 5.75552,-9.591913 0,-6.036745 -4.954499,-10.9304939 -11.066184,-10.9304939 -1.305803,0 -2.558782,0.223396 -3.7219,0.6336062 z"
|
||||
style="mix-blend-mode:overlay;fill:#000000;fill-opacity:0.49988679" />
|
||||
</g>
|
||||
<path
|
||||
id="path74"
|
||||
style="opacity:0.1;fill:url(#g8)"
|
||||
d="m 37.344501,37.708859 c 4.095388,-5.4421 2.953531,-13.220502 -2.550412,-17.373547 -5.503942,-4.153046 -13.285739,-3.10806 -17.381128,2.33404 l -0.117698,0.156401 c 0.293382,-0.395668 0.600429,-0.784933 0.921193,-1.167205 6.528123,-7.779903 16.895374,-10.466821 26.126496,-7.656386 l 0.535192,0.176422 c 6.537409,2.155006 10.150562,9.169416 8.070203,15.667122 -2.080359,6.497707 -9.066438,10.01816 -15.603846,7.863153 z" />
|
||||
<path
|
||||
id="path76"
|
||||
style="opacity:0.18013395;fill:url(#g7)"
|
||||
d="m 17.324475,22.990984 0.121843,-0.160265 c 4.165973,-5.47963 11.974565,-6.61226 17.440978,-2.529799 5.466411,4.082461 6.520625,11.834067 2.354651,17.313698 -0.564448,-0.835659 -1.214702,-1.579436 -1.931538,-2.227718 1.983791,-3.358057 2.123373,-7.64106 -0.0068,-11.186188 -3.109159,-5.1745 -9.87647,-6.817505 -15.115214,-3.669755 -1.119294,0.672539 -2.07825,1.509358 -2.863963,2.460027 z" />
|
||||
<g
|
||||
id="g82"
|
||||
style="opacity:0.18013395;fill:none"
|
||||
transform="matrix(0.85716853,-0.51503807,0.51503881,0.8571673,7.2277095,16.834214)">
|
||||
<path
|
||||
id="path78"
|
||||
d="m 5.5458544,10.697205 0.1869826,-0.07462 c 6.39315,-2.5513278 13.669757,0.499535 16.252757,6.814294 2.583,6.314758 -0.505736,13.502141 -6.898886,16.053469 -0.05343,-1.007011 -0.227732,-1.979458 -0.50829,-2.904342 3.429966,-1.856689 5.755521,-5.45605 5.755521,-9.591914 0,-6.036745 -4.9545,-10.930493 -11.0661847,-10.930493 -1.3058034,0 -2.5587821,0.223396 -3.7218999,0.633606 z"
|
||||
style="fill:url(#g6)" />
|
||||
<path
|
||||
id="path80"
|
||||
d="m 5.5458544,10.697205 0.1869826,-0.07462 c 6.39315,-2.5513278 13.669757,0.499535 16.252757,6.814294 2.583,6.314758 -0.505736,13.502141 -6.898886,16.053469 -0.05343,-1.007011 -0.227732,-1.979458 -0.50829,-2.904342 3.429966,-1.856689 5.755521,-5.45605 5.755521,-9.591914 0,-6.036745 -4.9545,-10.930493 -11.0661847,-10.930493 -1.3058034,0 -2.5587821,0.223396 -3.7218999,0.633606 z"
|
||||
style="mix-blend-mode:multiply;fill:#000000;fill-opacity:0.77284307" />
|
||||
</g>
|
||||
<g
|
||||
id="g88"
|
||||
style="opacity:0.5841518;fill:none"
|
||||
transform="matrix(-0.22495138,-0.97437006,0.97437146,-0.22495105,-3.413458,67.921439)">
|
||||
<path
|
||||
id="path84"
|
||||
d="m 10.654093,23.764822 0.186983,-0.07462 c 6.393149,-2.551328 13.669757,0.499535 16.252757,6.814293 2.583,6.314759 -0.505736,13.502142 -6.898886,16.05347 -0.05343,-1.007011 -0.227732,-1.979458 -0.50829,-2.904343 3.429966,-1.856689 5.75552,-5.45605 5.75552,-9.591913 0,-6.036745 -4.954499,-10.930493 -11.066184,-10.930493 -1.305803,0 -2.558782,0.223396 -3.7219,0.633606 z"
|
||||
style="fill:url(#g5)" />
|
||||
<path
|
||||
id="path86"
|
||||
d="m 10.654093,23.764822 0.186983,-0.07462 c 6.393149,-2.551328 13.669757,0.499535 16.252757,6.814293 2.583,6.314759 -0.505736,13.502142 -6.898886,16.05347 -0.05343,-1.007011 -0.227732,-1.979458 -0.50829,-2.904343 3.429966,-1.856689 5.75552,-5.45605 5.75552,-9.591913 0,-6.036745 -4.954499,-10.930493 -11.066184,-10.930493 -1.305803,0 -2.558782,0.223396 -3.7219,0.633606 z"
|
||||
style="mix-blend-mode:overlay;fill:#000000;fill-opacity:0.50308539" />
|
||||
</g>
|
||||
<g
|
||||
id="g94"
|
||||
style="opacity:0.56222097;fill:none"
|
||||
transform="matrix(-0.99863096,-0.05233596,0.05233603,-0.99862953,69.65441,85.048735)">
|
||||
<path
|
||||
id="path90"
|
||||
d="m 25.135241,22.73235 0.186983,-0.07462 c 6.39315,-2.551328 13.669757,0.499535 16.252757,6.814293 2.583001,6.314759 -0.505736,13.502142 -6.898886,16.05347 -0.05343,-1.007011 -0.227731,-1.979458 -0.50829,-2.904343 3.429966,-1.856689 5.755521,-5.45605 5.755521,-9.591913 0,-6.036745 -4.9545,-10.930494 -11.066185,-10.930494 -1.305803,0 -2.558782,0.223396 -3.7219,0.633607 z"
|
||||
style="fill:url(#g3)" />
|
||||
<path
|
||||
id="path92"
|
||||
d="m 25.135241,22.73235 0.186983,-0.07462 c 6.39315,-2.551328 13.669757,0.499535 16.252757,6.814293 2.583001,6.314759 -0.505736,13.502142 -6.898886,16.05347 -0.05343,-1.007011 -0.227731,-1.979458 -0.50829,-2.904343 3.429966,-1.856689 5.755521,-5.45605 5.755521,-9.591913 0,-6.036745 -4.9545,-10.930494 -11.066185,-10.930494 -1.305803,0 -2.558782,0.223396 -3.7219,0.633607 z"
|
||||
style="mix-blend-mode:overlay;fill:#000000" />
|
||||
</g>
|
||||
<path
|
||||
id="path96"
|
||||
d="m 44.686954,14.115568 0.191202,0.06303 c 6.537408,2.155006 10.150561,9.169416 8.070202,15.667122 -2.080359,6.497706 -9.066438,10.01816 -15.603846,7.863153 0.606364,-0.805759 1.097919,-1.662736 1.477505,-2.551578 3.820968,0.782433 7.916076,-0.48 10.574561,-3.648255 3.88035,-4.624415 3.230624,-11.557934 -1.451204,-15.486449 -1.000306,-0.839354 -2.10374,-1.473623 -3.25842,-1.907021 z"
|
||||
style="mix-blend-mode:overlay;fill:#000000;fill-opacity:0.49617866" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-12.5,-12.917718)"
|
||||
style="display:inline;opacity:1"
|
||||
id="layer3">
|
||||
<g
|
||||
id="g457">
|
||||
<g
|
||||
style="image-rendering:auto"
|
||||
transform="matrix(0.46524817,0,0,0.46524817,-220.42763,-8.4650049)"
|
||||
id="layer1">
|
||||
<g
|
||||
style="opacity:1"
|
||||
id="layer2">
|
||||
<g
|
||||
transform="translate(319.69342,64.960442)"
|
||||
id="g277">
|
||||
<path
|
||||
style="fill:url(#linearGradient887);stroke-width:0.09058464"
|
||||
d="m 220.58355,-1.2004795 h 28.353 a 2.8081241,2.8081241 0 0 1 2.80813,2.7990674 V 63.679864 a 2.8081241,2.8081241 0 0 1 -2.80813,2.799067 h -28.353 a 2.8081241,2.8081241 0 0 1 -2.80811,-2.799067 V 1.5976809 a 2.8081241,2.8081241 0 0 1 2.80811,-2.7981604 z"
|
||||
id="path16" />
|
||||
<rect
|
||||
style="fill:#4e5a86;stroke-width:0.09058464"
|
||||
x="-251.4847"
|
||||
y="-66.219849"
|
||||
width="33.451099"
|
||||
height="66.902199"
|
||||
rx="2.4340096"
|
||||
ry="2.4340096"
|
||||
transform="scale(-1)"
|
||||
id="rect18" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.09058464"
|
||||
x="-249.02083"
|
||||
y="-59.996696"
|
||||
width="28.524202"
|
||||
height="54.454964"
|
||||
transform="scale(-1)"
|
||||
id="rect20" />
|
||||
<circle
|
||||
style="fill:#ffffff;stroke-width:0.09058464"
|
||||
cx="238.12979"
|
||||
cy="2.4292343"
|
||||
r="0.25907207"
|
||||
id="circle22" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.09058464"
|
||||
x="-236.83263"
|
||||
y="-2.6883314"
|
||||
width="5.7050209"
|
||||
height="0.51905"
|
||||
rx="0.090584643"
|
||||
ry="0.090584643"
|
||||
transform="scale(-1)"
|
||||
id="rect24" />
|
||||
<circle
|
||||
style="fill:#ffffff;stroke-width:0.09058464"
|
||||
cx="234.88864"
|
||||
cy="62.589226"
|
||||
r="1.8153163"
|
||||
id="circle26" />
|
||||
<ellipse
|
||||
style="opacity:0.1;fill:#6c63ff;stroke-width:0.09058464"
|
||||
cx="233.40039"
|
||||
cy="64.434441"
|
||||
rx="23.008501"
|
||||
ry="4.4386477"
|
||||
id="ellipse28" />
|
||||
<rect
|
||||
style="opacity:0.1;fill:#6c63ff;stroke-width:0.09058464"
|
||||
x="223.75311"
|
||||
y="13.978788"
|
||||
width="22.012068"
|
||||
height="29.44001"
|
||||
id="rect30" />
|
||||
<path
|
||||
style="fill:none;stroke:#535461;stroke-width:0.18116929;stroke-miterlimit:10"
|
||||
d="m 252.89873,65.466194 c 0,0 -1.31168,-6.64529 1.38956,-11.199889 a 10.263241,10.263241 0 0 0 1.41583,-6.335483 17.260904,17.260904 0 0 0 -0.63409,-3.092559"
|
||||
stroke-miterlimit="10"
|
||||
id="path74-7" />
|
||||
<path
|
||||
style="fill:#6c63ff;stroke-width:0.09058464"
|
||||
d="m 256.75672,41.957668 c -0.0724,0.792613 -1.72111,2.960306 -1.72111,2.960306 0,0 -1.2247,-2.43129 -1.15134,-3.22481 a 1.4421076,1.4421076 0 1 1 2.87154,0.263596 z"
|
||||
id="path76-5" />
|
||||
<path
|
||||
style="fill:#6c63ff;stroke-width:0.09058464"
|
||||
d="m 258.72694,46.567519 c -0.49187,0.625941 -3.0527,1.550813 -3.0527,1.550813 0,0 0.29348,-2.706676 0.78537,-3.33261 a 1.4421076,1.4421076 0 0 1 2.26462,1.781797 z"
|
||||
id="path78-3" />
|
||||
<path
|
||||
style="fill:#6c63ff;stroke-width:0.09058464"
|
||||
d="m 257.93343,54.064307 c -0.74099,0.291683 -3.41777,-0.202902 -3.41777,-0.202902 0,0 1.61965,-2.188529 2.36063,-2.480212 a 1.4421076,1.4421076 0 0 1 1.05714,2.683119 z"
|
||||
id="path80-5" />
|
||||
<path
|
||||
style="fill:#6c63ff;stroke-width:0.09058464"
|
||||
d="m 256.05651,59.601743 c -0.68121,0.413066 -3.40328,0.377739 -3.40328,0.377739 0,0 1.22653,-2.430383 1.90771,-2.843449 a 1.4421076,1.4421076 0 1 1 1.49557,2.46571 z"
|
||||
id="path82" />
|
||||
<path
|
||||
style="fill:#6c63ff;stroke-width:0.09058464"
|
||||
d="m 252.64508,47.995134 c 0.51816,0.605105 3.1152,1.420368 3.1152,1.420368 0,0 -0.40763,-2.69218 -0.92486,-3.296376 a 1.4421076,1.4421076 0 1 0 -2.19034,1.876008 z"
|
||||
id="path84-6" />
|
||||
<path
|
||||
style="fill:#6c63ff;stroke-width:0.09058464"
|
||||
d="m 250.53174,54.498203 c 0.67486,0.422129 3.39782,0.423036 3.39782,0.423036 0,0 -1.1939,-2.445787 -1.86965,-2.868821 a 1.4421076,1.4421076 0 1 0 -1.52817,2.445785 z"
|
||||
id="path86-2" />
|
||||
<path
|
||||
style="fill:#6c63ff;stroke-width:0.09058464"
|
||||
d="m 249.34418,61.101827 c 0.59424,0.529921 3.27735,0.991902 3.27735,0.991902 0,0 -0.76362,-2.61337 -1.35876,-3.143285 a 1.4421076,1.4421076 0 1 0 -1.91949,2.152287 z"
|
||||
id="path88" />
|
||||
<path
|
||||
style="fill:#6c63ff;stroke-width:0.09058464"
|
||||
d="m 231.56577,10.289987 a 3.4295348,3.4295348 0 0 0 -3.42952,-3.4295355 h -18.68581 a 3.4295359,3.4295359 0 0 0 0,6.8590705 l 15.62314,-0.02988 3.59348,3.135132 v -3.15144 A 3.4268171,3.4268171 0 0 0 231.56577,10.29 Z"
|
||||
id="path90-9" />
|
||||
<circle
|
||||
style="opacity:0.2;fill:#ffffff;stroke-width:0.09058464"
|
||||
cx="210.04285"
|
||||
cy="10.407731"
|
||||
r="1.1830356"
|
||||
id="circle92" />
|
||||
<circle
|
||||
style="opacity:0.2;fill:#ffffff;stroke-width:0.09058464"
|
||||
cx="214.06299"
|
||||
cy="10.407731"
|
||||
r="1.1830356"
|
||||
id="circle94" />
|
||||
<circle
|
||||
style="opacity:0.2;fill:#ffffff;stroke-width:0.09058464"
|
||||
cx="218.08408"
|
||||
cy="10.407731"
|
||||
r="1.1830356"
|
||||
id="circle96" />
|
||||
<rect
|
||||
style="fill:#6c63ff;stroke-width:0.09058464"
|
||||
x="223.70779"
|
||||
y="48.129181"
|
||||
width="9.420804"
|
||||
height="2.8081243"
|
||||
id="rect98" />
|
||||
<rect
|
||||
style="opacity:0.1;fill:#6c63ff;stroke-width:0.09058464"
|
||||
x="236.29907"
|
||||
y="48.129181"
|
||||
width="9.420804"
|
||||
height="2.8081243"
|
||||
id="rect100" />
|
||||
<path
|
||||
style="fill:#ee7b0e;fill-opacity:1;stroke:none;stroke-width:0.39877287px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 226.43202,48.543745 c 0.1552,-5.07183 1.33557,-9.88736 2.51385,-14.7034 l 11.18922,0.20848 c 0.96681,2.53872 1.47268,4.51385 2.04322,7.33063 0.72228,-0.10617 1.63613,0.58322 2.40468,1.00917 0.95259,0.7607 1.01757,1.86823 1.04246,2.98843 -0.91888,0.51959 -1.88691,0.6354 -3.34639,0.75604 -0.87129,-0.6299 -2.21927,-1.3383 -3.68281,-3.00383 -2.18994,0.37489 -4.31887,0.53629 -6.24847,0 l -2.38677,6.38541 c -1.38616,0.20092 -2.66287,0.12815 -3.52899,-0.97093 z"
|
||||
id="path961-1-6" />
|
||||
<path
|
||||
style="fill:#ee7b0e;fill-opacity:1;stroke:none;stroke-width:0.39877287px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 230.38693,21.816615 c -1.8751,2.79634 -1.73552,5.99558 -2.35884,9.04226 -1.27705,6.24204 14.0321,8.19235 12.97369,0.29487 -0.43292,-3.23017 -0.10602,-6.71364 -2.064,-9.4354 -0.9447,0.85411 -1.85396,1.72342 -2.16227,2.85027 -1.60511,-0.58881 -2.9775,-0.24678 -4.32457,0.19659 -0.47648,-1.30014 -1.21855,-2.20191 -2.06401,-2.94859 z"
|
||||
id="path959-9-7" />
|
||||
<rect
|
||||
style="opacity:1;fill:#481800;fill-opacity:1;stroke:none;stroke-width:0.39877287;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect963-4-5"
|
||||
width="0.59073234"
|
||||
height="2.6409397"
|
||||
x="231.44785"
|
||||
y="27.620195"
|
||||
ry="0.29536617" />
|
||||
<rect
|
||||
style="opacity:1;fill:#481800;fill-opacity:1;stroke:none;stroke-width:0.39877287;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect963-7-7-3"
|
||||
width="0.5907324"
|
||||
height="2.6409397"
|
||||
x="236.01736"
|
||||
y="27.585466"
|
||||
ry="0.2953662" />
|
||||
<path
|
||||
style="fill:#481800;fill-opacity:1;stroke:none;stroke-width:0.39877287px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 235.16596,30.747655 h -2.2587 l 1.00773,1.28571 z"
|
||||
id="path980-8-5" />
|
||||
<path
|
||||
style="fill:none;stroke:#481800;stroke-width:0.39940086;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 232.87602,34.040375 c 1.76209,-0.0973 3.1945,0.21621 4.10041,-1.25096"
|
||||
id="path982-4-6" />
|
||||
<path
|
||||
style="fill:#a9550d;fill-opacity:1;stroke:none;stroke-width:0.39877287px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 228.07955,30.569965 c -0.0183,0.0962 -0.0318,0.19315 -0.0514,0.28896 -0.6013,2.93911 2.47426,4.92651 5.78696,5.3824 -0.0898,-0.52384 0,0 -0.0898,-0.52384 -2.62078,-0.29956 -5.06396,-1.91042 -5.64574,-5.14752 z"
|
||||
id="path959-0-5-2" />
|
||||
<path
|
||||
style="fill:#a9550d;fill-opacity:1;stroke:none;stroke-width:0.39877287px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 228.94561,33.840385 c -1.17827,4.81606 -2.35813,9.63137 -2.51335,14.70318 0.86613,1.09906 2.14283,1.17215 3.52898,0.97123 l 0.17524,-0.46964 c -1.23366,0.12889 -2.35545,-0.0221 -3.13955,-1.01718 0.14952,-4.88775 1.25361,-9.53746 2.38796,-14.17902 z m 3.96747,8.77299 -0.22275,0.59505 c 1.83832,0.42971 3.84412,0.27353 5.90607,-0.0794 1.46352,1.66553 2.81111,2.37413 3.68241,3.00403 1.45945,-0.12058 2.42783,-0.23668 3.34673,-0.75625 -0.001,-0.083 -0.009,-0.16413 -0.0119,-0.2469 -0.76129,0.29505 -1.60946,0.39167 -2.76962,0.48756 -0.87128,-0.62991 -2.21966,-1.33851 -3.6832,-3.00405 -2.18992,0.37489 -4.31838,0.53631 -6.24796,0 z"
|
||||
id="path961-3-0-9" />
|
||||
<path
|
||||
style="fill:#bf620f;fill-opacity:1;stroke:none;stroke-width:0.39877287px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 242.17831,41.379455 c -0.44726,0.12043 -0.9405,0.14875 -1.25795,0.52864 l -0.29879,-0.30134 c 0.47694,-0.32768 0.9873,-0.45461 1.55674,-0.2273 z"
|
||||
id="path1048-3-1" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 26 KiB |
Loading…
x
Reference in New Issue
Block a user