removed legacy shitty icon tint implementation

This commit is contained in:
Mariotaku Lee 2017-12-11 20:43:55 +08:00
parent e3bfd4091e
commit cea5cc42e8
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
46 changed files with 372 additions and 357 deletions

View File

@ -42,12 +42,12 @@ subprojects {
]
libVersions = [
Kotlin : "${kotlinVersion}",
SupportLib : '27.0.1',
SupportLib : '27.0.2',
SupportTest : '1.0.0',
MariotakuCommons : '0.9.21',
RestFu : '0.9.61',
ObjectCursor : '0.9.21',
PlayServices : '11.6.0',
PlayServices : '11.6.2',
PlayBilling : '1.0',
MapsUtils : '0.5',
DropboxCoreSdk : '3.0.3',

View File

@ -1,73 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.graphic;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.support.v7.graphics.drawable.DrawableWrapper;
import android.support.v7.view.menu.TwidereActionMenuItemView;
import android.view.MenuItem;
import org.mariotaku.twidere.util.menu.TwidereMenuInfo;
/**
* Created by mariotaku on 15/1/16.
*/
@SuppressWarnings("RestrictedApi")
public class ActionIconDrawable extends DrawableWrapper implements TwidereActionMenuItemView.IgnoreTinting {
private int mDefaultColor;
private int mHighlightColor;
public ActionIconDrawable(Drawable drawable, int defaultColor) {
super(drawable);
setDefaultColor(defaultColor);
setHighlightColor(0);
}
public int getDefaultColor() {
return mDefaultColor;
}
public void setDefaultColor(int defaultColor) {
mDefaultColor = defaultColor;
updateColorFilter();
}
public static void setMenuHighlight(MenuItem item, TwidereMenuInfo info) {
final Drawable icon = item.getIcon();
if (icon instanceof ActionIconDrawable) {
((ActionIconDrawable) icon).setHighlightColor(info.isHighlight() ? info.getHighlightColor(0) : 0);
}
}
private void setHighlightColor(int color) {
mHighlightColor = color;
updateColorFilter();
}
private void updateColorFilter() {
final int color = mHighlightColor == 0 ? mDefaultColor : mHighlightColor;
setColorFilter(color, Mode.SRC_ATOP);
invalidateSelf();
}
}

View File

@ -22,6 +22,7 @@ package android.support.v7.widget
import android.content.Context
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.support.v4.graphics.drawable.DrawableCompat
import android.util.AttributeSet
import android.view.Menu
import android.view.View
@ -58,7 +59,7 @@ class TwidereToolbar(context: Context, attrs: AttributeSet?) : Toolbar(context,
override fun setNavigationIcon(icon: Drawable?) {
if (icon != null && itemColor != 0) {
icon.setColorFilter(itemColor, PorterDuff.Mode.SRC_ATOP)
DrawableCompat.setTint(icon, itemColor)
}
super.setNavigationIcon(icon)
}

View File

@ -19,16 +19,12 @@
package org.mariotaku.ktextension
import android.content.Context
import android.graphics.drawable.Drawable
import android.support.annotation.DrawableRes
import android.support.v4.content.ContextCompat
import android.support.v4.view.ActionProvider
import android.support.v4.view.MenuItemCompat
import android.view.Menu
import android.view.MenuItem
import android.view.SubMenu
import org.mariotaku.twidere.graphic.ActionIconDrawable
fun Menu.setItemAvailability(id: Int, available: Boolean) {
val item = findItem(id) ?: return
@ -74,16 +70,6 @@ fun Menu.findSubmenu(id: Int): SubMenu? {
return findItem(id)?.subMenu
}
fun MenuItem.setActionIcon(context: Context, @DrawableRes iconRes: Int) {
val oldIcon = this.icon
if (oldIcon is ActionIconDrawable) {
val starIcon = ContextCompat.getDrawable(context, iconRes)
this.icon = ActionIconDrawable(starIcon, oldIcon.defaultColor)
} else {
setIcon(iconRes)
}
}
var MenuItem.supportActionProvider: ActionProvider?
get() = MenuItemCompat.getActionProvider(this)
set(value) {

View File

@ -919,7 +919,7 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
private fun updateActionsButton() {
if (!propertiesInitialized) return
val fragment = run {
if (pagerAdapter.getCount() == 0) return@run null
if (pagerAdapter.count == 0) return@run null
val position = mainPager.currentItem
val f = pagerAdapter.instantiateItem(mainPager, position) as? IFloatingActionButtonFragment
if (f is Fragment && (f.isDetached || f.host == null)) {

View File

@ -60,6 +60,7 @@ import org.mariotaku.twidere.fragment.iface.IBaseFragment
import org.mariotaku.twidere.fragment.media.*
import org.mariotaku.twidere.model.ParcelableMedia
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.SaveFileInfo
import org.mariotaku.twidere.provider.CacheProvider
import org.mariotaku.twidere.provider.ShareProvider
import org.mariotaku.twidere.task.SaveFileTask
@ -106,7 +107,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
return adapter.instantiateItem(viewPager, currentItem) as? MediaViewerFragment
}
private fun getCurrentCacheFileInfo(position: Int): SaveFileTask.FileInfo? {
private fun getCurrentCacheFileInfo(position: Int): SaveFileInfo? {
if (position == -1) return null
val viewPager = findViewPager()
val adapter = viewPager.adapter ?: return null
@ -521,11 +522,11 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
intent.type = fileInfo.mimeType ?: "*/*"
intent.addCategory(Intent.CATEGORY_OPENABLE)
val extension = fileInfo.fileExtension
val extension = fileInfo.extension
val saveFileName = if (extension != null) {
"${fileInfo.fileName?.removeSuffix("_$extension")}.$extension"
"${fileInfo.name?.removeSuffix("_$extension")}.$extension"
} else {
fileInfo.fileName
fileInfo.name
}
intent.putExtra(Intent.EXTRA_TITLE, saveFileName)
startActivityForResult(intent, REQUEST_SELECT_SAVE_MEDIA)
@ -536,7 +537,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
val weakThis = toWeak()
(showProgressDialog("save_media_to_progress") and task {
val a = weakThis.get() ?: throw InterruptedException()
fileInfo.inputStream().use { st ->
fileInfo.stream().use { st ->
st.copyTo(a.contentResolver.openOutputStream(data))
}
}).successUi {
@ -548,7 +549,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
}
}
private fun MediaViewerFragment.cacheFileInfo(): SaveFileTask.FileInfo? {
private fun MediaViewerFragment.cacheFileInfo(): SaveFileInfo? {
val context = this.context ?: return null
return when (this) {
is CacheDownloadMediaViewerFragment -> {
@ -568,7 +569,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
}
}
class SaveMediaTask(activity: MediaViewerActivity, destination: File, fileInfo: FileInfo) :
class SaveMediaTask(activity: MediaViewerActivity, destination: File, fileInfo: SaveFileInfo) :
SaveFileTask(activity, destination, fileInfo) {
private val PROGRESS_FRAGMENT_TAG = "progress"

View File

@ -34,6 +34,7 @@ import android.support.v4.content.Loader
import android.support.v4.view.ViewCompat
import android.support.v4.view.WindowInsetsCompat
import android.support.v4.widget.CursorAdapter
import android.support.v4.widget.ImageViewCompat
import android.text.Editable
import android.text.TextWatcher
import android.view.*
@ -417,7 +418,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
cursor.getString(indices.title))
holder.text2.visibility = View.VISIBLE
holder.text2.spannable = "@${cursor.getString(indices.summary)}"
holder.icon.clearColorFilter()
ImageViewCompat.setImageTintList(holder.icon, null)
requestManager.loadProfileImage(context, cursor.getString(indices.icon),
profileImageStyle, cornerRadius = holder.icon.cornerRadius,
cornerRadiusRatio = holder.icon.cornerRadiusRatio,
@ -427,7 +428,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
val holder = view.tag as UserViewHolder
holder.text1.spannable = "@${cursor.getString(indices.title)}"
holder.text2.visibility = View.GONE
holder.icon.setColorFilter(holder.text1.currentTextColor, Mode.SRC_ATOP)
ImageViewCompat.setImageTintList(holder.icon, holder.text1.textColors)
//TODO cancel image load
holder.icon.setImageResource(R.drawable.ic_action_user)
}

View File

@ -22,7 +22,7 @@ package org.mariotaku.twidere.adapter
import android.content.Context
import android.content.SharedPreferences
import android.database.Cursor
import android.graphics.PorterDuff.Mode
import android.support.v4.widget.ImageViewCompat
import android.support.v4.widget.SimpleCursorAdapter
import android.view.View
import android.widget.TextView
@ -99,7 +99,7 @@ class ComposeAutoCompleteAdapter(context: Context, val requestManager: RequestMa
text2.setText(R.string.hashtag)
icon.setImageResource(R.drawable.ic_action_hashtag)
icon.setColorFilter(text1.currentTextColor, Mode.SRC_ATOP)
ImageViewCompat.setImageTintList(icon, text1.textColors)
}
icon.visibility = if (displayProfileImage) View.VISIBLE else View.GONE
super.bindView(view, context, cursor)

View File

@ -41,4 +41,10 @@ fun Drawable.setBoundsFitCenter(left: Int, top: Int, right: Int, bottom: Int) {
setBounds(left, boundsHeight / 2 - actualHeight / 2, right,
boundsHeight / 2 + actualHeight / 2)
}
}
}
var Drawable.isActivated: Boolean
get() = android.R.attr.state_activated in state
set(value) {
state = if (value) intArrayOf(android.R.attr.state_activated) else intArrayOf()
}

View File

@ -27,12 +27,13 @@ import android.content.DialogInterface
import android.content.Intent
import android.database.Cursor
import android.graphics.Paint
import android.graphics.PorterDuff.Mode
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.app.LoaderManager.LoaderCallbacks
import android.support.v4.content.CursorLoader
import android.support.v4.content.Loader
import android.support.v4.graphics.drawable.DrawableCompat
import android.support.v4.widget.ImageViewCompat
import android.support.v7.app.AlertDialog
import android.util.SparseArray
import android.view.*
@ -152,9 +153,10 @@ class CustomTabsFragment : BaseFragment(), LoaderCallbacks<Cursor?>, MultiChoice
val shouldDisable = disabledByDuplicateTab || disabledByNoAccount
subItem.isVisible = !shouldDisable
subItem.isEnabled = !shouldDisable
val icon = conf.icon.createDrawable(context)
icon.mutate().setColorFilter(theme.textColorPrimary, Mode.SRC_ATOP)
subItem.icon = icon
subItem.icon = conf.icon.createDrawable(context).apply {
mutate()
DrawableCompat.setTint(this, theme.textColorPrimary)
}
val weakFragment = WeakReference(this)
subItem.setOnMenuItemClickListener {
val fragment = weakFragment.get()?.takeUnless(Fragment::isDetached) ?:
@ -470,10 +472,9 @@ class CustomTabsFragment : BaseFragment(), LoaderCallbacks<Cursor?>, MultiChoice
}
open class TabIconViewHolder(val adapter: TabIconsAdapter, itemView: View) : ViewHolder(itemView) {
private val icon: ImageView = itemView.findViewById(android.R.id.icon)
protected val icon: ImageView = itemView.findViewById(android.R.id.icon)
open fun display(item: DrawableHolder) {
icon.setColorFilter(adapter.iconColor, Mode.SRC_ATOP)
icon.setImageDrawable(item.createDrawable(icon.context))
}
}
@ -483,6 +484,7 @@ class CustomTabsFragment : BaseFragment(), LoaderCallbacks<Cursor?>, MultiChoice
private val text2: TextView = itemView.findViewById(android.R.id.text2)
override fun display(item: DrawableHolder) {
super.display(item)
ImageViewCompat.setImageTintList(icon, text1.textColors)
text1.spannable = item.name
text2.visibility = View.GONE
}
@ -492,7 +494,6 @@ class CustomTabsFragment : BaseFragment(), LoaderCallbacks<Cursor?>, MultiChoice
class CustomTabsAdapter(context: Context) : SimpleDragSortCursorAdapter(context,
R.layout.list_item_custom_tab, null, emptyArray(), intArrayOf(), 0) {
private val iconColor: Int = ThemeUtils.getThemeForegroundColor(context)
private val tempTab: Tab = Tab()
private var indices: ObjectCursor.CursorIndices<Tab>? = null
@ -521,7 +522,6 @@ class CustomTabsFragment : BaseFragment(), LoaderCallbacks<Cursor?>, MultiChoice
} else {
holder.icon.setImageResource(R.drawable.ic_action_list)
}
holder.icon.setColorFilter(iconColor, Mode.SRC_ATOP)
}
override fun changeCursor(cursor: Cursor?) {

View File

@ -23,13 +23,13 @@ import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.content.DialogInterface.OnClickListener
import android.graphics.PorterDuff
import android.os.Bundle
import android.os.Environment.getExternalStorageDirectory
import android.support.v4.app.LoaderManager.LoaderCallbacks
import android.support.v4.content.ContextCompat
import android.support.v4.content.FixedAsyncTaskLoader
import android.support.v4.content.Loader
import android.support.v4.content.res.ResourcesCompat
import android.support.v4.graphics.drawable.DrawableCompat
import android.support.v7.app.AlertDialog
import android.text.TextUtils.TruncateAt
import android.view.View
@ -194,19 +194,19 @@ class FileSelectorDialogFragment : BaseDialogFragment(), LoaderCallbacks<List<Fi
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = super.getView(position, convertView, parent)
val text = (view as? TextView ?: view.findViewById<View>(android.R.id.text1)) as TextView
val file = getItem(position)
val file = getItem(position)!!
if (file == currentPath?.parentFile) {
text.text = "build/generated/source/rs/androidTest"
text.text = ".."
} else {
text.text = file!!.name
text.text = file.name
}
text.setSingleLine(true)
text.ellipsize = TruncateAt.MARQUEE
text.setPadding(padding, padding, position, padding)
val icon = ResourcesCompat.getDrawable(resources,
if (file!!.isDirectory) R.drawable.ic_folder else R.drawable.ic_file, null)!!
icon.mutate()
icon.setColorFilter(actionIconColor, PorterDuff.Mode.SRC_ATOP)
val icon = ContextCompat.getDrawable(context, file.icon)!!.apply {
mutate()
DrawableCompat.setTint(this, actionIconColor)
}
text.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null)
return view
}
@ -219,6 +219,8 @@ class FileSelectorDialogFragment : BaseDialogFragment(), LoaderCallbacks<List<Fi
}
}
private val File.icon: Int
get() = if (isDirectory) R.drawable.ic_folder else R.drawable.ic_file
}
private class FilesLoader(context: Context, private val path: File?, private val extensions: Array<String>?) : FixedAsyncTaskLoader<List<File>>(context) {

View File

@ -27,7 +27,6 @@ import android.content.DialogInterface
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.Rect
import android.net.Uri
import android.nfc.NdefMessage
@ -105,7 +104,6 @@ import org.mariotaku.twidere.fragment.timeline.AbsTimelineFragment
import org.mariotaku.twidere.fragment.timeline.FavoritesTimelineFragment
import org.mariotaku.twidere.fragment.timeline.UserMediaTimelineFragment
import org.mariotaku.twidere.fragment.timeline.UserTimelineFragment
import org.mariotaku.twidere.graphic.ActionIconDrawable
import org.mariotaku.twidere.graphic.drawable.userprofile.ActionBarDrawable
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.event.FriendshipTaskEvent
@ -127,7 +125,6 @@ import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallb
import org.mariotaku.twidere.util.TwidereLinkify.OnLinkClickListener
import org.mariotaku.twidere.util.UserColorNameManager.UserColorChangedListener
import org.mariotaku.twidere.util.UserColorNameManager.UserNicknameChangedListener
import org.mariotaku.twidere.util.menu.TwidereMenuInfo
import org.mariotaku.twidere.util.shortcut.ShortcutCreator
import org.mariotaku.twidere.util.support.ActivitySupport
import org.mariotaku.twidere.util.support.ActivitySupport.TaskDescriptionCompat
@ -145,7 +142,7 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
override val currentVisibleFragment: Fragment?
get() {
val currentItem = viewPager.currentItem
if (currentItem < 0 || currentItem >= pagerAdapter.getCount()) return null
if (currentItem < 0 || currentItem >= pagerAdapter.count) return null
return pagerAdapter.instantiateItem(viewPager, currentItem)
}
@ -447,7 +444,7 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
relationship.following)
menu.findItem(R.id.block)?.apply {
ActionIconDrawable.setMenuHighlight(this, TwidereMenuInfo(relationship.blocking))
icon?.isActivated = relationship.blocking
this.setTitle(if (relationship.blocking) R.string.action_unblock else R.string.action_block)
}
menu.findItem(R.id.mute_user)?.apply {
@ -669,14 +666,14 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
when (action) {
ACTION_NAVIGATION_PREVIOUS_TAB -> {
val previous = viewPager.currentItem - 1
if (previous >= 0 && previous < pagerAdapter.getCount()) {
if (previous >= 0 && previous < pagerAdapter.count) {
viewPager.setCurrentItem(previous, true)
}
return true
}
ACTION_NAVIGATION_NEXT_TAB -> {
val next = viewPager.currentItem + 1
if (next >= 0 && next < pagerAdapter.getCount()) {
if (next >= 0 && next < pagerAdapter.count) {
viewPager.setCurrentItem(next, true)
}
return true
@ -859,7 +856,7 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
}
R.id.profileBirthdayBanner -> {
hideBirthdayView = true
profileBirthdayBanner.startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out))
profileBirthdayBanner.startAnimation(AnimationUtils.loadAnimation(activity, android.R.anim.fade_out))
profileBirthdayBanner.visibility = View.GONE
}
}
@ -1088,7 +1085,6 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
private fun setFollowEditButton(@DrawableRes icon: Int, @ColorRes color: Int, @StringRes label: Int) {
val followButton = followContainer.follow
followButton.setImageResource(icon)
ViewCompat.setBackgroundTintMode(followButton, PorterDuff.Mode.SRC_ATOP)
val backgroundTintList = ContextCompat.getColorStateList(context!!, color)!!
ViewCompat.setBackgroundTintList(followButton, backgroundTintList)
ImageViewCompat.setImageTintList(followButton,
@ -1105,7 +1101,7 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
private fun displayUser(user: ParcelableUser) {
val activity = activity ?: return
val adapter = pagerAdapter
(0 until adapter.getCount()).forEach { i ->
(0 until adapter.count).forEach { i ->
val sf = adapter.instantiateItem(viewPager, i) as? AbsTimelineFragment ?: return@forEach
if (sf.view == null) return@forEach
}

View File

@ -54,7 +54,6 @@ import org.mariotaku.twidere.util.TwidereColorUtils
import org.mariotaku.twidere.util.qr.QrCodeData
import org.mariotaku.uniqr.AndroidPlatform
import org.mariotaku.uniqr.UniqR
import java.lang.ref.WeakReference
import java.util.concurrent.ExecutionException
/**
@ -66,8 +65,9 @@ class UserQrDialogFragment : BaseDialogFragment() {
private val user: ParcelableUser
get() = arguments!!.user!!
init {
setStyle(STYLE_NO_TITLE, 0)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_FRAME, R.style.Theme_Twidere_Dark_Dialog_NoFrame)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@ -76,15 +76,19 @@ class UserQrDialogFragment : BaseDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
qrContainer.setAspectRatio(1.0)
val weakThis = WeakReference(this)
val weakThis by weak(this)
qrShare.setOnClickListener {
shareQrImage()
}
qrSave.setOnClickListener {
saveQrImage()
}
promiseOnUi {
val fragment = weakThis.get()?.takeIf { it.view != null } ?: return@promiseOnUi
val fragment = weakThis?.takeIf { it.view != null } ?: return@promiseOnUi
fragment.qrView.visibility = View.INVISIBLE
fragment.qrProgress.visibility = View.VISIBLE
} and loadProfileImage().then { drawable ->
val fragment = weakThis.get()?.takeIf { it.context != null } ?: throw InterruptedException()
val fragment = weakThis?.takeIf { it.context != null } ?: throw InterruptedException()
val background = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight,
Bitmap.Config.ARGB_8888)
val canvas = Canvas(background)
@ -104,7 +108,7 @@ class UserQrDialogFragment : BaseDialogFragment() {
background.recycle()
return@then result
}.successUi { bitmap ->
val fragment = weakThis.get()?.takeIf { it.context != null && it.view != null } ?: return@successUi
val fragment = weakThis?.takeIf { it.context != null && it.view != null } ?: return@successUi
fragment.qrView.visibility = View.VISIBLE
fragment.qrProgress.visibility = View.GONE
fragment.qrView.setImageDrawable(BitmapDrawable(fragment.resources, bitmap).apply {
@ -112,12 +116,19 @@ class UserQrDialogFragment : BaseDialogFragment() {
this.isFilterBitmap = false
})
}.failUi {
val fragment = weakThis.get()?.takeIf { it.dialog != null } ?: return@failUi
val fragment = weakThis?.takeIf { it.dialog != null } ?: return@failUi
Toast.makeText(fragment.context, R.string.message_toast_error_occurred, Toast.LENGTH_SHORT).show()
fragment.dismiss()
}
}
private fun saveQrImage() {
}
private fun shareQrImage() {
}
private fun loadProfileImage(): Promise<GlideDrawable, Exception> {
val activity = this.activity ?: return Promise.ofFail(InterruptedException())
if (isDetached || dialog == null || activity.isFinishing) {
@ -153,18 +164,19 @@ class UserQrDialogFragment : BaseDialogFragment() {
return color
}
private val Palette.patternColor: Int get() {
var color = getDarkVibrantColor(0)
if (color == 0) {
color = getDominantColor(0)
private val Palette.patternColor: Int
get() {
var color = getDarkVibrantColor(0)
if (color == 0) {
color = getDominantColor(0)
}
if (color == 0) {
color = getDarkMutedColor(0)
}
if (color == 0) {
return Color.BLACK
}
return getOptimalPatternColor(color)
}
if (color == 0) {
color = getDarkMutedColor(0)
}
if (color == 0) {
return Color.BLACK
}
return getOptimalPatternColor(color)
}
}
}

View File

@ -21,13 +21,13 @@ package org.mariotaku.twidere.fragment.filter
import android.content.Context
import android.database.Cursor
import android.graphics.PorterDuff
import android.net.Uri
import android.os.Bundle
import android.support.v4.app.LoaderManager
import android.support.v4.content.ContextCompat
import android.support.v4.content.CursorLoader
import android.support.v4.content.Loader
import android.support.v4.graphics.drawable.DrawableCompat
import android.support.v4.view.ViewCompat
import android.support.v4.widget.SimpleCursorAdapter
import android.text.SpannableStringBuilder
@ -54,7 +54,6 @@ import org.mariotaku.twidere.fragment.AbsContentListViewFragment
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
import org.mariotaku.twidere.text.style.EmojiSpan
import org.mariotaku.twidere.util.ThemeUtils
abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdapter>(),
@ -250,7 +249,6 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
emptyArray(), intArrayOf(), 0), IFilterAdapter {
private var indices: ObjectCursor.CursorIndices<FiltersData.BaseItem>? = null
private val secondaryTextColor = ThemeUtils.getTextColorSecondary(context)
override fun swapCursor(c: Cursor?): Cursor? {
indices = c?.let { ObjectCursor.indicesFrom(it, FiltersData.BaseItem::class.java) }
@ -267,8 +265,8 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
val start = ssb.length
ssb.append("*")
val end = start + 1
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_action_sync)
drawable!!.setColorFilter(secondaryTextColor, PorterDuff.Mode.SRC_ATOP)
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_action_sync)!!
DrawableCompat.setTintList(drawable, text1.textColors)
ssb.setSpan(EmojiSpan(drawable), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
text1.text = ssb

View File

@ -6,13 +6,13 @@ import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.database.Cursor
import android.graphics.PorterDuff
import android.net.Uri
import android.os.Bundle
import android.support.v4.app.FragmentActivity
import android.support.v4.content.ContextCompat
import android.support.v4.content.CursorLoader
import android.support.v4.content.Loader
import android.support.v4.graphics.drawable.DrawableCompat
import android.support.v4.widget.SimpleCursorAdapter
import android.text.SpannableStringBuilder
import android.text.Spanned
@ -261,8 +261,9 @@ class FilteredUsersFragment : BaseFiltersFragment() {
val start = ssb.length
ssb.append("*")
val end = start + 1
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_action_sync)!!
drawable.setColorFilter(secondaryTextColor, PorterDuff.Mode.SRC_ATOP)
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_action_sync)!!.apply {
DrawableCompat.setTint(this, secondaryTextColor)
}
ssb.setSpan(EmojiSpan(drawable), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
text1.spannable = ssb

View File

@ -73,8 +73,8 @@ import org.mariotaku.twidere.fragment.media.VideoPageFragment.Companion.isMutedB
import org.mariotaku.twidere.fragment.media.VideoPageFragment.Companion.media
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.ParcelableMedia
import org.mariotaku.twidere.model.SaveFileInfo
import org.mariotaku.twidere.provider.CacheProvider
import org.mariotaku.twidere.task.SaveFileTask
import org.mariotaku.twidere.util.media.TwidereMediaDownloader
import org.mariotaku.twidere.util.promotion.PromotionService
import java.io.InputStream
@ -396,20 +396,20 @@ class ExoPlayerPageFragment : MediaViewerFragment(), IBaseFragment<ExoPlayerPage
val uri: Uri,
val account: AccountDetails?,
val okHttpClient: OkHttpClient
) : SaveFileTask.FileInfo, CacheProvider.CacheFileTypeSupport {
) : SaveFileInfo, CacheProvider.CacheFileTypeSupport {
private var response: Response? = null
override val cacheFileType: String? = CacheFileType.VIDEO
override val fileName: String? = uri.lastPathSegment
override val name: String = uri.lastPathSegment ?: "media_file"
override val mimeType: String?
get() = request().body()?.contentType()?.toString()
override val specialCharacter: Char = '_'
override fun inputStream(): InputStream {
override fun stream(): InputStream {
return request().body()!!.byteStream()
}

View File

@ -26,12 +26,12 @@ import android.arch.lifecycle.Observer
import android.arch.paging.PagedList
import android.content.Context
import android.content.Intent
import android.graphics.PorterDuff
import android.graphics.Rect
import android.net.Uri
import android.os.Bundle
import android.support.v4.app.FragmentActivity
import android.support.v4.content.ContextCompat
import android.support.v4.graphics.drawable.DrawableCompat
import android.support.v4.widget.TextViewCompat
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.FixedLinearLayoutManager
@ -541,7 +541,7 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
val stateIcon = if (conversation.notificationDisabled) {
ContextCompat.getDrawable(activity, R.drawable.ic_message_type_speaker_muted)?.apply {
mutate()
setColorFilter(conversationTitle.currentTextColor, PorterDuff.Mode.SRC_ATOP)
DrawableCompat.setTint(this, conversationTitle.currentTextColor)
}
} else {
null

View File

@ -20,24 +20,24 @@
package org.mariotaku.twidere.menu
import android.content.Context
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.support.v4.content.ContextCompat
import android.support.v4.graphics.drawable.DrawableCompat
import android.support.v4.view.ActionProvider
import android.support.v4.view.MenuItemCompat
import android.support.v7.widget.ActionMenuView
import android.view.MenuItem
import android.view.View
import org.mariotaku.ktextension.toWeak
import org.mariotaku.twidere.extension.isActivated
import org.mariotaku.twidere.extension.view.findItemView
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable.Style
class FavoriteItemProvider(context: Context) : ActionProvider(context) {
var defaultColor: Int = 0
var activatedColor: Int = 0
var useStar: Boolean = false
var icon: Int = 0
var tint: Int = 0
var longClickListener: (() -> Boolean)? = null
override fun onCreateActionView() = null
@ -54,8 +54,10 @@ class FavoriteItemProvider(context: Context) : ActionProvider(context) {
fun init(menuBar: ActionMenuView, item: MenuItem) {
assert(MenuItemCompat.getActionProvider(item) === this)
val icon = ContextCompat.getDrawable(context, this.icon)
val drawable = LikeAnimationDrawable(icon,
if (useStar) Style.FAVORITE else Style.LIKE)
val drawable = LikeAnimationDrawable(icon, if (useStar) Style.FAVORITE else Style.LIKE)
if (tint != 0) {
DrawableCompat.setTintList(drawable, ContextCompat.getColorStateList(context, tint))
}
drawable.mutate()
drawable.callback = ViewCallback(menuBar)
item.icon = drawable
@ -69,8 +71,7 @@ class FavoriteItemProvider(context: Context) : ActionProvider(context) {
if (MenuItemCompat.getActionProvider(item) !== this) throw IllegalArgumentException()
val icon = item.icon
if (icon is LikeAnimationDrawable) {
icon.mutate()
icon.setColorFilter(if (isFavorite) activatedColor else defaultColor, PorterDuff.Mode.SRC_ATOP)
icon.isActivated = isFavorite
}
}

View File

@ -0,0 +1,45 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.model
import android.webkit.MimeTypeMap
import java.io.Closeable
import java.io.InputStream
import java.util.*
interface SaveFileInfo : Closeable {
val name: String
val mimeType: String?
val extension: String?
get() {
val typeLowered = mimeType?.toLowerCase(Locale.US) ?: return null
return when (typeLowered) {
// Hack for fanfou image type
"image/jpg" -> "jpg"
else -> MimeTypeMap.getSingleton().getExtensionFromMimeType(typeLowered)
}
}
val specialCharacter: Char
fun stream(): InputStream
}

View File

@ -0,0 +1,24 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.model
import java.io.File
data class SaveFileResult(val savedFile: File, val mimeType: String?)

View File

@ -0,0 +1,27 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.promise.file;
/**
* Created by mariotaku on 2017/12/11.
*/
public class SaveFilePromises {
}

View File

@ -16,7 +16,7 @@ import org.mariotaku.twidere.annotation.CacheFileType
import org.mariotaku.twidere.dagger.component.GeneralComponent
import org.mariotaku.twidere.extension.get
import org.mariotaku.twidere.model.CacheMetadata
import org.mariotaku.twidere.task.SaveFileTask
import org.mariotaku.twidere.model.SaveFileInfo
import org.mariotaku.twidere.util.JsonSerializer
import java.io.ByteArrayInputStream
import java.io.FileNotFoundException
@ -106,8 +106,8 @@ class CacheProvider : ContentProvider() {
private val context: Context,
private val uri: Uri,
@CacheFileType override val cacheFileType: String?
) : SaveFileTask.FileInfo, CacheFileTypeSupport {
override val fileName: String by lazy {
) : SaveFileInfo, CacheFileTypeSupport {
override val name: String by lazy {
var cacheKey = getCacheKey(uri)
val indexOfSsp = cacheKey.indexOf("://")
if (indexOfSsp != -1) {
@ -128,7 +128,7 @@ class CacheProvider : ContentProvider() {
override val specialCharacter: Char
get() = '_'
override fun inputStream(): InputStream {
override fun stream(): InputStream {
return context.contentResolver.openInputStream(uri)
}

View File

@ -23,6 +23,7 @@ import android.content.Context
import android.support.v4.app.DialogFragment
import org.mariotaku.twidere.activity.iface.IBaseActivity
import org.mariotaku.twidere.fragment.ProgressDialogFragment
import org.mariotaku.twidere.model.SaveFileInfo
import java.io.File
/**
@ -31,7 +32,7 @@ import java.io.File
abstract class ProgressSaveFileTask(
context: Context,
destination: File,
fileInfo: FileInfo
fileInfo: SaveFileInfo
) : SaveFileTask(context, destination, fileInfo) {
override fun showProgress() {

View File

@ -23,20 +23,18 @@ import android.content.Context
import android.os.AsyncTask
import android.text.TextUtils.isEmpty
import android.util.Log
import android.webkit.MimeTypeMap
import org.mariotaku.twidere.TwidereConstants.LOGTAG
import java.io.Closeable
import org.mariotaku.twidere.model.SaveFileInfo
import org.mariotaku.twidere.model.SaveFileResult
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.lang.ref.WeakReference
import java.util.*
abstract class SaveFileTask(
context: Context,
private val destination: File,
private val fileInfo: FileInfo
) : AsyncTask<Any, Any, SaveFileTask.SaveFileResult>() {
private val fileInfo: SaveFileInfo
) : AsyncTask<Any, Any, SaveFileResult>() {
private val contextRef = WeakReference(context)
@ -54,8 +52,8 @@ abstract class SaveFileTask(
override fun onPostExecute(result: SaveFileResult?) {
dismissProgress()
if (result != null && result.savedFile != null) {
onFileSaved(result.savedFile!!, result.mimeType)
if (result != null) {
onFileSaved(result.savedFile, result.mimeType)
} else {
onFileSaveFailed()
}
@ -74,48 +72,17 @@ abstract class SaveFileTask(
protected val context: Context?
get() = contextRef.get()
interface FileInfo : Closeable {
val fileName: String?
val mimeType: String?
val fileExtension: String? get() {
val typeLowered = mimeType?.toLowerCase(Locale.US) ?: return null
return when (typeLowered) {
// Hack for fanfou image type
"image/jpg" -> "jpg"
else -> MimeTypeMap.getSingleton().getExtensionFromMimeType(typeLowered)
}
}
val specialCharacter: Char
fun inputStream(): InputStream
}
class SaveFileResult(savedFile: File, mimeType: String) {
var savedFile: File? = null
internal set
var mimeType: String
internal set
init {
this.savedFile = savedFile
this.mimeType = mimeType
}
}
companion object {
fun saveFile(fileInfo: FileInfo, destinationDir: File, requiresValidExtension: Boolean) = try {
fun saveFile(fileInfo: SaveFileInfo, destinationDir: File, requiresValidExtension: Boolean) = try {
fileInfo.use {
var name: String = it.fileName ?: return null
var name: String = it.name
if (isEmpty(name)) return null
if (name.length > 32) {
name = name.substring(0, 32)
}
val mimeType = it.mimeType ?: return null
val extension = it.fileExtension
val extension = it.extension
if (requiresValidExtension && extension == null) {
return null
}
@ -130,7 +97,7 @@ abstract class SaveFileTask(
saveFile = File(destinationDir, nameToSave)
}
saveFile.outputStream().use { output ->
it.inputStream().use { input ->
it.stream().use { input ->
input.copyTo(output)
}
}

View File

@ -23,6 +23,7 @@ import android.app.Activity
import android.media.MediaScannerConnection
import android.widget.Toast
import org.mariotaku.twidere.R
import org.mariotaku.twidere.model.SaveFileInfo
import java.io.File
/**
@ -30,7 +31,7 @@ import java.io.File
*/
class SaveMediaToGalleryTask(
activity: Activity,
fileInfo: FileInfo,
fileInfo: SaveFileInfo,
destination: File
) : ProgressSaveFileTask(activity, destination, fileInfo) {

View File

@ -26,12 +26,13 @@ import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.graphics.PorterDuff
import android.content.res.ColorStateList
import android.os.Parcelable
import android.support.annotation.UiThread
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.content.ContextCompat
import android.support.v4.graphics.drawable.DrawableCompat
import android.support.v4.view.MenuItemCompat
import android.support.v7.widget.ShareActionProvider
import android.util.Log
@ -42,7 +43,6 @@ import android.widget.Toast
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.Bundle
import org.mariotaku.ktextension.set
import org.mariotaku.ktextension.setActionIcon
import org.mariotaku.ktextension.setItemAvailability
import org.mariotaku.microblog.library.mastodon.annotation.StatusVisibility
import org.mariotaku.twidere.Constants.*
@ -62,7 +62,6 @@ import org.mariotaku.twidere.fragment.BaseFragment
import org.mariotaku.twidere.fragment.SetUserNicknameDialogFragment
import org.mariotaku.twidere.fragment.status.*
import org.mariotaku.twidere.fragment.timeline.AbsTimelineFragment
import org.mariotaku.twidere.graphic.ActionIconDrawable
import org.mariotaku.twidere.graphic.PaddingDrawable
import org.mariotaku.twidere.menu.FavoriteItemProvider
import org.mariotaku.twidere.menu.SupportStatusShareProvider
@ -72,7 +71,6 @@ import org.mariotaku.twidere.task.CreateFavoriteTask
import org.mariotaku.twidere.task.DestroyFavoriteTask
import org.mariotaku.twidere.task.DestroyStatusTask
import org.mariotaku.twidere.task.RetweetStatusTask
import org.mariotaku.twidere.util.menu.TwidereMenuInfo
import java.io.IOException
object MenuUtils {
@ -140,47 +138,42 @@ object MenuUtils {
when (status.extras?.visibility) {
StatusVisibility.PRIVATE -> {
retweet.setActionIcon(context, R.drawable.ic_action_lock)
retweet.setIcon(R.drawable.ic_action_lock)
}
StatusVisibility.DIRECT -> {
retweet.setActionIcon(context, R.drawable.ic_action_message)
retweet.setIcon(R.drawable.ic_action_message)
}
else -> {
retweet.setActionIcon(context, R.drawable.ic_action_retweet)
retweet.setIcon(R.drawable.ic_action_retweet)
}
}
MenuItemCompat.setIconTintList(retweet, if (isMyRetweet) ColorStateList.valueOf(retweetHighlight) else null)
retweet.setTitle(if (isMyRetweet) R.string.action_cancel_retweet else R.string.action_retweet)
ActionIconDrawable.setMenuHighlight(retweet, TwidereMenuInfo(isMyRetweet, retweetHighlight))
}
val favorite = menu.findItem(R.id.favorite)
if (favorite != null) {
val isFavorite: Boolean
if (CreateFavoriteTask.isRunning(status.account_key, status.id)) {
isFavorite = true
} else if (DestroyFavoriteTask.isRunning(status.account_key, status.id)) {
isFavorite = false
} else {
isFavorite = status.is_favorite
val isFavorite = when {
CreateFavoriteTask.isRunning(status.account_key, status.id) -> true
DestroyFavoriteTask.isRunning(status.account_key, status.id) -> false
else -> status.is_favorite
}
val provider = MenuItemCompat.getActionProvider(favorite)
val useStar = preferences[iWantMyStarsBackKey]
if (provider is FavoriteItemProvider) {
provider.setIsFavorite(favorite, isFavorite)
} else {
if (useStar) {
favorite.setActionIcon(context, R.drawable.ic_action_star)
ActionIconDrawable.setMenuHighlight(favorite, TwidereMenuInfo(isFavorite, favoriteHighlight))
} else {
ActionIconDrawable.setMenuHighlight(favorite, TwidereMenuInfo(isFavorite, likeHighlight))
}
MenuItemCompat.setIconTintList(retweet, when {
!isFavorite -> null
useStar -> ColorStateList.valueOf(favoriteHighlight)
else -> ColorStateList.valueOf(likeHighlight)
})
}
if (useStar) {
favorite.setTitle(if (isFavorite) R.string.action_unfavorite else R.string.action_favorite)
favorite.setIcon(R.drawable.ic_action_star)
} else {
favorite.setTitle(if (isFavorite) R.string.action_undo_like else R.string.action_like)
favorite.setIcon(R.drawable.ic_action_heart)
}
}
val translate = menu.findItem(R.id.translate)
@ -397,7 +390,7 @@ object MenuUtils {
val actionIconColor = ThemeUtils.getThemeForegroundColor(context)
if (metaDataDrawable != null) {
metaDataDrawable.mutate()
metaDataDrawable.setColorFilter(actionIconColor, PorterDuff.Mode.SRC_ATOP)
DrawableCompat.setTint(metaDataDrawable, actionIconColor)
item.icon = metaDataDrawable
} else {
val icon = info.loadIcon(pm)

View File

@ -25,15 +25,15 @@ import android.content.SharedPreferences
import android.content.res.ColorStateList
import android.content.res.Resources
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.os.Build
import android.support.annotation.AttrRes
import android.support.annotation.ColorInt
import android.support.annotation.StyleRes
import android.support.v4.content.ContextCompat
import android.support.v4.graphics.ColorUtils
import android.support.v4.graphics.drawable.DrawableCompat
import android.support.v4.view.MenuItemCompat
import android.support.v7.app.TwilightManagerAccessor
import android.support.v7.view.menu.ActionMenuItemView
import android.support.v7.widget.ActionMenuView
@ -52,10 +52,7 @@ import org.mariotaku.twidere.annotation.ThemeBackgroundOption.MIN_ALPHA
import org.mariotaku.twidere.constant.SharedPreferenceConstants.VALUE_THEME_BACKGROUND_SOLID
import org.mariotaku.twidere.constant.SharedPreferenceConstants.VALUE_THEME_BACKGROUND_TRANSPARENT
import org.mariotaku.twidere.constant.themeColorKey
import org.mariotaku.twidere.graphic.ActionIconDrawable
import org.mariotaku.twidere.graphic.WindowBackgroundDrawable
import org.mariotaku.twidere.graphic.iface.DoNotWrapDrawable
import org.mariotaku.twidere.util.menu.TwidereMenuInfo
import org.mariotaku.twidere.util.support.ViewSupport
object ThemeUtils {
@ -145,7 +142,7 @@ object ThemeUtils {
fun wrapMenuIcon(menu: Menu, itemColor: Int, subItemColor: Int, vararg excludeGroups: Int) {
for (i in 0 until menu.size()) {
val item = menu.getItem(i)
wrapMenuItemIcon(item, itemColor, *excludeGroups)
setTint(item, itemColor, *excludeGroups)
if (item.hasSubMenu()) {
wrapMenuIcon(item.subMenu, subItemColor, subItemColor, *excludeGroups)
}
@ -165,7 +162,7 @@ object ThemeUtils {
var k = 0
for (i in 0 until menu.size()) {
val item = menu.getItem(i)
wrapMenuItemIcon(item, itemColor, *excludeGroups)
setTint(item, itemColor, *excludeGroups)
if (item.hasSubMenu()) {
wrapMenuIcon(item.subMenu, popupItemColor, popupItemColor, *excludeGroups)
}
@ -181,7 +178,7 @@ object ThemeUtils {
var k = 0
for (i in 0 until menu.size()) {
val item = menu.getItem(i)
wrapMenuItemIcon(item, itemColor, *excludeGroups)
setTint(item, itemColor, *excludeGroups)
if (item.hasSubMenu()) {
wrapMenuIcon(item.subMenu, popupItemColor, popupItemColor, *excludeGroups)
}
@ -191,24 +188,9 @@ object ThemeUtils {
}
}
fun wrapMenuItemIcon(item: MenuItem, itemColor: Int, vararg excludeGroups: Int) {
fun setTint(item: MenuItem, itemColor: Int, vararg excludeGroups: Int) {
if (item.groupId in excludeGroups) return
val icon = item.icon?.takeUnless { it is DoNotWrapDrawable } ?: return
if (icon is ActionIconDrawable) {
icon.defaultColor = itemColor
item.icon = icon
return
}
icon.mutate()
val callback = icon.callback
val newIcon = ActionIconDrawable(icon, itemColor)
newIcon.callback = callback
item.icon = newIcon
}
fun getActionIconColor(context: Context): Int {
val itemBackgroundColor = getColorBackground(context)
return getActionIconColor(context, itemBackgroundColor)
MenuItemCompat.setIconTintList(item, ColorStateList.valueOf(itemColor))
}
fun getActionIconColor(context: Context, backgroundColor: Int): Int {
@ -354,39 +336,9 @@ object ThemeUtils {
if (toolbar is TwidereToolbar) {
toolbar.setItemColor(itemColor)
}
val overflowIcon = toolbar.overflowIcon
if (overflowIcon != null) {
overflowIcon.setColorFilter(itemColor, PorterDuff.Mode.SRC_ATOP)
toolbar.overflowIcon = overflowIcon
}
}
fun applyColorFilterToMenuIcon(menu: Menu, @ColorInt color: Int,
@ColorInt popupColor: Int, @ColorInt highlightColor: Int, mode: PorterDuff.Mode,
vararg excludedGroups: Int) {
var i = 0
val j = menu.size()
while (i < j) {
val item = menu.getItem(i)
val icon = item.icon
val info = item.menuInfo
if (icon != null && item.groupId !in excludedGroups) {
icon.mutate()
if (info is TwidereMenuInfo) {
val sInfo = info
val stateColor = if (sInfo.isHighlight) sInfo.getHighlightColor(highlightColor) else color
if (stateColor != 0) {
icon.setColorFilter(stateColor, mode)
}
} else if (color != 0) {
icon.setColorFilter(color, mode)
}
}
if (item.hasSubMenu()) {
// SubMenu item is always in popup
applyColorFilterToMenuIcon(item.subMenu, popupColor, popupColor, highlightColor, mode, *excludedGroups)
}
i++
toolbar.overflowIcon = toolbar.overflowIcon?.apply {
mutate()
DrawableCompat.setTint(this, itemColor)
}
}
@ -394,17 +346,14 @@ object ThemeUtils {
val contrastForegroundColor = getColorDependent(toolbarColor)
toolbar.setTitleTextColor(contrastForegroundColor)
toolbar.setSubtitleTextColor(contrastForegroundColor)
val popupItemColor: Int
val popupTheme = toolbar.popupTheme
if (popupTheme != 0) {
popupItemColor = getThemeForegroundColor(context, popupTheme)
val popupItemColor = if (popupTheme != 0) {
getThemeForegroundColor(context, popupTheme)
} else {
popupItemColor = getThemeForegroundColor(context)
getThemeForegroundColor(context)
}
val navigationIcon = toolbar.navigationIcon
if (navigationIcon != null) {
navigationIcon.setColorFilter(contrastForegroundColor, PorterDuff.Mode.SRC_ATOP)
toolbar.navigationIcon = navigationIcon
toolbar.navigationIcon = toolbar.navigationIcon?.apply {
DrawableCompat.setTint(this, contrastForegroundColor)
}
getThemeForegroundColor(context)
setActionBarOverflowColor(toolbar, contrastForegroundColor)

View File

@ -21,7 +21,6 @@ package org.mariotaku.twidere.view
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.PorterDuff.Mode
import android.support.annotation.ColorInt
import android.support.v4.widget.TextViewCompat
import android.util.AttributeSet
@ -103,7 +102,7 @@ class ActionIconThemedTextView(
d.setBounds(left, top, left + iconWidth, top + iconHeight)
}
d.setColorFilter(color, Mode.SRC_ATOP)
// d.setColorFilter(color, Mode.SRC_ATOP)
}
}

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.view
import android.content.Context
import android.graphics.Canvas
import android.graphics.ColorFilter
import android.graphics.Paint
import android.support.annotation.Dimension
import android.support.v4.view.ViewCompat
@ -128,6 +129,10 @@ class LabeledImageButton(context: Context, attrs: AttributeSet?) : AppCompatImag
textSize = TypedValue.applyDimension(unit, size, resources.displayMetrics)
}
override fun setColorFilter(cf: ColorFilter?) {
super.setColorFilter(cf)
}
private fun updateLayout() {
val text = this.text
if (text == null) {

View File

@ -23,7 +23,6 @@ import android.content.Context
import android.content.SharedPreferences
import android.graphics.Rect
import android.support.annotation.UiThread
import android.support.v4.content.ContextCompat
import android.support.v4.view.ViewCompat
import android.support.v7.widget.ActionMenuView
import android.support.v7.widget.LinearLayoutManager
@ -43,7 +42,7 @@ import kotlinx.android.synthetic.main.header_status.view.*
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.*
import org.mariotaku.microblog.library.twitter.model.TranslationResult
import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.Constants.MENU_GROUP_STATUS_SHARE
import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.BaseRecyclerViewAdapter
import org.mariotaku.twidere.adapter.StatusDetailsAdapter
@ -440,13 +439,9 @@ class DetailStatusViewHolder(
val favoriteItem = menu.findItem(R.id.favorite)
val favoriteProvider = favoriteItem?.supportActionProvider
if (favoriteProvider is FavoriteItemProvider) {
val defaultColor = ThemeUtils.getActionIconColor(activity)
favoriteProvider.defaultColor = defaultColor
val favoriteHighlight = ContextCompat.getColor(activity, R.color.highlight_favorite)
val likeHighlight = ContextCompat.getColor(activity, R.color.highlight_like)
val useStar = adapter.useStarsForLikes
favoriteProvider.activatedColor = if (useStar) favoriteHighlight else likeHighlight
favoriteProvider.icon = if (useStar) R.drawable.ic_action_star else R.drawable.ic_action_heart
favoriteProvider.tint = if (useStar) R.color.btn_tint_favorite_stateful else R.color.btn_tint_like_stateful
favoriteProvider.useStar = useStar
favoriteProvider.longClickListener = {
val status = adapter.getStatus(layoutPosition)
@ -467,7 +462,7 @@ class DetailStatusViewHolder(
retweetProvider.init(itemView.menuBar, retweetItem)
}
ThemeUtils.wrapMenuIcon(itemView.menuBar, excludeGroups = Constants.MENU_GROUP_STATUS_SHARE)
ThemeUtils.wrapMenuIcon(itemView.menuBar, excludeGroups = *intArrayOf(MENU_GROUP_STATUS_SHARE))
itemView.mediaPreviewLoad.setOnClickListener(this)
itemView.profileContainer.setOnClickListener(this)
retweetedByView.setOnClickListener(this)

View File

@ -394,6 +394,7 @@ class StatusViewHolder(private val adapter: IStatusesAdapter, itemView: View) :
replyButton.text = null
replyButton.contentDescription = context.getString(R.string.action_reply)
}
replyButton.drawable?.mutate()
when (status.extras?.visibility) {
StatusVisibility.PRIVATE -> {
@ -406,6 +407,7 @@ class StatusViewHolder(private val adapter: IStatusesAdapter, itemView: View) :
retweetButton.setImageResource(R.drawable.ic_action_retweet)
}
}
retweetButton.drawable?.mutate()
retweetButton.isActivated = isRetweetIconActivated(status)
@ -548,7 +550,6 @@ class StatusViewHolder(private val adapter: IStatusesAdapter, itemView: View) :
mediaPreview.style = adapter.mediaPreviewStyle
quotedMediaPreview.style = adapter.mediaPreviewStyle
// profileImageView.setStyle(adapter.getProfileImageStyle());
val nameFirst = adapter.nameFirst
nameView.nameFirst = nameFirst

View File

@ -20,5 +20,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/highlight_favorite" android:state_activated="true"/>
<item android:color="@color/highlight_favorite" android:state_checked="true"/>
<item android:color="?android:textColorSecondary"/>
</selector>

View File

@ -20,5 +20,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/highlight_like" android:state_activated="true"/>
<item android:color="@color/highlight_like" android:state_checked="true"/>
<item android:color="?android:textColorSecondary"/>
</selector>

View File

@ -20,5 +20,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/highlight_retweet" android:state_activated="true"/>
<item android:color="@color/highlight_retweet" android:state_checked="true"/>
<item android:color="?android:textColorSecondary"/>
</selector>

View File

@ -26,7 +26,6 @@
android:layout_height="match_parent"
android:padding="@dimen/element_spacing_normal">
<android.support.v7.widget.CardView
android:id="@+id/searchContainer"
android:layout_width="match_parent"

View File

@ -31,6 +31,7 @@
android:id="@+id/profileImage"
android:layout_width="@dimen/icon_size_large_media_status_profile_image"
android:layout_height="@dimen/icon_size_large_media_status_profile_image"
android:layout_marginLeft="@dimen/element_spacing_normal"
android:layout_marginStart="@dimen/element_spacing_normal"
android:layout_marginTop="@dimen/element_spacing_normal"
app:layout_constraintStart_toStartOf="parent"
@ -93,7 +94,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/mediaPreviewPager"
app:layout_goneMarginBottom="@dimen/element_spacing_normal"
app:tintMode="multiply"
tools:text="@string/sample_status_text"
tools:visibility="visible"/>
@ -116,7 +116,6 @@
app:layout_constraintTop_toBottomOf="@+id/text"
app:srcCompat="@drawable/ic_action_reply"
app:tint="?android:textColorSecondary"
app:tintMode="multiply"
tools:text="255"/>
<org.mariotaku.twidere.view.LabeledImageButton
@ -137,7 +136,6 @@
app:layout_constraintTop_toBottomOf="@+id/text"
app:srcCompat="@drawable/ic_action_retweet"
app:tint="@color/btn_tint_retweet_stateful"
app:tintMode="multiply"
tools:text="255"/>
<org.mariotaku.twidere.view.LabeledImageButton
@ -158,7 +156,6 @@
app:layout_constraintTop_toBottomOf="@+id/text"
app:srcCompat="@drawable/ic_action_heart"
app:tint="@color/btn_tint_like_stateful"
app:tintMode="multiply"
tools:text="255"/>
<android.support.v7.widget.AppCompatImageButton

View File

@ -17,30 +17,74 @@
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<com.commonsware.cwac.layouts.AspectLockedFrameLayout
<android.support.constraint.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/qrContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
tools:layout_height="320dp"
tools:layout_width="320dp">
tools:layout_gravity="center">
<ImageView
android:id="@+id/qrView"
<android.support.v7.widget.CardView
android:id="@+id/qrContainer"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="48dp"
android:layout_marginRight="48dp"
app:cardBackgroundColor="?cardItemBackgroundColor"
app:cardCornerRadius="2dp"
app:cardElevation="2dp"
app:layout_constraintDimensionRatio="W,1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:id="@+id/qrView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:padding="@dimen/element_spacing_xlarge"
android:scaleType="fitCenter"
tools:ignore="ContentDescription"/>
<ProgressBar
android:id="@+id/qrProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</android.support.v7.widget.CardView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:padding="@dimen/element_spacing_xlarge"
android:scaleType="fitCenter"
tools:ignore="ContentDescription"/>
<ProgressBar
android:id="@+id/qrProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
android:gravity="center"
android:orientation="horizontal"
android:paddingBottom="@dimen/element_spacing_xlarge"
android:paddingTop="@dimen/element_spacing_xlarge"
app:layout_constraintTop_toBottomOf="@+id/qrContainer">
</com.commonsware.cwac.layouts.AspectLockedFrameLayout>
<android.support.v7.widget.AppCompatImageButton
android:id="@+id/qrShare"
style="?borderlessButtonStyle"
android:layout_width="@dimen/element_size_normal"
android:layout_height="@dimen/element_size_normal"
android:background="?selectableItemBackgroundBorderless"
app:srcCompat="@drawable/ic_action_share"
app:tint="@android:color/white"/>
<Space
android:layout_width="@dimen/element_spacing_xlarge"
android:layout_height="0dp"/>
<android.support.v7.widget.AppCompatImageButton
android:id="@+id/qrSave"
style="?borderlessButtonStyle"
android:layout_width="@dimen/element_size_normal"
android:layout_height="@dimen/element_size_normal"
android:background="?selectableItemBackgroundBorderless"
app:srcCompat="@drawable/ic_action_save"
app:tint="@android:color/white"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>

View File

@ -63,8 +63,7 @@
android:layout_gravity="end|center_vertical"
android:contentDescription="@string/action_search"
android:scaleType="centerInside"
android:src="@drawable/ic_action_search"
app:backgroundTintMode="src_atop"/>
android:src="@drawable/ic_action_search"/>
</FrameLayout>
</RelativeLayout>

View File

@ -38,14 +38,15 @@
android:layout_weight="0"
android:background="@drawable/list_drag_handle"/>
<ImageView
<android.support.v7.widget.AppCompatImageView
android:id="@android:id/icon"
android:layout_width="48dip"
android:layout_height="48dip"
android:layout_margin="4dip"
android:layout_weight="0"
android:contentDescription="@string/icon"
android:scaleType="fitCenter"/>
android:scaleType="fitCenter"
app:tint="?android:colorForeground"/>
<LinearLayout
android:layout_width="match_parent"

View File

@ -351,7 +351,6 @@
android:textColor="?android:textColorSecondary"
app:srcCompat="@drawable/ic_action_reply"
app:tint="?android:textColorSecondary"
app:tintMode="multiply"
tools:text="255"/>
<org.mariotaku.twidere.view.LabeledImageButton
@ -372,7 +371,6 @@
android:textColor="?android:textColorSecondary"
app:srcCompat="@drawable/ic_action_retweet"
app:tint="@color/btn_tint_retweet_stateful"
app:tintMode="multiply"
tools:text="255"/>
<org.mariotaku.twidere.view.LabeledImageButton
@ -393,7 +391,6 @@
android:textColor="?android:textColorSecondary"
app:srcCompat="@drawable/ic_action_heart"
app:tint="@color/btn_tint_like_stateful"
app:tintMode="multiply"
tools:text="255"/>
</LinearLayout>
@ -411,7 +408,6 @@
android:focusable="false"
app:srcCompat="@drawable/ic_action_more_horizontal"
app:tint="?android:textColorSecondary"
app:tintMode="multiply"
tools:visibility="visible"/>
</org.mariotaku.twidere.view.ColorLabelRelativeLayout>

View File

@ -20,14 +20,18 @@
<FrameLayout
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="wrap_content"
android:layout_height="wrap_content">
<ImageView
<android.support.v7.widget.AppCompatImageView
android:id="@android:id/icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="@string/icon"
android:padding="@dimen/element_spacing_small"/>
android:padding="@dimen/element_spacing_small"
app:tint="?android:textColorPrimary"
tools:srcCompat="@drawable/ic_action_twidere"/>
</FrameLayout>

View File

@ -13,6 +13,8 @@
<style name="Theme.Twidere.QuickSearchBar.DayNight" parent="Theme.Twidere.Light.QuickSearchBar"/>
<style name="Theme.Twidere.Dialog.NoFrame.DayNight" parent="Theme.Twidere.Light.Dialog.NoFrame"/>
<style name="Theme.Twidere.NoDisplay.DayNight" parent="Theme.Twidere.Light.NoDisplay"/>
</resources>

View File

@ -32,6 +32,11 @@
<item name="lightThemeResource">@style/Theme.Twidere.Light.QuickSearchBar</item>
</style>
<style name="Theme.Twidere.Dialog.NoFrame" parent="Theme.Twidere.Dialog.NoFrame.DayNight">
<item name="darkThemeResource">@style/Theme.Twidere.Dark.Dialog.NoFrame</item>
<item name="lightThemeResource">@style/Theme.Twidere.Light.Dialog.NoFrame</item>
</style>
<style name="Theme.Twidere.NoDisplay" parent="Theme.Twidere.NoDisplay.DayNight">
<item name="darkThemeResource">@style/Theme.Twidere.Dark.NoDisplay</item>
<item name="lightThemeResource">@style/Theme.Twidere.Light.NoDisplay</item>

View File

@ -120,6 +120,18 @@
<item name="android:windowActionModeOverlay">false</item>
</style>
<style name="Theme.Twidere.Dark.Dialog.NoFrame" parent="Theme.Twidere.Dark.Dialog">
<item name="windowNoTitle">true</item>
<item name="windowActionModeOverlay">false</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
<item name="android:windowActionBarOverlay">false</item>
<item name="android:windowActionModeOverlay">false</item>
</style>
<style name="Theme.Twidere.Dark.Launcher" parent="Theme.Twidere.Dark.NoActionBar"/>
</resources>

View File

@ -128,6 +128,18 @@
<item name="android:windowActionModeOverlay">false</item>
</style>
<style name="Theme.Twidere.Light.Dialog.NoFrame" parent="Theme.Twidere.Light.Dialog">
<item name="windowNoTitle">true</item>
<item name="windowActionModeOverlay">false</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
<item name="android:windowActionBarOverlay">false</item>
<item name="android:windowActionModeOverlay">false</item>
</style>
<style name="Theme.Twidere.Light.Launcher" parent="Theme.Twidere.Light.NoActionBar"/>
</resources>

View File

@ -13,6 +13,8 @@
<style name="Theme.Twidere.QuickSearchBar.DayNight" parent="Theme.Twidere.Dark.QuickSearchBar"/>
<style name="Theme.Twidere.Dialog.NoFrame.DayNight" parent="Theme.Twidere.Dark.Dialog.NoFrame"/>
<style name="Theme.Twidere.NoDisplay.DayNight" parent="Theme.Twidere.Dark.NoDisplay"/>
</resources>