Forráskód Böngészése

Added copy user link functionality

Vadik Sirekanyan 7 éve
szülő
commit
57e6d1e79d
25 módosított fájl, 219 hozzáadás és 80 törlés
  1. 3 11
      app/src/main/java/me/vadik/knigopis/MainActivity.kt
  2. 0 1
      app/src/main/java/me/vadik/knigopis/Router.kt
  3. 3 3
      app/src/main/java/me/vadik/knigopis/adapters/BooksAdapter.kt
  4. 3 3
      app/src/main/java/me/vadik/knigopis/adapters/books/BooksAdapter.kt
  5. 13 7
      app/src/main/java/me/vadik/knigopis/adapters/users/SocialNetwork.kt
  6. 11 0
      app/src/main/java/me/vadik/knigopis/adapters/users/UriItem.kt
  7. 13 8
      app/src/main/java/me/vadik/knigopis/adapters/users/UsersAdapter.kt
  8. 7 0
      app/src/main/java/me/vadik/knigopis/common/CommonResource.kt
  9. 21 0
      app/src/main/java/me/vadik/knigopis/common/DrawableResource.kt
  10. 20 0
      app/src/main/java/me/vadik/knigopis/common/StringResource.kt
  11. 1 1
      app/src/main/java/me/vadik/knigopis/dialog/DialogFactory.kt
  12. 10 2
      app/src/main/java/me/vadik/knigopis/dialog/DialogItem.kt
  13. 27 30
      app/src/main/java/me/vadik/knigopis/user/UserActivity.kt
  14. 9 0
      app/src/main/res/drawable/ic_public.xml
  15. 7 0
      app/src/main/res/drawable/ic_social_facebook.xml
  16. 7 0
      app/src/main/res/drawable/ic_social_googleplus.xml
  17. 7 0
      app/src/main/res/drawable/ic_social_instagram.xml
  18. 7 0
      app/src/main/res/drawable/ic_social_linkedin.xml
  19. 7 0
      app/src/main/res/drawable/ic_social_mailru.xml
  20. 7 0
      app/src/main/res/drawable/ic_social_twitter.xml
  21. 7 0
      app/src/main/res/drawable/ic_social_vkontakte.xml
  22. 2 2
      app/src/main/res/layout/bottom_sheet_dialog_item.xml
  23. 15 0
      app/src/main/res/menu/user_menu.xml
  24. 6 6
      app/src/main/res/values-ru/strings.xml
  25. 6 6
      app/src/main/res/values/strings.xml

+ 3 - 11
app/src/main/java/me/vadik/knigopis/MainActivity.kt

@@ -23,6 +23,7 @@ import me.vadik.knigopis.adapters.users.UsersAdapter
 import me.vadik.knigopis.api.BookCoverSearch
 import me.vadik.knigopis.api.Endpoint
 import me.vadik.knigopis.auth.KAuth
+import me.vadik.knigopis.common.ResourceProvider
 import me.vadik.knigopis.dialog.DialogFactory
 import me.vadik.knigopis.model.Book
 import me.vadik.knigopis.model.CurrentTab
@@ -50,12 +51,13 @@ class MainActivity : AppCompatActivity(), Router {
     private val auth by inject<KAuth>()
     private val dialogs by inject<DialogFactory> { mapOf("activity" to this) }
     private val bookRepository by inject<BookRepository>()
+    private val resources by inject<ResourceProvider>()
     private val allBooks = mutableListOf<Book>()
     private val allUsers = mutableListOf<Subscription>()
     private val allNotes = mutableListOf<Note>()
     private val booksAdapter by lazy { BooksAdapter(bookCoverSearch, api, auth, this, dialogs) }
     private val allBooksAdapter by lazy { booksAdapter.build(allBooks) }
-    private val usersAdapter by lazy { UsersAdapter(allUsers, this, dialogs) }
+    private val usersAdapter by lazy { UsersAdapter(allUsers, this, dialogs, resources) }
     private val notesAdapter by lazy { NotesAdapter(allNotes, this) }
     private var userLoggedIn = false
     private var booksChanged = false
@@ -173,16 +175,6 @@ class MainActivity : AppCompatActivity(), Router {
         )
     }
 
