投稿画面に言語選択を追加。言語選択の候補に「Web設定を使う」を追加。

This commit is contained in:
tateisu 2022-05-31 23:39:22 +09:00
parent f57ac32c78
commit d800557796
15 changed files with 172 additions and 87 deletions

2
.gitignore vendored
View File

@ -128,3 +128,5 @@ _Emoji/*.log
_Emoji/*.txt
detektReport/
.idea/deploymentTargetDropDown.xml

View File

@ -37,10 +37,7 @@ import jp.juggler.subwaytooter.pref.PrefB
import jp.juggler.subwaytooter.pref.PrefS
import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.subwaytooter.util.EmojiDecoder
import jp.juggler.subwaytooter.util.NetworkEmojiInvalidator
import jp.juggler.subwaytooter.util.openBrowser
import jp.juggler.subwaytooter.util.*
import jp.juggler.util.*
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
@ -152,20 +149,7 @@ class ActAccountSetting : AppCompatActivity(), View.OnClickListener,
internal var visibility = TootVisibility.Public
private val languages by lazy {
ArrayList<Pair<String, String>>().apply {
add(Pair("", getString(R.string.device_language)))
val nameMap = HashMap<String, String>()
addAll(
Locale.getAvailableLocales().mapNotNull { locale ->
locale.language.takeIf { it.length == 2 || it.contains('-') }
?.also { code -> nameMap[code] = "$code ${locale.displayLanguage}" }
}
.toSet()
.toList()
.sorted()
.map { Pair(it, nameMap[it]!!) }
)
}
loadLanguageList()
}
///////////////////////////////////////////////////////////////////
@ -610,8 +594,8 @@ class ActAccountSetting : AppCompatActivity(), View.OnClickListener,
account.movieTranscodeBitrate = etMovieBitrate.text.toString()
account.movieTranscodeFramerate = etMovieFrameRate.text.toString()
account.movieTranscodeSquarePixels = etMovieSquarePixels.text.toString()
account.lang =
languages.elementAtOrNull(spLanguageCode.selectedItemPosition)?.first ?: ""
account.lang = languages.elementAtOrNull(spLanguageCode.selectedItemPosition)?.first
?: SavedAccount.LANG_WEB
}
account.saveSetting()

View File

@ -110,6 +110,10 @@ class ActPost : AppCompatActivity(),
var density: Float = 0f
val languages by lazy{
loadLanguageList()
}
private lateinit var progressChannel: Channel<Unit>
///////////////////////////////////////////////////
@ -434,5 +438,13 @@ class ActPost : AppCompatActivity(),
views.etContent.contentMineTypeArray = AttachmentUploader.acceptableMimeTypes.toTypedArray()
views.etContent.contentCallback = { addAttachment(it) }
views.spLanguage.adapter =ArrayAdapter(
this,
android.R.layout.simple_spinner_item,
languages.map { it.second }.toTypedArray()
).apply {
setDropDownViewResource(R.layout.lv_spinner_dropdown)
}
}
}

View File

@ -131,6 +131,7 @@ fun ActMain.performQuickPost(account: SavedAccount?) {
editStatusId = null,
emojiMapCustom = App1.custom_emoji_lister.getMapNonBlocking(account),
useQuoteToot = false,
lang = account.lang,
).runSuspend()
if (postResult is PostResult.Normal) {

View File

@ -9,12 +9,14 @@ import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.*
import org.jetbrains.anko.textColor
import kotlin.math.max
private val log = LogCategory("ActPostAccount")
fun ActPost.selectAccount(a: SavedAccount?) {
this.account = a
completionHelper.setInstance(a)
if (a == null) {
@ -28,6 +30,8 @@ fun ActPost.selectAccount(a: SavedAccount?) {
App1.custom_emoji_lister.getList(a)
}
views.spLanguage.setSelection(max(0,languages.indexOfFirst { it.first == a.lang}))
val ac = AcctColor.load(a)
views.btnAccount.text = ac.nickname

View File

@ -4,14 +4,22 @@ import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import jp.juggler.subwaytooter.*
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.ActPost
import jp.juggler.subwaytooter.App1
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.actmain.onCompleteActPost
import jp.juggler.subwaytooter.api.entity.*
import jp.juggler.subwaytooter.api.entity.TootPollsType
import jp.juggler.subwaytooter.api.entity.TootVisibility
import jp.juggler.subwaytooter.api.entity.unknownHostAndDomain
import jp.juggler.subwaytooter.dialog.ActionsDialog
import jp.juggler.subwaytooter.pref.PrefB
import jp.juggler.subwaytooter.table.PostDraft
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.*
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.subwaytooter.util.PostAttachment
import jp.juggler.subwaytooter.util.PostImpl
import jp.juggler.subwaytooter.util.PostResult
import jp.juggler.util.*
private val log = LogCategory("ActPostExtra")
@ -316,7 +324,7 @@ fun ActPost.performPost() {
}
}
val postResult = PostImpl(
val postResult = PostImpl(
activity = activity,
account = account,
content = views.etContent.text.toString().trim { it <= ' ' },
@ -339,9 +347,11 @@ fun ActPost.performPost() {
editStatusId = states.editStatusId,
emojiMapCustom = App1.custom_emoji_lister.getMapNonBlocking(account),
useQuoteToot = views.cbQuote.isChecked,
lang = languages.elementAtOrNull(views.spLanguage.selectedItemPosition)?.first
?: SavedAccount.LANG_WEB
).runSuspend()
when(postResult){
is PostResult.Normal ->{
when (postResult) {
is PostResult.Normal -> {
val data = Intent()
data.putExtra(ActPost.EXTRA_POSTED_ACCT, postResult.targetAccount.acct.ascii)
postResult.status.id.putTo(data, ActPost.EXTRA_POSTED_STATUS_ID)
@ -363,10 +373,10 @@ fun ActPost.performPost() {
this@performPost.finish()
}
}
is PostResult.Scheduled ->{
is PostResult.Scheduled -> {
showToast(false, getString(R.string.scheduled_status_sent))
val data = Intent()
data.putExtra(ActPost.EXTRA_POSTED_ACCT,postResult. targetAccount.acct.ascii)
data.putExtra(ActPost.EXTRA_POSTED_ACCT, postResult.targetAccount.acct.ascii)
if (isMultiWindowPost) {
resetText()

View File

@ -15,7 +15,6 @@ import jp.juggler.subwaytooter.notification.PollingWorker
import jp.juggler.subwaytooter.util.LinkHelper
import jp.juggler.util.*
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.max
class SavedAccount(
@ -88,33 +87,25 @@ class SavedAccount(
private val extraJson = JsonObject()
var movieTranscodeMode: Int by JsonProperty(
extraJson,
"movieTranscodeMode",
0)
private val jsonDelegates = JsonDelegates(extraJson)
var movieTranscodeBitrate: String by JsonProperty(
extraJson,
"movieTranscodeBitrate",
"2000000")
var movieTranscodeFramerate: String by JsonProperty(
extraJson,
"movieTranscodeFramerate",
"30")
var movieTranscodeSquarePixels: String by JsonProperty(
extraJson,
"movieTranscodeSquarePixels",
"2304000")
@JsonPropInt("movieTranscodeMode", 0)
var movieTranscodeMode by jsonDelegates.int
var lang: String by JsonProperty(
extraJson,
"lang",
"")
@JsonPropString("movieTranscodeBitrate", "2000000")
var movieTranscodeBitrate by jsonDelegates.string
var notification_status_reference: Boolean by JsonProperty(
extraJson,
"notification_status_reference",
true)
@JsonPropString("movieTranscodeFramerate", "30")
var movieTranscodeFramerate by jsonDelegates.string
@JsonPropString("movieTranscodeSquarePixels", "2304000")
var movieTranscodeSquarePixels by jsonDelegates.string
@JsonPropString("lang2", LANG_WEB)
var lang by jsonDelegates.string
@JsonPropBoolean("notification_status_reference", true)
var notification_status_reference by jsonDelegates.boolean
init {
val tmpAcct = Acct.parse(acctArg)
@ -601,6 +592,9 @@ class SavedAccount(
}
}
const val LANG_WEB = "(web)"
const val LANG_DEVICE = "(device)"
private const val REGISTER_KEY_UNREGISTERED = "unregistered"
fun clearRegistrationCache() {

View File

@ -55,6 +55,7 @@ class PostImpl(
val editStatusId: EntityId?,
val emojiMapCustom: HashMap<String, CustomEmoji>?,
var useQuoteToot: Boolean,
var lang : String,
) {
companion object {
private val log = LogCategory("PostImpl")
@ -283,7 +284,16 @@ class PostImpl(
private fun encodeParamsMastodon(json: JsonObject, instance: TootInstance) {
json["language"] = account.lang.notBlank() ?: Locale.getDefault().language
when(val lang = lang.trim()){
// Web設定に従うなら指定しない
SavedAccount.LANG_WEB,"" -> Unit
// 端末の言語コード
SavedAccount.LANG_DEVICE->
json["language"] = Locale.getDefault().language
// その他
else->
json["language"] = lang
}
visibilityChecked?.let { json["visibility"] = it.strMastodon }

View File

@ -0,0 +1,24 @@
package jp.juggler.subwaytooter.util
import android.content.Context
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.table.SavedAccount
import java.util.*
// 言語コードと表示文字列のペアのリストを返す
fun Context.loadLanguageList() =
ArrayList<Pair<String, String>>().apply {
add(Pair(SavedAccount.LANG_WEB, getString(R.string.use_web_settings)))
add(Pair(SavedAccount.LANG_DEVICE, getString(R.string.device_language)))
val nameMap = HashMap<String, String>()
addAll(
Locale.getAvailableLocales().mapNotNull { locale ->
locale.language.takeIf { it.length == 2 || it.contains('-') }
?.also { code -> nameMap[code] = "$code ${locale.displayLanguage}" }
}
.toSet()
.toList()
.sorted()
.map { Pair(it, nameMap[it]!!) }
)
}

View File

@ -12,6 +12,7 @@ class JsonException : RuntimeException {
private const val CHAR0 = '\u0000'
@Suppress("RegExpUnnecessaryNonCapturingGroup")
private val reDecimal = """(?:\A-0\z)|[.eE]""".toRegex()
// Tests if the value should be tried as a decimal.

View File

@ -0,0 +1,50 @@
package jp.juggler.util
import kotlin.reflect.KProperty
import kotlin.reflect.full.findAnnotation
private interface JsonAnnotationBase :Annotation
annotation class JsonPropInt(val key:String,val defVal:Int)
annotation class JsonPropString(val key:String,val defVal:String)
annotation class JsonPropBoolean(val key:String,val defVal:Boolean)
class JsonDelegate<T>(val parent: JsonDelegates)
class JsonDelegates(val src: JsonObject){
val int = JsonDelegate<Int>(this)
val string = JsonDelegate<String>(this)
val boolean = JsonDelegate<Boolean>(this)
}
private fun getMetaString(property: KProperty<*>) =
property.findAnnotation<JsonPropString>()
?: error("${property.name}, required=String, defined=(missing)")
operator fun JsonDelegate<String>.getValue(thisRef: Any?, property: KProperty<*>): String =
getMetaString(property).let { parent.src.string(it.key) ?: it.defVal }
operator fun JsonDelegate<String>.setValue(thisRef: Any?, property: KProperty<*>, value: String) {
getMetaString(property).let { parent.src[it.key] = value }
}
private fun getMetaInt(property: KProperty<*>) =
property.findAnnotation<JsonPropInt>()
?: error("${property.name}, required=Int, defined=(missing)")
operator fun JsonDelegate<Int>.getValue(thisRef: Any?, property: KProperty<*>): Int =
getMetaInt(property).let { parent.src.int(it.key) ?: it.defVal }
operator fun JsonDelegate<Int>.setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
getMetaInt(property).let { parent.src[it.key] = value }
}
private fun getMetaBoolean(property: KProperty<*>) =
property.findAnnotation<JsonPropBoolean>()
?: error("${property.name}, required=Boolean, defined=(missing)")
operator fun JsonDelegate<Boolean>.getValue(thisRef: Any?, property: KProperty<*>): Boolean =
getMetaBoolean(property).let { parent.src.boolean(it.key) ?: it.defVal }
operator fun JsonDelegate<Boolean>.setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
getMetaBoolean(property).let { parent.src[it.key] = value }
}

View File

@ -1,32 +0,0 @@
package jp.juggler.util
import kotlin.reflect.KProperty
class JsonProperty<ValueType>(
val src: JsonObject,
val key: String,
val defVal: ValueType,
)
operator fun JsonProperty<String>.getValue(thisRef: Any?, property: KProperty<*>): String {
return src.string(key) ?: defVal
}
operator fun JsonProperty<String>.setValue(thisRef: Any?, property: KProperty<*>, value: String) {
src[key] = value
}
operator fun JsonProperty<Int>.getValue(thisRef: Any?, property: KProperty<*>): Int {
return src.int(key) ?: defVal
}
operator fun JsonProperty<Int>.setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
src[key] = value
}
operator fun JsonProperty<Boolean>.getValue(thisRef: Any?, property: KProperty<*>): Boolean {
return src.boolean(key) ?: defVal
}
operator fun JsonProperty<Boolean>.setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
src[key] = value
}

View File

@ -209,7 +209,7 @@
android:layout_gravity="bottom"
android:layout_marginTop="8dp"
android:layout_weight="1"
android:text="@string/status" />
android:text="@string/content" />
<ImageButton
android:id="@+id/btnFeaturedTag"
@ -254,6 +254,27 @@
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:baselineAligned="false"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:text="@string/language" />
<Spinner
android:id="@+id/spLanguage"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@ -1147,4 +1147,6 @@
<string name="emoji_picker_custom_of">カスタム: %1$s</string>
<string name="others" >その他</string>
<string name="post_error_attachments_duplicated">Misskeyは添付データの重複を許可していません。</string>
<string name="use_web_settings">Web設定を使う</string>
<string name="content">本文</string>
</resources>

View File

@ -1156,4 +1156,6 @@
<string name="emoji_picker_custom_of">Custom: %1$s</string>
<string name="others">Others</string>
<string name="post_error_attachments_duplicated">Misskey does not allow duplicate in attachments.</string>
<string name="use_web_settings">(Use web setting)</string>
<string name="content">Content</string>
</resources>