Compare commits

..

No commits in common. "master" and "feature/SA-28-facebook-api-poc-impl" have entirely different histories.

83 changed files with 228 additions and 3040 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" /> <mapping directory="$PROJECT_DIR$" vcs="Git" />
</component> </component>
</project> </project>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -25,16 +25,6 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
} }
dependencies { dependencies {
@ -49,36 +39,9 @@ dependencies {
implementation "io.reactivex.rxjava2:rxandroid:2.1.0" implementation "io.reactivex.rxjava2:rxandroid:2.1.0"
implementation 'com.jakewharton.rxbinding2:rxbinding:2.2.0' implementation 'com.jakewharton.rxbinding2:rxbinding:2.2.0'
implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.2.0' implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.2.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.0.0' implementation 'com.google.android.material:material:1.0.0'
androidTestImplementation 'androidx.test:core-ktx:1.2.0'
androidTestImplementation 'androidx.test.ext:junit:' + rootProject.extJUnitVersion
androidTestImplementation 'androidx.test:runner:' + rootProject.runnerVersion
androidTestImplementation 'androidx.test:rules:' + rootProject.rulesVersion
androidTestImplementation 'androidx.test.espresso:espresso-core:' + rootProject.espressoVersion
androidTestImplementation 'androidx.test.espresso:espresso-intents:' + rootProject.espressoVersion
androidTestImplementation 'androidx.test.espresso:espresso-contrib:' + rootProject.espressoVersion
androidTestImplementation 'androidx.test.ext:truth:' + rootProject.extTruthVersion
androidTestImplementation 'androidx.test.ext:junit:' + rootProject.extJUnitVersion
androidTestImplementation 'org.robolectric:annotations:' + rootProject.robolectricVersion
testImplementation 'androidx.test:core:' + rootProject.coreVersion
testImplementation 'androidx.test.ext:junit:' + rootProject.extJUnitVersion
testImplementation 'androidx.test.espresso:espresso-core:' + rootProject.espressoVersion
testImplementation 'androidx.test.espresso:espresso-intents:' + rootProject.espressoVersion
testImplementation 'androidx.test.espresso:espresso-contrib:' + rootProject.espressoVersion
testImplementation 'androidx.test.ext:truth:' + rootProject.extTruthVersion
testImplementation 'androidx.test.ext:junit:' + rootProject.extJUnitVersion
testImplementation 'org.robolectric:robolectric:' + rootProject.robolectricVersion
implementation 'com.facebook.android:facebook-login:[5,6)'
implementation 'com.facebook.android:facebook-share:[5,6)'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation([
'com.snapchat.kit.sdk:creative:1.1.4',
'com.snapchat.kit.sdk:core:1.1.4'
])
} }

View File

@ -1,82 +0,0 @@
package pl.edu.amu.wmi.socialaggregator
import androidx.recyclerview.widget.RecyclerView
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
import junit.framework.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import pl.edu.amu.wmi.socialaggregator.TestUtils.actionOnChild
import pl.edu.amu.wmi.socialaggregator.TestUtils.cleanLocalStorage
import pl.edu.amu.wmi.socialaggregator.activity.AddSocialActivity
@RunWith(AndroidJUnit4::class)
class AddSocialActivityTest {
@Rule
@JvmField
val activity = IntentsTestRule(AddSocialActivity::class.java)
@Test
fun initialState_noAddedSocials_oneAvailableSocial() {
cleanLocalStorage(activity)
val newActivity = launchActivity<AddSocialActivity>()
assertEquals(
0, activity.activity.findViewById<RecyclerView>(R.id.availableSocialsRecyclerView)
.adapter?.itemCount
)
assertEquals(
1, activity.activity.findViewById<RecyclerView>(R.id.addSocialRecyclerView)
.adapter?.itemCount
)
}
@Test
fun clickingSocials_movesThemFormAvailableToAdded_etViceVersa() {
cleanLocalStorage(activity)
onView(withId(R.id.addSocialRecyclerView))
.perform(
RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
0,
actionOnChild(click(), R.id.socialPlatformImage)
)
)
assertEquals(
1, activity.activity.findViewById<RecyclerView>(R.id.availableSocialsRecyclerView)
.adapter?.itemCount
)
assertEquals(
0, activity.activity.findViewById<RecyclerView>(R.id.addSocialRecyclerView)
.adapter?.itemCount
)
onView(withId(R.id.availableSocialsRecyclerView))
.perform(
RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
0,
actionOnChild(click(), R.id.socialPlatformImage)
)
)
assertEquals(
0, activity.activity.findViewById<RecyclerView>(R.id.availableSocialsRecyclerView)
.adapter?.itemCount
)
assertEquals(
1, activity.activity.findViewById<RecyclerView>(R.id.addSocialRecyclerView)
.adapter?.itemCount
)
}
}

View File

@ -15,12 +15,10 @@ import org.junit.Assert.*
*/ */
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest { class ExampleInstrumentedTest {
@Test @Test
fun useAppContext() { fun useAppContext() {
// Context of the app under test. // Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext val appContext = InstrumentationRegistry.getInstrumentation().targetContext
appContext.filesDir.delete()
assertEquals("pl.edu.amu.wmi.socialaggregator", appContext.packageName) assertEquals("pl.edu.amu.wmi.socialaggregator", appContext.packageName)
} }
} }

View File

@ -1,38 +0,0 @@
package pl.edu.amu.wmi.socialaggregator
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import pl.edu.amu.wmi.socialaggregator.activity.AddSocialActivity
import pl.edu.amu.wmi.socialaggregator.activity.MainActivity
import pl.edu.amu.wmi.socialaggregator.activity.NewPostActivity
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
@Rule
@JvmField
val activity = IntentsTestRule(MainActivity::class.java)
@Test
fun clickAddNewSocial_shouldOpenAddNewSocialActivity() {
onView(withId(R.id.connectedSocialsButton)).perform(click())
intended(hasComponent(AddSocialActivity::class.java.name))
}
@Test
fun clickCreatePost_shouldOpenAddNewNewPostActivity() {
onView(withId(R.id.createPostButton)).perform(click())
intended(hasComponent(NewPostActivity::class.java.name))
}
}

View File