-    override fun unsubscribe(userId: String) {
-        api.deleteSubscription(userId, auth.getAccessToken())
-            .io2main()
-            .subscribe({
-                refresh(isForce = true)
-            }, {
-                handleNetworkError("Cannot unsubscribe", it)
-            })
-    }
-
     private fun initNavigationView(currentTab: CurrentTab?) {
         val defaultTab = if (auth.isAuthorized()) HOME_TAB else NOTES_TAB
         refresh(currentTab ?: defaultTab)

+ 0 - 1
app/src/main/java/me/vadik/knigopis/Router.kt

@@ -11,5 +11,4 @@ interface Router {
     fun openUserScreen(user: Identity)
     fun openBrowser(uri: Uri)
     fun shareProfile(url: String)
-    fun unsubscribe(userId: String)
 }

+ 3 - 3
app/src/main/java/me/vadik/knigopis/adapters/BooksAdapter.kt

@@ -13,7 +13,7 @@ import me.vadik.knigopis.api.BookCoverSearch
 import me.vadik.knigopis.api.Endpoint
 import me.vadik.knigopis.auth.KAuth
 import me.vadik.knigopis.dialog.DialogFactory
-import me.vadik.knigopis.dialog.DialogItem
+import me.vadik.knigopis.dialog.createDialogItem
 import me.vadik.knigopis.model.Book
 import me.vadik.knigopis.model.BookHeader
 import me.vadik.knigopis.model.FinishedBook
@@ -75,10 +75,10 @@ class BooksAdapter(
             setOnLongClickListener {
                 dialogs.showDialog(
                     book.fullTitle,
-                    DialogItem(R.string.book_option_edit, R.drawable.ic_edit) {
+                    createDialogItem(R.string.book_option_edit, R.drawable.ic_edit) {
                         router.openEditBookScreen(book)
                     },
-                    DialogItem(R.string.book_option_delete, R.drawable.ic_delete) {
+                    createDialogItem(R.string.book_option_delete, R.drawable.ic_delete) {
                         onDeleteClicked(book)
                     }
                 )

+ 3 - 3
app/src/main/java/me/vadik/knigopis/adapters/books/BooksAdapter.kt

@@ -5,7 +5,7 @@ import android.view.ViewGroup
 import me.vadik.knigopis.R
 import me.vadik.knigopis.createNewBookIntent
 import me.vadik.knigopis.dialog.DialogFactory
-import me.vadik.knigopis.dialog.DialogItem
+import me.vadik.knigopis.dialog.createDialogItem
 import me.vadik.knigopis.inflate
 
 class BooksAdapter(
@@ -28,10 +28,10 @@ class BooksAdapter(
         holder.view.setOnLongClickListener {
             dialogs.showDialog(
                 book.title + " — " + book.author,
-                DialogItem(R.string.add_book_todo, R.drawable.ic_playlist_add) {
+                createDialogItem(R.string.add_book_todo, R.drawable.ic_playlist_add) {
                     context.startActivity(context.createNewBookIntent(book.title, book.author))
                 },
-                DialogItem(R.string.add_book_done, R.drawable.ic_playlist_add_check) {
+                createDialogItem(R.string.add_book_done, R.drawable.ic_playlist_add_check) {
                     context.startActivity(context.createNewBookIntent(book.title, book.author, 100))
                 }
             )

+ 13 - 7
app/src/main/java/me/vadik/knigopis/adapters/users/SocialNetwork.kt

@@ -1,16 +1,22 @@
 package me.vadik.knigopis.adapters.users
 
 import android.net.Uri
+import android.support.annotation.DrawableRes
 import android.support.annotation.StringRes
 import me.vadik.knigopis.R
 
 fun Uri.toSocialNetwork() = SocialNetwork.values().find { it.host == host }
 
-enum class SocialNetwork(@StringRes val titleRes: Int, val host: String) {
-    FACEBOOK(R.string.social_facebook, "www.facebook.com"),
-    INSTAGRAM(R.string.social_instagram, "www.instagram.com"),
-    TWITTER(R.string.social_twitter, "twitter.com"),
-    GOOGLE(R.string.social_google_plus, "plus.google.com"),
-    VK_COM(R.string.social_vk_com, "vk.com"),
-    MAIL_RU(R.string.social_mail_ru, "my.mail.ru");
+enum class SocialNetwork(
+    @StringRes val titleRes: Int,
+    @DrawableRes val iconRes: Int,
+    val host: String
+) {
+    FACEBOOK(R.string.social_facebook, R.drawable.ic_social_facebook, "www.facebook.com"),
+    INSTAGRAM(R.string.social_instagram, R.drawable.ic_social_instagram, "www.instagram.com"),
+    TWITTER(R.string.social_twitter, R.drawable.ic_social_twitter, "twitter.com"),
+    GOOGLE(R.string.social_googleplus, R.drawable.ic_social_googleplus, "plus.google.com"),
+    VK_COM(R.string.social_vkontakte, R.drawable.ic_social_vkontakte, "vk.com"),
+    MAIL_RU(R.string.social_mailru, R.drawable.ic_social_mailru, "my.mail.ru"),
+    LINKEDIN(R.string.social_linkedin, R.drawable.ic_social_linkedin, "www.linkedin.com")
 }

+ 11 - 0
app/src/main/java/me/vadik/knigopis/adapters/users/UriItem.kt

@@ -0,0 +1,11 @@
+package me.vadik.knigopis.adapters.users
+
+import android.net.Uri
+import me.vadik.knigopis.R
+import me.vadik.knigopis.common.ResourceProvider
+
+class UriItem(val uri: Uri, resource: ResourceProvider) {
+    private val social = uri.toSocialNetwork()
+    val title = social?.titleRes?.let { resource.getString(it) } ?: "${uri.scheme}://${uri.host}"
+    val iconRes = social?.iconRes ?: R.drawable.ic_public
+}

+ 13 - 8
app/src/main/java/me/vadik/knigopis/adapters/users/UsersAdapter.kt

@@ -4,15 +4,17 @@ import android.support.v7.widget.RecyclerView
 import android.view.ViewGroup
 import me.vadik.knigopis.R
 import me.vadik.knigopis.Router
+import me.vadik.knigopis.common.ResourceProvider
 import me.vadik.knigopis.dialog.DialogFactory
-import me.vadik.knigopis.dialog.DialogItem
+import me.vadik.knigopis.dialog.createDialogItem
 import me.vadik.knigopis.inflate
 import me.vadik.knigopis.model.subscription.Subscription
 
 class UsersAdapter(
     private val users: List<Subscription>,
     private val router: Router,
-    private val dialogs: DialogFactory
+    private val dialogs: DialogFactory,
+    private val resources: ResourceProvider
 ) : RecyclerView.Adapter<UserViewHolder>() {
 
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
@@ -33,13 +35,16 @@ class UsersAdapter(
         holder.view.setOnClickListener {
             router.openUserScreen(user)
         }
-        holder.view.setOnLongClickListener {
-            dialogs.showDialog(
-                user.subUser.name,
-                DialogItem(R.string.user_option_delete, R.drawable.ic_delete) {
-                    router.unsubscribe(user.subUser.id)
+        val dialogItems = user.subUser.profiles
+            .map { UriItem(it, resources) }
+            .distinctBy(UriItem::title)
+            .map { uriItem ->
+                createDialogItem(uriItem.title, uriItem.iconRes) {
+                    router.openBrowser(uriItem.uri)
                 }
-            )
+            }
+        holder.view.setOnLongClickListener {
+            dialogs.showDialog(user.subUser.name, *dialogItems.toTypedArray())
             true
         }
     }

+ 7 - 0
app/src/main/java/me/vadik/knigopis/common/CommonResource.kt

@@ -0,0 +1,7 @@
+package me.vadik.knigopis.common
+
+import android.view.View
+
+interface CommonResource<in T : View> {
+    fun setValueTo(view: T)
+}

+ 21 - 0
app/src/main/java/me/vadik/knigopis/common/DrawableResource.kt

@@ -0,0 +1,21 @@
+package me.vadik.knigopis.common
+
+import android.graphics.drawable.Drawable
+import android.support.annotation.DrawableRes
+import android.widget.ImageView
+
+interface DrawableResource : CommonResource<ImageView> {
+    override fun setValueTo(view: ImageView)
+}
+
+class PlainDrawableResource(private val drawable: Drawable) : DrawableResource {
+    override fun setValueTo(view: ImageView) {
+        view.setImageDrawable(drawable)
+    }
+}
+
+class DrawableIdResource(@DrawableRes private val resId: Int) : DrawableResource {
+    override fun setValueTo(view: ImageView) {
+        view.setImageResource(resId)
+    }
+}

+ 20 - 0
app/src/main/java/me/vadik/knigopis/common/StringResource.kt

@@ -0,0 +1,20 @@
+package me.vadik.knigopis.common
+
+import android.support.annotation.StringRes
+import android.widget.TextView
+
+interface StringResource : CommonResource<TextView> {
+    override fun setValueTo(view: TextView)
+}
+
+class PlainStringResource(private val text: String) : StringResource {
+    override fun setValueTo(view: TextView) {
+        view.text = text
+    }
+}
+
+class IntegerStringResource(@StringRes private val textRes: Int) : StringResource {
+    override fun setValueTo(view: TextView) {
+        view.setText(textRes)
+    }
+}

+ 1 - 1
app/src/main/java/me/vadik/knigopis/dialog/DialogFactory.kt

@@ -23,7 +23,7 @@ class BottomSheetDialogFactory(private val context: Context) : DialogFactory {
         items.forEach { item ->
             val itemView = container.inflate(R.layout.bottom_sheet_dialog_item)
             itemView.bottomSheetItemIcon.setImageResource(item.iconRes)
-            itemView.bottomSheetItemText.setText(item.titleRes)
+            item.title.setValueTo(itemView.bottomSheetItemText)
             itemView.setOnClickListener {
                 item.onClick()
                 dialog.hide()

+ 10 - 2
app/src/main/java/me/vadik/knigopis/dialog/DialogItem.kt

@@ -1,10 +1,18 @@
 package me.vadik.knigopis.dialog
 
 import android.support.annotation.DrawableRes
-import android.support.annotation.StringRes
+import me.vadik.knigopis.common.IntegerStringResource
+import me.vadik.knigopis.common.PlainStringResource
+import me.vadik.knigopis.common.StringResource
+
+fun createDialogItem(titleRes: Int, iconRes: Int, onClick: () -> Unit) =
+    DialogItem(IntegerStringResource(titleRes), iconRes, onClick)
+
+fun createDialogItem(title: String, iconRes: Int, onClick: () -> Unit) =
+    DialogItem(PlainStringResource(title), iconRes, onClick)
 
 class DialogItem(
-    @StringRes val titleRes: Int,
+    val title: StringResource,
     @DrawableRes val iconRes: Int,
     val onClick: () -> Unit
 )

+ 27 - 30
app/src/main/java/me/vadik/knigopis/user/UserActivity.kt

@@ -1,5 +1,7 @@
 package me.vadik.knigopis.user
 
+import android.content.ClipData
+import android.content.ClipboardManager
 import android.content.Context
 import android.content.Intent
 import android.net.Uri
@@ -11,15 +13,17 @@ import android.support.v7.widget.LinearLayoutManager
 import android.view.Menu
 import android.view.MenuItem
 import kotlinx.android.synthetic.main.user_activity.*
-import me.vadik.knigopis.*
+import me.vadik.knigopis.R
 import me.vadik.knigopis.adapters.books.BooksAdapter
 import me.vadik.knigopis.adapters.books.UserBook
-import me.vadik.knigopis.adapters.users.toSocialNetwork
 import me.vadik.knigopis.api.Endpoint
 import me.vadik.knigopis.auth.KAuth
 import me.vadik.knigopis.dialog.DialogFactory
+import me.vadik.knigopis.io2main
+import me.vadik.knigopis.logError
 import me.vadik.knigopis.model.note.Identity
 import me.vadik.knigopis.model.subscription.Subscription
+import me.vadik.knigopis.toast
 import org.koin.android.ext.android.inject
 
 private const val EXTRA_USER_ID = "me.vadik.knigopis.extra_user_id"
@@ -48,7 +52,6 @@ class UserActivity : AppCompatActivity() {
     private val userId by lazy { intent.getStringExtra(EXTRA_USER_ID) }
     private val books = mutableListOf<UserBook>()
     private val booksAdapter = BooksAdapter(books, dialogs)
-    private lateinit var menuItems: Map<Int, UriItem>
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -74,14 +77,6 @@ class UserActivity : AppCompatActivity() {
             DividerItemDecoration(this, layoutManager.orientation)
         )
         userBooksRecyclerView.adapter = booksAdapter
-        menuItems = intent.getParcelableArrayExtra(EXTRA_USER_PROFILES)
-            .filterIsInstance(Uri::class.java)
-            .map(::UriItem)
-            .distinctBy(UriItem::key)
-            .mapIndexed { index, item ->
-                Menu.FIRST + index to item
-            }
-            .toMap()
     }
 
     override fun onStart() {
@@ -107,29 +102,31 @@ class UserActivity : AppCompatActivity() {
     }
 
     override fun onCreateOptionsMenu(menu: Menu): Boolean {
-        menuItems.forEach { (id, item) ->
-            if (item.socialNetworkTitleRes == null) {
-                menu.add(Menu.NONE, id, 0, item.personalPageTitle)
-            } else {
-                menu.add(Menu.NONE, id, 0, item.socialNetworkTitleRes)
-            }
-        }
+        menuInflater.inflate(R.menu.user_menu, menu)
         return true
     }
 
     override fun onOptionsItemSelected(item: MenuItem): Boolean {
-        menuItems[item.itemId]?.uri?.let { uri ->
-            startActivityOrElse(Intent(Intent.ACTION_VIEW, uri)) {
-                toast("Невозможно открыть страницу")
+        return when (item.itemId) {
+            R.id.option_copy -> {
+                val link = "http://www.knigopis.com/#/user/books?u=$userId"
+                getSystemService(CLIPBOARD_SERVICE)?.let { clipboard ->
+                    clipboard as ClipboardManager
+                    clipboard.primaryClip = ClipData.newPlainText(null, link)
+                }
+                toast(link)
+                true
+            }
+            R.id.option_unsubscribe -> {
+                api.deleteSubscription(userId, auth.getAccessToken())
+                    .io2main()
+                    .subscribe({}, {
+                        logError("Cannot unsubscribe", it)
+                        toast("Не удалось отписаться")
+                    })
+                true
             }
-            return true
+            else -> false
         }
-        return false
     }
-}
-
-private class UriItem(val uri: Uri) {
-    val socialNetworkTitleRes = uri.toSocialNetwork()?.titleRes
-    val personalPageTitle = uri.scheme + "://" + uri.host
-    val key = socialNetworkTitleRes ?: personalPageTitle
-}
+}

+ 9 - 0
app/src/main/res/drawable/ic_public.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,19.93c-3.95,-0.49 -7,-3.85 -7,-7.93 0,-0.62 0.08,-1.21 0.21,-1.79L9,15v1c0,1.1 0.9,2 2,2v1.93zM17.9,17.39c-0.26,-0.81 -1,-1.39 -1.9,-1.39h-1v-3c0,-0.55 -0.45,-1 -1,-1L8,12v-2h2c0.55,0 1,-0.45 1,-1L11,7h2c1.1,0 2,-0.9 2,-2v-0.41c2.93,1.19 5,4.06 5,7.41 0,2.08 -0.8,3.97 -2.1,5.39z"/>
+</vector>

+ 7 - 0
app/src/main/res/drawable/ic_social_facebook.xml

@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#000" android:pathData="M5,3H19A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5A2,2 0 0,1 3,19V5A2,2 0 0,1 5,3M18,5H15.5A3.5,3.5 0 0,0 12,8.5V11H10V14H12V21H15V14H18V11H15V9A1,1 0 0,1 16,8H18V5Z" />
+</vector>

+ 7 - 0
app/src/main/res/drawable/ic_social_googleplus.xml

@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#000" android:pathData="M5,3H19A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5A2,2 0 0,1 3,19V5A2,2 0 0,1 5,3M19.5,12H18V10.5H17V12H15.5V13H17V14.5H18V13H19.5V12M9.65,11.36V12.9H12.22C12.09,13.54 11.45,14.83 9.65,14.83C8.11,14.83 6.89,13.54 6.89,12C6.89,10.46 8.11,9.17 9.65,9.17C10.55,9.17 11.13,9.56 11.45,9.88L12.67,8.72C11.9,7.95 10.87,7.5 9.65,7.5C7.14,7.5 5.15,9.5 5.15,12C5.15,14.5 7.14,16.5 9.65,16.5C12.22,16.5 13.96,14.7 13.96,12.13C13.96,11.81 13.96,11.61 13.89,11.36H9.65Z" />
+</vector>

+ 7 - 0
app/src/main/res/drawable/ic_social_instagram.xml

@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#000" android:pathData="M7.8,2H16.2C19.4,2 22,4.6 22,7.8V16.2A5.8,5.8 0 0,1 16.2,22H7.8C4.6,22 2,19.4 2,16.2V7.8A5.8,5.8 0 0,1 7.8,2M7.6,4A3.6,3.6 0 0,0 4,7.6V16.4C4,18.39 5.61,20 7.6,20H16.4A3.6,3.6 0 0,0 20,16.4V7.6C20,5.61 18.39,4 16.4,4H7.6M17.25,5.5A1.25,1.25 0 0,1 18.5,6.75A1.25,1.25 0 0,1 17.25,8A1.25,1.25 0 0,1 16,6.75A1.25,1.25 0 0,1 17.25,5.5M12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9Z" />
+</vector>

+ 7 - 0
app/src/main/res/drawable/ic_social_linkedin.xml

@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#000" android:pathData="M19,3A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5A2,2 0 0,1 3,19V5A2,2 0 0,1 5,3H19M18.5,18.5V13.2A3.26,3.26 0 0,0 15.24,9.94C14.39,9.94 13.4,10.46 12.92,11.24V10.13H10.13V18.5H12.92V13.57C12.92,12.8 13.54,12.17 14.31,12.17A1.4,1.4 0 0,1 15.71,13.57V18.5H18.5M6.88,8.56A1.68,1.68 0 0,0 8.56,6.88C8.56,5.95 7.81,5.19 6.88,5.19A1.69,1.69 0 0,0 5.19,6.88C5.19,7.81 5.95,8.56 6.88,8.56M8.27,18.5V10.13H5.5V18.5H8.27Z" />
+</vector>

+ 7 - 0
app/src/main/res/drawable/ic_social_mailru.xml

@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#000" android:pathData="M15.45,11.91C15.34,9.7 13.7,8.37 11.72,8.37H11.64C9.35,8.37 8.09,10.17 8.09,12.21C8.09,14.5 9.62,15.95 11.63,15.95C13.88,15.95 15.35,14.3 15.46,12.36M11.65,6.39C13.18,6.39 14.62,7.07 15.67,8.13V8.13C15.67,7.62 16,7.24 16.5,7.24H16.61C17.35,7.24 17.5,7.94 17.5,8.16V16.06C17.46,16.58 18.04,16.84 18.37,16.5C19.64,15.21 21.15,9.81 17.58,6.69C14.25,3.77 9.78,4.25 7.4,5.89C4.88,7.63 3.26,11.5 4.83,15.11C6.54,19.06 11.44,20.24 14.35,19.06C15.83,18.47 16.5,20.46 15,21.11C12.66,22.1 6.23,22 3.22,16.79C1.19,13.27 1.29,7.08 6.68,3.87C10.81,1.42 16.24,2.1 19.5,5.5C22.95,9.1 22.75,15.8 19.4,18.41C17.89,19.59 15.64,18.44 15.66,16.71L15.64,16.15C14.59,17.2 13.18,17.81 11.65,17.81C8.63,17.81 6,15.15 6,12.13C6,9.08 8.63,6.39 11.65,6.39Z" />
+</vector>

+ 7 - 0
app/src/main/res/drawable/ic_social_twitter.xml

@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#000" android:pathData="M22.46,6C21.69,6.35 20.86,6.58 20,6.69C20.88,6.16 21.56,5.32 21.88,4.31C21.05,4.81 20.13,5.16 19.16,5.36C18.37,4.5 17.26,4 16,4C13.65,4 11.73,5.92 11.73,8.29C11.73,8.63 11.77,8.96 11.84,9.27C8.28,9.09 5.11,7.38 3,4.79C2.63,5.42 2.42,6.16 2.42,6.94C2.42,8.43 3.17,9.75 4.33,10.5C3.62,10.5 2.96,10.3 2.38,10C2.38,10 2.38,10 2.38,10.03C2.38,12.11 3.86,13.85 5.82,14.24C5.46,14.34 5.08,14.39 4.69,14.39C4.42,14.39 4.15,14.36 3.89,14.31C4.43,16 6,17.26 7.89,17.29C6.43,18.45 4.58,19.13 2.56,19.13C2.22,19.13 1.88,19.11 1.54,19.07C3.44,20.29 5.7,21 8.12,21C16,21 20.33,14.46 20.33,8.79C20.33,8.6 20.33,8.42 20.32,8.23C21.16,7.63 21.88,6.87 22.46,6Z" />
+</vector>

+ 7 - 0
app/src/main/res/drawable/ic_social_vkontakte.xml

@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#000" android:pathData="M20.8,7.74C20.93,7.32 20.8,7 20.18,7H18.16C17.64,7 17.41,7.27 17.28,7.57C17.28,7.57 16.25,10.08 14.79,11.72C14.31,12.19 14.1,12.34 13.84,12.34C13.71,12.34 13.5,12.19 13.5,11.76V7.74C13.5,7.23 13.38,7 12.95,7H9.76C9.44,7 9.25,7.24 9.25,7.47C9.25,7.95 10,8.07 10.05,9.44V12.42C10.05,13.08 9.93,13.2 9.68,13.2C9,13.2 7.32,10.67 6.33,7.79C6.13,7.23 5.94,7 5.42,7H3.39C2.82,7 2.7,7.27 2.7,7.57C2.7,8.11 3.39,10.77 5.9,14.29C7.57,16.7 9.93,18 12.08,18C13.37,18 13.53,17.71 13.53,17.21V15.39C13.53,14.82 13.65,14.7 14.06,14.7C14.36,14.7 14.87,14.85 16.07,16C17.45,17.38 17.67,18 18.45,18H20.47C21.05,18 21.34,17.71 21.18,17.14C21,16.57 20.34,15.74 19.47,14.76C19,14.21 18.29,13.61 18.07,13.3C17.77,12.92 17.86,12.75 18.07,12.4C18.07,12.4 20.54,8.93 20.8,7.74Z" />
+</vector>

+ 2 - 2
app/src/main/res/layout/bottom_sheet_dialog_item.xml

@@ -10,8 +10,8 @@
 
     <ImageView
         android:id="@+id/bottomSheetItemIcon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
         android:layout_gravity="center_vertical"
         android:tint="#777777"
         tools:ignore="ContentDescription"

+ 15 - 0
app/src/main/res/menu/user_menu.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <item
+        android:id="@+id/option_copy"
+        android:title="@string/user_option_copy"
+        app:showAsAction="never" />
+
+    <item
+        android:id="@+id/option_unsubscribe"
+        android:title="@string/user_option_unsubscribe"
+        app:showAsAction="never" />
+
+</menu>

+ 6 - 6
app/src/main/res/values-ru/strings.xml

@@ -41,10 +41,9 @@
     <string name="cannot_delete_book">Не получилось удалить</string>
     <string name="book_hint_notes">Примечания</string>
 
-    <!-- following menu -->
-    <string name="user_option_delete">Отписаться</string>
-
     <!-- user menu -->
+    <string name="user_option_copy">Скопировать ссылку</string>
+    <string name="user_option_unsubscribe">Отписаться</string>
     <string name="add_book_todo">К прочтению</string>
     <string name="add_book_done">Прочитано</string>
 
@@ -74,7 +73,8 @@
     <string name="social_facebook">Фейсбук</string>
     <string name="social_instagram">Инстаграм</string>
     <string name="social_twitter">Твиттер</string>
-    <string name="social_google_plus">Google+</string>
-    <string name="social_vk_com">Вконтакте</string>
-    <string name="social_mail_ru">Mail.Ru</string>
+    <string name="social_googleplus">Google+</string>
+    <string name="social_vkontakte">Вконтакте</string>
+    <string name="social_mailru">Mail.Ru</string>
+    <string name="social_linkedin">LinkedIn</string>
 </resources>

+ 6 - 6
app/src/main/res/values/strings.xml

@@ -44,10 +44,9 @@
     <!-- following -->
     <string name="user_new_books_count" translatable="false"><![CDATA[<sup><small>+%d</small><sup>]]></string>
 
-    <!-- following menu -->
-    <string name="user_option_delete">Unsubscribe</string>
-
     <!-- user menu -->
+    <string name="user_option_copy">Copy link</string>
+    <string name="user_option_unsubscribe">Unsubscribe</string>
     <string name="add_book_todo">Todo</string>
     <string name="add_book_done">Done</string>
 
@@ -80,7 +79,8 @@
     <string name="social_facebook">Facebook</string>
     <string name="social_instagram">Instagram</string>
     <string name="social_twitter">Twitter</string>
-    <string name="social_google_plus">Google+</string>
-    <string name="social_vk_com">VKontakte</string>
-    <string name="social_mail_ru">Mail.Ru</string>
+    <string name="social_googleplus">Google+</string>
+    <string name="social_vkontakte">VKontakte</string>
+    <string name="social_mailru">Mail.Ru</string>
+    <string name="social_linkedin">LinkedIn</string>
 </resources>