投稿時に焦点を設定。通報時に投稿元タンスに転送。

This commit is contained in:
tateisu 2018-03-10 08:12:40 +09:00
parent 0c7bab2085
commit b5b6855a81
12 changed files with 685 additions and 122 deletions

View File

@ -61,6 +61,7 @@ import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.span.MyClickableSpan
import jp.juggler.subwaytooter.span.MyClickableSpanClickCallback
import jp.juggler.subwaytooter.util.*
import jp.juggler.subwaytooter.view.FocusPointView
import jp.juggler.subwaytooter.view.MyEditText
import jp.juggler.subwaytooter.view.MyNetworkImageView
import okhttp3.MediaType
@ -1035,18 +1036,64 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
.setItems(
arrayOf<CharSequence>(
getString(R.string.set_description),
getString(R.string.set_focus_point),
getString(R.string.delete)
)
) { _, i ->
when(i) {
0 -> editAttachmentDescription(pa)
1 -> deleteAttachment(pa)
1 -> openFocusPoint(pa)
2->deleteAttachment(pa)
}
}
.setNegativeButton(R.string.cancel, null)
.show()
}
private fun openFocusPoint(pa : PostAttachment) {
val attachment = pa.attachment
if( attachment != null) {
DlgFocusPoint(this, attachment)
.setCallback(object: FocusPointView.Callback{
override fun onFocusPointUpdate(x : Float, y : Float) {
val account = this@ActPost.account ?:return
TootTaskRunner(this@ActPost,TootTaskRunner.PROGRESS_NONE).run(account,object:TootTask{
override fun background(client : TootApiClient) : TootApiResult? {
try{
val json = JSONObject()
json.put("focus","%.2f,%.2f".format(x,y))
val result = client.request(
"/api/v1/media/"+ attachment.id,
Request.Builder().put(RequestBody.create(
TootApiClient.MEDIA_TYPE_JSON,json.toString()
)))
new_attachment = parseItem(::TootAttachment, result?.jsonObject)
return result
}catch(ex:Throwable){
return TootApiResult(ex.withCaption("set focus point failed."))
}
}
var new_attachment : TootAttachment? = null
override fun handleResult(result : TootApiResult?) {
result ?: return
if( new_attachment != null ){
pa.attachment = attachment
}else{
showToast(this@ActPost,true,result.error)
}
}
})
}
})
.show()
}
}
private fun deleteAttachment(pa : PostAttachment) {
AlertDialog.Builder(this)
.setTitle(R.string.confirm_delete_attachment)

View File

@ -52,15 +52,25 @@ object Action_User {
if(! bMute)
RequestBody.create(TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, "")
else if(bMuteNotification)
RequestBody.create(TootApiClient.MEDIA_TYPE_JSON, "{\"notifications\": true}")
RequestBody.create(
TootApiClient.MEDIA_TYPE_JSON,
"{\"notifications\": true}"
)
else
RequestBody.create(TootApiClient.MEDIA_TYPE_JSON, "{\"notifications\": false}")
RequestBody.create(
TootApiClient.MEDIA_TYPE_JSON,
"{\"notifications\": false}"
)
)
val result = client.request("/api/v1/accounts/" + who.id + if(bMute) "/mute" else "/unmute", request_builder)
val result = client.request(
"/api/v1/accounts/" + who.id + if(bMute) "/mute" else "/unmute",
request_builder
)
val jsonObject = result?.jsonObject
if(jsonObject != null) {
relation = saveUserRelation(access_info, parseItem(::TootRelationShip, jsonObject))
relation =
saveUserRelation(access_info, parseItem(::TootRelationShip, jsonObject))
}
return result
}
@ -90,7 +100,11 @@ object Action_User {
}
}
showToast(activity, false, if(relation.muting) R.string.mute_succeeded else R.string.unmute_succeeded)
showToast(
activity,
false,
if(relation.muting) R.string.mute_succeeded else R.string.unmute_succeeded
)
} else {
showToast(activity, false, result.error)
@ -117,14 +131,17 @@ object Action_User {
val request_builder = Request.Builder().post(
RequestBody.create(
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, "" // 空データ
))
)
)
val result = client.request(
"/api/v1/accounts/" + who.id + if(bBlock) "/block" else "/unblock", request_builder
"/api/v1/accounts/" + who.id + if(bBlock) "/block" else "/unblock",
request_builder
)
val jsonObject = result?.jsonObject
if(jsonObject != null) {
relation = saveUserRelation(access_info, parseItem(::TootRelationShip, jsonObject))
relation =
saveUserRelation(access_info, parseItem(::TootRelationShip, jsonObject))
}
return result
@ -157,7 +174,11 @@ object Action_User {
}
}
showToast(activity, false, if(relation.blocking) R.string.block_succeeded else R.string.unblock_succeeded)
showToast(
activity,
false,
if(relation.blocking) R.string.block_succeeded else R.string.unblock_succeeded
)
} else {
showToast(activity, false, result.error)
@ -174,10 +195,10 @@ object Action_User {
access_info : SavedAccount,
who : TootAccount
) {
if( access_info.isPseudo){
if(access_info.isPseudo) {
// ココを通る動線はないっぽいが、念のため
profileFromAnotherAccount(activity, pos, access_info, who)
}else{
} else {
activity.addColumn(pos, access_info, Column.TYPE_PROFILE, who.id)
}
}
@ -194,7 +215,11 @@ object Action_User {
internal var who_local : TootAccount? = null
override fun background(client : TootApiClient) : TootApiResult? {
val path = String.format(Locale.JAPAN, Column.PATH_SEARCH, who_url.encodePercent()) + "&resolve=1"
val path = String.format(
Locale.JAPAN,
Column.PATH_SEARCH,
who_url.encodePercent()
) + "&resolve=1"
val result = client.request(path)
val jsonObject = result?.jsonObject
@ -241,7 +266,10 @@ object Action_User {
activity,
bAllowPseudo = false,
bAuto = false,
message = activity.getString(R.string.account_picker_open_user_who, AcctColor.getNickname(who.acct)),
message = activity.getString(
R.string.account_picker_open_user_who,
AcctColor.getNickname(who.acct)
),
accountListArg = makeAccountListNonPseudo(activity, who_host)
) { ai ->
if(ai.host.equals(access_info.host, ignoreCase = true)) {
@ -295,7 +323,10 @@ object Action_User {
activity,
bAllowPseudo = false,
bAuto = false,
message = activity.getString(R.string.account_picker_open_user_who, AcctColor.getNickname(user + "@" + host)),
message = activity.getString(
R.string.account_picker_open_user_who,
AcctColor.getNickname(user + "@" + host)
),
accountListArg = makeAccountListNonPseudo(activity, host)
) { ai ->
profileFromUrl(
@ -310,10 +341,10 @@ object Action_User {
// 通報フォームを開く
fun reportForm(
activity : ActMain, account : SavedAccount, who : TootAccount, status : TootStatus
activity : ActMain, access_info : SavedAccount, who : TootAccount, status : TootStatus
) {
ReportForm.showReportForm(activity, who, status) { dialog, comment ->
report(activity, account, who, status, comment) { _ ->
ReportForm.showReportForm(activity, access_info, who, status) { dialog, comment, forward ->
report(activity, access_info, who, status, comment, forward) { _ ->
// 成功したらダイアログを閉じる
try {
dialog.dismiss()
@ -331,6 +362,7 @@ object Action_User {
who : TootAccount,
status : TootStatus,
comment : String,
forward : Boolean,
onReportComplete : TootApiResultCallback
) {
if(access_info.isMe(who)) {
@ -340,14 +372,18 @@ object Action_User {
TootTaskRunner(activity).run(access_info, object : TootTask {
override fun background(client : TootApiClient) : TootApiResult? {
val sb = ("account_id=" + who.id.toString()
+ "&comment=" + comment.encodePercent()
+ "&status_ids[]=" + status.id.toString())
val sb = (
"account_id=" + who.id.toString()
+ "&comment=" + comment.encodePercent()
+ "&status_ids[]=" + status.id.toString()
+ "&forward=" + if(forward) "true" else "false"
)
val request_builder = Request.Builder().post(
RequestBody.create(
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, sb
))
)
)
return client.request("/api/v1/reports", request_builder)
}
@ -390,9 +426,11 @@ object Action_User {
val request_builder = Request.Builder().post(
RequestBody.create(
TootApiClient.MEDIA_TYPE_JSON, content.toString()
))
)
)
val result = client.request("/api/v1/accounts/" + who.id + "/follow", request_builder)
val result =
client.request("/api/v1/accounts/" + who.id + "/follow", request_builder)
val jsonObject = result?.jsonObject
if(jsonObject != null) {
relation = parseItem(::TootRelationShip, jsonObject)

View File

@ -271,6 +271,71 @@ class TootApiClient(
}
}
// レスポンスがエラーかボディがカラならエラー状態を設定する
// 例外を出すかも
internal fun readBodyBytes(
result : TootApiResult,
progressPath : String? = null,
jsonErrorParser : (json : JSONObject) -> String? = DEFAULT_JSON_ERROR_PARSER
) : ByteArray? {
if(isApiCancelled) return null
val response = result.response !!
val request = response.request()
if(request != null) {
publishApiProgress(
context.getString(
R.string.reading_api,
request.method(),
progressPath ?: result.caption
)
)
}
val bodyBytes = response.body()?.bytes()
if(isApiCancelled) return null
if(! response.isSuccessful || bodyBytes?.isEmpty() != false) {
result.error = TootApiClient.formatResponse(
response,
result.caption,
if(bodyBytes?.isNotEmpty() == true) bodyBytes.decodeUTF8() else NO_INFORMATION,
jsonErrorParser
)
}
return if(result.error != null) {
null
} else {
result.bodyString = "(binary data)"
result.data = bodyBytes
bodyBytes
}
}
internal fun parseBytes(
result : TootApiResult,
progressPath : String? = null,
jsonErrorParser : (json : JSONObject) -> String? = DEFAULT_JSON_ERROR_PARSER
) : TootApiResult? {
val response = result.response !! // nullにならないはず
try {
readBodyBytes(result, progressPath, jsonErrorParser)
?: return if(isApiCancelled) null else result
} catch(ex : Throwable) {
log.trace(ex)
result.error =
formatResponse(response, result.caption, result.bodyString ?: NO_INFORMATION)
}
return result
}
internal fun parseString(
result : TootApiResult,
progressPath : String? = null,
@ -706,6 +771,17 @@ class TootApiClient(
}
fun getHttpBytes(url : String) : TootApiResult? {
val result = TootApiResult.makeWithCaption(url)
if(result.error != null) return result
if(! sendRequest(result, progressPath = url) {
Request.Builder().url(url).build()
}) return result
return parseBytes(result)
}
fun webSocket(path : String, ws_listener : WebSocketListener) : TootApiResult? {
val result = TootApiResult.makeWithCaption(instance)
if(result.error != null) return result

View File

@ -0,0 +1,140 @@
package jp.juggler.subwaytooter.dialog
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Dialog
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.view.View
import android.view.WindowManager
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.api.TootApiClient
import jp.juggler.subwaytooter.api.TootApiResult
import jp.juggler.subwaytooter.api.TootTask
import jp.juggler.subwaytooter.api.TootTaskRunner
import jp.juggler.subwaytooter.api.entity.TootAttachment
import jp.juggler.subwaytooter.util.*
import jp.juggler.subwaytooter.view.FocusPointView
@SuppressLint("InflateParams")
class DlgFocusPoint(val activity : Activity, val attachment : TootAttachment) :
View.OnClickListener {
companion object {
val log = LogCategory("DlgFocusPoint")
}
val dialog : Dialog
val focusPointView : FocusPointView
var bitmap : Bitmap? = null
init {
val viewRoot = activity.layoutInflater.inflate(R.layout.dlg_focus_point, null, false)
focusPointView = viewRoot.findViewById(R.id.ivFocus)
viewRoot.findViewById<View>(R.id.btnClose).setOnClickListener(this)
this.dialog = Dialog(activity)
dialog.setContentView(viewRoot)
dialog.setOnDismissListener {
bitmap?.recycle()
}
}
override fun onClick(v : View) {
when(v.id) {
R.id.btnClose -> dialog.dismiss()
}
}
fun setCallback(callback : FocusPointView.Callback?) : DlgFocusPoint {
focusPointView.callback = callback
return this
}
fun show() {
val url = attachment.preview_url
if(url == null) {
showToast(activity, false, "missing image url")
return
}
TootTaskRunner(activity).run(object : TootTask {
private val options = BitmapFactory.Options()
private fun decodeBitmap(data : ByteArray, pixel_max : Int) : Bitmap? {
options.inJustDecodeBounds = true
options.inScaled = false
options.outWidth = 0
options.outHeight = 0
BitmapFactory.decodeByteArray(data, 0, data.size, options)
var w = options.outWidth
var h = options.outHeight
if(w <= 0 || h <= 0) {
log.e("can't decode bounds.")
return null
}
var bits = 0
while(w > pixel_max || h > pixel_max) {
++ bits
w = w shr 1
h = h shr 1
}
options.inJustDecodeBounds = false
options.inSampleSize = 1 shl bits
return BitmapFactory.decodeByteArray(data, 0, data.size, options)
}
var bitmap : Bitmap? = null
override fun background(client : TootApiClient) : TootApiResult? {
val result = client.getHttpBytes(url)
try {
val data = result?.data as? ByteArray ?: return result
bitmap = decodeBitmap(data, 1024)
if(bitmap == null) return TootApiResult("image decode failed.")
} catch(ex : Throwable) {
return TootApiResult(ex.withCaption("preview loading failed."))
}
return result
}
override fun handleResult(result : TootApiResult?) {
val bitmap = this.bitmap
if(bitmap == null) {
showToast(activity, true, result?.error ?: "?")
try {
dialog.dismiss()
} catch(ignored : Throwable) {
}
return
}
if(activity.isFinishing) {
bitmap.recycle()
try {
dialog.dismiss()
} catch(ignored : Throwable) {
}
return
}
this@DlgFocusPoint.bitmap = bitmap
focusPointView.setAttachment(attachment, bitmap)
dialog.window?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT
)
dialog.show()
}
})
}
}

View File

@ -5,12 +5,14 @@ import android.app.Activity
import android.app.Dialog
import android.view.View
import android.view.WindowManager
import android.widget.CheckBox
import android.widget.EditText
import android.widget.TextView
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.api.entity.TootAccount
import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.showToast
object ReportForm {
@ -18,15 +20,32 @@ object ReportForm {
@SuppressLint("InflateParams")
fun showReportForm(
activity : Activity,
access_info : SavedAccount,
who : TootAccount,
status : TootStatus?,
onClickOk : (dialog : Dialog, comment : String) -> Unit
onClickOk : (dialog : Dialog, comment : String,forward:Boolean) -> Unit
) {
val view = activity.layoutInflater.inflate(R.layout.dlg_report_user, null, false)
val tvUser = view.findViewById<TextView>(R.id.tvUser)
val tvStatus = view.findViewById<TextView>(R.id.tvStatus)
val etComment = view.findViewById<EditText>(R.id.etComment)
val tvUser :TextView = view.findViewById(R.id.tvUser)
val tvStatus :TextView = view.findViewById(R.id.tvStatus)
val etComment :EditText = view.findViewById(R.id.etComment)
val cbForward : CheckBox = view.findViewById(R.id.cbForward)
val tvForwardDesc:TextView = view.findViewById(R.id.tvForwardDesc)
val canForward = access_info.host != who.host
cbForward.isChecked = false
if(!canForward){
cbForward.visibility = View.GONE
tvForwardDesc.visibility = View.GONE
}else{
cbForward.visibility = View.VISIBLE
tvForwardDesc.visibility = View.VISIBLE
cbForward.text = activity.getString(R.string.report_forward_to,who.host)
}
tvUser.text = who.acct
tvStatus.text = status?.decoded_content ?: ""
@ -40,12 +59,15 @@ object ReportForm {
return@OnClickListener
}
onClickOk(dialog, comment)
onClickOk(dialog, comment,cbForward.isChecked)
})
view.findViewById<View>(R.id.btnCancel).setOnClickListener { dialog.cancel() }
dialog.window?.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT)
dialog.window?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT
)
dialog.show()
}
}

View File

@ -0,0 +1,164 @@
package jp.juggler.subwaytooter.view
import android.content.Context
import android.graphics.*
import android.os.SystemClock
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import jp.juggler.subwaytooter.api.entity.TootAttachment
import jp.juggler.subwaytooter.util.clipRange
class FocusPointView : View {
interface Callback {
fun onFocusPointUpdate(x : Float, y : Float)
}
constructor(context : Context) : super(context) {
init(context)
}
constructor(context : Context, attrs : AttributeSet?) : super(context, attrs) {
init(context)
}
constructor(context : Context, attrs : AttributeSet?, defStyleAttr : Int) : super(
context,
attrs,
defStyleAttr
) {
init(context)
}
private val paint = Paint()
private val rect = Rect()
private val rectF = RectF()
private var strokeWidth : Float = 0f
private var circleRadius : Float = 0f
private var crossRadius : Float = 0f
private var attachment : TootAttachment? = null
private var bitmap : Bitmap? = null
var callback : Callback? = null
private var focusX : Float = 0f
private var focusY : Float = 0f
private fun init(context : Context) {
paint.isFilterBitmap = true
paint.isAntiAlias = true
val density = context.resources.displayMetrics.density
this.strokeWidth = density * 2f
this.circleRadius = density * 10f
this.crossRadius = density * 13f
}
fun setAttachment(
attachment : TootAttachment,
bitmap : Bitmap
) {
this.attachment = attachment
this.bitmap = bitmap
this.focusX = attachment.focusX
this.focusY = attachment.focusY
invalidate()
}
private var scale : Float = 0f
private var draw_w : Float = 0f
private var draw_h : Float = 0f
private var draw_x : Float = 0f
private var draw_y : Float = 0f
override fun onDraw(canvas : Canvas) {
super.onDraw(canvas)
val bitmap = this.bitmap
val attachment = this.attachment
if(bitmap == null || attachment == null || bitmap.isRecycled) return
// draw bitmap
val view_w = this.width.toFloat()
val view_h = this.height.toFloat()
if(view_w <= 0f || view_h <= 0f) return
val bitmap_w = bitmap.width.toFloat()
val bitmap_h = bitmap.height.toFloat()
if(bitmap_w <= 0f || bitmap_h <= 0f) return
val view_aspect = view_w / view_h
val bitmap_aspect = bitmap_w / bitmap_h
if(bitmap_aspect >= view_aspect) {
scale = view_w / bitmap_w
draw_w = view_w
draw_h = scale * bitmap_h
} else {
scale = view_h / bitmap_h
draw_w = scale * bitmap_w
draw_h = view_h
}
draw_x = (view_w - draw_w) * 0.5f
draw_y = (view_h - draw_h) * 0.5f
rect.left = 0
rect.top = 0
rect.right = bitmap_w.toInt()
rect.bottom = bitmap_h.toInt()
rectF.left = draw_x
rectF.top = draw_y
rectF.right = draw_x + draw_w
rectF.bottom = draw_y + draw_h
paint.style = Paint.Style.FILL
canvas.drawBitmap(bitmap, rect, rectF, paint)
// draw focus point
paint.style = Paint.Style.STROKE
paint.strokeWidth = strokeWidth
paint.color = when((SystemClock.elapsedRealtime() / 500L) % 3) {
2L -> Color.RED
1L -> Color.BLUE
else -> Color.GREEN
}
val point_x = (focusX + 1f) * 0.5f * draw_w + draw_x
val point_y = (- focusY + 1f) * 0.5f * draw_h + draw_y
canvas.drawCircle(point_x, point_y, circleRadius, paint)
canvas.drawLine(point_x, point_y - crossRadius, point_x, point_y + crossRadius, paint)
canvas.drawLine(point_x - crossRadius, point_y, point_x + crossRadius, point_y, paint)
postInvalidateDelayed(500L)
}
override fun onTouchEvent(event : MotionEvent) : Boolean {
when(event.action) {
MotionEvent.ACTION_DOWN -> {
updateFocusPoint(event)
}
MotionEvent.ACTION_MOVE -> {
updateFocusPoint(event)
}
MotionEvent.ACTION_UP -> {
updateFocusPoint(event)
callback?.onFocusPointUpdate(focusX, focusY)
}
}
return true
}
private fun updateFocusPoint(event : MotionEvent) {
focusX = clipRange(- 1f, 1f, ((event.x - draw_x) / draw_w) * 2f - 1f)
focusY = - clipRange(- 1f, 1f, ((event.y - draw_y) / draw_h) * 2f - 1f)
invalidate()
}
}

View File

@ -501,13 +501,13 @@ class MyNetworkImageView : AppCompatImageView {
// ビューのサイズが0より大きい
val view_w = width.toFloat()
val view_h = height.toFloat()
if(view_w <= 0 || view_h <= 0) return
if(view_w <= 0f || view_h <= 0f) return
// 画像のサイズが0より大きい
val drawable = this.drawable ?: return
val drawable_w = drawable.intrinsicWidth.toFloat()
val drawable_h = drawable.intrinsicHeight.toFloat()
if(drawable_w <= 0 || drawable_h <= 0) return
if(drawable_w <= 0f || drawable_h <= 0f) return
when(scaleType) {
ImageView.ScaleType.CENTER_CROP, ImageView.ScaleType.MATRIX -> {

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<jp.juggler.subwaytooter.view.FocusPointView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginBottom="12dp"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:orientation="vertical"
android:id="@+id/ivFocus"
/>
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:id="@+id/btnClose"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/close"
/>
</LinearLayout>
</LinearLayout>

View File

@ -1,102 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_height="match_parent"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:text="@string/user"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:textSize="20sp"
android:id="@+id/tvUser"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:text="@string/status"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:id="@+id/tvStatus"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:text="@string/report_reason"
android:labelFor="@+id/etComment"
/>
<EditText
android:id="@+id/etComment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:inputType="text"
/>
<LinearLayout
style="?android:attr/buttonBarStyle"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:orientation="vertical"
>
<Button
android:id="@+id/btnCancel"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/cancel"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:text="@string/user"
/>
<Button
android:id="@+id/btnOk"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
<TextView
android:id="@+id/tvUser"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/ok"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:textSize="20sp"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:text="@string/status"
/>
<TextView
android:id="@+id/tvStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:labelFor="@+id/etComment"
android:text="@string/report_reason"
/>
<EditText
android:id="@+id/etComment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:inputType="text"
/>
<TextView
android:id="@+id/tvForwardDesc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:text="@string/report_forward_desc"
/>
<CheckBox
android:id="@+id/cbForward"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
/>
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:id="@+id/btnCancel"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/cancel"
/>
<Button
android:id="@+id/btnOk"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/ok"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@ -524,7 +524,7 @@
<string name="not_blocked">Not blocked.</string>
<string name="not_muted">Not muted.</string>
<string name="media_description">(attachment %1$d) %2$s</string>
<string name="set_description">set description(Mastodon 2.0.0 or later)</string>
<string name="set_description">set description(Mastodon 2.0 or later)</string>
<string name="attachment_description_cant_edit_while_uploading">Attachment description can\'t be edit while uploading.</string>
<string name="attachment_description">attachment description</string>
<string name="description_empty">description is not specified.</string>
@ -614,8 +614,11 @@
<string name="notification_type_boost">boost</string>
<string name="notification_type_favourite">fav.</string>
<string name="dont_show_normal_toot">Don\'t show normal toot</string>
<string name="set_focus_point">set focus point (Mastodon 2.3 or later)</string>
<string name="report_forward_desc">The account is from another instance. Send an anonymized copy of the report there as well?</string>
<string name="report_forward_to">Forward to %1$s</string>
<!--<string name="abc_action_bar_home_description">Revenir à l\'accueil</string>-->
<!--<string name="abc_action_bar_home_description">Revenir à l\'accueil</string>-->
<!--<string name="abc_action_bar_home_description_format">%1$s, %2$s</string>-->
<!--<string name="abc_action_bar_home_subtitle_description_format">%1$s, %2$s, %3$s</string>-->
<!--<string name="abc_action_bar_up_description">Revenir en haut de la page</string>-->

View File

@ -807,7 +807,7 @@
<string name="not_blocked">ブロックできません</string>
<string name="not_muted">ミュートできません</string>
<string name="media_description">(添付 %1$d) %2$s</string>
<string name="set_description">説明文を設定(マストドン2.0.0以降)</string>
<string name="set_description">説明文を設定(マストドン2.0以降)</string>
<string name="attachment_description_cant_edit_while_uploading">添付メディアのアップロード中は説明文を設定できません</string>
<string name="attachment_description">添付メディアの説明文</string>
<string name="description_empty">説明文が指定されてません</string>
@ -897,5 +897,8 @@
<string name="notification_type_boost">ブースト</string>
<string name="notification_type_favourite">お気に入り</string>
<string name="dont_show_normal_toot">通常トゥートを表示しない</string>
<string name="set_focus_point">焦点を設定 (マストドン2.3以降)</string>
<string name="report_forward_desc">対象ユーザは別のインスタンスに所属しています。通報内容を投稿元タンスに匿名で転送しますか?</string>
<string name="report_forward_to">%1$s に転送する</string>
</resources>

View File

@ -519,7 +519,7 @@
<string name="not_blocked">Not blocked.</string>
<string name="not_muted">Not muted.</string>
<string name="media_description">(attachment %1$d) %2$s</string>
<string name="set_description">set description(Mastodon 2.0.0 or later)</string>
<string name="set_description">set description(Mastodon 2.0 or later)</string>
<string name="attachment_description_cant_edit_while_uploading">Attachment description can\'t be edit while uploading.</string>
<string name="attachment_description">attachment description</string>
<string name="description_empty">description is not specified.</string>
@ -603,4 +603,7 @@
<string name="notification_type_boost">boost</string>
<string name="notification_type_favourite">fav.</string>
<string name="dont_show_normal_toot">Don\'t show normal toot</string>
<string name="set_focus_point">set focus point (Mastodon 2.3 or later)</string>
<string name="report_forward_desc">The account is from another instance. Send an anonymized copy of the report there as well?</string>
<string name="report_forward_to">Forward to %1$s</string>
</resources>