Merge branch 'feature/SA-28-facebook-api-poc-impl' of s452086/social-aggregator into master

This commit is contained in:
Mateusz Hinc 2019-12-09 16:12:41 +00:00 committed by Gogs
commit 8130012710
37 changed files with 900 additions and 30 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<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" />
</component>
<component name="ProjectType">

View File

@ -5,12 +5,16 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
compileSdkVersion 28
buildToolsVersion "29.0.2"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "pl.edu.amu.wmi.socialaggregator"
minSdkVersion 21
targetSdkVersion 29
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -26,14 +30,18 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'com.android.support:appcompat-v7:28.1.0'
implementation 'com.android.support:design:28.1.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation "io.reactivex.rxjava2:rxjava:2.2.2"
implementation "io.reactivex.rxjava2:rxandroid:2.1.0"
implementation 'com.jakewharton.rxbinding2:rxbinding: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.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
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 'com.google.android.material:material:1.0.0'
}

View File

@ -9,7 +9,25 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<activity
android:name=".activity.AddSocialActivity"
android:label="@string/title_activity_add_social"
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
android:name=".activity.NewPostActivity"
android:label="@string/title_activity_new_post"
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 android:name=".activity.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -1,12 +0,0 @@
package pl.edu.amu.wmi.socialaggregator
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}

View File

@ -0,0 +1,56 @@
package pl.edu.amu.wmi.socialaggregator.activity
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_add_social.*
import kotlinx.android.synthetic.main.content_add_social.*
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithImageRecycler
class AddSocialActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_social)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val notLoggedInSocials = SocialPlatformsManager.getNotLoggedIn(this)
val loggedInSocials = SocialPlatformsManager.getLoggedIn(this)
val recyclers = mutableListOf(availableSocialsRecyclerView, addSocialRecyclerView)
availableSocialsRecyclerView.apply {
layoutManager = LinearLayoutManager(this@AddSocialActivity)
adapter = SocialWithImageRecycler(
loggedInSocials,
R.drawable.ic_remove_circle
) {
it.logout(context)
loggedInSocials.remove(it)
notLoggedInSocials.add(it)
recyclers.forEach { it.adapter?.notifyDataSetChanged() }
Toast.makeText(context, "Logged out from ${it.getName()}!", Toast.LENGTH_SHORT).show()
}
}
addSocialRecyclerView.apply {
layoutManager = LinearLayoutManager(this@AddSocialActivity)
adapter = SocialWithImageRecycler(
notLoggedInSocials,
R.drawable.ic_add_circle
) {
it.login(context)
notLoggedInSocials.remove(it)
loggedInSocials.add(it)
recyclers.forEach { it.adapter?.notifyDataSetChanged() }
Toast.makeText(context, "Logged in to ${it.getName()}!", Toast.LENGTH_SHORT).show()
}
}
}
}

View File

@ -0,0 +1,58 @@
package pl.edu.amu.wmi.socialaggregator.activity
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.jakewharton.rxbinding2.view.RxView
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.activity_main.*
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
import pl.edu.amu.wmi.socialaggregator.viewholders.PostTextRecycler
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithImageRecycler
class MainActivity : AppCompatActivity() {
private val subs = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
subs.addAll(
RxView.clicks(createPostButton)
.subscribe {
val intent = Intent(this, NewPostActivity::class.java)
startActivity(intent)
},
RxView.clicks(connectedSocialsButton)
.subscribe {
val intent = Intent(this, AddSocialActivity::class.java)
startActivity(intent)
}
)
}
override fun onResume() {
super.onResume()
connectedSocialsRecyclerView.apply {
layoutManager = LinearLayoutManager(this@MainActivity)
adapter = SocialWithImageRecycler(SocialPlatformsManager.getLoggedIn(this@MainActivity),
R.drawable.ic_launcher_background) {}
}
previousPostsRecyclerView.apply {
layoutManager = LinearLayoutManager(this@MainActivity)
adapter = PostTextRecycler(SocialPlatformsManager.getLoggedIn(this@MainActivity)
.map { it to it.getPosts(this@MainActivity).size })
}
}
override fun onDestroy() {
super.onDestroy()
subs.clear()
}
}