@ -1,73 +0,0 @@
package pl.edu.amu.wmi.socialaggregator
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.*
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import pl.edu.amu.wmi.socialaggregator.TestUtils.atPosition
import pl.edu.amu.wmi.socialaggregator.TestUtils.cleanLocalStorage
import pl.edu.amu.wmi.socialaggregator.TestUtils.getCurrentActivity
import pl.edu.amu.wmi.socialaggregator.activity.MainActivity
@RunWith(AndroidJUnit4::class)
class NewPostActivityTest {
@Rule
@JvmField
val activity = IntentsTestRule(MainActivity::class.java)
@Test
fun clickPublishPost_shouldEndActivity() {
onView(withId(R.id.createPostButton)).perform(click())
closeSoftKeyboard()
onView(withId(R.id.publishPost)).perform(click())
assertTrue(getCurrentActivity()!!::class.java.simpleName == "MainActivity")
}
@Test
fun clickPublishPost_shouldIncreasePostCount() {
cleanLocalStorage(activity)
onView(withId(R.id.connectedSocialsButton)).perform(click())
onView(withId(R.id.addSocialRecyclerView))
.perform(
RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
0,
TestUtils.actionOnChild(click(), R.id.socialPlatformImage)
)
)
pressBack()
onView(withId(R.id.createPostButton)).perform(click())
closeSoftKeyboard()
onView(withId(R.id.availableSocials))
.perform(
RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
0,
TestUtils.actionOnChild(click(), R.id.chip)
)
)
onView(withId(R.id.publishPost)).perform(click())
onView(withId(R.id.previousPostsRecyclerView)).check(
matches(atPosition(0, hasDescendant(withText("Facebook"))))
)
}
}

View File

@ -1,109 +0,0 @@
package pl.edu.amu.wmi.socialaggregator
import android.app.Activity
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.NoMatchingViewException
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.ViewAssertion
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.matcher.BoundedMatcher
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import androidx.test.runner.lifecycle.Stage
import org.hamcrest.CoreMatchers
import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.core.AllOf
import org.junit.runner.RunWith
import java.io.File
object TestUtils {
fun cleanLocalStorage(activity: IntentsTestRule<out Activity>) {
deleteRecursive(activity.activity.filesDir)
}
private fun deleteRecursive(fileOrDirectory: File) {
if (fileOrDirectory.isDirectory())
for (child in fileOrDirectory.listFiles())
deleteRecursive(child)
fileOrDirectory.delete()
}
fun actionOnChild(action: ViewAction, childId: Int): ViewAction? {
return object : ViewAction {
override fun getDescription(): String {
return "Action on child"
}
override fun getConstraints(): Matcher<View> {
return AllOf.allOf(
ViewMatchers.isDisplayed(),
ViewMatchers.isAssignableFrom(View::class.java)
)
}
override fun perform(uiController: UiController?, view: View?) {
view?.let {
val child = it.findViewById<View>(childId)
action.perform(uiController, child)
}
}
}
}
fun atPosition(position: Int, itemMatcher: Matcher<View>): Matcher<View> {
checkNotNull(itemMatcher)
return object : BoundedMatcher<View, RecyclerView>(RecyclerView::class.java) {
override fun describeTo(description: Description) {
description.appendText("has item at position $position: ")
itemMatcher.describeTo(description)
}
override fun matchesSafely(view: RecyclerView): Boolean {
val viewHolder = view.findViewHolderForAdapterPosition(position)
?: // has no item on such position
return false
return itemMatcher.matches(viewHolder.itemView)
}
}
}
fun atPosition(position: Int, id: Int, itemMatcher: Matcher<View>): Matcher<View> {
checkNotNull(itemMatcher)
return object : BoundedMatcher<View, RecyclerView>(RecyclerView::class.java) {
override fun describeTo(description: Description) {
description.appendText("has item at position $position: ")
itemMatcher.describeTo(description)
}
override fun matchesSafely(view: RecyclerView): Boolean {
val viewHolder = view.findViewHolderForAdapterPosition(position)
?: // has no item on such position
return false
val view = viewHolder.itemView.findViewById<View>(id)
return itemMatcher.matches(view)
}
}
}
fun getCurrentActivity(): Activity? {
var currentActivity: Activity? = null
getInstrumentation().runOnMainSync {
run {
currentActivity =
ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(
Stage.RESUMED
).elementAtOrNull(0)
}
}
return currentActivity
}
}

View File

@ -2,25 +2,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pl.edu.amu.wmi.socialaggregator"> package="pl.edu.amu.wmi.socialaggregator">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity
android:name=".activity.PostHistoryActivity"
android:label="@string/title_activity_post_history"
android:parentActivityName=".activity.MainActivity"
android:theme="@style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="pl.edu.amu.wmi.socialaggregator.activity.MainActivity" />
</activity>
<activity <activity
android:name=".activity.AddSocialActivity" android:name=".activity.AddSocialActivity"
android:label="@string/title_activity_add_social" android:label="@string/title_activity_add_social"
@ -46,50 +34,6 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id"/>
<activity android:name="com.facebook.FacebookActivity"
android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
<provider android:authorities="com.facebook.app.FacebookContentProvider2437098899888167"
android:name="com.facebook.FacebookContentProvider"
android:exported="true"/>
<meta-data android:name="com.snapchat.kit.sdk.clientId" android:value="240836fb-b762-4be8-a42f-5472a22f2114" />
<!-- <meta-data android:name="com.snapchat.kit.sdk.clientId" android:value="your apps client id" />-->
<!-- <meta-data android:name="com.snapchat.kit.sdk.redirectUrl" android:value="the url that will handle login completion" />-->
<!-- <meta-data android:name="com.snapchat.kit.sdk.scopes" android:resource="@array/snap_connect_scopes" />-->
<provider
android:authorities="${applicationId}.fileprovider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"
/>
</provider>
</application> </application>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest> </manifest>

View File

