Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 479e1688 authored by cketti's avatar cketti Committed by GitHub
Browse files

Merge pull request #6175 from thundernest/message_view_menu_cleanup

Clean up message view menu code
parents 52f9b9dd 17c51a49
Loading
Loading
Loading
Loading
+25 −192
Original line number Diff line number Diff line
@@ -49,12 +49,10 @@ import com.fsck.k9.ui.BuildConfig
import com.fsck.k9.ui.K9Drawer
import com.fsck.k9.ui.R
import com.fsck.k9.ui.base.K9Activity
import com.fsck.k9.ui.base.Theme
import com.fsck.k9.ui.changelog.RecentChangesActivity
import com.fsck.k9.ui.changelog.RecentChangesViewModel
import com.fsck.k9.ui.managefolders.ManageFoldersActivity
import com.fsck.k9.ui.messagelist.DefaultFolderProvider
import com.fsck.k9.ui.messagesource.MessageSourceActivity
import com.fsck.k9.ui.messageview.MessageViewFragment
import com.fsck.k9.ui.messageview.MessageViewFragment.MessageViewFragmentListener
import com.fsck.k9.ui.messageview.PlaceholderFragment
@@ -334,16 +332,21 @@ open class MessageList :
                showMessageView()
            }
            DisplayMode.SPLIT_VIEW -> {
                val messageListFragment = checkNotNull(this.messageListFragment)

                messageListWasDisplayed = true
                messageListFragment?.onListVisible()
                messageListFragment.onListVisible()

                messageViewFragment.let { messageViewFragment ->
                    if (messageViewFragment == null) {
                        showMessageViewPlaceHolder()
                    } else {
                    val activeMessage = messageViewFragment!!.messageReference
                    if (activeMessage != null) {
                        messageListFragment!!.setActiveMessage(activeMessage)
                        messageViewFragment.isActive = true
                        val activeMessage = messageViewFragment.messageReference
                        messageListFragment.setActiveMessage(activeMessage)
                    }
                }

                setDrawerLockState()
                onMessageListDisplayed()
            }
@@ -916,63 +919,9 @@ open class MessageList :
                goBack()
            }
            return true
        } else if (id == R.id.toggle_message_view_theme) {
            onToggleTheme()
            return true
        } else if (id == R.id.search_everywhere) {
            searchEverywhere()
            return true
        } else if (id == R.id.next_message) { // MessageView
            showNextMessage()
            return true
        } else if (id == R.id.previous_message) {
            showPreviousMessage()
            return true
        } else if (id == R.id.delete) {
            messageViewFragment!!.onDelete()
            return true
        } else if (id == R.id.reply) {
            messageViewFragment!!.onReply()
            return true
        } else if (id == R.id.reply_all) {
            messageViewFragment!!.onReplyAll()
            return true
        } else if (id == R.id.forward) {
            messageViewFragment!!.onForward()
            return true
        } else if (id == R.id.forward_as_attachment) {
            messageViewFragment!!.onForwardAsAttachment()
            return true
        } else if (id == R.id.edit_as_new_message) {
            messageViewFragment!!.onEditAsNewMessage()
            return true
        } else if (id == R.id.share) {
            messageViewFragment!!.onSendAlternate()
            return true
        } else if (id == R.id.toggle_unread) {
            messageViewFragment!!.onToggleRead()
            return true
        } else if (id == R.id.archive || id == R.id.refile_archive) {
            messageViewFragment!!.onArchive()
            return true
        } else if (id == R.id.spam || id == R.id.refile_spam) {
            messageViewFragment!!.onSpam()
            return true
        } else if (id == R.id.move || id == R.id.refile_move) {
            messageViewFragment!!.onMove()
            return true
        } else if (id == R.id.copy || id == R.id.refile_copy) {
            messageViewFragment!!.onCopy()
            return true
        } else if (id == R.id.move_to_drafts) {
            messageViewFragment!!.onMoveToDrafts()
            return true
        } else if (id == R.id.unsubscribe) {
            messageViewFragment!!.onUnsubscribe()
            return true
        } else if (id == R.id.show_headers) {
            startActivity(MessageSourceActivity.createLaunchIntent(this, messageViewFragment!!.messageReference))
            return true
        }

        return super.onOptionsItemSelected(item)