View File

@ -0,0 +1,51 @@
package pl.edu.amu.wmi.socialaggregator.activity
import android.annotation.SuppressLint
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar
import com.jakewharton.rxbinding2.view.RxView
import kotlinx.android.synthetic.main.activity_new_post.*
import kotlinx.android.synthetic.main.content_new_post.*
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithToggleRecycler
class NewPostActivity : AppCompatActivity() {
@SuppressLint("CheckResult")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new_post)
setSupportActionBar(toolbar)
publishPost.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val loggedInSocials = SocialPlatformsManager.getLoggedIn(this)
val availablesRecycler = SocialWithToggleRecycler(loggedInSocials)
availableSocials.apply {
layoutManager = LinearLayoutManager(this@NewPostActivity)
adapter = availablesRecycler
}
RxView.clicks(publishPost)
.subscribe {
availablesRecycler.chips.entries.forEach { (social, chip) ->
if (chip.isChecked) {
social.addPost(this, postText.text?.toString() ?: "test", emptyList())
Toast.makeText(this, "Posted to ${social.getName()}!", Toast.LENGTH_LONG)
.show()
}
}
finish()
}
}
}

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

@ -0,0 +1,14 @@
package pl.edu.amu.wmi.socialaggregator.socialplatforms
import android.content.Context
import android.graphics.Bitmap
interface SocialPlatform {
fun getName(): String
fun login(context: Context)
fun logout(context: Context)
fun isLoggedIn(context: Context): Boolean
fun addPost(context: Context, text: String, images: List<Bitmap>)
fun getPosts(context: Context): List<String>
}

View File

@ -0,0 +1,25 @@
package pl.edu.amu.wmi.socialaggregator.utils
import android.content.Context
import java.io.File
object InternalStorage {
fun getFileOrDir(context: Context, name: String): File? {
var file = context.filesDir
if (name.indexOf("/") > 0) {
val subdirs = name.split("/")
subdirs.subList(0, subdirs.size - 1).forEach {
file = File(file, it)
file.mkdir()
}
file = File(file, subdirs.last())
} else {
file = File(file, name)
}
return file
}
}

View File

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

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

@ -0,0 +1,52 @@
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 SocialWithImageRecycler(
val availableSocials: List<SocialPlatform>,
private val imageResource: Int,
private val action: (SocialPlatform) -> Unit
) : RecyclerView.Adapter<SocialWithImageRecycler.ViewHolder>() {
private val disposables = HashMap<SocialPlatform, Disposable>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layout = LayoutInflater.from(parent.context)
.inflate(R.layout.social_platform_image, parent, false) as ConstraintLayout
val textView = layout.findViewById<TextView>(R.id.socialPlatformName)
val imageView = layout.findViewById<ImageView>(R.id.socialPlatformImage)
return ViewHolder(layout, textView, imageView)
}
override fun getItemCount(): Int {
return availableSocials.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val social = availableSocials[position]
holder.text.text = social.getName()
holder.image.setImageResource(imageResource)
disposables[social] = RxView.clicks(holder.image)
.map { social }
.subscribe(action)
}
class ViewHolder(
root: ConstraintLayout,
val text: TextView,
val image: ImageView
) : RecyclerView.ViewHolder(root)
}

View File