@ -8,7 +8,7 @@ import kotlinx.android.synthetic.main.activity_add_social.*
import kotlinx.android.synthetic.main.content_add_social.* import kotlinx.android.synthetic.main.content_add_social.*
import pl.edu.amu.wmi.socialaggregator.R import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithImageRecycler
class AddSocialActivity : AppCompatActivity() { class AddSocialActivity : AppCompatActivity() {
@ -23,33 +23,33 @@ class AddSocialActivity : AppCompatActivity() {
val loggedInSocials = SocialPlatformsManager.getLoggedIn(this) val loggedInSocials = SocialPlatformsManager.getLoggedIn(this)
val recyclers = mutableListOf(availableSocialsRecyclerView, addSocialRecyclerView) val recyclers = mutableListOf(availableSocialsRecyclerView, addSocialRecyclerView)
// availableSocialsRecyclerView.apply { availableSocialsRecyclerView.apply {
// layoutManager = LinearLayoutManager(this@AddSocialActivity) layoutManager = LinearLayoutManager(this@AddSocialActivity)
// adapter = SocialWithButtonRecycler( adapter = SocialWithImageRecycler(
// loggedInSocials, loggedInSocials,
// R.mipmap.ic_opaque_remove R.drawable.ic_remove_circle
// ) { ) {
// it.logout(context) it.logout(context)
// loggedInSocials.remove(it) loggedInSocials.remove(it)
// notLoggedInSocials.add(it) notLoggedInSocials.add(it)
// recyclers.forEach { it.adapter?.notifyDataSetChanged() } recyclers.forEach { it.adapter?.notifyDataSetChanged() }
// Toast.makeText(context, "Logged out from ${it.getName()}!", Toast.LENGTH_SHORT).show() Toast.makeText(context, "Logged out from ${it.getName()}!", Toast.LENGTH_SHORT).show()
// } }
// } }
//
// addSocialRecyclerView.apply { addSocialRecyclerView.apply {
// layoutManager = LinearLayoutManager(this@AddSocialActivity) layoutManager = LinearLayoutManager(this@AddSocialActivity)
// adapter = SocialWithButtonRecycler( adapter = SocialWithImageRecycler(
// notLoggedInSocials, notLoggedInSocials,
// R.mipmap.ic_opaque_add R.drawable.ic_add_circle
// ) { ) {
// it.login(context) it.login(context)
// notLoggedInSocials.remove(it) notLoggedInSocials.remove(it)
// loggedInSocials.add(it) loggedInSocials.add(it)
// recyclers.forEach { it.adapter?.notifyDataSetChanged() } recyclers.forEach { it.adapter?.notifyDataSetChanged() }
// Toast.makeText(context, "Logged in to ${it.getName()}!", Toast.LENGTH_SHORT).show() Toast.makeText(context, "Logged in to ${it.getName()}!", Toast.LENGTH_SHORT).show()
// } }
// } }
} }

View File

@ -5,21 +5,17 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.jakewharton.rxbinding2.view.RxView import com.jakewharton.rxbinding2.view.RxView
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import pl.edu.amu.wmi.socialaggregator.R import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
import pl.edu.amu.wmi.socialaggregator.viewholders.PostSummaryRecycler import pl.edu.amu.wmi.socialaggregator.viewholders.PostTextRecycler
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithImageRecycler
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private val subs = CompositeDisposable() private val subs = CompositeDisposable()
private val TAG = MainActivity::class.java.simpleName
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
@ -30,18 +26,13 @@ class MainActivity : AppCompatActivity() {
val intent = Intent(this, NewPostActivity::class.java) val intent = Intent(this, NewPostActivity::class.java)
startActivity(intent) startActivity(intent)
}, },
RxView.clicks(previousPostsButton) RxView.clicks(connectedSocialsButton)
.subscribe { .subscribe {
val intent = Intent(this, PostHistoryActivity::class.java) val intent = Intent(this, AddSocialActivity::class.java)
startActivity(intent) startActivity(intent)
} }
) )
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
SocialPlatformsManager.getAll()
.forEach { it.onActivityResult(requestCode, resultCode, data) }
super.onActivityResult(requestCode, resultCode, data)
} }
override fun onResume() { override fun onResume() {
@ -49,20 +40,14 @@ class MainActivity : AppCompatActivity() {
connectedSocialsRecyclerView.apply { connectedSocialsRecyclerView.apply {
layoutManager = LinearLayoutManager(this@MainActivity) layoutManager = LinearLayoutManager(this@MainActivity)
adapter = adapter = SocialWithImageRecycler(SocialPlatformsManager.getLoggedIn(this@MainActivity),
SocialWithButtonRecycler(SocialPlatformsManager.getAll(), this@MainActivity) R.drawable.ic_launcher_background) {}
} }
previousPostsRecyclerView.apply { previousPostsRecyclerView.apply {
layoutManager = LinearLayoutManager(this@MainActivity) layoutManager = LinearLayoutManager(this@MainActivity)
adapter = PostSummaryRecycler( adapter = PostTextRecycler(SocialPlatformsManager.getLoggedIn(this@MainActivity)
Observable.merge(SocialPlatformsManager.getLoggedIn(this@MainActivity) .map { it to it.getPosts(this@MainActivity).size })
.map { social ->
social.getPosts(this@MainActivity)
.map { social to it }
.toObservable()
})
)
} }
} }

View File

@ -1,41 +1,20 @@
package pl.edu.amu.wmi.socialaggregator.activity package pl.edu.amu.wmi.socialaggregator.activity
import android.Manifest
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.provider.MediaStore import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.jakewharton.rxbinding2.view.RxView import com.jakewharton.rxbinding2.view.RxView
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.BiFunction
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import kotlinx.android.synthetic.main.activity_new_post.* import kotlinx.android.synthetic.main.activity_new_post.*
import kotlinx.android.synthetic.main.content_new_post.* import kotlinx.android.synthetic.main.content_new_post.*
import pl.edu.amu.wmi.socialaggregator.R import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithToggleRecycler import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithToggleRecycler
class NewPostActivity : AppCompatActivity() { class NewPostActivity : AppCompatActivity() {
var file: String? = null
val postedSubject = PublishSubject.create<Any>()
val resumedSubject = PublishSubject.create<Any>()
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -57,115 +36,16 @@ class NewPostActivity : AppCompatActivity() {
} }
RxView.clicks(publishPost) RxView.clicks(publishPost)
.filter { file != null } .subscribe {
.doOnNext { availablesRecycler.chips.entries.forEach { (social, chip) ->
val sdk = android.os.Build.VERSION.SDK_INT if (chip.isChecked) {
if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) { social.addPost(this, postText.text?.toString() ?: "test", emptyList())
val clipboard = Toast.makeText(this, "Posted to ${social.getName()}!", Toast.LENGTH_LONG)
getSystemService(Context.CLIPBOARD_SERVICE) as android.text.ClipboardManager .show()
clipboard.text = postText.text?.toString() ?: "" }
} else {
val clipboard =
getSystemService(Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
val clip = android.content.ClipData.newPlainText(
"text label",
postText.text?.toString() ?: ""
)
clipboard.primaryClip = clip
} }
finish()
} }
.observeOn(Schedulers.io())
.doOnNext {
resumedSubject
.zipWith(
Observable.fromIterable(availablesRecycler.chips.entries
.filter { (_, chip) -> chip.isChecked }
.map { it.key }),
BiFunction<Any, SocialPlatform, SocialPlatform> { _, t2 -> t2 }
)
.observeOn(Schedulers.io())
.doOnNext {
val bitmap = BitmapFactory.decodeFile(file!!)
it.addPost(
postedSubject, this,
postText.text?.toString() ?: "",
listOf(bitmap),
listOf(file!!)
)
}
.take(availablesRecycler.chips.count { it.value.isChecked }.toLong() + 1)
.toList()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { _ ->
finish()
}
}
.subscribe {
resumedSubject.onNext(Any())
}
RxView.clicks(imageView2)
.subscribe {
val getIntent = Intent(Intent.ACTION_GET_CONTENT)
getIntent.type = "image/*"
val pickIntent = Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
)
pickIntent.type = "image/*"
val chooserIntent = Intent.createChooser(getIntent, "Select Image")
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(pickIntent))
startActivityForResult(chooserIntent, PICK_IMAGE_REQUEST_CODE)
}
if (canAccessGallery()) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 0
)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
SocialPlatformsManager.getAll()
.forEach { it.onActivityResult(requestCode, resultCode, data) }
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PICK_IMAGE_REQUEST_CODE) {
data?.data?.let { uri ->
file = getPath(uri)
imageView2.setImageURI(uri)
}
}
}
fun getPath(uri: Uri): String? {
val projection = arrayOf(MediaStore.Images.Media.DATA)
val cursor = contentResolver.query(uri, projection, null, null, null) ?: return null
val column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
cursor.moveToFirst()
val s = cursor.getString(column_index)
cursor.close()
return s
}
override fun onResume() {
super.onResume()
resumedSubject.onNext(Any())
}
private fun canAccessGallery() =
(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED)
companion object {
const val PICK_IMAGE_REQUEST_CODE = 69
} }
} }