@@ -1011,126 +960,6 @@ open class MessageList :
        return true
    }

    override fun onPrepareOptionsMenu(menu: Menu): Boolean {
        super.onPrepareOptionsMenu(menu)
        configureMenu(menu)
        return true
    }

    /**
     * Hide menu items not appropriate for the current context.
     *
     * **Note:**
     * Please adjust the comments in `res/menu/message_list_option.xml` if you change the  visibility of a menu item
     * in this method.
     */
    private fun configureMenu(menu: Menu?) {
        if (menu == null) return

        // Set visibility of menu items related to the message view
        if (displayMode == DisplayMode.MESSAGE_LIST || messageViewFragment == null ||
            !messageViewFragment!!.isInitialized
        ) {
            menu.findItem(R.id.next_message).isVisible = false
            menu.findItem(R.id.previous_message).isVisible = false
            menu.findItem(R.id.single_message_options).isVisible = false
            menu.findItem(R.id.delete).isVisible = false
            menu.findItem(R.id.compose).isVisible = false
            menu.findItem(R.id.archive).isVisible = false
            menu.findItem(R.id.move).isVisible = false
            menu.findItem(R.id.copy).isVisible = false
            menu.findItem(R.id.spam).isVisible = false
            menu.findItem(R.id.refile).isVisible = false
            menu.findItem(R.id.toggle_unread).isVisible = false
            menu.findItem(R.id.toggle_message_view_theme).isVisible = false
            menu.findItem(R.id.unsubscribe).isVisible = false
            menu.findItem(R.id.show_headers).isVisible = false
        } else {
            // hide prev/next buttons in split mode
            if (displayMode != DisplayMode.MESSAGE_VIEW) {
                menu.findItem(R.id.next_message).isVisible = false
                menu.findItem(R.id.previous_message).isVisible = false
            } else {
                val ref = messageViewFragment!!.messageReference
                val initialized = messageListFragment != null &&
                    messageListFragment!!.isLoadFinished
                val canDoPrev = initialized && !messageListFragment!!.isFirst(ref)
                val canDoNext = initialized && !messageListFragment!!.isLast(ref)
                val prev = menu.findItem(R.id.previous_message)
                prev.isEnabled = canDoPrev
                prev.icon.alpha = if (canDoPrev) 255 else 127
                val next = menu.findItem(R.id.next_message)
                next.isEnabled = canDoNext
                next.icon.alpha = if (canDoNext) 255 else 127
            }

            val toggleTheme = menu.findItem(R.id.toggle_message_view_theme)
            if (generalSettingsManager.getSettings().fixedMessageViewTheme) {
                toggleTheme.isVisible = false
            } else {
                // Set title of menu item to switch to dark/light theme
                if (themeManager.messageViewTheme === Theme.DARK) {
                    toggleTheme.setTitle(R.string.message_view_theme_action_light)
                } else {
                    toggleTheme.setTitle(R.string.message_view_theme_action_dark)
                }
                toggleTheme.isVisible = true
            }

            if (messageViewFragment!!.isOutbox) {
                menu.findItem(R.id.toggle_unread).isVisible = false
            } else {
                // Set title of menu item to toggle the read state of the currently displayed message
                val drawableAttr = if (messageViewFragment!!.isMessageRead) {
                    menu.findItem(R.id.toggle_unread).setTitle(R.string.mark_as_unread_action)
                    intArrayOf(R.attr.iconActionMarkAsUnread)
                } else {
                    menu.findItem(R.id.toggle_unread).setTitle(R.string.mark_as_read_action)
                    intArrayOf(R.attr.iconActionMarkAsRead)
                }
                val typedArray = obtainStyledAttributes(drawableAttr)
                menu.findItem(R.id.toggle_unread).icon = typedArray.getDrawable(0)
                typedArray.recycle()
            }

            menu.findItem(R.id.delete).isVisible = K9.isMessageViewDeleteActionVisible

            // Set visibility of copy, move, archive, spam in action bar and refile submenu
            if (messageViewFragment!!.isCopyCapable) {
                menu.findItem(R.id.copy).isVisible = K9.isMessageViewCopyActionVisible
                menu.findItem(R.id.refile_copy).isVisible = true
            } else {
                menu.findItem(R.id.copy).isVisible = false
                menu.findItem(R.id.refile_copy).isVisible = false
            }

            if (messageViewFragment!!.isMoveCapable) {
                val canMessageBeArchived = messageViewFragment!!.canMessageBeArchived()
                val canMessageBeMovedToSpam = messageViewFragment!!.canMessageBeMovedToSpam()

                menu.findItem(R.id.move).isVisible = K9.isMessageViewMoveActionVisible
                menu.findItem(R.id.archive).isVisible = canMessageBeArchived && K9.isMessageViewArchiveActionVisible
                menu.findItem(R.id.spam).isVisible = canMessageBeMovedToSpam && K9.isMessageViewSpamActionVisible

                menu.findItem(R.id.refile_move).isVisible = true
                menu.findItem(R.id.refile_archive).isVisible = canMessageBeArchived
                menu.findItem(R.id.refile_spam).isVisible = canMessageBeMovedToSpam
            } else {
                menu.findItem(R.id.move).isVisible = false
                menu.findItem(R.id.archive).isVisible = false
                menu.findItem(R.id.spam).isVisible = false

                menu.findItem(R.id.refile).isVisible = false
            }

            if (messageViewFragment!!.isOutbox) {
                menu.findItem(R.id.move_to_drafts).isVisible = true
            }

            menu.findItem(R.id.unsubscribe).isVisible = messageViewFragment!!.canMessageBeUnsubscribed()
        }
    }

    fun setActionBarTitle(title: String, subtitle: String? = null) {
        actionBar.title = title
        actionBar.subtitle = subtitle
@@ -1163,12 +992,15 @@ open class MessageList :
            }

            val fragment = MessageViewFragment.newInstance(messageReference)
            val fragmentTransaction = supportFragmentManager.beginTransaction()
            fragmentTransaction.replace(R.id.message_view_container, fragment, FRAGMENT_TAG_MESSAGE_VIEW)
            fragmentTransaction.commit()
            supportFragmentManager.commit {
                replace(R.id.message_view_container, fragment, FRAGMENT_TAG_MESSAGE_VIEW)
            }

            messageViewFragment = fragment

            if (displayMode != DisplayMode.SPLIT_VIEW) {
            if (displayMode == DisplayMode.SPLIT_VIEW) {
                fragment.isActive = true
            } else {
                showMessageView()
            }
        }