@ -0,0 +1,46 @@
package pl.edu.amu.wmi.socialaggregator.viewholders
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.chip.Chip
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
class SocialWithToggleRecycler(
private val availableSocials: List<SocialPlatform>
) : RecyclerView.Adapter<SocialWithToggleRecycler.ViewHolder>() {
val chips = HashMap<SocialPlatform, CheckBox>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layout = LayoutInflater.from(parent.context)
.inflate(R.layout.social_platform_toggle, parent, false) as ConstraintLayout
val textView = layout.findViewById<TextView>(R.id.socialPlatformName)
val chip = layout.findViewById<CheckBox>(R.id.chip)
return ViewHolder(layout, textView, chip)
}
override fun getItemCount(): Int {
return availableSocials.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val social = availableSocials[position]
holder.text.text = social.getName()
chips[social] = holder.chip
}
class ViewHolder(
root: ConstraintLayout,
val text: TextView,
val chip: CheckBox
) : RecyclerView.ViewHolder(root)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,25 @@
<?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.AddSocialActivity">
<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_add_social" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -4,15 +4,136 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
tools:context=".activity.MainActivity">
<TextView
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
android:id="@+id/connectedSocialsTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="Connected Socials"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/connectedSocialsRecyclerView"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/connectedSocialsTextView"
tools:listitem="@layout/social_platform_image">
</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
android:id="@+id/divider"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:background="?android:attr/listDivider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/connectedSocialsButton" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="Previous Posts"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/previousPostsRecyclerView"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.25"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
<Button
android:id="@+id/previousPostsButton"
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="See more"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider2" />
<View
android:id="@+id/divider2"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:background="?android:attr/listDivider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/previousPostsRecyclerView" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="Add New Post"
app:layout_constraintBottom_toBottomOf="@+id/createPostButton"
app:layout_constraintEnd_toStartOf="@+id/createPostButton"
app:layout_constraintTop_toTopOf="@+id/createPostButton" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/createPostButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:clickable="true"
android:tint="#00FFFFFF"
app:fabSize="auto"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/previousPostsButton"
app:srcCompat="@android:drawable/ic_input_add" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,25 @@
<?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.NewPostActivity">
<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_new_post" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,70 @@
<?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.AddSocialActivity"
tools:showIn="@layout/activity_add_social">
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="Available Socials"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/availableSocialsRecyclerView"
android:layout_width="0dp"
android:layout_height="300dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3"
tools:itemCount="3"
tools:listitem="@layout/social_platform_image" />
<View
android:id="@+id/divider3"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:background="?android:attr/listDivider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/availableSocialsRecyclerView" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="Add New Social"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider3" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/addSocialRecyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
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_toBottomOf="@+id/textView4"
tools:itemCount="3"
tools:listitem="@layout/social_platform_image" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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="fill_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".activity.NewPostActivity"
tools:showIn="@layout/activity_new_post">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="32dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="32dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/ic_menu_gallery" />
<EditText
android:id="@+id/postText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:gravity="start|top"
android:inputType="textMultiLine"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView2" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/availableSocials"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/postText"
tools:itemCount="4"
tools:listitem="@layout/social_platform_toggle" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/publishPost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/availableSocials"
app:srcCompat="@drawable/ic_add_circle" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View File

@ -0,0 +1,44 @@
<?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/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/socialTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="Bla bla bla"
android:textColor="@android:color/primary_text_light"
app:layout_constraintBottom_toTopOf="@+id/postCountTextView"
app:layout_constraintEnd_toStartOf="@+id/imageView3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/imageView3"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="@+id/postCountTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="Bla bla bla"
android:textColor="@android:color/secondary_text_light"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toStartOf="@+id/imageView3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/socialTextView" />
<ImageView
android:id="@+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/ic_launcher_round" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,31 @@
<?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="wrap_content">
<TextView
android:id="@+id/socialPlatformName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toStartOf="@+id/socialPlatformImage"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Some Sample Text" />
<ImageView
android:id="@+id/socialPlatformImage"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="-4dp"
android:layout_marginBottom="-4dp"
app:layout_constraintBottom_toBottomOf="@+id/socialPlatformName"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/socialPlatformName"
tools:srcCompat="@mipmap/ic_launcher_round" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,28 @@
<?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="wrap_content">
<TextView
android:id="@+id/socialPlatformName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toStartOf="@+id/chip"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Some Sample Text" />
<CheckBox
android:id="@+id/chip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@+id/socialPlatformName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/socialPlatformName" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
<color name="colorPrimary">#4267b2</color>
<color name="colorPrimaryDark">#4267b2</color>
<color name="colorAccent">#4267b2</color>
</resources>

View File

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

View File

@ -1,3 +1,5 @@
<resources>
<string name="app_name">Social Aggregator</string>
<string name="title_activity_new_post">NewPostActivity</string>
<string name="title_activity_add_social">AddSocialActivity</string>
</resources>

View File

@ -8,4 +8,13 @@
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

View File

@ -8,7 +8,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files