View File

@ -1,41 +0,0 @@
package pl.edu.amu.wmi.socialaggregator.activity
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import io.reactivex.Observable
import kotlinx.android.synthetic.main.activity_post_history.*
import kotlinx.android.synthetic.main.content_post_history.*
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
import pl.edu.amu.wmi.socialaggregator.viewholders.PostDetailsRecycler
import androidx.recyclerview.widget.DividerItemDecoration
class PostHistoryActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_post_history)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
postHistoryRecycler.apply {
layoutManager = LinearLayoutManager(this@PostHistoryActivity)
adapter = PostDetailsRecycler(
Observable.fromIterable(SocialPlatformsManager.getLoggedIn(this@PostHistoryActivity))
.flatMap {
it.getPosts(this@PostHistoryActivity)
.toObservable()
})
addItemDecoration(
DividerItemDecoration(
context,
(layoutManager as LinearLayoutManager).orientation
))
}
}
}

View File

@ -1,234 +0,0 @@
package pl.edu.amu.wmi.socialaggregator.socialplatforms
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import com.facebook.*
import com.facebook.login.LoginManager
import com.facebook.login.LoginResult
import com.facebook.login.widget.LoginButton
import com.facebook.share.Sharer
import com.facebook.share.model.ShareMediaContent
import com.facebook.share.model.SharePhoto
import com.facebook.share.widget.ShareDialog
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import org.json.JSONArray
import org.json.JSONObject
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.utils.Utils
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler
class Facebook : SocialPlatform {
private var callbackManager: CallbackManager = CallbackManager.Factory.create()
override fun getName(): String = "Facebook"
override fun getLogo(): Int = R.mipmap.ic_logo_facebook
override fun login(context: Context) {
}
override fun logout(context: Context) {
}
override fun isLoggedIn(context: Context): Boolean {
val accessToken = AccessToken.getCurrentAccessToken()
return accessToken != null && !accessToken.isExpired
}
override fun addPost(
publishSubject: PublishSubject<Any>,
context: Context,
text: String,
images: List<Bitmap>,
imagePaths: List<String>
) {
val content = ShareMediaContent.Builder().apply {
images.forEach {
addMedium(
SharePhoto.Builder().setBitmap(it).build()
)
}
}.build()
val shareDialog = ShareDialog(context as Activity)
shareDialog.registerCallback(callbackManager, object : FacebookCallback<Sharer.Result?> {
override fun onSuccess(result: Sharer.Result?) {
publishSubject.onNext(Any())
}
override fun onCancel() {
publishSubject.onNext(Any())
}
override fun onError(error: FacebookException?) {
publishSubject.onError(Exception(error?.localizedMessage))
}
})
shareDialog.show(content, ShareDialog.Mode.AUTOMATIC)
}
override fun getPosts(context: Context): Single<List<Post>> {
return Single.just(AccessToken.getCurrentAccessToken())
.observeOn(Schedulers.io())
.map { token ->
if (token.isExpired) {
return@map emptyList<Post>()
} else {
val request = GraphRequest.newGraphPathRequest(
AccessToken.getCurrentAccessToken(),
"/me/posts"
) {
Log.i(getName(), it.toString())
}
val parameters = Bundle()
parameters.putString(
"fields",
"likes.summary(true),created_time,message,attachments{url,unshimmed_url,media,subattachments}"
)
request.parameters = parameters
val res = request.executeAndWait()
val data = res.jsonObject["data"] as JSONArray
val size = data.length()
return@map (0 until size).map {
val obj = data[it] as JSONObject
val msg = if (obj.has("message")) obj.getString("message") else ""
val date =
if (obj.has("created_time")) obj.getString("created_time") else ""
// SimpleDateFormat("YYYY-MM-DD\'T\'hh:mm:ssZ").parse(date)
Post(this, msg, date, getImages(obj))
}
}
}
.observeOn(AndroidSchedulers.mainThread())
}
private fun getImages(obj: JSONObject): List<String> {
val list = emptyList<String>().toMutableList()
if (obj.has("attachments")) {
val attachments = obj.getJSONObject("attachments").getJSONArray("data")
try {
list.addAll((0 until attachments.length())
.map { attachments[it] as JSONObject }
.flatMap {
val urls = mutableListOf<String>()
if (it.has("media")) {
urls.add(
it.getJSONObject("media")
.getJSONObject("image")
.getString("src")
)
}
if (it.has("subattachments")) {
val subattachments =
it.getJSONObject("subattachments").getJSONArray("data")
urls.addAll((0 until subattachments.length())
.map { subattachments[it] as JSONObject }
.map {
it.getJSONObject("media")
.getJSONObject("image")
.getString("src")
})
}
return@flatMap urls
})
} catch (e: Exception) {
Log.e(getName(), e.toString())
}
}
return list
}
override fun handleButtonView(context: Context): (SocialWithButtonRecycler.ViewHolder) -> Unit =
{ viewHolder ->
viewHolder.textView.text = this.getName()
val constraintSet = ConstraintSet()
val button = LoginButton(context)
button.id = View.generateViewId()
val parent = viewHolder.image.parent as ViewGroup
parent.removeView(viewHolder.image)
parent.addView(button)
constraintSet.clone(parent as ConstraintLayout)
constraintSet.connect(
button.id, ConstraintSet.TOP,
parent.id, ConstraintSet.TOP, 8.toPx(context)
)
constraintSet.connect(
button.id, ConstraintSet.END,
parent.id, ConstraintSet.END
)
constraintSet.connect(
button.id, ConstraintSet.BOTTOM,
parent.id, ConstraintSet.BOTTOM, 8.toPx(context)
)
constraintSet.connect(
viewHolder.textView.id, ConstraintSet.BOTTOM,
button.id, ConstraintSet.BOTTOM
)
constraintSet.connect(
viewHolder.textView.id, ConstraintSet.END,
button.id, ConstraintSet.START, 8.toPx(context)
)
constraintSet.connect(
viewHolder.textView.id, ConstraintSet.START,
parent.id, ConstraintSet.START
)
constraintSet.connect(
viewHolder.textView.id, ConstraintSet.TOP,
button.id, ConstraintSet.TOP
)
constraintSet.setHorizontalBias(viewHolder.textView.id, 0.toFloat())
constraintSet.applyTo(parent)
button.setPermissions(listOf("email"))
val callback = object : FacebookCallback<LoginResult> {
override fun onSuccess(result: LoginResult?) {
Log.i(getName(), "SUCCESS!")
LoginManager.getInstance().logInWithReadPermissions(
context as Activity,
listOf("email")
)
}
override fun onCancel() {
Log.i(getName(), "CANCEL!")
}
override fun onError(error: FacebookException?) {
Log.i(getName(), "FAIL!")
}
}
button.registerCallback(callbackManager, callback)
LoginManager.getInstance().registerCallback(callbackManager, callback)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
callbackManager.onActivityResult(requestCode, resultCode, data)
}
private fun Int.toPx(context: Context): Int {
return Utils.convertDpToPixel(this.toFloat(), context).toInt()
}
}

