内蔵メディアビューアはリモートURLでダメなら自タンスのURLを試す。TL中項目のビューをXMLからAnko Layoutに変更。
@ -11,8 +11,10 @@ android {
|
||||
applicationId "jp.juggler.subwaytooter"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 27
|
||||
versionCode 201
|
||||
versionName "2.0.1"
|
||||
|
||||
versionCode 202
|
||||
versionName "2.0.2"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
// https://stackoverflow.com/questions/47791227/java-lang-illegalstateexception-dex-archives-setting-dex-extension-only-for
|
||||
@ -105,6 +107,15 @@ dependencies {
|
||||
|
||||
|
||||
implementation 'com.google.android.exoplayer:exoplayer:r2.5.4'
|
||||
|
||||
compile "org.jetbrains.anko:anko:$anko_version"
|
||||
// Anko Layouts
|
||||
compile "org.jetbrains.anko:anko-sdk25:$anko_version" // sdk15, sdk19, sdk21, sdk23 are also available
|
||||
compile "org.jetbrains.anko:anko-appcompat-v7:$anko_version"
|
||||
|
||||
// Coroutine listeners for Anko Layouts
|
||||
compile "org.jetbrains.anko:anko-sdk25-coroutines:$anko_version"
|
||||
compile "org.jetbrains.anko:anko-appcompat-v7-coroutines:$anko_version"
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
@ -0,0 +1,24 @@
|
||||
package jp.juggler.subwaytooter.util
|
||||
|
||||
import android.support.test.runner.AndroidJUnit4
|
||||
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@Suppress("MemberVisibilityCanPrivate")
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class TestBucketList {
|
||||
@Test fun test1(){
|
||||
val list = BucketList<String>(bucketCapacity=2)
|
||||
assertEquals(true,list.isEmpty())
|
||||
list.addAll( listOf("A","B","C"))
|
||||
list.addAll( 3, listOf("a","b","c"))
|
||||
list.addAll( 1, listOf("a","b","c"))
|
||||
list.removeAt(7)
|
||||
assertEquals(8,list.size)
|
||||
listOf("A","a","b","c","B","C","a","c").forEachIndexed { i,v->
|
||||
assertEquals( v,list[i])
|
||||
}
|
||||
}
|
||||
}
|
@ -52,7 +52,6 @@ import jp.juggler.subwaytooter.util.LogCategory
|
||||
import jp.juggler.subwaytooter.util.ProgressResponseBody
|
||||
import jp.juggler.subwaytooter.util.Utils
|
||||
import jp.juggler.subwaytooter.view.PinchBitmapView
|
||||
import okhttp3.Response
|
||||
|
||||
class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
|
||||
|
||||
@ -316,8 +315,8 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak") private fun loadBitmap(ta : TootAttachment) {
|
||||
val url = ta.getLargeUrl(App1.pref)
|
||||
if(url == null) {
|
||||
val urlList = ta.getLargeUrlList(App1.pref)
|
||||
if(urlList.isEmpty() ) {
|
||||
showError("missing media attachment url.")
|
||||
return
|
||||
}
|
||||
@ -332,7 +331,6 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
|
||||
|
||||
private val options = BitmapFactory.Options()
|
||||
|
||||
internal var data : ByteArray? = null
|
||||
internal var bitmap : Bitmap? = null
|
||||
|
||||
private fun decodeBitmap(data : ByteArray, pixel_max : Int) : Bitmap? {
|
||||
@ -359,50 +357,53 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
|
||||
return BitmapFactory.decodeByteArray(data, 0, data.size, options)
|
||||
}
|
||||
|
||||
internal fun getHttpCached(client : TootApiClient, url : String) : TootApiResult {
|
||||
val response : Response
|
||||
internal fun getHttpCached(client : TootApiClient, url : String) : TootApiResult? {
|
||||
val result = TootApiResult.makeWithCaption(url)
|
||||
|
||||
try {
|
||||
val request = okhttp3.Request.Builder()
|
||||
if(!client.sendRequest(result){
|
||||
okhttp3.Request.Builder()
|
||||
.url(url)
|
||||
.cacheControl(App1.CACHE_5MIN)
|
||||
.build()
|
||||
|
||||
client.publishApiProgress(getString(R.string.request_api, request.method(), url))
|
||||
val call = App1.ok_http_client2.newCall(request)
|
||||
response = call.execute()
|
||||
} catch(ex : Throwable) {
|
||||
return TootApiResult(Utils.formatError(ex, "network error."))
|
||||
}
|
||||
}) return result
|
||||
|
||||
if( client.isApiCancelled ) return null
|
||||
val response = requireNotNull(result.response)
|
||||
if(! response.isSuccessful) {
|
||||
return TootApiResult(TootApiClient.formatResponse(response, "response error"))
|
||||
return result.setError( TootApiClient.formatResponse(response,result.caption))
|
||||
}
|
||||
|
||||
return try {
|
||||
|
||||
data = ProgressResponseBody.bytes(response) { bytesRead, bytesTotal ->
|
||||
try {
|
||||
result.data = ProgressResponseBody.bytes(response) { bytesRead, bytesTotal ->
|
||||
// 50MB以上のデータはキャンセルする
|
||||
if(Math.max(bytesRead, bytesTotal) >= 50000000) {
|
||||
throw RuntimeException("media attachment is larger than 50000000")
|
||||
}
|
||||
client.publishApiProgressRatio(bytesRead.toInt(), bytesTotal.toInt())
|
||||
}
|
||||
|
||||
TootApiResult("")
|
||||
if( client.isApiCancelled ) return null
|
||||
} catch(ex : Throwable) {
|
||||
TootApiResult(Utils.formatError(ex, "content error."))
|
||||
result.setError( TootApiClient.formatResponse(response,result.caption,"?"))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun background(client : TootApiClient) : TootApiResult {
|
||||
val result = getHttpCached(client, url)
|
||||
val data = this.data ?: return result
|
||||
client.publishApiProgress("decoding image…")
|
||||
val bitmap = decodeBitmap(data, 2048)
|
||||
this.bitmap = bitmap
|
||||
return if(bitmap != null) result else TootApiResult("image decode failed.")
|
||||
override fun background(client : TootApiClient) : TootApiResult? {
|
||||
if( urlList.isEmpty()) return TootApiResult("missing url")
|
||||
var result : TootApiResult? = null
|
||||
for(url in urlList) {
|
||||
result = getHttpCached(client, url)
|
||||
val data = result?.data as? ByteArray
|
||||
if(data != null) {
|
||||
client.publishApiProgress("decoding image…")
|
||||
val bitmap = decodeBitmap(data, 2048)
|
||||
if( bitmap != null ) {
|
||||
this.bitmap = bitmap
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun handleResult(result : TootApiResult?) {
|
||||
|
@ -291,6 +291,7 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
|
||||
R.id.btnRemoveReply -> removeReply()
|
||||
R.id.btnMore -> performMore()
|
||||
R.id.btnPlugin -> openMushroom()
|
||||
R.id.btnEmojiPicker -> post_helper.openEmojiPickerFromMore()
|
||||
}
|
||||
}
|
||||
|
||||
@ -752,7 +753,8 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
|
||||
btnRemoveReply.setOnClickListener(this)
|
||||
|
||||
findViewById<View>(R.id.btnPlugin).setOnClickListener(this)
|
||||
|
||||
findViewById<View>(R.id.btnEmojiPicker).setOnClickListener(this)
|
||||
|
||||
for(iv in ivMedia) {
|
||||
iv.setOnClickListener(this)
|
||||
iv.setDefaultImageResId(Styler.getAttributeResourceId(this, R.attr.ic_loading))
|
||||
@ -1569,6 +1571,7 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
|
||||
dialog.show(this, null)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// post
|
||||
|
||||
|
@ -60,8 +60,8 @@ internal class ItemListAdapter(private val activity : ActMain, private val colum
|
||||
val holder : ItemViewHolder
|
||||
val view : View
|
||||
if(viewOld == null) {
|
||||
view = activity.layoutInflater.inflate(if(bSimpleList) R.layout.lv_status_simple else R.layout.lv_status, parent, false)
|
||||
holder = ItemViewHolder(activity, column, this, view, bSimpleList)
|
||||
holder = ItemViewHolder(activity, column, this, bSimpleList)
|
||||
view = holder.viewRoot
|
||||
view.tag = holder
|
||||
} else {
|
||||
view = viewOld
|
||||
|
@ -3,17 +3,17 @@ package jp.juggler.subwaytooter
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.net.Uri
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.view.ViewCompat
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.TextUtils
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.ImageButton
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
@ -35,79 +35,88 @@ import jp.juggler.subwaytooter.table.ContentWarning
|
||||
import jp.juggler.subwaytooter.table.MediaShown
|
||||
import jp.juggler.subwaytooter.table.SavedAccount
|
||||
import jp.juggler.subwaytooter.table.UserRelation
|
||||
import jp.juggler.subwaytooter.util.DecodeOptions
|
||||
import jp.juggler.subwaytooter.span.EmojiImageSpan
|
||||
import jp.juggler.subwaytooter.util.HTMLDecoder
|
||||
import jp.juggler.subwaytooter.util.LogCategory
|
||||
import jp.juggler.subwaytooter.util.NetworkEmojiInvalidator
|
||||
import jp.juggler.subwaytooter.util.Utils
|
||||
import jp.juggler.subwaytooter.util.*
|
||||
import jp.juggler.subwaytooter.view.*
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import org.jetbrains.anko.*
|
||||
import org.json.JSONObject
|
||||
|
||||
internal class ItemViewHolder(
|
||||
val activity : ActMain,
|
||||
val column : Column,
|
||||
private val list_adapter : ItemListAdapter,
|
||||
view : View,
|
||||
private val bSimpleList : Boolean
|
||||
) : View.OnClickListener, View.OnLongClickListener {
|
||||
|
||||
|
||||
companion object {
|
||||
private val log = LogCategory("ItemViewHolder")
|
||||
}
|
||||
|
||||
var viewRoot : View
|
||||
|
||||
private lateinit var llBoosted : View
|
||||
private lateinit var ivBoosted : ImageView
|
||||
private lateinit var tvBoosted : TextView
|
||||
private lateinit var tvBoostedAcct : TextView
|
||||
private lateinit var tvBoostedTime : TextView
|
||||
|
||||
private lateinit var llFollow : View
|
||||
private lateinit var ivFollow : MyNetworkImageView
|
||||
private lateinit var tvFollowerName : TextView
|
||||
private lateinit var tvFollowerAcct : TextView
|
||||
private lateinit var btnFollow : ImageButton
|
||||
private lateinit var ivFollowedBy : ImageView
|
||||
|
||||
private lateinit var llStatus : View
|
||||
private lateinit var ivThumbnail : MyNetworkImageView
|
||||
private lateinit var tvName : TextView
|
||||
private lateinit var tvTime : TextView
|
||||
private lateinit var tvAcct : TextView
|
||||
|
||||
private lateinit var llContentWarning : View
|
||||
private lateinit var tvContentWarning : MyTextView
|
||||
private lateinit var btnContentWarning : Button
|
||||
|
||||
private lateinit var llContents : View
|
||||
private lateinit var tvMentions : MyTextView
|
||||
private lateinit var tvContent : MyTextView
|
||||
|
||||
private lateinit var flMedia : View
|
||||
private lateinit var btnShowMedia : TextView
|
||||
private lateinit var ivMedia1 : MyNetworkImageView
|
||||
private lateinit var ivMedia2 : MyNetworkImageView
|
||||
private lateinit var ivMedia3 : MyNetworkImageView
|
||||
private lateinit var ivMedia4 : MyNetworkImageView
|
||||
private lateinit var btnHideMedia : View
|
||||
|
||||
private lateinit var llButtonBar : View
|
||||
private lateinit var btnConversation : ImageButton
|
||||
private lateinit var btnReply : ImageButton
|
||||
private lateinit var btnBoost : Button
|
||||
private lateinit var btnFavourite : Button
|
||||
private lateinit var llFollow2 : View
|
||||
private lateinit var btnFollow2 : ImageButton
|
||||
private lateinit var ivFollowedBy2 : ImageView
|
||||
private lateinit var btnMore : ImageButton
|
||||
|
||||
private lateinit var llSearchTag : View
|
||||
private lateinit var btnSearchTag : Button
|
||||
|
||||
private lateinit var llList : View
|
||||
private lateinit var btnListTL : Button
|
||||
private lateinit var btnListMore : ImageButton
|
||||
|
||||
private lateinit var llExtra : LinearLayout
|
||||
|
||||
private lateinit var tvApplication : TextView
|
||||
|
||||
|
||||
private val access_info : SavedAccount
|
||||
|
||||
private val llBoosted : View
|
||||
private val ivBoosted : ImageView
|
||||
private val tvBoosted : TextView
|
||||
private val tvBoostedAcct : TextView
|
||||
private val tvBoostedTime : TextView
|
||||
|
||||
private val llFollow : View
|
||||
private val ivFollow : MyNetworkImageView
|
||||
private val tvFollowerName : TextView
|
||||
private val tvFollowerAcct : TextView
|
||||
private val btnFollow : ImageButton
|
||||
private val ivFollowedBy : ImageView
|
||||
|
||||
private val llStatus : View
|
||||
private val ivThumbnail : MyNetworkImageView
|
||||
private val tvName : TextView
|
||||
private val tvTime : TextView
|
||||
private val tvAcct : TextView
|
||||
|
||||
private val llContentWarning : View
|
||||
private val tvContentWarning : MyTextView
|
||||
private val btnContentWarning : Button
|
||||
|
||||
private val llContents : View
|
||||
private val tvMentions : MyTextView
|
||||
private val tvContent : MyTextView
|
||||
|
||||
private val flMedia : View
|
||||
private val btnShowMedia : TextView
|
||||
|
||||
private val ivMedia1 : MyNetworkImageView
|
||||
private val ivMedia2 : MyNetworkImageView
|
||||
private val ivMedia3 : MyNetworkImageView
|
||||
private val ivMedia4 : MyNetworkImageView
|
||||
|
||||
private val buttons_for_status : StatusButtons?
|
||||
|
||||
private val llSearchTag : View
|
||||
private val btnSearchTag : Button
|
||||
|
||||
private val llList : View
|
||||
private val btnListTL : Button
|
||||
|
||||
private val llExtra : LinearLayout
|
||||
|
||||
private val tvApplication : TextView?
|
||||
|
||||
private var item : Any? = null
|
||||
|
||||
private var status__showing : TootStatus? = null
|
||||
@ -126,22 +135,17 @@ internal class ItemViewHolder(
|
||||
private val extra_invalidator_list = ArrayList<NetworkEmojiInvalidator>()
|
||||
|
||||
init {
|
||||
this.viewRoot = inflate(activity.UI {})
|
||||
this.access_info = column.access_info
|
||||
|
||||
this.tvName = view.findViewById(R.id.tvName)
|
||||
this.tvFollowerName = view.findViewById(R.id.tvFollowerName)
|
||||
this.tvBoosted = view.findViewById(R.id.tvBoosted)
|
||||
|
||||
if(activity.timeline_font != null || activity.timeline_font_bold != null) {
|
||||
Utils.scanView(view) { v ->
|
||||
Utils.scanView(this.viewRoot) { v ->
|
||||
try {
|
||||
if(v is Button) {
|
||||
// ボタンは太字なので触らない
|
||||
} else if(v is TextView) {
|
||||
val typeface = when(v.getId()) {
|
||||
R.id.tvName,
|
||||
R.id.tvFollowerName,
|
||||
R.id.tvBoosted -> activity.timeline_font_bold ?: activity.timeline_font
|
||||
val typeface = when {
|
||||
v === tvName || v === tvFollowerName || v === tvBoosted -> activity.timeline_font_bold ?: activity.timeline_font
|
||||
else -> activity.timeline_font ?: activity.timeline_font_bold
|
||||
}
|
||||
if(typeface != null) v.typeface = typeface
|
||||
@ -156,49 +160,27 @@ internal class ItemViewHolder(
|
||||
tvBoosted.typeface = Typeface.DEFAULT_BOLD
|
||||
}
|
||||
|
||||
this.llBoosted = view.findViewById(R.id.llBoosted)
|
||||
this.ivBoosted = view.findViewById(R.id.ivBoosted)
|
||||
this.tvBoostedTime = view.findViewById(R.id.tvBoostedTime)
|
||||
this.tvBoostedAcct = view.findViewById(R.id.tvBoostedAcct)
|
||||
|
||||
this.llFollow = view.findViewById(R.id.llFollow)
|
||||
this.ivFollow = view.findViewById(R.id.ivFollow)
|
||||
this.tvFollowerAcct = view.findViewById(R.id.tvFollowerAcct)
|
||||
this.btnFollow = view.findViewById(R.id.btnFollow)
|
||||
this.ivFollowedBy = view.findViewById(R.id.ivFollowedBy)
|
||||
|
||||
this.llStatus = view.findViewById(R.id.llStatus)
|
||||
|
||||
this.ivThumbnail = view.findViewById(R.id.ivThumbnail)
|
||||
this.tvTime = view.findViewById(R.id.tvTime)
|
||||
this.tvAcct = view.findViewById(R.id.tvAcct)
|
||||
|
||||
this.llContentWarning = view.findViewById(R.id.llContentWarning)
|
||||
this.tvContentWarning = view.findViewById(R.id.tvContentWarning)
|
||||
this.btnContentWarning = view.findViewById(R.id.btnContentWarning)
|
||||
|
||||
this.llContents = view.findViewById(R.id.llContents)
|
||||
this.tvContent = view.findViewById(R.id.tvContent)
|
||||
this.tvMentions = view.findViewById(R.id.tvMentions)
|
||||
|
||||
this.llExtra = view.findViewById(R.id.llExtra)
|
||||
|
||||
this.buttons_for_status = if(bSimpleList) null else StatusButtons(activity, column, view, false)
|
||||
|
||||
this.flMedia = view.findViewById(R.id.flMedia)
|
||||
this.btnShowMedia = view.findViewById(R.id.btnShowMedia)
|
||||
this.ivMedia1 = view.findViewById(R.id.ivMedia1)
|
||||
this.ivMedia2 = view.findViewById(R.id.ivMedia2)
|
||||
this.ivMedia3 = view.findViewById(R.id.ivMedia3)
|
||||
this.ivMedia4 = view.findViewById(R.id.ivMedia4)
|
||||
|
||||
this.llSearchTag = view.findViewById(R.id.llSearchTag)
|
||||
this.btnSearchTag = view.findViewById(R.id.btnSearchTag)
|
||||
this.tvApplication = view.findViewById(R.id.tvApplication)
|
||||
|
||||
this.llList = view.findViewById(R.id.llList)
|
||||
this.btnListTL = view.findViewById(R.id.btnListTL)
|
||||
val btnListMore = view.findViewById<View>(R.id.btnListMore)
|
||||
if(bSimpleList) {
|
||||
llButtonBar.visibility = View.GONE
|
||||
this.buttons_for_status = null
|
||||
} else {
|
||||
llButtonBar.visibility = View.VISIBLE
|
||||
this.buttons_for_status = StatusButtons(
|
||||
activity,
|
||||
column,
|
||||
false,
|
||||
|
||||
btnConversation = btnConversation,
|
||||
btnReply = btnReply,
|
||||
btnBoost = btnBoost,
|
||||
btnFavourite = btnFavourite,
|
||||
llFollow2 = llFollow2,
|
||||
btnFollow2 = btnFollow2,
|
||||
ivFollowedBy2 = ivFollowedBy2,
|
||||
btnMore = btnMore
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
btnListTL.setOnClickListener(this)
|
||||
btnListMore.setOnClickListener(this)
|
||||
@ -230,10 +212,7 @@ internal class ItemViewHolder(
|
||||
tvMentions.movementMethod = MyLinkMovementMethod
|
||||
tvContentWarning.movementMethod = MyLinkMovementMethod
|
||||
|
||||
val v : View
|
||||
//
|
||||
v = view.findViewById(R.id.btnHideMedia)
|
||||
v.setOnClickListener(this)
|
||||
btnHideMedia.setOnClickListener(this)
|
||||
|
||||
val lp = flMedia.layoutParams
|
||||
lp.height = activity.app_state.media_thumb_height
|
||||
@ -248,9 +227,7 @@ internal class ItemViewHolder(
|
||||
tvContentWarning.textSize = activity.timeline_font_size_sp
|
||||
tvContent.textSize = activity.timeline_font_size_sp
|
||||
btnShowMedia.textSize = activity.timeline_font_size_sp
|
||||
if(tvApplication != null) {
|
||||
tvApplication.textSize = activity.timeline_font_size_sp
|
||||
}
|
||||
tvApplication.textSize = activity.timeline_font_size_sp
|
||||
btnListTL.textSize = activity.timeline_font_size_sp
|
||||
}
|
||||
|
||||
@ -288,9 +265,11 @@ internal class ItemViewHolder(
|
||||
llList.visibility = View.GONE
|
||||
llExtra.removeAllViews()
|
||||
|
||||
|
||||
|
||||
if(item == null) return
|
||||
|
||||
var c: Int
|
||||
var c : Int
|
||||
|
||||
c = if(column.content_color != 0) column.content_color else content_color_default
|
||||
tvBoosted.setTextColor(c)
|
||||
@ -300,15 +279,15 @@ internal class ItemViewHolder(
|
||||
tvContentWarning.setTextColor(c)
|
||||
tvContent.setTextColor(c)
|
||||
//NSFWは文字色固定 btnShowMedia.setTextColor( c );
|
||||
tvApplication?.setTextColor(c)
|
||||
tvApplication.setTextColor(c)
|
||||
|
||||
c =if(column.acct_color != 0) column.acct_color else Styler.getAttributeColor(activity, R.attr.colorTimeSmall)
|
||||
this.acct_color = c
|
||||
tvBoostedTime.setTextColor(c)
|
||||
tvTime.setTextColor(c)
|
||||
// tvBoostedAcct.setTextColor( c );
|
||||
// tvFollowerAcct.setTextColor( c );
|
||||
// tvAcct.setTextColor( c );
|
||||
c = if(column.acct_color != 0) column.acct_color else Styler.getAttributeColor(activity, R.attr.colorTimeSmall)
|
||||
this.acct_color = c
|
||||
tvBoostedTime.setTextColor(c)
|
||||
tvTime.setTextColor(c)
|
||||
// tvBoostedAcct.setTextColor( c );
|
||||
// tvFollowerAcct.setTextColor( c );
|
||||
// tvAcct.setTextColor( c );
|
||||
|
||||
this.item = item
|
||||
when(item) {
|
||||
@ -563,18 +542,16 @@ internal class ItemViewHolder(
|
||||
|
||||
buttons_for_status?.bind(status, (item as? TootNotification))
|
||||
|
||||
if(tvApplication != null) {
|
||||
val application = status.application
|
||||
when(column.column_type) {
|
||||
|
||||
Column.TYPE_CONVERSATION -> if(application == null) {
|
||||
tvApplication.visibility = View.GONE
|
||||
} else {
|
||||
tvApplication.visibility = View.VISIBLE
|
||||
tvApplication.text = activity.getString(R.string.application_is, application.name ?: "")
|
||||
}
|
||||
else -> tvApplication.visibility = View.GONE
|
||||
val application = status.application
|
||||
when(column.column_type) {
|
||||
|
||||
Column.TYPE_CONVERSATION -> if(application == null) {
|
||||
tvApplication.visibility = View.GONE
|
||||
} else {
|
||||
tvApplication.visibility = View.VISIBLE
|
||||
tvApplication.text = activity.getString(R.string.application_is, application.name ?: "")
|
||||
}
|
||||
else -> tvApplication.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
@ -597,7 +574,7 @@ internal class ItemViewHolder(
|
||||
val start = sb.length
|
||||
sb.append(status.visibility)
|
||||
val end = sb.length
|
||||
val iconResId = Styler.getAttributeResourceId(activity,visIconAttrId )
|
||||
val iconResId = Styler.getAttributeResourceId(activity, visIconAttrId)
|
||||
sb.setSpan(EmojiImageSpan(activity, iconResId), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
|
||||
@ -700,34 +677,30 @@ internal class ItemViewHolder(
|
||||
val pos = activity.nextPosition(column)
|
||||
val item = this.item
|
||||
val notification = (item as? TootNotification)
|
||||
when(v.id) {
|
||||
when(v) {
|
||||
|
||||
R.id.btnHideMedia -> status__showing?.let { status ->
|
||||
btnHideMedia -> status__showing?.let { status ->
|
||||
MediaShown.save(status, false)
|
||||
btnShowMedia.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
R.id.btnShowMedia -> status__showing?.let { status ->
|
||||
btnShowMedia -> status__showing?.let { status ->
|
||||
MediaShown.save(status, true)
|
||||
btnShowMedia.visibility = View.GONE
|
||||
}
|
||||
|
||||
R.id.ivMedia1 -> clickMedia(0)
|
||||
R.id.ivMedia2 -> clickMedia(1)
|
||||
R.id.ivMedia3 -> clickMedia(2)
|
||||
R.id.ivMedia4 -> clickMedia(3)
|
||||
ivMedia1 -> clickMedia(0)
|
||||
ivMedia2 -> clickMedia(1)
|
||||
ivMedia3 -> clickMedia(2)
|
||||
ivMedia4 -> clickMedia(3)
|
||||
|
||||
R.id.ivCardThumbnail -> status__showing?.card?.url?.let { url ->
|
||||
if(url.isNotEmpty()) App1.openCustomTab(activity, url)
|
||||
}
|
||||
|
||||
R.id.btnContentWarning -> status__showing?.let { status ->
|
||||
btnContentWarning -> status__showing?.let { status ->
|
||||
val new_shown = llContents.visibility == View.GONE
|
||||
ContentWarning.save(status, new_shown)
|
||||
list_adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
R.id.ivThumbnail -> status_account?.let { who ->
|
||||
ivThumbnail -> status_account?.let { who ->
|
||||
if(access_info.isPseudo) {
|
||||
DlgContextMenu(activity, column, who, null, notification).show()
|
||||
} else {
|
||||
@ -735,7 +708,7 @@ internal class ItemViewHolder(
|
||||
}
|
||||
}
|
||||
|
||||
R.id.llBoosted -> boost_account?.let { who ->
|
||||
llBoosted -> boost_account?.let { who ->
|
||||
if(access_info.isPseudo) {
|
||||
DlgContextMenu(activity, column, who, null, notification).show()
|
||||
} else {
|
||||
@ -743,18 +716,18 @@ internal class ItemViewHolder(
|
||||
}
|
||||
}
|
||||
|
||||
R.id.llFollow -> follow_account?.let { who ->
|
||||
llFollow -> follow_account?.let { who ->
|
||||
if(access_info.isPseudo) {
|
||||
DlgContextMenu(activity, column, who, null, notification).show()
|
||||
} else {
|
||||
Action_User.profileLocal(activity, pos, access_info, who)
|
||||
}
|
||||
}
|
||||
R.id.btnFollow -> follow_account?.let { who ->
|
||||
btnFollow -> follow_account?.let { who ->
|
||||
DlgContextMenu(activity, column, who, null, notification).show()
|
||||
}
|
||||
|
||||
R.id.btnSearchTag -> when(item) {
|
||||
btnSearchTag -> when(item) {
|
||||
is TootGap -> column.startGap(item)
|
||||
|
||||
is TootDomainBlock -> {
|
||||
@ -772,11 +745,11 @@ internal class ItemViewHolder(
|
||||
}
|
||||
}
|
||||
|
||||
R.id.btnListTL -> if(item is TootList) {
|
||||
btnListTL -> if(item is TootList) {
|
||||
activity.addColumn(pos, access_info, Column.TYPE_LIST_TL, item.id)
|
||||
}
|
||||
|
||||
R.id.btnListMore -> if(item is TootList) {
|
||||
btnListMore -> if(item is TootList) {
|
||||
ActionsDialog()
|
||||
.addAction(activity.getString(R.string.list_timeline)) {
|
||||
activity.addColumn(pos, access_info, Column.TYPE_LIST_TL, item.id)
|
||||
@ -794,6 +767,13 @@ internal class ItemViewHolder(
|
||||
}
|
||||
.show(activity, item.title)
|
||||
}
|
||||
|
||||
else -> when(v.id) {
|
||||
R.id.ivCardThumbnail -> status__showing?.card?.url?.let { url ->
|
||||
if(url.isNotEmpty()) App1.openCustomTab(activity, url)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -801,41 +781,41 @@ internal class ItemViewHolder(
|
||||
|
||||
val notification = (item as? TootNotification)
|
||||
|
||||
when(v.id) {
|
||||
when(v) {
|
||||
|
||||
R.id.ivThumbnail -> {
|
||||
ivThumbnail -> {
|
||||
status_account?.let { who -> DlgContextMenu(activity, column, who, null, notification).show() }
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.llBoosted -> {
|
||||
llBoosted -> {
|
||||
boost_account?.let { who -> DlgContextMenu(activity, column, who, null, notification).show() }
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.llFollow -> {
|
||||
llFollow -> {
|
||||
follow_account?.let { who -> DlgContextMenu(activity, column, who, null, notification).show() }
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.btnFollow -> {
|
||||
btnFollow -> {
|
||||
follow_account?.let { who -> Action_Follow.followFromAnotherAccount(activity, activity.nextPosition(column), access_info, who) }
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.btnSearchTag -> {
|
||||
btnSearchTag -> {
|
||||
val item = this.item
|
||||
when(item) {
|
||||
// is TootGap -> column.startGap(item)
|
||||
//
|
||||
// is TootDomainBlock -> {
|
||||
// val domain = item.domain
|
||||
// AlertDialog.Builder(activity)
|
||||
// .setMessage(activity.getString(R.string.confirm_unblock_domain, domain))
|
||||
// .setNegativeButton(R.string.cancel, null)
|
||||
// .setPositiveButton(R.string.ok) { _, _ -> Action_Instance.blockDomain(activity, access_info, domain, false) }
|
||||
// .show()
|
||||
// }
|
||||
// is TootGap -> column.startGap(item)
|
||||
//
|
||||
// is TootDomainBlock -> {
|
||||
// val domain = item.domain
|
||||
// AlertDialog.Builder(activity)
|
||||
// .setMessage(activity.getString(R.string.confirm_unblock_domain, domain))
|
||||
// .setNegativeButton(R.string.cancel, null)
|
||||
// .setPositiveButton(R.string.ok) { _, _ -> Action_Instance.blockDomain(activity, access_info, domain, false) }
|
||||
// .show()
|
||||
// }
|
||||
|
||||
is String -> {
|
||||
// search_tag は#を含まない
|
||||
@ -843,10 +823,10 @@ internal class ItemViewHolder(
|
||||
val host = access_info.host
|
||||
val url = "https://$host/tags/$tagEncoded"
|
||||
Action_HashTag.timelineOtherInstance(
|
||||
activity =activity,
|
||||
pos =activity.nextPosition(column),
|
||||
url =url,
|
||||
host =host,
|
||||
activity = activity,
|
||||
pos = activity.nextPosition(column),
|
||||
url = url,
|
||||
host = host,
|
||||
tag_without_sharp = item
|
||||
)
|
||||
}
|
||||
@ -918,7 +898,7 @@ internal class ItemViewHolder(
|
||||
addLinkAndCaption(sb, activity.getString(R.string.card_header_provider), card.provider_url, card.provider_name)
|
||||
|
||||
val description = card.description
|
||||
if( description != null && description.isNotEmpty() ) {
|
||||
if(description != null && description.isNotEmpty()) {
|
||||
if(sb.isNotEmpty()) sb.append("<br>")
|
||||
sb.append(HTMLDecoder.encodeEntity(description))
|
||||
}
|
||||
@ -928,7 +908,7 @@ internal class ItemViewHolder(
|
||||
llExtra.addView(tv)
|
||||
|
||||
val image = card.image
|
||||
if( image != null && image.isNotEmpty()) {
|
||||
if(image != null && image.isNotEmpty()) {
|
||||
lp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, activity.app_state.media_thumb_height)
|
||||
lp.topMargin = (0.5f + llExtra.resources.displayMetrics.density * 3f).toInt()
|
||||
val iv = MyNetworkImageView(activity)
|
||||
@ -1027,7 +1007,7 @@ internal class ItemViewHolder(
|
||||
try {
|
||||
form.put("item_index", Integer.toString(idx))
|
||||
} catch(ex : Throwable) {
|
||||
log.e(ex,"json encode failed.")
|
||||
log.e(ex, "json encode failed.")
|
||||
ex.printStackTrace()
|
||||
}
|
||||
|
||||
@ -1056,6 +1036,414 @@ internal class ItemViewHolder(
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun inflate(ui : AnkoContext<Context>) = with(ui) {
|
||||
verticalLayout {
|
||||
// トップレベルのViewGroupのlparamsはイニシャライザ内部に置くしかないみたい
|
||||
lparams(matchParent, wrapContent)
|
||||
|
||||
topPadding = dip(3)
|
||||
bottomPadding = dip(3)
|
||||
descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS
|
||||
|
||||
llBoosted = linearLayout {
|
||||
lparams(matchParent, wrapContent) {
|
||||
bottomMargin = dip(6)
|
||||
}
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
|
||||
ivBoosted = imageView {
|
||||
scaleType = ImageView.ScaleType.FIT_END
|
||||
importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
|
||||
}.lparams(dip(48), dip(32)) {
|
||||
endMargin = dip(4)
|
||||
}
|
||||
|
||||
verticalLayout {
|
||||
lparams(dip(0), wrapContent) {
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
linearLayout {
|
||||
lparams(matchParent, wrapContent)
|
||||
|
||||
tvBoostedAcct = textView {
|
||||
ellipsize = TextUtils.TruncateAt.END
|
||||
gravity = Gravity.END
|
||||
maxLines = 1
|
||||
textColor = Styler.getAttributeColor(context, R.attr.colorTimeSmall)
|
||||
textSize = 12f // textSize の単位はSP
|
||||
// tools:text ="who@hoge"
|
||||
}.lparams(dip(0), wrapContent) {
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
tvBoostedTime = textView {
|
||||
|
||||
startPadding = dip(2)
|
||||
|
||||
gravity = Gravity.END
|
||||
textColor = Styler.getAttributeColor(context, R.attr.colorTimeSmall)
|
||||
textSize = 12f // textSize の単位はSP
|
||||
// tools:ignore="RtlSymmetry"
|
||||
// tools:text="2017-04-16 09:37:14"
|
||||
}.lparams(wrapContent, wrapContent)
|
||||
|
||||
}
|
||||
|
||||
tvBoosted = textView {
|
||||
// tools:text = "~にブーストされました"
|
||||
}.lparams(matchParent, wrapContent)
|
||||
}
|
||||
}
|
||||
|
||||
llFollow = linearLayout {
|
||||
lparams(matchParent, wrapContent)
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
|
||||
ivFollow = myNetworkImageView {
|
||||
contentDescription = context.getString(R.string.thumbnail)
|
||||
scaleType = ImageView.ScaleType.FIT_END
|
||||
}.lparams(dip(48), dip(40)) {
|
||||
endMargin = dip(4)
|
||||
}
|
||||
|
||||
verticalLayout {
|
||||
|
||||
lparams(dip(0), wrapContent) {
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
tvFollowerName = textView {
|
||||
// tools:text="Follower Name"
|
||||
}.lparams(matchParent, wrapContent)
|
||||
|
||||
tvFollowerAcct = textView {
|
||||
setPaddingStartEnd(dip(4), dip(4))
|
||||
textColor = Styler.getAttributeColor(context, R.attr.colorTimeSmall)
|
||||
textSize = 12f // SP
|
||||
// tools:text="aaaaaaaaaaaaaaaa"
|
||||
}.lparams(matchParent, wrapContent)
|
||||
}
|
||||
|
||||
frameLayout {
|
||||
lparams(dip(40), dip(40)) {
|
||||
startMargin = dip(4)
|
||||
}
|
||||
|
||||
btnFollow = imageButton {
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
contentDescription = context.getString(R.string.follow)
|
||||
scaleType = ImageView.ScaleType.CENTER
|
||||
// tools:src="?attr/ic_follow_plus"
|
||||
}.lparams(matchParent, matchParent)
|
||||
|
||||
ivFollowedBy = imageView {
|
||||
scaleType = ImageView.ScaleType.CENTER
|
||||
// tools:src="?attr/ic_followed_by"
|
||||
importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
|
||||
}.lparams(matchParent, matchParent)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
llStatus = verticalLayout {
|
||||
lparams(matchParent, wrapContent)
|
||||
|
||||
linearLayout {
|
||||
lparams(matchParent, wrapContent)
|
||||
|
||||
tvAcct = textView {
|
||||
ellipsize = TextUtils.TruncateAt.END
|
||||
gravity = Gravity.END
|
||||
maxLines = 1
|
||||
textColor = Styler.getAttributeColor(context, R.attr.colorTimeSmall)
|
||||
textSize = 12f // SP
|
||||
// tools:text="who@hoge"
|
||||
}.lparams(dip(0), wrapContent) {
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
tvTime = textView {
|
||||
gravity = Gravity.END
|
||||
startPadding = dip(2)
|
||||
textColor = Styler.getAttributeColor(context, R.attr.colorTimeSmall)
|
||||
textSize = 12f // SP
|
||||
// tools:ignore="RtlSymmetry"
|
||||
// tools:text="2017-04-16 09:37:14"
|
||||
}.lparams(wrapContent, wrapContent)
|
||||
|
||||
}
|
||||
|
||||
linearLayout {
|
||||
lparams(matchParent, wrapContent)
|
||||
|
||||
ivThumbnail = myNetworkImageView {
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
contentDescription = context.getString(R.string.thumbnail)
|
||||
scaleType = ImageView.ScaleType.CENTER_CROP
|
||||
}.lparams(dip(48), dip(48)) {
|
||||
topMargin = dip(4)
|
||||
endMargin = dip(4)
|
||||
}
|
||||
|
||||
verticalLayout {
|
||||
lparams(dip(0), wrapContent) {
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
tvName = textView {
|
||||
|
||||
// tools:text="Displayname"
|
||||
}.lparams(matchParent, wrapContent)
|
||||
|
||||
llContentWarning = linearLayout {
|
||||
lparams(matchParent, wrapContent) {
|
||||
topMargin = dip(3)
|
||||
isBaselineAligned = false
|
||||
}
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
|
||||
btnContentWarning = button {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_ddd)
|
||||
minWidthCompat = dip(40)
|
||||
padding = dip(4)
|
||||
//tools:text="見る"
|
||||
}.lparams(wrapContent, dip(40)) {
|
||||
endMargin = dip(8)
|
||||
}
|
||||
|
||||
verticalLayout {
|
||||
lparams(dip(0), wrapContent) {
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
tvMentions = myTextView {
|
||||
}.lparams(matchParent, wrapContent)
|
||||
|
||||
tvContentWarning = myTextView {
|
||||
}.lparams(matchParent, wrapContent) {
|
||||
topMargin = dip(3)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
llContents = verticalLayout {
|
||||
lparams(matchParent, wrapContent)
|
||||
|
||||
tvContent = myTextView {
|
||||
setLineSpacing(lineSpacingExtra, 1.1f)
|
||||
// tools:text="Contents\nContents"
|
||||
}.lparams(matchParent, wrapContent) {
|
||||
topMargin = dip(3)
|
||||
}
|
||||
|
||||
flMedia = frameLayout {
|
||||
lparams(matchParent, dip(64)) {
|
||||
topMargin = dip(3)
|
||||
}
|
||||
|
||||
linearLayout {
|
||||
lparams(matchParent, matchParent)
|
||||
|
||||
ivMedia1 = myNetworkImageView {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_ddd)
|
||||
contentDescription = context.getString(R.string.thumbnail)
|
||||
scaleType = ImageView.ScaleType.CENTER_CROP
|
||||
|
||||
}.lparams(0, matchParent) {
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
ivMedia2 = myNetworkImageView {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_ddd)
|
||||
contentDescription = context.getString(R.string.thumbnail)
|
||||
scaleType = ImageView.ScaleType.CENTER_CROP
|
||||
|
||||
}.lparams(0, matchParent) {
|
||||
startMargin = dip(8)
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
ivMedia3 = myNetworkImageView {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_ddd)
|
||||
contentDescription = context.getString(R.string.thumbnail)
|
||||
scaleType = ImageView.ScaleType.CENTER_CROP
|
||||
|
||||
}.lparams(0, matchParent) {
|
||||
startMargin = dip(8)
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
ivMedia4 = myNetworkImageView {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_ddd)
|
||||
contentDescription = context.getString(R.string.thumbnail)
|
||||
scaleType = ImageView.ScaleType.CENTER_CROP
|
||||
|
||||
}.lparams(0, matchParent) {
|
||||
startMargin = dip(8)
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
btnHideMedia = imageButton {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
contentDescription = "@string/hide"
|
||||
imageResource = Styler.getAttributeResourceId(context, R.attr.btn_close)
|
||||
}.lparams(dip(32), matchParent) {
|
||||
startMargin = dip(8)
|
||||
}
|
||||
}
|
||||
|
||||
btnShowMedia = textView {
|
||||
|
||||
backgroundColor = Styler.getAttributeColor(context, R.attr.colorShowMediaBackground)
|
||||
gravity = Gravity.CENTER
|
||||
text = context.getString(R.string.tap_to_show)
|
||||
textColor = Styler.getAttributeColor(context, R.attr.colorShowMediaText)
|
||||
|
||||
}.lparams(matchParent, matchParent)
|
||||
}
|
||||
|
||||
|
||||
llExtra = verticalLayout {
|
||||
lparams(matchParent, wrapContent) {
|
||||
topMargin = dip(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// button bar
|
||||
llButtonBar = linearLayout {
|
||||
lparams(wrapContent, dip(40)) {
|
||||
topMargin = dip(3)
|
||||
}
|
||||
|
||||
btnConversation = imageButton {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
contentDescription = context.getString(R.string.conversation_view)
|
||||
minimumWidth = dip(40)
|
||||
imageResource = Styler.getAttributeResourceId(context, R.attr.ic_conversation)
|
||||
}.lparams(wrapContent, matchParent)
|
||||
|
||||
btnReply = imageButton {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
contentDescription = context.getString(R.string.reply)
|
||||
minimumWidth = dip(40)
|
||||
imageResource = Styler.getAttributeResourceId(context, R.attr.btn_reply)
|
||||
|
||||
}.lparams(wrapContent, matchParent) {
|
||||
startMargin = dip(2)
|
||||
}
|
||||
|
||||
btnBoost = button {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
compoundDrawablePadding = dip(4)
|
||||
|
||||
minWidthCompat = dip(48)
|
||||
setPaddingStartEnd(dip(4), dip(4))
|
||||
}.lparams(wrapContent, matchParent) {
|
||||
startMargin = dip(2)
|
||||
}
|
||||
|
||||
btnFavourite = button {
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
compoundDrawablePadding = dip(4)
|
||||
minWidthCompat = dip(48)
|
||||
setPaddingStartEnd(dip(4), dip(4))
|
||||
|
||||
}.lparams(wrapContent, matchParent) {
|
||||
startMargin = dip(2)
|
||||
}
|
||||
|
||||
llFollow2 = frameLayout {
|
||||
lparams(dip(40), dip(40)) {
|
||||
startMargin = dip(2)
|
||||
}
|
||||
|
||||
btnFollow2 = imageButton {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
contentDescription = context.getString(R.string.follow)
|
||||
scaleType = ImageView.ScaleType.CENTER
|
||||
// tools:src="?attr/ic_follow_plus"
|
||||
minimumWidth = dip(40)
|
||||
|
||||
}.lparams(matchParent, matchParent)
|
||||
|
||||
ivFollowedBy2 = imageView {
|
||||
|
||||
scaleType = ImageView.ScaleType.CENTER
|
||||
imageResource = Styler.getAttributeResourceId(context, R.attr.ic_followed_by)
|
||||
importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
|
||||
}.lparams(matchParent, matchParent)
|
||||
}
|
||||
|
||||
btnMore = imageButton {
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
contentDescription = context.getString(R.string.more)
|
||||
imageResource = Styler.getAttributeResourceId(context, R.attr.btn_more)
|
||||
minimumWidth = dip(40)
|
||||
}.lparams(wrapContent, matchParent) {
|
||||
startMargin = dip(2)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tvApplication = textView {
|
||||
gravity = Gravity.END
|
||||
}.lparams(matchParent, wrapContent)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
llSearchTag = linearLayout {
|
||||
lparams(matchParent, wrapContent)
|
||||
|
||||
btnSearchTag = button {
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
allCaps = false
|
||||
}.lparams(matchParent, wrapContent)
|
||||
}
|
||||
|
||||
llList = linearLayout {
|
||||
lparams(matchParent, wrapContent)
|
||||
|
||||
btnListTL = button {
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
allCaps = false
|
||||
}.lparams(0, wrapContent) {
|
||||
weight = 1f
|
||||
}
|
||||
|
||||
btnListMore = imageButton {
|
||||
|
||||
background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent)
|
||||
imageResource = Styler.getAttributeResourceId(context, R.attr.btn_more)
|
||||
contentDescription = context.getString(R.string.more)
|
||||
}.lparams(dip(40), dip(40)) {
|
||||
startMargin = dip(4)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,20 +19,23 @@ import jp.juggler.subwaytooter.util.LogCategory
|
||||
internal class StatusButtons(
|
||||
private val activity : ActMain,
|
||||
private val column : Column,
|
||||
viewRoot : View,
|
||||
private val bSimpleList : Boolean
|
||||
private val bSimpleList : Boolean,
|
||||
|
||||
private val btnConversation : ImageButton,
|
||||
private val btnReply : ImageButton,
|
||||
private val btnBoost : Button,
|
||||
private val btnFavourite : Button,
|
||||
private val llFollow2 : View,
|
||||
private val btnFollow2 : ImageButton,
|
||||
private val ivFollowedBy2 : ImageView,
|
||||
private val btnMore : ImageButton
|
||||
|
||||
) : View.OnClickListener, View.OnLongClickListener {
|
||||
|
||||
companion object {
|
||||
val log = LogCategory("StatusButtons")
|
||||
}
|
||||
|
||||
private val btnBoost : Button
|
||||
private val btnFavourite : Button
|
||||
private val btnFollow2 : ImageButton
|
||||
private val ivFollowedBy2 : ImageView
|
||||
private val llFollow2 : View
|
||||
|
||||
private val access_info : SavedAccount
|
||||
private var relation : UserRelation? = null
|
||||
private var status : TootStatus? = null
|
||||
@ -43,12 +46,6 @@ internal class StatusButtons(
|
||||
init {
|
||||
this.access_info = column.access_info
|
||||
|
||||
btnBoost = viewRoot.findViewById(R.id.btnBoost)
|
||||
btnFavourite = viewRoot.findViewById(R.id.btnFavourite)
|
||||
btnFollow2 = viewRoot.findViewById(R.id.btnFollow2)
|
||||
ivFollowedBy2 = viewRoot.findViewById(R.id.ivFollowedBy2)
|
||||
llFollow2 = viewRoot.findViewById(R.id.llFollow2)
|
||||
|
||||
val listener = this
|
||||
|
||||
btnBoost.setOnClickListener(listener)
|
||||
@ -57,20 +54,12 @@ internal class StatusButtons(
|
||||
btnFavourite.setOnLongClickListener(listener)
|
||||
btnFollow2.setOnClickListener(listener)
|
||||
btnFollow2.setOnLongClickListener(listener)
|
||||
btnMore.setOnClickListener(listener)
|
||||
btnConversation.setOnClickListener(listener)
|
||||
btnConversation.setOnLongClickListener(listener)
|
||||
btnReply.setOnClickListener(listener)
|
||||
btnReply.setOnLongClickListener(listener)
|
||||
|
||||
with(viewRoot.findViewById<View>(R.id.btnMore)) {
|
||||
setOnClickListener(listener)
|
||||
}
|
||||
|
||||
with(viewRoot.findViewById<View>(R.id.btnConversation)) {
|
||||
setOnClickListener(listener)
|
||||
setOnLongClickListener(listener)
|
||||
}
|
||||
|
||||
with(viewRoot.findViewById<View>(R.id.btnReply)) {
|
||||
setOnClickListener(listener)
|
||||
setOnLongClickListener(listener)
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(status : TootStatus, notification : TootNotification?) {
|
||||
@ -81,6 +70,7 @@ internal class StatusButtons(
|
||||
val color_accent = Styler.getAttributeColor(activity, R.attr.colorImageButtonAccent)
|
||||
val fav_icon_attr = if(access_info.isNicoru(status.account)) R.attr.ic_nicoru else R.attr.btn_favourite
|
||||
|
||||
// ブーストボタン
|
||||
when {
|
||||
TootStatus.VISIBILITY_DIRECT == status.visibility -> setButton(btnBoost, false, color_accent, R.attr.ic_mail, "")
|
||||
TootStatus.VISIBILITY_PRIVATE == status.visibility -> setButton(btnBoost, false, color_accent, R.attr.ic_lock, "")
|
||||
@ -131,66 +121,70 @@ internal class StatusButtons(
|
||||
|
||||
val status = this.status ?: return
|
||||
|
||||
when(v.id) {
|
||||
when(v) {
|
||||
|
||||
R.id.btnConversation -> Action_Toot.conversation(activity, activity.nextPosition(column), access_info, status)
|
||||
btnConversation -> Action_Toot.conversation(activity, activity.nextPosition(column), access_info, status)
|
||||
|
||||
R.id.btnReply -> if( ! access_info.isPseudo) {
|
||||
btnReply -> if( ! access_info.isPseudo) {
|
||||
Action_Toot.reply(activity, access_info, status)
|
||||
} else {
|
||||
Action_Toot.replyFromAnotherAccount(activity, access_info, status)
|
||||
}
|
||||
|
||||
R.id.btnBoost -> if(access_info.isPseudo) {
|
||||
Action_Toot.boostFromAnotherAccount(activity, access_info, status)
|
||||
} else {
|
||||
|
||||
// トグル動作
|
||||
val willRoost = ! status.reblogged
|
||||
|
||||
// 簡略表示なら結果をトースト表示
|
||||
val callback = when {
|
||||
! bSimpleList -> null
|
||||
willRoost -> activity.boost_complete_callback
|
||||
else -> activity.unboost_complete_callback
|
||||
btnBoost -> {
|
||||
if(access_info.isPseudo) {
|
||||
Action_Toot.boostFromAnotherAccount(activity, access_info, status)
|
||||
} else {
|
||||
|
||||
// トグル動作
|
||||
val willRoost = ! status.reblogged
|
||||
|
||||
// 簡略表示なら結果をトースト表示
|
||||
val callback = when {
|
||||
! bSimpleList -> null
|
||||
willRoost -> activity.boost_complete_callback
|
||||
else -> activity.unboost_complete_callback
|
||||
}
|
||||
|
||||
Action_Toot.boost(
|
||||
activity,
|
||||
access_info,
|
||||
status,
|
||||
NOT_CROSS_ACCOUNT,
|
||||
willRoost,
|
||||
false,
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
Action_Toot.boost(
|
||||
activity,
|
||||
access_info,
|
||||
status,
|
||||
NOT_CROSS_ACCOUNT,
|
||||
willRoost,
|
||||
false,
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
R.id.btnFavourite -> if(access_info.isPseudo) {
|
||||
Action_Toot.favouriteFromAnotherAccount(activity, access_info, status)
|
||||
} else {
|
||||
|
||||
// トグル動作
|
||||
val willFavourite = ! status.favourited
|
||||
|
||||
// 簡略表示なら結果をトースト表示
|
||||
val callback = when {
|
||||
! bSimpleList -> null
|
||||
status.favourited -> activity.unfavourite_complete_callback
|
||||
else -> activity.favourite_complete_callback
|
||||
btnFavourite -> {
|
||||
if(access_info.isPseudo) {
|
||||
Action_Toot.favouriteFromAnotherAccount(activity, access_info, status)
|
||||
} else {
|
||||
|
||||
// トグル動作
|
||||
val willFavourite = ! status.favourited
|
||||
|
||||
// 簡略表示なら結果をトースト表示
|
||||
val callback = when {
|
||||
! bSimpleList -> null
|
||||
status.favourited -> activity.unfavourite_complete_callback
|
||||
else -> activity.favourite_complete_callback
|
||||
}
|
||||
|
||||
Action_Toot.favourite(
|
||||
activity,
|
||||
access_info,
|
||||
status,
|
||||
NOT_CROSS_ACCOUNT,
|
||||
willFavourite,
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
Action_Toot.favourite(
|
||||
activity,
|
||||
access_info,
|
||||
status,
|
||||
NOT_CROSS_ACCOUNT,
|
||||
willFavourite,
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
R.id.btnFollow2 -> {
|
||||
btnFollow2 -> {
|
||||
val account = status.account
|
||||
val relation = this.relation ?: return
|
||||
|
||||
@ -235,7 +229,7 @@ internal class StatusButtons(
|
||||
}
|
||||
}
|
||||
|
||||
R.id.btnMore -> DlgContextMenu(activity, column, status.account, status, notification).show()
|
||||
btnMore -> DlgContextMenu(activity, column, status.account, status, notification).show()
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,15 +240,22 @@ internal class StatusButtons(
|
||||
|
||||
val status = this.status ?: return true
|
||||
|
||||
when(v.id) {
|
||||
R.id.btnConversation -> Action_Toot.conversationOtherInstance(activity, activity.nextPosition(column), status)
|
||||
R.id.btnBoost -> Action_Toot.boostFromAnotherAccount(activity, access_info, status)
|
||||
R.id.btnFavourite -> Action_Toot.favouriteFromAnotherAccount(activity, access_info, status)
|
||||
R.id.btnReply -> Action_Toot.replyFromAnotherAccount(activity, access_info, status)
|
||||
when(v) {
|
||||
btnConversation -> Action_Toot.conversationOtherInstance(
|
||||
activity, activity.nextPosition(column), status)
|
||||
|
||||
btnBoost -> Action_Toot.boostFromAnotherAccount(
|
||||
activity, access_info, status)
|
||||
|
||||
btnFavourite -> Action_Toot.favouriteFromAnotherAccount(
|
||||
activity, access_info, status)
|
||||
|
||||
btnReply -> Action_Toot.replyFromAnotherAccount(
|
||||
activity, access_info, status)
|
||||
|
||||
btnFollow2 -> Action_Follow.followFromAnotherAccount(
|
||||
activity, activity.nextPosition(column), access_info, status.account)
|
||||
|
||||
R.id.btnFollow2 -> {
|
||||
Action_Follow.followFromAnotherAccount(activity, activity.nextPosition(column), access_info, status.account)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -38,7 +38,19 @@ class StatusButtonsPopup(
|
||||
init {
|
||||
@SuppressLint("InflateParams")
|
||||
this.viewRoot = activity.layoutInflater.inflate(R.layout.list_item_popup, null, false)
|
||||
this.buttons_for_status = StatusButtons(activity, column, viewRoot, bSimpleList)
|
||||
this.buttons_for_status = StatusButtons(
|
||||
activity,
|
||||
column,
|
||||
bSimpleList,
|
||||
btnConversation =viewRoot.findViewById(R.id.btnConversation),
|
||||
btnReply = viewRoot.findViewById(R.id.btnReply),
|
||||
btnBoost = viewRoot.findViewById(R.id.btnBoost),
|
||||
btnFavourite = viewRoot.findViewById(R.id.btnFavourite),
|
||||
llFollow2 = viewRoot.findViewById(R.id.llFollow2),
|
||||
btnFollow2 = viewRoot.findViewById(R.id.btnFollow2),
|
||||
ivFollowedBy2 = viewRoot.findViewById(R.id.ivFollowedBy2),
|
||||
btnMore = viewRoot.findViewById(R.id.btnMore)
|
||||
)
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
|
@ -63,7 +63,17 @@ class TootAttachment(src : JSONObject) : TootAttachmentLike {
|
||||
if( remote_url?.isNotEmpty() == true ) remote_url else url
|
||||
}
|
||||
}
|
||||
|
||||
fun getLargeUrlList(pref : SharedPreferences) : ArrayList<String> {
|
||||
val result = ArrayList<String>()
|
||||
if( pref.getBoolean(Pref.KEY_PRIOR_LOCAL_URL, false) ){
|
||||
if( url?.isNotEmpty() ==true) result.add(url)
|
||||
if( remote_url?.isNotEmpty()==true) result.add( remote_url)
|
||||
} else {
|
||||
if( remote_url?.isNotEmpty()==true) result.add( remote_url)
|
||||
if( url?.isNotEmpty() ==true) result.add(url)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// v1.3 から 添付ファイルの画像のピクセルサイズが取得できるようになった
|
||||
|
@ -0,0 +1,17 @@
|
||||
package jp.juggler.subwaytooter.util
|
||||
|
||||
import android.view.ViewManager
|
||||
import jp.juggler.subwaytooter.view.MyNetworkImageView
|
||||
import jp.juggler.subwaytooter.view.MyTextView
|
||||
import org.jetbrains.anko.custom.ankoView
|
||||
|
||||
// Anko Layout中にカスタムビューを指定する為に拡張関数を定義する
|
||||
|
||||
inline fun ViewManager.myNetworkImageView(init: MyNetworkImageView.() -> Unit): MyNetworkImageView {
|
||||
return ankoView({ MyNetworkImageView(it) }, theme = 0, init = init)
|
||||
}
|
||||
|
||||
inline fun ViewManager.myTextView(init: MyTextView.() -> Unit): MyTextView {
|
||||
return ankoView({ MyTextView(it) }, theme = 0, init = init)
|
||||
}
|
||||
|
49
app/src/main/java/jp/juggler/subwaytooter/util/AnkoHelper.kt
Normal file
@ -0,0 +1,49 @@
|
||||
package jp.juggler.subwaytooter.util
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
|
||||
// marginStart,marginEnd と leftMargin,topMargin の表記ゆれの対策
|
||||
var ViewGroup.MarginLayoutParams.startMargin : Int
|
||||
get() = marginStart
|
||||
set(start) {
|
||||
marginStart = start
|
||||
}
|
||||
|
||||
// marginStart,marginEnd と leftMargin,topMargin の表記ゆれの対策
|
||||
var ViewGroup.MarginLayoutParams.endMargin : Int
|
||||
get() = marginEnd
|
||||
set(end) {
|
||||
marginEnd = end
|
||||
}
|
||||
|
||||
// paddingStart,paddingEndにはsetterが提供されてない問題の対策
|
||||
// 表記もtopPadding,bottomPaddingと揃えてある
|
||||
var View.startPadding : Int
|
||||
get() = paddingStart
|
||||
set(start) {
|
||||
setPaddingRelative(start, paddingTop, paddingEnd, paddingBottom)
|
||||
}
|
||||
|
||||
// paddingStart,paddingEndにはsetterが提供されてない問題の対策
|
||||
// 表記もtopPadding,bottomPaddingと揃えてある
|
||||
var View.endPadding : Int
|
||||
get() = paddingEnd
|
||||
set(end) {
|
||||
setPaddingRelative(paddingStart, paddingTop, end, paddingBottom)
|
||||
}
|
||||
|
||||
// paddingStart,paddingEndにはsetterが提供されてない問題の対策
|
||||
fun View.setPaddingStartEnd(start : Int, end : Int) {
|
||||
setPaddingRelative(start, paddingTop, end, paddingBottom)
|
||||
}
|
||||
|
||||
// XMLのandroid:minWidthと同じことをしたい場合、View#setMinimumWidthとTextView#setMinWidthの両方を呼び出す必要がある
|
||||
// http://www.thekingsmuseum.info/entry/2015/12/01/233134
|
||||
var TextView.minWidthCompat : Int
|
||||
get() = minWidth
|
||||
set(value) {
|
||||
minimumWidth = value
|
||||
minWidth = value
|
||||
}
|
@ -5,10 +5,11 @@ import java.util.ArrayList
|
||||
import java.util.NoSuchElementException
|
||||
import java.util.RandomAccess
|
||||
|
||||
class BucketList<E> constructor(private val bucketCapacity : Int = 1024) : AbstractList<E>(), MutableIterable<E>, RandomAccess {
|
||||
class BucketList<E> constructor(
|
||||
val bucketCapacity : Int = 1024
|
||||
) : AbstractList<E>(), MutableIterable<E>, RandomAccess {
|
||||
|
||||
companion object {
|
||||
|
||||
private val pos_internal = object : ThreadLocal<BucketPos>() {
|
||||
override fun initialValue() : BucketPos {
|
||||
return BucketPos()
|
||||
@ -22,10 +23,11 @@ class BucketList<E> constructor(private val bucketCapacity : Int = 1024) : Abstr
|
||||
return 0 == size
|
||||
}
|
||||
|
||||
private class Bucket<E> internal constructor(capacity : Int) : ArrayList<E>(capacity) {
|
||||
internal var total_start : Int = 0
|
||||
internal var total_end : Int = 0
|
||||
}
|
||||
private class Bucket<E>(
|
||||
capacity : Int,
|
||||
var total_start : Int = 0,
|
||||
var total_end : Int = 0
|
||||
) : ArrayList<E>(capacity)
|
||||
|
||||
private val groups = ArrayList<Bucket<E>>()
|
||||
|
||||
@ -44,8 +46,11 @@ class BucketList<E> constructor(private val bucketCapacity : Int = 1024) : Abstr
|
||||
size = n
|
||||
}
|
||||
|
||||
private class BucketPos(var group_index : Int = 0, var bucket_index : Int = 0) {
|
||||
internal fun update(group_index : Int, bucket_index : Int) : BucketPos {
|
||||
internal class BucketPos(
|
||||
var group_index : Int = 0,
|
||||
var bucket_index : Int = 0
|
||||
) {
|
||||
internal fun set(group_index : Int, bucket_index : Int) : BucketPos {
|
||||
this.group_index = group_index
|
||||
this.bucket_index = bucket_index
|
||||
return this
|
||||
@ -53,15 +58,18 @@ class BucketList<E> constructor(private val bucketCapacity : Int = 1024) : Abstr
|
||||
}
|
||||
|
||||
// allocalted を指定しない場合は BucketPosを生成します
|
||||
private fun findPos(total_index : Int, allocated : BucketPos? = pos_internal.get()) : BucketPos {
|
||||
private fun findPos(
|
||||
total_index : Int,
|
||||
result : BucketPos = pos_internal.get()
|
||||
) : BucketPos {
|
||||
|
||||
if(total_index < 0 || total_index >= size) {
|
||||
throw IndexOutOfBoundsException("findPos: bad index=$total_index, size=$size")
|
||||
}
|
||||
|
||||
// binary search
|
||||
val groups_size = groups.size
|
||||
var gs = 0
|
||||
var ge = groups_size
|
||||
var ge = groups.size
|
||||
while(true) {
|
||||
val gi = (gs + ge) shr 1
|
||||
val group = groups[gi]
|
||||
@ -69,8 +77,7 @@ class BucketList<E> constructor(private val bucketCapacity : Int = 1024) : Abstr
|
||||
total_index < group.total_start -> ge = gi
|
||||
total_index >= group.total_end -> gs = gi + 1
|
||||
else -> {
|
||||
return (allocated ?: BucketPos())
|
||||
.update(gi, total_index - group.total_start)
|
||||
return result.set(gi, total_index - group.total_start)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -87,9 +94,9 @@ class BucketList<E> constructor(private val bucketCapacity : Int = 1024) : Abstr
|
||||
if(c_size == 0) return false
|
||||
|
||||
// 最後のバケツに収まるなら、最後のバケツの中に追加する
|
||||
if(groups.size > 0) {
|
||||
val bucket = groups[groups.size - 1]
|
||||
if(bucket.size + c_size <= bucketCapacity) {
|
||||
if( groups.isNotEmpty() ) {
|
||||
val bucket = groups[groups.size -1]
|
||||
if( bucket.size + c_size <= bucketCapacity) {
|
||||
bucket.addAll(elements)
|
||||
bucket.total_end += c_size
|
||||
size += c_size
|
||||
@ -111,7 +118,7 @@ class BucketList<E> constructor(private val bucketCapacity : Int = 1024) : Abstr
|
||||
|
||||
// indexが終端なら、終端に追加する
|
||||
// バケツがカラの場合もここ
|
||||
if(index == size) {
|
||||
if(index >= size) {
|
||||
return addAll(elements)
|
||||
}
|
||||
|
||||
@ -193,5 +200,4 @@ class BucketList<E> constructor(private val bucketCapacity : Int = 1024) : Abstr
|
||||
override fun iterator() : MutableIterator<E> {
|
||||
return MyIterator()
|
||||
}
|
||||
|
||||
}
|
||||
|
BIN
app/src/main/res/drawable-hdpi/ic_face.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-hdpi/ic_face_dark.png
Normal file
After Width: | Height: | Size: 1003 B |
BIN
app/src/main/res/drawable-mdpi/ic_face.png
Normal file
After Width: | Height: | Size: 712 B |
BIN
app/src/main/res/drawable-mdpi/ic_face_dark.png
Normal file
After Width: | Height: | Size: 625 B |
BIN
app/src/main/res/drawable-xhdpi/ic_face.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_face_dark.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_face.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_face_dark.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
@ -189,12 +189,29 @@
|
||||
/>
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/status"
|
||||
/>
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/status"
|
||||
android:layout_gravity="bottom"
|
||||
/>
|
||||
<ImageButton
|
||||
android:id="@+id/btnEmojiPicker"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/btn_bg_transparent"
|
||||
android:contentDescription="@string/open_picker_emoji"
|
||||
android:src="?attr/ic_face"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -375,7 +375,7 @@
|
||||
<string name="text_to_speech_initialize_failed">TextToSpeech initializing failed. status=%1$s</string>
|
||||
<string name="text_to_speech_shutdown">TextToSpeech shutdown…</string>
|
||||
<string name="show_post_button_bar_top">Show buttons bar at the top of posting screen</string>
|
||||
<string name="client_name">Client name (access token update required)</string>
|
||||
<string name="client_name">Client name (access token set required)</string>
|
||||
<string name="toot_search">Toot search</string>
|
||||
<string name="mastodon_search_portal">MSP(JP)</string>
|
||||
<string name="search_desc_mastodon_api">Account/Hashtag search using Mastodon API.</string>
|
||||
@ -519,7 +519,7 @@
|
||||
<string name="card_header_card">Card</string>
|
||||
<string name="card_header_author">Author</string>
|
||||
<string name="card_header_provider">Provider</string>
|
||||
<string name="allow_non_space_before_emoji_code">Allow non-space character before emoji shortcode (Affect to display and post. to update display, please restart app and reload column. The emojis converted at posting can\'t be restored to shortcode.)</string>
|
||||
<string name="allow_non_space_before_emoji_code">Allow non-space character before emoji shortcode (Affect to display and post. to set display, please restart app and reload column. The emojis converted at posting can\'t be restored to shortcode.)</string>
|
||||
<string name="emoji">Emoji</string>
|
||||
<string name="not_blocked">Not blocked.</string>
|
||||
<string name="not_muted">Not muted.</string>
|
||||
@ -594,7 +594,7 @@
|
||||
<string name="new_item">New item…</string>
|
||||
<string name="word_empty">Please input keyword.</string>
|
||||
<string name="already_exist">already exist.</string>
|
||||
<string name="highlight_desc">Swipe to delete. You may need reload column to check update.</string>
|
||||
<string name="highlight_desc">Swipe to delete. You may need reload column to check set.</string>
|
||||
<string name="check_sound">Check sound</string>
|
||||
<string name="keyword">Keyword</string>
|
||||
<string name="domain_block_from_pseudo">Can\'t use domain block from pseudo account.</string>
|
||||
|
@ -134,5 +134,6 @@
|
||||
<attr name="ic_left" format="reference" />
|
||||
<attr name="ic_right" format="reference" />
|
||||
<attr name="ic_volume_up" format="reference" />
|
||||
<attr name="ic_face" format="reference" />
|
||||
|
||||
</resources>
|
@ -24,7 +24,7 @@
|
||||
<string name="home">Home</string>
|
||||
<string name="local_timeline">Local timeline</string>
|
||||
<string name="federate_timeline">Federated timeline</string>
|
||||
<string name="login_required">Please update your access token from the account setting.</string>
|
||||
<string name="login_required">Please set your access token from the account setting.</string>
|
||||
<string name="cancelled">Cancelled</string>
|
||||
<string name="account_pick">Select an account</string>
|
||||
<string name="account_confirmed">Account confirmed.</string>
|
||||
@ -367,7 +367,7 @@
|
||||
<string name="text_to_speech_initialize_failed">TextToSpeech initializing failed. status=%1$s</string>
|
||||
<string name="text_to_speech_shutdown">TextToSpeech shutdown…</string>
|
||||
<string name="show_post_button_bar_top">Show buttons bar at the top of posting screen</string>
|
||||
<string name="client_name">Client name (access token update required)</string>
|
||||
<string name="client_name">Client name (access token set required)</string>
|
||||
<string name="toot_search">Toot search</string>
|
||||
<string name="toot_search_msp">Toot search(MSP)</string>
|
||||
<string name="toot_search_ts">Toot search(ts)</string>
|
||||
@ -514,7 +514,7 @@
|
||||
<string name="card_header_card">Card</string>
|
||||
<string name="card_header_author">Author</string>
|
||||
<string name="card_header_provider">Provider</string>
|
||||
<string name="allow_non_space_before_emoji_code">Allow non-space character before emoji shortcode (Affect to display and post. to update display, please restart app and reload column. The emojis converted at posting can\'t be restored to shortcode.)</string>
|
||||
<string name="allow_non_space_before_emoji_code">Allow non-space character before emoji shortcode (Affect to display and post. to set display, please restart app and reload column. The emojis converted at posting can\'t be restored to shortcode.)</string>
|
||||
<string name="emoji">Emoji</string>
|
||||
<string name="not_blocked">Not blocked.</string>
|
||||
<string name="not_muted">Not muted.</string>
|
||||
@ -583,7 +583,7 @@
|
||||
<string name="new_item">New item…</string>
|
||||
<string name="word_empty">Please input keyword.</string>
|
||||
<string name="already_exist">already exist.</string>
|
||||
<string name="highlight_desc">Swipe to delete. You may need reload column to check update.</string>
|
||||
<string name="highlight_desc">Swipe to delete. You may need reload column to check set.</string>
|
||||
<string name="check_sound">Check sound</string>
|
||||
<string name="keyword">Keyword</string>
|
||||
<string name="domain_block_from_pseudo">Can\'t use domain block from pseudo account.</string>
|
||||
|
@ -107,6 +107,7 @@
|
||||
<item name="ic_left">@drawable/ic_left</item>
|
||||
<item name="ic_right">@drawable/ic_right</item>
|
||||
<item name="ic_volume_up">@drawable/ic_volume_up</item>
|
||||
<item name="ic_face">@drawable/ic_face</item>
|
||||
|
||||
</style>
|
||||
|
||||
@ -217,7 +218,7 @@
|
||||
<item name="ic_left">@drawable/ic_left_dark</item>
|
||||
<item name="ic_right">@drawable/ic_right_dark</item>
|
||||
<item name="ic_volume_up">@drawable/ic_volume_up_dark</item>
|
||||
|
||||
<item name="ic_face">@drawable/ic_face_dark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Dark.NoActionBar" parent="AppTheme.Dark">
|
||||
|
@ -3,6 +3,7 @@
|
||||
buildscript {
|
||||
|
||||
ext.kotlin_version = '1.2.10'
|
||||
ext.anko_version='0.10.4'
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
|