@@ -1200,6 +1032,8 @@ open class MessageList :

    override fun onBackStackChanged() {
        findFragments()
        messageListFragment?.onListVisible()

        if (isDrawerEnabled && !isAdditionalMessageListDisplayed) {
            unlockDrawer()
        }
@@ -1371,6 +1205,7 @@ open class MessageList :
        displayMode = DisplayMode.MESSAGE_LIST
        viewSwitcher!!.showFirstView()

        messageViewFragment?.isActive = false
        messageListFragment!!.onListVisible()
        messageListFragment!!.setActiveMessage(null)

@@ -1393,8 +1228,11 @@ open class MessageList :
    }

    private fun showMessageView() {
        val messageViewFragment = checkNotNull(this.messageViewFragment)

        displayMode = DisplayMode.MESSAGE_VIEW
        messageListFragment?.onListHidden()
        messageViewFragment.isActive = true

        if (!messageListWasDisplayed) {
            viewSwitcher!!.animateFirstView = false
@@ -1413,11 +1251,6 @@ open class MessageList :
        menu!!.findItem(R.id.delete).isEnabled = false
    }

    private fun onToggleTheme() {
        themeManager.toggleMessageViewTheme()
        recreateCompat()
    }

    private fun showDefaultTitleView() {
        if (messageListFragment != null) {
            messageListFragment!!.updateTitle()
+2 −0
Original line number Diff line number Diff line
@@ -706,6 +706,7 @@ class MessageListFragment :
    }

    private fun prepareMenu(menu: Menu) {
        menu.findItem(R.id.compose).isVisible = true
        menu.findItem(R.id.set_sort).isVisible = true
        menu.findItem(R.id.select_all).isVisible = true
        menu.findItem(R.id.compose).isVisible = true
@@ -726,6 +727,7 @@ class MessageListFragment :
    }

    private fun hideMenu(menu: Menu) {
        menu.findItem(R.id.compose).isVisible = false
        menu.findItem(R.id.search).isVisible = false
        menu.findItem(R.id.search_remote).isVisible = false
        menu.findItem(R.id.set_sort).isVisible = false
+147 −28
Original line number Diff line number Diff line
@@ -11,10 +11,14 @@ import android.os.Parcelable
import android.os.SystemClock
import android.view.ContextThemeWrapper
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.withStyledAttributes
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import com.fsck.k9.Account
@@ -36,9 +40,12 @@ import com.fsck.k9.mailstore.AttachmentViewInfo
import com.fsck.k9.mailstore.LocalMessage
import com.fsck.k9.mailstore.MessageViewInfo
import com.fsck.k9.preferences.AccountManager
import com.fsck.k9.preferences.GeneralSettingsManager
import com.fsck.k9.ui.R
import com.fsck.k9.ui.base.Theme
import com.fsck.k9.ui.base.ThemeManager
import com.fsck.k9.ui.choosefolder.ChooseFolderActivity
import com.fsck.k9.ui.messagesource.MessageSourceActivity
import com.fsck.k9.ui.messageview.CryptoInfoDialog.OnClickShowCryptoKeyListener
import com.fsck.k9.ui.messageview.MessageCryptoPresenter.MessageCryptoMvpView
import com.fsck.k9.ui.settings.account.AccountSettingsActivity
@@ -60,6 +67,7 @@ class MessageViewFragment :
    private val accountManager: AccountManager by inject()
    private val messagingController: MessagingController by inject()
    private val shareIntentBuilder: ShareIntentBuilder by inject()
    private val generalSettingsManager: GeneralSettingsManager by inject()

    private lateinit var messageTopView: MessageTopView

@@ -79,14 +87,18 @@ class MessageViewFragment :
    private lateinit var account: Account
    lateinit var messageReference: MessageReference

    private var currentAttachmentViewInfo: AttachmentViewInfo? = null

    /**
     * `true` after [.onCreate] has been executed. This is used by `MessageList.configureMenu()` to make sure the
     * fragment has been initialized before it is used.
     * Set this to `true` when the fragment should be considered active. When active, the fragment adds its actions to
     * the toolbar. When inactive, the fragment won't add its actions to the toolbar, even it is still visible, e.g. as
     * part of an animation.
     */
    var isInitialized = false
        private set

    private var currentAttachmentViewInfo: AttachmentViewInfo? = null
    var isActive: Boolean = false
        set(value) {
            field = value
            invalidateMenu()
        }

    override fun onAttach(context: Context) {
        super.onAttach(context)
@@ -103,6 +115,9 @@ class MessageViewFragment :

        setHasOptionsMenu(true)

        messageReference = MessageReference.parse(arguments?.getString(ARG_REFERENCE))
            ?: error("Invalid argument '$ARG_REFERENCE'")

        messageCryptoPresenter = MessageCryptoPresenter(messageCryptoMvpView)
        messageLoaderHelper = messageLoaderHelperFactory.createForMessageView(
            context = requireContext().applicationContext,
@@ -110,8 +125,6 @@ class MessageViewFragment :
            fragmentManager = parentFragmentManager,
            callback = messageLoaderCallbacks
        )

        isInitialized = true
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@@ -147,16 +160,12 @@ class MessageViewFragment :
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val messageReference = MessageReference.parse(arguments?.getString(ARG_REFERENCE))
            ?: error("Invalid argument '$ARG_REFERENCE'")

        displayMessage(messageReference)
        loadMessage(messageReference)
    }

    private fun displayMessage(messageReference: MessageReference) {
    private fun loadMessage(messageReference: MessageReference) {
        Timber.d("MessageViewFragment displaying message %s", messageReference)

        this.messageReference = messageReference
        account = accountManager.getAccount(messageReference.accountUuid)
            ?: error("Account ${messageReference.accountUuid} not found")

@@ -180,6 +189,116 @@ class MessageViewFragment :
        }
    }

    override fun onPrepareOptionsMenu(menu: Menu) {
        if (!isActive) return

        menu.findItem(R.id.delete).isVisible = K9.isMessageViewDeleteActionVisible

        val showToggleUnread = !isOutbox
        menu.findItem(R.id.toggle_unread).isVisible = showToggleUnread

        if (showToggleUnread) {
            // Set title of menu item to toggle the read state of the currently displayed message
            if (isMessageRead) {
                menu.findItem(R.id.toggle_unread).setTitle(R.string.mark_as_unread_action)
            } else {
                menu.findItem(R.id.toggle_unread).setTitle(R.string.mark_as_read_action)
            }

            val drawableAttr = if (isMessageRead) {
                intArrayOf(R.attr.iconActionMarkAsUnread)
            } else {
                intArrayOf(R.attr.iconActionMarkAsRead)
            }

            requireContext().withStyledAttributes(attrs = drawableAttr) {
                menu.findItem(R.id.toggle_unread).icon = getDrawable(0)
            }
        }

        if (isMoveCapable) {
            val canMessageBeArchived = canMessageBeArchived()
            val canMessageBeMovedToSpam = canMessageBeMovedToSpam()

            menu.findItem(R.id.move).isVisible = K9.isMessageViewMoveActionVisible
            menu.findItem(R.id.archive).isVisible = canMessageBeArchived && K9.isMessageViewArchiveActionVisible
            menu.findItem(R.id.spam).isVisible = canMessageBeMovedToSpam && K9.isMessageViewSpamActionVisible

            menu.findItem(R.id.refile_move).isVisible = true
            menu.findItem(R.id.refile_archive).isVisible = canMessageBeArchived
            menu.findItem(R.id.refile_spam).isVisible = canMessageBeMovedToSpam

            menu.findItem(R.id.refile).isVisible = true
        } else {
            menu.findItem(R.id.move).isVisible = false
            menu.findItem(R.id.archive).isVisible = false
            menu.findItem(R.id.spam).isVisible = false

            menu.findItem(R.id.refile).isVisible = false
        }

        if (isCopyCapable) {
            menu.findItem(R.id.copy).isVisible = K9.isMessageViewCopyActionVisible
            menu.findItem(R.id.refile_copy).isVisible = true
        } else {
            menu.findItem(R.id.copy).isVisible = false
            menu.findItem(R.id.refile_copy).isVisible = false
        }

        menu.findItem(R.id.move_to_drafts).isVisible = isOutbox
        menu.findItem(R.id.single_message_options).isVisible = true
        menu.findItem(R.id.unsubscribe).isVisible = canMessageBeUnsubscribed()
        menu.findItem(R.id.show_headers).isVisible = true
        menu.findItem(R.id.compose).isVisible = true

        val toggleTheme = menu.findItem(R.id.toggle_message_view_theme)
        if (generalSettingsManager.getSettings().fixedMessageViewTheme) {
            toggleTheme.isVisible = false
        } else {
            // Set title of menu item to switch to dark/light theme
            if (themeManager.messageViewTheme === Theme.DARK) {
                toggleTheme.setTitle(R.string.message_view_theme_action_light)
            } else {
                toggleTheme.setTitle(R.string.message_view_theme_action_dark)
            }
            toggleTheme.isVisible = true
        }
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.toggle_message_view_theme -> onToggleTheme()
            R.id.delete -> onDelete()
            R.id.reply -> onReply()
            R.id.reply_all -> onReplyAll()
            R.id.forward -> onForward()
            R.id.forward_as_attachment -> onForwardAsAttachment()
            R.id.edit_as_new_message -> onEditAsNewMessage()
            R.id.share -> onSendAlternate()
            R.id.toggle_unread -> onToggleRead()
            R.id.archive, R.id.refile_archive -> onArchive()
            R.id.spam, R.id.refile_spam -> onSpam()
            R.id.move, R.id.refile_move -> onMove()
            R.id.copy, R.id.refile_copy -> onCopy()
            R.id.move_to_drafts -> onMoveToDrafts()
            R.id.unsubscribe -> onUnsubscribe()
            R.id.show_headers -> onShowHeaders()
            else -> return false
        }

        return true
    }

    private fun onShowHeaders() {
        val launchIntent = MessageSourceActivity.createLaunchIntent(requireActivity(), messageReference)
        startActivity(launchIntent)
    }

    private fun onToggleTheme() {
        themeManager.toggleMessageViewTheme()
        ActivityCompat.recreate(requireActivity())
    }

    private fun showMessage(messageViewInfo: MessageViewInfo) {
        hideKeyboard()

@@ -319,7 +438,7 @@ class MessageViewFragment :
        )
    }

    fun onForwardAsAttachment() {
    private fun onForwardAsAttachment() {
        val message = checkNotNull(this.message)

        fragmentListener.onForwardAsAttachment(
@@ -328,7 +447,7 @@ class MessageViewFragment :
        )
    }

    fun onEditAsNewMessage() {
    private fun onEditAsNewMessage() {
        val message = checkNotNull(this.message)

        fragmentListener.onEditAsNewMessage(message.makeMessageReference())
@@ -358,7 +477,7 @@ class MessageViewFragment :
        startRefileActivity(FolderOperation.COPY, ACTIVITY_CHOOSE_FOLDER_COPY)
    }

    fun onMoveToDrafts() {
    private fun onMoveToDrafts() {
        fragmentListener.showNextMessageOrReturn()

        val account = account
@@ -371,7 +490,7 @@ class MessageViewFragment :
        onRefile(account.archiveFolderId)
    }

    fun onSpam() {
    private fun onSpam() {
        onRefile(account.spamFolderId)
    }

@@ -449,7 +568,7 @@ class MessageViewFragment :
        copyMessage(messageReference, destinationFolderId)
    }

    fun onSendAlternate() {
    private fun onSendAlternate() {
        val message = checkNotNull(message)

        val shareIntent = shareIntentBuilder.createShareIntent(message)
@@ -557,33 +676,33 @@ class MessageViewFragment :

    override fun dialogCancelled(dialogId: Int) = Unit

    val isOutbox: Boolean
    private val isOutbox: Boolean
        get() = messageReference.folderId == account.outboxFolderId

    val isMessageRead: Boolean
    private val isMessageRead: Boolean
        get() = message?.isSet(Flag.SEEN) == true

    val isCopyCapable: Boolean
    private val isCopyCapable: Boolean
        get() = !isOutbox && messagingController.isCopyCapable(account)

    val isMoveCapable: Boolean
    private val isMoveCapable: Boolean
        get() = !isOutbox && messagingController.isMoveCapable(account)

    fun canMessageBeArchived(): Boolean {
    private fun canMessageBeArchived(): Boolean {
        val archiveFolderId = account.archiveFolderId ?: return false
        return messageReference.folderId != archiveFolderId
    }

    fun canMessageBeMovedToSpam(): Boolean {
    private fun canMessageBeMovedToSpam(): Boolean {
        val spamFolderId = account.spamFolderId ?: return false
        return messageReference.folderId != spamFolderId
    }

    fun canMessageBeUnsubscribed(): Boolean {
    private fun canMessageBeUnsubscribed(): Boolean {
        return preferredUnsubscribeUri != null
    }

    fun onUnsubscribe() {
    private fun onUnsubscribe() {
        val intent = when (val unsubscribeUri = preferredUnsubscribeUri) {
            is MailtoUnsubscribeUri -> {
                Intent(requireContext(), MessageCompose::class.java).apply {
@@ -781,7 +900,7 @@ class MessageViewFragment :
    }

    private fun invalidateMenu() {
        requireActivity().invalidateMenu()
        activity?.invalidateMenu()
    }

    private enum class FolderOperation {
+0 −10
Original line number Diff line number Diff line
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:tint="?attr/colorControlNormal"
    android:viewportHeight="24"
    android:viewportWidth="24">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z" />
</vector>
+77 −83

File changed.

Preview size limit exceeded, changes collapsed.

Loading