View File

@ -0,0 +1,65 @@
package pl.edu.amu.wmi.socialaggregator.socialplatforms
import android.content.Context
import android.graphics.Bitmap
import android.util.Log
import pl.edu.amu.wmi.socialaggregator.utils.InternalStorage
import java.io.ByteArrayOutputStream
import java.io.File
class FacebookMock : SocialPlatform {
companion object {
val TAG = FacebookMock::class.java.canonicalName
}
override fun getName(): String = "Facebook"
override fun login(context: Context) {
val loginsDir = InternalStorage.getFileOrDir(context, "logins")
if (loginsDir != null) {
val loginFile = File(loginsDir, "facebook")
loginFile.createNewFile()
} else {
Log.e(TAG, "Could not create logins directory")
}
}
override fun logout(context: Context) {
InternalStorage.getFileOrDir(context, "logins/facebook")?.delete()
}
override fun isLoggedIn(context: Context): Boolean {
return InternalStorage.getFileOrDir(context, "logins/facebook")?.exists() ?: false
}
override fun addPost(context: Context, text: String, images: List<Bitmap>) {
val postsDir = InternalStorage.getFileOrDir(context, "posts/facebook")
if (postsDir != null) {
val postDir = File(postsDir, System.currentTimeMillis().toString())
postDir.mkdirs()
val textFile = File(postDir, "content")
textFile.createNewFile()
textFile.writeText(text)
images.forEachIndexed { index, image ->
val imageFile = File(postDir, "image$index")
imageFile.createNewFile()
ByteArrayOutputStream().use { stream ->
image.compress(Bitmap.CompressFormat.JPEG, 100, stream)
imageFile.writeBytes(stream.toByteArray())
}
}
} else {
Log.e(TAG, "Could not create posts directory")
}
}
override fun getPosts(context: Context): List<String> {
val postsDir = InternalStorage.getFileOrDir(context, "posts/facebook")
return postsDir?.listFiles()?.map { it.name }?.toList() ?: emptyList()
}
}

View File

@ -1,5 +0,0 @@
package pl.edu.amu.wmi.socialaggregator.socialplatforms
import java.lang.Exception
class NotApplicableException(val socialPlatform: SocialPlatform) : Exception()

View File

@ -1,8 +0,0 @@
package pl.edu.amu.wmi.socialaggregator.socialplatforms
data class Post(
val social: SocialPlatform,
val content: String,
val dateTime: String,
val images: List<String>
)

View File

@ -1,83 +0,0 @@
package pl.edu.amu.wmi.socialaggregator.socialplatforms
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.util.Log
import com.snapchat.kit.sdk.SnapCreative
import com.snapchat.kit.sdk.creative.api.SnapCreativeKitCompletionCallback
import com.snapchat.kit.sdk.creative.api.SnapCreativeKitSendError
import com.snapchat.kit.sdk.creative.exceptions.SnapMediaSizeException
import com.snapchat.kit.sdk.creative.models.SnapPhotoContent
import io.reactivex.Single
import io.reactivex.subjects.PublishSubject
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler
import java.io.File
import java.lang.Exception
class Snapchat : SocialPlatform {
override fun getName(): String = "Snapchat"
override fun login(context: Context) {
}
override fun logout(context: Context) {
}
override fun isLoggedIn(context: Context): Boolean = true
override fun addPost(
publishSubject: PublishSubject<Any>,
context: Context,
text: String,
images: List<Bitmap>,
imagePaths: List<String>
) {
val snapCreativeKitApi = SnapCreative.getApi(context)
val content = imagePaths.map {
val snapMediaFactory = SnapCreative.getMediaFactory(context)
val photoFile = try {
snapMediaFactory.getSnapPhotoFromFile(File(it))
} catch (e: SnapMediaSizeException) {
Log.e(getName(), e.toString())
null
}
SnapPhotoContent(photoFile!!)
}.first()
if (text.isNotBlank()) {
content.captionText = text
}
snapCreativeKitApi.sendWithCompletionHandler(
content,
object : SnapCreativeKitCompletionCallback {
override fun onSendSuccess() {
publishSubject.onNext(Any())
}
override fun onSendFailed(p0: SnapCreativeKitSendError?) {
publishSubject.onError(Exception("Snapchat error"))
}
})
}
override fun getPosts(context: Context): Single<List<Post>> {
return Single.just(emptyList())
}
override fun getLogo(): Int = R.drawable.ic_icon_snapchat
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
}
override fun handleButtonView(context: Context): (SocialWithButtonRecycler.ViewHolder) -> Unit =
{
it.image.setImageResource(getLogo())
it.textView.text = getName()
}
}

View File

@ -1,11 +1,7 @@
package pl.edu.amu.wmi.socialaggregator.socialplatforms package pl.edu.amu.wmi.socialaggregator.socialplatforms
import android.content.Context import android.content.Context
import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
import io.reactivex.Single
import io.reactivex.subjects.PublishSubject
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler
interface SocialPlatform { interface SocialPlatform {
@ -13,12 +9,6 @@ interface SocialPlatform {
fun login(context: Context) fun login(context: Context)
fun logout(context: Context) fun logout(context: Context)
fun isLoggedIn(context: Context): Boolean fun isLoggedIn(context: Context): Boolean
fun addPost(publishSubject: PublishSubject<Any>, fun addPost(context: Context, text: String, images: List<Bitmap>)
context: Context, text: String, images: List<Bitmap>, fun getPosts(context: Context): List<String>
imagePaths: List<String>)
fun getPosts(context: Context): Single<List<Post>>
fun getLogo(): Int
fun handleButtonView(context: Context): (SocialWithButtonRecycler.ViewHolder) -> Unit = {}
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {}
} }

View File

@ -1,19 +1,14 @@
package pl.edu.amu.wmi.socialaggregator.utils package pl.edu.amu.wmi.socialaggregator.utils
import android.content.Context import android.content.Context
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Facebook import pl.edu.amu.wmi.socialaggregator.socialplatforms.FacebookMock
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Snapchat
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
object SocialPlatformsManager { object SocialPlatformsManager {
private val IMPLEMENTED_PLATFORMS = listOf( private val IMPLEMENTED_PLATFORMS = listOf<SocialPlatform>(
// FacebookMock() FacebookMock()
Facebook(),
Snapchat()
) )
fun getAll() = IMPLEMENTED_PLATFORMS
fun getLoggedIn(context: Context) = fun getLoggedIn(context: Context) =
IMPLEMENTED_PLATFORMS.filter { it.isLoggedIn(context) }.toMutableList() IMPLEMENTED_PLATFORMS.filter { it.isLoggedIn(context) }.toMutableList()

View File

@ -1,12 +0,0 @@
package pl.edu.amu.wmi.socialaggregator.utils
import android.content.Context
import android.util.DisplayMetrics
object Utils {
fun convertDpToPixel(dp: Float, context: Context): Float {
return dp * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}
}

View File

@ -1,105 +0,0 @@
package pl.edu.amu.wmi.socialaggregator.viewholders
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.squareup.picasso.Picasso
import io.reactivex.Observable
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.socialplatforms.NotApplicableException
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Post
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
@SuppressLint("CheckResult")
class PostDetailsRecycler(
postsObservable: Observable<List<Post>>
) : RecyclerView.Adapter<PostDetailsRecycler.ViewHolder>() {
val posts = emptyList<Post>().toMutableList()
init {
postsObservable
.subscribe {
posts.addAll(it)
notifyDataSetChanged()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layout = LayoutInflater.from(parent.context)
.inflate(R.layout.item_post, parent, false) as ConstraintLayout
val dateTime = layout.findViewById<TextView>(R.id.postDateTimeTextView)
val postContent = layout.findViewById<TextView>(R.id.postContentTextView)
val imageView = layout.findViewById<ImageView>(R.id.postSocialImage)
val imagesContainer = layout.findViewById<LinearLayout>(R.id.imagesContainer)
return ViewHolder(layout, dateTime, postContent, imageView, imagesContainer)
}
override fun getItemCount(): Int {
return posts.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val post = posts[position]
holder.dateTime.text = formatDate(post.dateTime)
holder.postContent.text = post.content
holder.postContent.visibility = if (post.content.isBlank()) View.GONE else View.VISIBLE
holder.imageView.setImageResource(post.social.getLogo())
holder.imagesContainer.apply {
removeAllViews()
post {
val imgWidth = (parent as ConstraintLayout).width / post.images.size - 10
post.images.forEach {
val imageView = ImageView(context)
addView(imageView)
imageView.apply {
(layoutParams as ViewGroup.MarginLayoutParams)
.apply {
marginEnd = 10
}
}
Picasso.with(context)
.load(it)
.placeholder(android.R.drawable.ic_menu_gallery)
.resize(imgWidth, imgWidth)
.centerCrop()
.into(imageView)
}
}
}
}
private fun formatDate(str: String): String {
val regex = """(\d+-\d+-\d+)T(\d+:\d+:\d+)""".toRegex()
val matchResult = regex.find(str)
val (date, time) = matchResult!!.destructured
return "$date $time"
}
class ViewHolder(
root: ConstraintLayout,
val dateTime: TextView,
val postContent: TextView,
val imageView: ImageView,
val imagesContainer: LinearLayout
) : RecyclerView.ViewHolder(root)
}

View File

@ -1,65 +0,0 @@
package pl.edu.amu.wmi.socialaggregator.viewholders
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observable
import io.reactivex.Single
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.socialplatforms.NotApplicableException
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Post
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
@SuppressLint("CheckResult")
class PostSummaryRecycler(
socialsObservable: Observable<Pair<SocialPlatform, List<Post>?>>
) : RecyclerView.Adapter<PostSummaryRecycler.ViewHolder>() {
private val socials = mutableListOf<Pair<SocialPlatform, List<Post>?>>()
init {
socialsObservable
.doOnNext {
socials.add(it)
notifyDataSetChanged()
}
.subscribe()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layout = LayoutInflater.from(parent.context)
.inflate(R.layout.previous_posts, parent, false) as ConstraintLayout
val socialName = layout.findViewById<TextView>(R.id.socialTextView)
val postCount = layout.findViewById<TextView>(R.id.post)
val imageView = layout.findViewById<ImageView>(R.id.postSocialImage)
return ViewHolder(layout, socialName, postCount, imageView)
}
override fun getItemCount(): Int {
return socials.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val (social, posts) = socials[position]
val count = posts?.size
holder.socialName.text = social.getName()
holder.postCount.text = count?.let {
count.toString() + if (count > 1) " posts" else " post"
} ?: "Not applicable"
holder.imageView.setImageResource(social.getLogo())
}
class ViewHolder(
root: ConstraintLayout,
val socialName: TextView,
val postCount: TextView,
val imageView: ImageView
) : RecyclerView.ViewHolder(root)
}

View File

@ -0,0 +1,44 @@
package pl.edu.amu.wmi.socialaggregator.viewholders
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.jakewharton.rxbinding2.view.RxView
import io.reactivex.disposables.Disposable
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
class PostTextRecycler(
val socials: List<Pair<SocialPlatform, Int>>) : RecyclerView.Adapter<PostTextRecycler.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layout = LayoutInflater.from(parent.context)
.inflate(R.layout.previous_posts, parent, false) as ConstraintLayout
val socialName = layout.findViewById<TextView>(R.id.socialTextView)
val postCount = layout.findViewById<TextView>(R.id.postCountTextView)
return ViewHolder(layout, socialName, postCount)
}
override fun getItemCount(): Int {
return socials.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val pair = socials[position]
holder.socialName.text = pair.first.getName()
val count = pair.second
holder.postCount.text = count.toString() + if (count > 1) " posts" else " post"
}
class ViewHolder(
root: ConstraintLayout,
val socialName: TextView,
val postCount: TextView
) : RecyclerView.ViewHolder(root)
}

View File

@ -1,6 +1,5 @@
package pl.edu.amu.wmi.socialaggregator.viewholders package pl.edu.amu.wmi.socialaggregator.viewholders
import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
@ -12,10 +11,11 @@ import io.reactivex.disposables.Disposable
import pl.edu.amu.wmi.socialaggregator.R import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
class SocialWithButtonRecycler( class SocialWithImageRecycler(
val availableSocials: List<SocialPlatform>, val availableSocials: List<SocialPlatform>,
val context: Context private val imageResource: Int,
) : RecyclerView.Adapter<SocialWithButtonRecycler.ViewHolder>() { private val action: (SocialPlatform) -> Unit
) : RecyclerView.Adapter<SocialWithImageRecycler.ViewHolder>() {
private val disposables = HashMap<SocialPlatform, Disposable>() private val disposables = HashMap<SocialPlatform, Disposable>()
@ -34,18 +34,18 @@ class SocialWithButtonRecycler(
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
availableSocials[position].handleButtonView(context)(holder) val social = availableSocials[position]
// holder.textView.text = social.getName() holder.text.text = social.getName()
// holder.image.setImageResource(imageResource ?: social.getLogo()) holder.image.setImageResource(imageResource)
//
// disposables[social] = RxView.clicks(holder.image) disposables[social] = RxView.clicks(holder.image)
// .map { social } .map { social }
// .subscribe(action) .subscribe(action)
} }
class ViewHolder( class ViewHolder(
root: ConstraintLayout, root: ConstraintLayout,
val textView: TextView, val text: TextView,
val image: ImageView val image: ImageView
) : RecyclerView.ViewHolder(root) ) : RecyclerView.ViewHolder(root)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 725 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -14,7 +14,7 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/logo" /> app:srcCompat="@mipmap/ic_launcher" />
<TextView <TextView
android:id="@+id/connectedSocialsTextView" android:id="@+id/connectedSocialsTextView"
@ -22,14 +22,14 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:text="Available Socials" android:text="Connected Socials"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" /> app:layout_constraintTop_toBottomOf="@+id/imageView" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/connectedSocialsRecyclerView" android:id="@+id/connectedSocialsRecyclerView"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="150dp" android:layout_height="100dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
@ -41,6 +41,17 @@
</androidx.recyclerview.widget.RecyclerView> </androidx.recyclerview.widget.RecyclerView>
<Button
android:id="@+id/connectedSocialsButton"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:text="Connect new"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/connectedSocialsRecyclerView" />
<View <View
android:id="@+id/divider" android:id="@+id/divider"
android:layout_width="0dp" android:layout_width="0dp"
@ -52,7 +63,7 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0" app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/connectedSocialsRecyclerView" /> app:layout_constraintTop_toBottomOf="@+id/connectedSocialsButton" />
<TextView <TextView
android:id="@+id/textView2" android:id="@+id/textView2"
@ -118,12 +129,11 @@
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
android:clickable="true" android:clickable="true"
android:tint="@android:color/background_light" android:tint="#00FFFFFF"
app:fabSize="auto" app:fabSize="auto"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/previousPostsButton" app:layout_constraintTop_toBottomOf="@+id/previousPostsButton"
app:layout_constraintVertical_bias="1.0" app:srcCompat="@android:drawable/ic_input_add" />
app:srcCompat="@mipmap/ic_opaque_add" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.PostHistoryActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_post_history" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -61,11 +61,10 @@
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:clickable="true" android:clickable="true"
android:tint="@android:color/background_light"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/availableSocials" app:layout_constraintTop_toBottomOf="@+id/availableSocials"
app:srcCompat="@mipmap/ic_opaque_send" /> app:srcCompat="@drawable/ic_add_circle" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView> </ScrollView>

View File

@ -1,23 +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:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".activity.PostHistoryActivity"
tools:showIn="@layout/activity_post_history">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/postHistoryRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,58 +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/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/postContentTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toStartOf="@+id/postSocialImage"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/postDateTimeTextView"
tools:visibility="visible" />
<ImageView
android:id="@+id/postSocialImage"
android:layout_width="@dimen/social_logo_size"
android:layout_height="@dimen/social_logo_size"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:srcCompat="@mipmap/ic_logo_facebook" />
<TextView
android:id="@+id/postDateTimeTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="TextView"
android:textSize="10sp"
app:layout_constraintEnd_toStartOf="@+id/postSocialImage"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/imagesContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal"
android:layout_gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/postContentTextView" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -13,32 +13,32 @@
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:text="Bla bla bla" android:text="Bla bla bla"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
app:layout_constraintBottom_toTopOf="@+id/post" app:layout_constraintBottom_toTopOf="@+id/postCountTextView"
app:layout_constraintEnd_toStartOf="@+id/postSocialImage" app:layout_constraintEnd_toStartOf="@+id/imageView3"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/postSocialImage" app:layout_constraintTop_toTopOf="@+id/imageView3"
app:layout_constraintVertical_chainStyle="packed" /> app:layout_constraintVertical_chainStyle="packed" />
<TextView <TextView
android:id="@+id/post" android:id="@+id/postCountTextView"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:text="Bla bla bla" android:text="Bla bla bla"
android:textColor="@android:color/secondary_text_light" android:textColor="@android:color/secondary_text_light"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toStartOf="@+id/postSocialImage" app:layout_constraintEnd_toStartOf="@+id/imageView3"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/socialTextView" /> app:layout_constraintTop_toBottomOf="@+id/socialTextView" />
<ImageView <ImageView
android:id="@+id/postSocialImage" android:id="@+id/imageView3"
android:layout_width="@dimen/social_logo_size" android:layout_width="wrap_content"
android:layout_height="@dimen/social_logo_size" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/ic_logo_facebook" /> app:srcCompat="@mipmap/ic_launcher_round" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -9,23 +9,23 @@
android:id="@+id/socialPlatformName" android:id="@+id/socialPlatformName"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="@+id/socialPlatformImage"
app:layout_constraintEnd_toStartOf="@+id/socialPlatformImage" app:layout_constraintEnd_toStartOf="@+id/socialPlatformImage"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/socialPlatformImage" app:layout_constraintTop_toTopOf="parent"
tools:text="Some Sample Text" /> tools:text="Some Sample Text" />
<ImageView <ImageView
android:id="@+id/socialPlatformImage" android:id="@+id/socialPlatformImage"
android:layout_width="@dimen/social_logo_size" android:layout_width="0dp"
android:layout_height="@dimen/social_logo_size" android:layout_height="0dp"
android:layout_marginTop="8dp" android:layout_marginTop="-4dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="-4dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="@+id/socialPlatformName"
app:layout_constraintDimensionRatio="1:1" app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="@+id/socialPlatformName"
tools:srcCompat="@mipmap/ic_logo_facebook" /> tools:srcCompat="@mipmap/ic_launcher_round" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 742 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="colorPrimary">#512DA8</color> <color name="colorPrimary">#4267b2</color>
<color name="colorAccent">#5E35B1</color> <color name="colorPrimaryDark">#4267b2</color>
<color name="colorPrimaryDark">#4A148C</color> <color name="colorAccent">#4267b2</color>
</resources> </resources>

View File

@ -1,4 +1,3 @@
<resources> <resources>
<dimen name="fab_margin">16dp</dimen> <dimen name="fab_margin">16dp</dimen>
<dimen name="social_logo_size">32dp</dimen>
</resources> </resources>

View File

@ -1,15 +1,5 @@
<resources> <resources>
<string name="app_name">Social Aggregator</string> <string name="app_name">Social Aggregator</string>
<string name="title_activity_new_post">Create new post!</string> <string name="title_activity_new_post">NewPostActivity</string>
<string name="title_activity_add_social">AddSocialActivity</string> <string name="title_activity_add_social">AddSocialActivity</string>
<string name="title_activity_post_history">Posts history</string>
<string name="facebook_app_id">2437098899888167</string>
<string name="fb_login_protocol_scheme">fb2437098899888167</string>
<!-- <key>SCSDKScopes</key>-->
<!-- <array name="snap_connect_scopes">-->
<!-- <string>https://auth.snapchat.com/oauth2/api/user.bitmoji.avatar</string>-->
<!-- &lt;!&ndash; other scopes you might have... &ndash;&gt;-->
<!-- </array>-->
</resources> </resources>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path name="root" path="." />
<external-cache-path name="external_files" path="."/>
<external-path name="external_files" path="."/>
</paths>

View File

@ -20,27 +20,9 @@ allprojects {
google() google()
jcenter() jcenter()
maven {
url "https://storage.googleapis.com/snap-kit-build/maven"
}
} }
} }
task clean(type: Delete) { task clean(type: Delete) {
delete rootProject.buildDir delete rootProject.buildDir
} }
ext {
buildToolsVersion = "28.0.3"
androidxLibVersion = "1.0.0"
coreVersion = "1.3.0-alpha03"
extJUnitVersion = "1.1.2-alpha03"
runnerVersion = "1.3.0-alpha03"
rulesVersion = "1.3.0-alpha03"
espressoVersion = "3.3.0-alpha03"
extJUnitVersion = "1.1.2-alpha03"
extTruthVersion = "1.3.0-alpha03"
robolectricVersion = "4.3.1"
}

View File

@ -19,4 +19,3 @@ android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete": # Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official kotlin.code.style=official
android.enableUnitTestBinaryResources=true