baseモジュールにコードを少し移動した

This commit is contained in:
tateisu 2023-01-13 21:22:25 +09:00
parent d53ec384db
commit d391a1ab8f
304 changed files with 2411 additions and 1631 deletions

View File

@ -5,6 +5,7 @@
<module name="apng" target="1.7" />
<module name="SubwayTooter.apng_android" target="11" />
<module name="SubwayTooter.app" target="11" />
<module name="SubwayTooter.base" target="11" />
<module name="SubwayTooter.colorpicker" target="11" />
<module name="SubwayTooter.emoji" target="11" />
<module name="SubwayTooter.icon_material_symbols" target="11" />

View File

@ -14,6 +14,7 @@
<option value="$PROJECT_DIR$/apng" />
<option value="$PROJECT_DIR$/apng_android" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/base" />
<option value="$PROJECT_DIR$/colorpicker" />
<option value="$PROJECT_DIR$/emoji" />
<option value="$PROJECT_DIR$/icon_material_symbols" />

View File

@ -14,6 +14,10 @@
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/SubwayTooter.app.androidTest.iml" filepath="$PROJECT_DIR$/.idea/modules/app/SubwayTooter.app.androidTest.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/SubwayTooter.app.main.iml" filepath="$PROJECT_DIR$/.idea/modules/app/SubwayTooter.app.main.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/SubwayTooter.app.unitTest.iml" filepath="$PROJECT_DIR$/.idea/modules/app/SubwayTooter.app.unitTest.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/base/SubwayTooter.base.iml" filepath="$PROJECT_DIR$/.idea/modules/base/SubwayTooter.base.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/base/SubwayTooter.base.androidTest.iml" filepath="$PROJECT_DIR$/.idea/modules/base/SubwayTooter.base.androidTest.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/base/SubwayTooter.base.main.iml" filepath="$PROJECT_DIR$/.idea/modules/base/SubwayTooter.base.main.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/base/SubwayTooter.base.unitTest.iml" filepath="$PROJECT_DIR$/.idea/modules/base/SubwayTooter.base.unitTest.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/colorpicker/SubwayTooter.colorpicker.iml" filepath="$PROJECT_DIR$/.idea/modules/colorpicker/SubwayTooter.colorpicker.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/colorpicker/SubwayTooter.colorpicker.androidTest.iml" filepath="$PROJECT_DIR$/.idea/modules/colorpicker/SubwayTooter.colorpicker.androidTest.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/colorpicker/SubwayTooter.colorpicker.main.iml" filepath="$PROJECT_DIR$/.idea/modules/colorpicker/SubwayTooter.colorpicker.main.iml" />

View File

@ -126,12 +126,15 @@ kapt {
}
dependencies {
implementation(project(":base"))
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation fileTree(include: ['*.aar'], dir: 'src/main/libs')
// desugar_jdk_libs 2.0.0 AGP 7.4.0-alpha10
//noinspection GradleDependency
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.0'
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:$desugar_lib_bersion"
// targetSdkVersion 31 androidTest android:exported
// https://github.com/android/android-test/issues/1022
@ -144,7 +147,6 @@ dependencies {
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$detekt_version")
detektPlugins("io.gitlab.arturbosch.detekt:detekt-cli:$detekt_version")
// implementation project(':exif')
implementation project(':colorpicker')
implementation project(':emoji')
implementation project(':apng_android')
@ -165,8 +167,6 @@ dependencies {
// NavigationView
implementation "com.google.android.material:material:1.7.0"
implementation "androidx.exifinterface:exifinterface:1.3.5"
// CustomTabs
implementation "androidx.browser:browser:1.4.0"
@ -188,7 +188,7 @@ dependencies {
testImplementation "junit:junit:$junit_version" // kotlin-testとjunitを併用
def okhttpVersion = "4.10.0"
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
implementation "com.squareup.okhttp3:okhttp-urlconnection:$okhttpVersion"
@ -218,9 +218,6 @@ dependencies {
implementation "org.conscrypt:conscrypt-android:2.5.2"
implementation 'io.github.inflationx:calligraphy3:3.1.1'
implementation 'io.github.inflationx:viewpump:2.0.3'
implementation 'com.github.woxthebox:draglistview:1.6.6'
implementation 'com.github.omadahealth:swipy:1.2.3@aar'
@ -269,7 +266,7 @@ dependencies {
implementation 'androidx.work:work-runtime-ktx:2.8.0-rc01'
def roomVersion = "2.4.3"
def roomVersion = "2.5.0"
implementation "androidx.room:room-runtime:$roomVersion"
implementation "androidx.room:room-ktx:$roomVersion"
kapt "androidx.room:room-compiler:$roomVersion"
@ -278,7 +275,8 @@ dependencies {
implementation "androidx.work:work-runtime:$workVersion"
implementation "androidx.work:work-runtime-ktx:$workVersion"
implementation "androidx.startup:startup-runtime:1.1.1"
implementation "androidx.startup:startup-runtime:$startup_version"
// Koin main features for Android
implementation "io.insert-koin:koin-android:$koin_version"
@ -287,9 +285,6 @@ dependencies {
// implementation "io.insert-koin:koin-androidx-navigation:$koin_version"
// implementation "io.insert-koin:koin-androidx-compose:$koin_version"
// video transcoder https://github.com/natario1/Transcoder
implementation "com.otaliastudios:transcoder:0.10.4"
// LiveEvent
implementation "com.github.hadilq:live-event:1.3.0"
}

View File

@ -8,9 +8,9 @@ import jp.juggler.subwaytooter.api.entity.Host
import jp.juggler.subwaytooter.api.entity.TootInstance
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.SimpleHttpClientImpl
import jp.juggler.util.LogCategory
import jp.juggler.util.MySslSocketFactory
import kotlinx.coroutines.Dispatchers
import jp.juggler.util.coroutine.AppDispatchers
import jp.juggler.util.log.LogCategory
import jp.juggler.util.network.MySslSocketFactory
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import okhttp3.ConnectionSpec
@ -78,7 +78,7 @@ class TestTootInstance {
@Test
fun testWithoutAccount() {
runBlocking {
withContext(Dispatchers.IO) {
withContext(AppDispatchers.io) {
suspend fun a(host: Host) {
val (ti, ri) = TootInstance.getEx(client, hostArg = host)
assertNotNull(ti)
@ -94,7 +94,7 @@ class TestTootInstance {
@Test
fun testWithAccount() {
runBlocking {
withContext(Dispatchers.IO) {
withContext(AppDispatchers.io) {
suspend fun a(account: SavedAccount) {
val (ti, ri) = TootInstance.getEx(client, account = account)
assertNull(ri?.error)

View File

@ -2,7 +2,7 @@ package jp.juggler.subwaytooter
import androidx.test.runner.AndroidJUnit4
import jp.juggler.util.CharacterGroup
import jp.juggler.util.WordTrieTree
import jp.juggler.util.data.WordTrieTree
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Test

View File

@ -13,8 +13,8 @@ import com.bumptech.glide.gifdecoder.GifDecoder.TOTAL_ITERATION_COUNT_FOREVER
import com.bumptech.glide.load.Transformation
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
import com.bumptech.glide.util.Preconditions
import jp.juggler.util.LogCategory
import jp.juggler.util.errorEx
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.errorEx
import java.lang.reflect.Field
import java.nio.ByteBuffer

View File

@ -10,8 +10,8 @@ import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatButton
import jp.juggler.subwaytooter.util.openBrowser
import jp.juggler.util.LogCategory
import jp.juggler.util.getPackageInfoCompat
import jp.juggler.util.log.LogCategory
class ActAbout : AppCompatActivity() {
@ -76,7 +76,7 @@ class ActAbout : AppCompatActivity() {
setContentView(R.layout.act_about)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding(findViewById(R.id.svContent))
fixHorizontalPadding(findViewById(R.id.svContent))
try {
packageManager.getPackageInfoCompat(packageName)?.let { pInfo ->

View File

@ -15,7 +15,6 @@ import android.view.View
import android.widget.*
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import jp.juggler.subwaytooter.Styler.defaultColorIcon
import jp.juggler.subwaytooter.action.accountRemove
import jp.juggler.subwaytooter.api.TootApiClient
import jp.juggler.subwaytooter.api.TootApiResult
@ -31,6 +30,18 @@ import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.*
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.coroutine.launchProgress
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.media.ResizeConfig
import jp.juggler.util.media.ResizeType
import jp.juggler.util.media.createResizedBitmap
import jp.juggler.util.network.toPatch
import jp.juggler.util.network.toPost
import jp.juggler.util.network.toPostRequestBuilder
import jp.juggler.util.ui.*
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import okhttp3.MediaType
@ -241,7 +252,7 @@ class ActAccountSetting : AppCompatActivity(),
setContentView(viewBinding.root)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding(viewBinding.root)
fixHorizontalPadding(viewBinding.root)
setSwitchColor(viewBinding.root)
viewBinding.apply {
@ -623,7 +634,7 @@ class ActAccountSetting : AppCompatActivity(),
private fun showVisibility() {
viewBinding.btnVisibility.text =
Styler.getVisibilityString(this, account.isMisskey, visibility)
getVisibilityString(this, account.isMisskey, visibility)
}
private fun performVisibility() {
@ -651,7 +662,7 @@ class ActAccountSetting : AppCompatActivity(),
}
val captionList = list.map {
Styler.getVisibilityCaption(this, account.isMisskey, it)
getVisibilityCaption(this, account.isMisskey, it)
}.toTypedArray()
AlertDialog.Builder(this)
@ -854,7 +865,7 @@ class ActAccountSetting : AppCompatActivity(),
profileBusy = true
try {
viewBinding.ivProfileAvatar.setImageUrl(
Styler.calcIconRound(viewBinding.ivProfileAvatar.layoutParams),
calcIconRound(viewBinding.ivProfileAvatar.layoutParams),
src.avatar_static,
src.avatar
)

View File

@ -47,6 +47,11 @@ import jp.juggler.subwaytooter.util.CustomShareTarget
import jp.juggler.subwaytooter.util.cn
import jp.juggler.subwaytooter.view.MyTextView
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchProgress
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.*
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
@ -132,6 +137,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
private var colorTarget: AppSettingItem? = null
override fun onCreate(savedInstanceState: Bundle?) {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
super.onCreate(savedInstanceState)
backPressed {
when {
@ -146,7 +152,6 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
arTimelineFont.register(this)
arTimelineFontBold.register(this)
requestWindowFeature(Window.FEATURE_NO_TITLE)
App1.setActivityTheme(this, noActionBar = true)
this.handler = App1.getAppState(this).handler
@ -177,7 +182,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
setContentView(views.root)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding0(views.llContent)
fixHorizontalPadding0(views.llContent)
views.lvList.layoutManager = LinearLayoutManager(this)
views.lvList.adapter = adapter
@ -273,8 +278,10 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
if (item.type == SettingType.Group) {
for (child in item.items) {
if (child.caption == 0) continue
if (getString(item.caption).contains(query,
ignoreCase = true)
if (getString(item.caption).contains(
query,
ignoreCase = true
)
) {
match = true
break
@ -368,13 +375,15 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
oldItemPosition: Int,
newItemPosition: Int,
) = oldItems.elementAtOrNull(oldItemPosition) == newItems.elementAtOrNull(
newItemPosition)
newItemPosition
)
override fun areContentsTheSame(
oldItemPosition: Int,
newItemPosition: Int,
) = oldItems.elementAtOrNull(oldItemPosition) == newItems.elementAtOrNull(
newItemPosition)
newItemPosition
)
}, true).dispatchUpdatesTo(this)
}

View File

@ -6,6 +6,9 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import jp.juggler.util.*
import jp.juggler.util.data.digestSHA256Hex
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import okhttp3.internal.toHexString
import java.io.File
import java.io.FileOutputStream

View File

@ -22,7 +22,16 @@ import com.jrummyapps.android.colorpicker.ColorPickerDialogListener
import jp.juggler.subwaytooter.api.TootApiResult
import jp.juggler.subwaytooter.api.runApiTask
import jp.juggler.subwaytooter.column.*
import jp.juggler.util.*
import jp.juggler.util.backPressed
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.log.withCaption
import jp.juggler.util.media.createResizedBitmap
import jp.juggler.util.ui.ActivityResultHandler
import jp.juggler.util.ui.hideKeyboard
import jp.juggler.util.ui.isNotOk
import org.jetbrains.anko.textColor
import java.io.File
import java.io.FileOutputStream
@ -187,12 +196,11 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
}
R.id.btnColumnBackgroundImage -> {
val intent =
intentGetContent(
false,
getString(R.string.pick_image),
arrayOf("image/*")
)
val intent = intentGetContent(
false,
getString(R.string.pick_image),
arrayOf("image/*")
)
arColumnBackgroundImage.launch(intent)
}
@ -289,7 +297,7 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
setContentView(R.layout.act_column_customize)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding(findViewById(R.id.svContent))
fixHorizontalPadding(findViewById(R.id.svContent))
llColumnHeader = findViewById(R.id.llColumnHeader)
ivColumnHeader = findViewById(R.id.ivColumnHeader)

View File

@ -17,7 +17,14 @@ import com.woxthebox.draglistview.swipe.ListSwipeItem
import jp.juggler.subwaytooter.api.entity.Acct
import jp.juggler.subwaytooter.column.ColumnEncoder
import jp.juggler.subwaytooter.column.ColumnType
import jp.juggler.util.*
import jp.juggler.util.backPressed
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.notZero
import jp.juggler.util.data.toJsonArray
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.activity
import jp.juggler.util.ui.attrColor
class ActColumnList : AppCompatActivity() {
@ -71,7 +78,7 @@ class ActColumnList : AppCompatActivity() {
setContentView(R.layout.act_column_list)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding0(findViewById(R.id.llContent))
fixHorizontalPadding0(findViewById(R.id.llContent))
// リストのアダプター
listAdapter = MyListAdapter()

View File

@ -7,10 +7,10 @@ import android.widget.BaseAdapter
import android.widget.ImageView
import android.widget.ListView
import android.widget.TextView
import jp.juggler.subwaytooter.global.appDispatchers
import jp.juggler.subwaytooter.util.AsyncActivity
import jp.juggler.util.LogCategory
import jp.juggler.util.asciiPattern
import jp.juggler.util.coroutine.AppDispatchers
import jp.juggler.util.coroutine.AsyncActivity
import jp.juggler.util.data.asciiPattern
import jp.juggler.util.log.LogCategory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -37,7 +37,7 @@ class ActDrawableList : AsyncActivity(), CoroutineScope {
private fun initUI() {
setContentView(R.layout.act_drawable_list)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding(findViewById(R.id.llContent))
fixHorizontalPadding(findViewById(R.id.llContent))
listView = findViewById(R.id.listView)
adapter = MyAdapter()
@ -50,7 +50,7 @@ class ActDrawableList : AsyncActivity(), CoroutineScope {
val reSkipName =
"""^(abc_|avd_|btn_checkbox_|btn_radio_|googleg_|ic_keyboard_arrow_|ic_menu_arrow_|notification_|common_|emj_|cpv_|design_|exo_|mtrl_|ic_mtrl_)"""
.asciiPattern()
val list = withContext(appDispatchers.io) {
val list = withContext(AppDispatchers.io) {
R.drawable::class.java.fields
.mapNotNull {
val id = it.get(null) as? Int ?: return@mapNotNull null

View File

@ -13,9 +13,9 @@ import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.util.LogCategory
import jp.juggler.util.decodeUTF8
import jp.juggler.util.withCaption
import jp.juggler.util.log.LogCategory
import jp.juggler.util.data.decodeUTF8
import jp.juggler.util.log.withCaption
@RequiresApi(Build.VERSION_CODES.R)
class ActExitReasons : AppCompatActivity() {

View File

@ -13,9 +13,9 @@ import com.woxthebox.draglistview.swipe.ListSwipeHelper
import com.woxthebox.draglistview.swipe.ListSwipeItem
import jp.juggler.subwaytooter.api.entity.Acct
import jp.juggler.subwaytooter.table.FavMute
import jp.juggler.util.LogCategory
import jp.juggler.util.attrColor
import jp.juggler.util.backPressed
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.attrColor
class ActFavMute : AppCompatActivity() {
@ -41,7 +41,7 @@ class ActFavMute : AppCompatActivity() {
setContentView(R.layout.act_word_list)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding0(findViewById(R.id.llContent))
fixHorizontalPadding0(findViewById(R.id.llContent))
// リストのアダプター
listAdapter = MyListAdapter()

View File

@ -14,7 +14,16 @@ import androidx.appcompat.widget.SwitchCompat
import com.jrummyapps.android.colorpicker.ColorPickerDialog
import com.jrummyapps.android.colorpicker.ColorPickerDialogListener
import jp.juggler.subwaytooter.table.HighlightWord
import jp.juggler.util.*
import jp.juggler.util.backPressed
import jp.juggler.util.data.decodeJsonObject
import jp.juggler.util.data.mayUri
import jp.juggler.util.data.notEmpty
import jp.juggler.util.data.notZero
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.ActivityResultHandler
import jp.juggler.util.ui.attrColor
import jp.juggler.util.ui.decodeRingtonePickerResult
import org.jetbrains.anko.textColor
class ActHighlightWordEdit
@ -54,7 +63,7 @@ class ActHighlightWordEdit
private var bBusy = false
private val arNotificationSound = ActivityResultHandler(log) { r ->
r.decodeRingtonePickerResult()?.let { uri ->
r.decodeRingtonePickerResult?.let { uri ->
item.sound_uri = uri.toString()
item.sound_type = HighlightWord.SOUND_TYPE_CUSTOM
showSound()
@ -62,7 +71,7 @@ class ActHighlightWordEdit
}
override fun onCreate(savedInstanceState: Bundle?) {
backPressed{
backPressed {
AlertDialog.Builder(this)
.setCancelable(true)
.setMessage(R.string.discard_changes)

View File

@ -17,7 +17,14 @@ import com.woxthebox.draglistview.DragListView
import com.woxthebox.draglistview.swipe.ListSwipeHelper
import com.woxthebox.draglistview.swipe.ListSwipeItem
import jp.juggler.subwaytooter.table.HighlightWord
import jp.juggler.util.*
import jp.juggler.util.data.mayUri
import jp.juggler.util.data.notZero
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.errorEx
import jp.juggler.util.ui.ActivityResultHandler
import jp.juggler.util.ui.attrColor
import jp.juggler.util.ui.isNotOk
import jp.juggler.util.ui.vg
import java.lang.ref.WeakReference
class ActHighlightWordList : AppCompatActivity(), View.OnClickListener {
@ -63,7 +70,7 @@ class ActHighlightWordList : AppCompatActivity(), View.OnClickListener {
setContentView(R.layout.act_highlight_list)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding0(findViewById(R.id.llContent))
fixHorizontalPadding0(findViewById(R.id.llContent))
// リストのアダプター
listAdapter = MyListAdapter()

View File

@ -14,7 +14,15 @@ import jp.juggler.subwaytooter.api.runApiTask
import jp.juggler.subwaytooter.column.ColumnType
import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.JsonArray
import jp.juggler.util.data.buildJsonObject
import jp.juggler.util.data.notEmpty
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.network.toPostRequestBuilder
import jp.juggler.util.network.toPut
import jp.juggler.util.network.toRequestBody
class ActKeywordFilter
: AppCompatActivity(), View.OnClickListener {
@ -133,7 +141,7 @@ class ActKeywordFilter
setContentView(R.layout.act_keyword_filter)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding(findViewById(R.id.svContent))
fixHorizontalPadding(findViewById(R.id.svContent))
tvAccount = findViewById(R.id.tvAccount)
etPhrase = findViewById(R.id.etPhrase)
@ -233,7 +241,7 @@ class ActKeywordFilter
private fun save() {
if (loading) return
val params = jsonObject {
val params = buildJsonObject {
put("phrase", etPhrase.text.toString())

View File

@ -18,6 +18,11 @@ import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.subwaytooter.column.Column
import jp.juggler.subwaytooter.dialog.ActionsDialog
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchProgress
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.*
import org.jetbrains.anko.textColor
import java.io.File
import java.io.FileOutputStream
@ -172,7 +177,7 @@ class ActLanguageFilter : AppCompatActivity(), View.OnClickListener {
private fun initUI() {
setContentView(R.layout.act_language_filter)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding(findViewById(R.id.llContent))
fixHorizontalPadding(findViewById(R.id.llContent))
for (id in intArrayOf(
R.id.btnAdd,
@ -189,7 +194,7 @@ class ActLanguageFilter : AppCompatActivity(), View.OnClickListener {
}
// UIのデータをJsonObjectにエンコード
private fun encodeLanguageList() = jsonObject {
private fun encodeLanguageList() = buildJsonObject {
for (item in languageList) {
put(item.code, item.allow)
}

View File

@ -39,12 +39,18 @@ import jp.juggler.subwaytooter.pref.put
import jp.juggler.subwaytooter.span.MyClickableSpan
import jp.juggler.subwaytooter.span.MyClickableSpanHandler
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.EmojiDecoder
import jp.juggler.subwaytooter.util.checkPrivacyPolicy
import jp.juggler.subwaytooter.util.openBrowser
import jp.juggler.subwaytooter.util.*
import jp.juggler.subwaytooter.view.MyDrawerLayout
import jp.juggler.subwaytooter.view.MyEditText
import jp.juggler.util.*
import jp.juggler.util.backPressed
import jp.juggler.util.data.notEmpty
import jp.juggler.util.int
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.benchmark
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.ActivityResultHandler
import jp.juggler.util.ui.attrColor
import jp.juggler.util.ui.isNotOk
import okhttp3.internal.toHexString
import java.lang.ref.WeakReference
import java.util.*
@ -315,7 +321,7 @@ class ActMain : AppCompatActivity(),
}
}
var prNotification = permissionSpecNotification.requester {
private val prNotification = permissionSpecNotification.requester {
// 特に何もしない
}
@ -323,10 +329,11 @@ class ActMain : AppCompatActivity(),
// ライフサイクルイベント
override fun onCreate(savedInstanceState: Bundle?) {
backPressed { onBackPressedImpl() }
log.d("onCreate")
super.onCreate(savedInstanceState)
refActMain = WeakReference(this)
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
super.onCreate(savedInstanceState)
backPressed { onBackPressedImpl() }
prNotification.register(this)
arColumnColor.register(this)
@ -339,7 +346,6 @@ class ActMain : AppCompatActivity(),
arActPost.register(this)
arActText.register(this)
requestWindowFeature(Window.FEATURE_NO_TITLE)
App1.setActivityTheme(this, noActionBar = true)
appState = App1.getAppState(this)

View File

@ -14,6 +14,7 @@ import android.os.SystemClock
import android.view.View
import android.view.Window
import androidx.appcompat.app.AppCompatActivity
import androidx.core.net.toUri
import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.Player.TimelineChangeReason
import com.google.android.exoplayer2.source.LoadEventInfo
@ -33,8 +34,20 @@ import jp.juggler.subwaytooter.global.appPref
import jp.juggler.subwaytooter.pref.PrefI
import jp.juggler.subwaytooter.pref.put
import jp.juggler.subwaytooter.util.ProgressResponseBody
import jp.juggler.subwaytooter.util.permissionSpecMediaDownload
import jp.juggler.subwaytooter.util.requester
import jp.juggler.subwaytooter.view.PinchBitmapView
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.log.withCaption
import jp.juggler.util.media.imageOrientation
import jp.juggler.util.media.resolveOrientation
import jp.juggler.util.media.rotateSize
import jp.juggler.util.network.MySslSocketFactory
import jp.juggler.util.ui.*
import kotlinx.coroutines.yield
import okhttp3.Request
import java.io.ByteArrayInputStream
@ -67,10 +80,9 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
internal fun decodeMediaList(src: String?) =
ArrayList<TootAttachment>().apply {
src?.decodeJsonArray()?.forEach {
if (it !is JsonObject) return@forEach
add(TootAttachment.decodeJson(it))
}
src?.decodeJsonArray()?.objectList()
?.map { TootAttachment.decodeJson(it) }
?.let { addAll(it) }
}
fun open(
@ -242,9 +254,9 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
}
override fun onCreate(savedInstanceState: Bundle?) {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
super.onCreate(savedInstanceState)
prDownload.register(this)
requestWindowFeature(Window.FEATURE_NO_TITLE)
App1.setActivityTheme(this, noActionBar = true, forceDark = true)
this.showDescription = intent.getBooleanExtra(EXTRA_SHOW_DESCRIPTION, showDescription)
@ -698,7 +710,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
val fileName = (
url.mayUri()?.pathSegments?.findLast { !it.isNullOrBlank() }
?: url
.replaceFirst("https?://".asciiPattern(), "")
.replaceFirst("https?://".asciiRegex(), "")
.replaceAll("[^.\\w\\d]+".asciiPattern(), "-")
)
.take(20)

View File

@ -12,9 +12,9 @@ import com.woxthebox.draglistview.DragListView
import com.woxthebox.draglistview.swipe.ListSwipeHelper
import com.woxthebox.draglistview.swipe.ListSwipeItem
import jp.juggler.subwaytooter.table.MutedApp
import jp.juggler.util.LogCategory
import jp.juggler.util.attrColor
import jp.juggler.util.backPressed
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.attrColor
class ActMutedApp : AppCompatActivity() {
@ -41,7 +41,7 @@ class ActMutedApp : AppCompatActivity() {
setContentView(R.layout.act_word_list)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding0(findViewById(R.id.llContent))
fixHorizontalPadding0(findViewById(R.id.llContent))
// リストのアダプター
listAdapter = MyListAdapter()

View File

@ -12,9 +12,9 @@ import com.woxthebox.draglistview.DragListView
import com.woxthebox.draglistview.swipe.ListSwipeHelper
import com.woxthebox.draglistview.swipe.ListSwipeItem
import jp.juggler.subwaytooter.table.UserRelation
import jp.juggler.util.LogCategory
import jp.juggler.util.attrColor
import jp.juggler.util.backPressed
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.attrColor
class ActMutedPseudoAccount : AppCompatActivity() {
@ -40,7 +40,7 @@ class ActMutedPseudoAccount : AppCompatActivity() {
setContentView(R.layout.act_word_list)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding0(findViewById(R.id.llContent))
fixHorizontalPadding0(findViewById(R.id.llContent))
// リストのアダプター
listAdapter = MyListAdapter()

View File

@ -12,9 +12,9 @@ import com.woxthebox.draglistview.DragListView
import com.woxthebox.draglistview.swipe.ListSwipeHelper
import com.woxthebox.draglistview.swipe.ListSwipeItem
import jp.juggler.subwaytooter.table.MutedWord
import jp.juggler.util.LogCategory
import jp.juggler.util.attrColor
import jp.juggler.util.backPressed
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.attrColor
class ActMutedWord : AppCompatActivity() {
@ -40,7 +40,7 @@ class ActMutedWord : AppCompatActivity() {
setContentView(R.layout.act_word_list)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding0(findViewById(R.id.llContent))
fixHorizontalPadding0(findViewById(R.id.llContent))
// リストのアダプター
listAdapter = MyListAdapter()

View File

@ -14,7 +14,12 @@ import com.jrummyapps.android.colorpicker.ColorPickerDialogListener
import jp.juggler.subwaytooter.api.entity.Acct
import jp.juggler.subwaytooter.databinding.ActNicknameBinding
import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.util.*
import jp.juggler.util.backPressed
import jp.juggler.util.data.mayUri
import jp.juggler.util.data.notEmpty
import jp.juggler.util.data.notZero
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.*
import org.jetbrains.anko.backgroundColor
import org.jetbrains.anko.textColor
@ -51,7 +56,7 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog
private var loadingBusy = false
private val arNotificationSound = ActivityResultHandler(log) { r ->
r.decodeRingtonePickerResult()?.let { uri ->
r.decodeRingtonePickerResult?.let { uri ->
notificationSoundUri = uri.toString()
}
}
@ -86,7 +91,7 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog
setContentView(views.root)
App1.initEdgeToEdge(this)
Styler.fixHorizontalPadding(findViewById(R.id.llContent))
fixHorizontalPadding(findViewById(R.id.llContent))
views.btnTextColorEdit.setOnClickListener(this)
views.btnTextColorReset.setOnClickListener(this)

View File

@ -3,9 +3,9 @@ package jp.juggler.subwaytooter
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import jp.juggler.util.LogCategory
import jp.juggler.util.decodeUTF8
import jp.juggler.util.loadRawResource
import jp.juggler.util.data.decodeUTF8
import jp.juggler.util.data.loadRawResource
import jp.juggler.util.log.LogCategory
class ActOSSLicense : AppCompatActivity() {

View File

@ -30,6 +30,12 @@ import jp.juggler.subwaytooter.util.*
import jp.juggler.subwaytooter.view.MyEditText
import jp.juggler.subwaytooter.view.MyNetworkImageView
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchIO
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.GetContentResultEntry
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.ActivityResultHandler
import jp.juggler.util.ui.isNotOk
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.ClosedReceiveChannelException
@ -320,8 +326,8 @@ class ActPost : AppCompatActivity(),
}
if (!isMultiWindowPost) {
Styler.fixHorizontalMargin(findViewById(R.id.scrollView))
Styler.fixHorizontalMargin(findViewById(R.id.llFooterBar))
fixHorizontalMargin(findViewById(R.id.scrollView))
fixHorizontalMargin(findViewById(R.id.llFooterBar))
}
views.root.callbackOnSizeChanged = { _, _, _, _ ->

View File

@ -16,7 +16,13 @@ import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.CustomShare
import jp.juggler.subwaytooter.util.CustomShareTarget
import jp.juggler.subwaytooter.util.TootTextEncoder
import jp.juggler.subwaytooter.util.copyToClipboard
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.*
class ActText : AppCompatActivity() {
@ -134,7 +140,7 @@ class ActText : AppCompatActivity() {
setContentView(R.layout.act_text)
etText = findViewById(R.id.etText)
App1.initEdgeToEdge(this)
Styler.fixHorizontalMargin(etText)
fixHorizontalMargin(etText)
setSupportActionBar(findViewById(R.id.toolbar))
supportActionBar?.apply {

View File

@ -30,6 +30,12 @@ import jp.juggler.subwaytooter.util.CustomEmojiCache
import jp.juggler.subwaytooter.util.CustomEmojiLister
import jp.juggler.subwaytooter.util.ProgressResponseBody
import jp.juggler.util.*
import jp.juggler.util.data.asciiPattern
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.initializeToastUtils
import jp.juggler.util.network.MySslSocketFactory
import jp.juggler.util.network.toPostRequestBuilder
import jp.juggler.util.ui.*
import okhttp3.*
import okhttp3.OkHttpClient
import org.conscrypt.Conscrypt

View File

@ -24,6 +24,11 @@ import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.NetworkStateTracker
import jp.juggler.subwaytooter.util.PostAttachment
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchIO
import jp.juggler.util.coroutine.runOnMainLooper
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import java.io.File
import java.io.FileNotFoundException
import java.lang.ref.WeakReference
@ -226,7 +231,7 @@ class AppState(
} else {
log.d(
"proc_flushSpeechQueue: tts is speaking. queue_count=$queue_count, expire_remain=${
expire_remain.div(1000f).toString("%.3f")
"%.3f".format(expire_remain.div(1000f))
}"
)
handler.postDelayed(this, expire_remain)

View File

@ -4,10 +4,10 @@ import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import jp.juggler.util.LogCategory
import jp.juggler.util.getIntOrNull
import jp.juggler.util.getStringOrNull
import jp.juggler.util.showToast
import jp.juggler.util.data.getIntOrNull
import jp.juggler.util.data.getStringOrNull
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
class DownloadReceiver : BroadcastReceiver() {

View File

@ -6,9 +6,9 @@ import android.content.Intent
import jp.juggler.subwaytooter.notification.TrackingType
import jp.juggler.subwaytooter.notification.onNotificationDeleted
import jp.juggler.subwaytooter.table.NotificationTracking
import jp.juggler.util.LogCategory
import jp.juggler.util.launchMain
import jp.juggler.util.notEmpty
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.notEmpty
import jp.juggler.util.log.LogCategory
class EventReceiver : BroadcastReceiver() {

View File

@ -7,7 +7,7 @@ import jp.juggler.subwaytooter.notification.restartAllWorker
import jp.juggler.subwaytooter.pref.PrefDevice
import jp.juggler.subwaytooter.table.NotificationCache
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.LogCategory
import jp.juggler.util.log.LogCategory
import kotlinx.coroutines.runBlocking
import java.util.*

View File

@ -1,16 +1,22 @@
package jp.juggler.subwaytooter
import android.content.Context
import android.content.res.ColorStateList
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.os.Build
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.ImageButton
import android.widget.ImageView
import androidx.annotation.DrawableRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SwitchCompat
import androidx.core.content.ContextCompat
import jp.juggler.subwaytooter.api.entity.TootAccount
import jp.juggler.subwaytooter.api.entity.TootVisibility
@ -21,352 +27,350 @@ import jp.juggler.subwaytooter.pref.pref
import jp.juggler.subwaytooter.span.EmojiImageSpan
import jp.juggler.subwaytooter.span.createSpan
import jp.juggler.subwaytooter.table.UserRelation
import jp.juggler.util.LogCategory
import jp.juggler.util.attrColor
import jp.juggler.util.notZero
import jp.juggler.util.setIconDrawableId
import jp.juggler.util.*
import jp.juggler.util.data.notZero
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.*
import org.xmlpull.v1.XmlPullParser
import kotlin.math.max
import kotlin.math.min
private val log = LogCategory("Styler")
object Styler {
fun defaultColorIcon(context: Context, iconId: Int): Drawable? =
ContextCompat.getDrawable(context, iconId)?.also {
it.setTint(context.attrColor(R.attr.colorVectorDrawable))
it.setTintMode(PorterDuff.Mode.SRC_IN)
}
fun defaultColorIcon(context: Context, iconId: Int): Drawable? =
ContextCompat.getDrawable(context, iconId)?.also {
it.setTint(context.attrColor(R.attr.colorVectorDrawable))
it.setTintMode(PorterDuff.Mode.SRC_IN)
}
fun getVisibilityIconId(isMisskeyData: Boolean, visibility: TootVisibility): Int {
val isMisskey = when (PrefI.ipVisibilityStyle()) {
PrefI.VS_MASTODON -> false
PrefI.VS_MISSKEY -> true
else -> isMisskeyData
}
return when {
isMisskey -> when (visibility) {
TootVisibility.Public -> R.drawable.ic_public
TootVisibility.UnlistedHome -> R.drawable.ic_home
TootVisibility.PrivateFollowers -> R.drawable.ic_lock_open
TootVisibility.DirectSpecified -> R.drawable.ic_mail
TootVisibility.DirectPrivate -> R.drawable.ic_lock
TootVisibility.WebSetting -> R.drawable.ic_question
TootVisibility.AccountSetting -> R.drawable.ic_question
fun getVisibilityIconId(isMisskeyData: Boolean, visibility: TootVisibility): Int {
val isMisskey = when (PrefI.ipVisibilityStyle()) {
PrefI.VS_MASTODON -> false
PrefI.VS_MISSKEY -> true
else -> isMisskeyData
TootVisibility.LocalPublic -> R.drawable.ic_local_ltl
TootVisibility.LocalHome -> R.drawable.ic_local_home
TootVisibility.LocalFollowers -> R.drawable.ic_local_lock_open
TootVisibility.Unknown -> R.drawable.ic_question
TootVisibility.Limited -> R.drawable.ic_account_circle
TootVisibility.Mutual -> R.drawable.ic_bidirectional
}
return when {
else -> when (visibility) {
TootVisibility.Public -> R.drawable.ic_public
TootVisibility.UnlistedHome -> R.drawable.ic_lock_open
TootVisibility.PrivateFollowers -> R.drawable.ic_lock
TootVisibility.DirectSpecified -> R.drawable.ic_mail
TootVisibility.DirectPrivate -> R.drawable.ic_mail
TootVisibility.WebSetting -> R.drawable.ic_question
TootVisibility.AccountSetting -> R.drawable.ic_question
TootVisibility.LocalPublic -> R.drawable.ic_local_ltl
TootVisibility.LocalHome -> R.drawable.ic_local_lock_open
TootVisibility.LocalFollowers -> R.drawable.ic_local_lock
TootVisibility.Unknown -> R.drawable.ic_question
TootVisibility.Limited -> R.drawable.ic_account_circle
TootVisibility.Mutual -> R.drawable.ic_bidirectional
}
}
}
fun getVisibilityString(
context: Context,
isMisskeyData: Boolean,
visibility: TootVisibility,
): String {
val isMisskey = when (PrefI.ipVisibilityStyle()) {
PrefI.VS_MASTODON -> false
PrefI.VS_MISSKEY -> true
else -> isMisskeyData
}
return context.getString(
when {
isMisskey -> when (visibility) {
TootVisibility.Public -> R.drawable.ic_public
TootVisibility.UnlistedHome -> R.drawable.ic_home
TootVisibility.PrivateFollowers -> R.drawable.ic_lock_open
TootVisibility.DirectSpecified -> R.drawable.ic_mail
TootVisibility.DirectPrivate -> R.drawable.ic_lock
TootVisibility.WebSetting -> R.drawable.ic_question
TootVisibility.AccountSetting -> R.drawable.ic_question
TootVisibility.Public -> R.string.visibility_public
TootVisibility.UnlistedHome -> R.string.visibility_home
TootVisibility.PrivateFollowers -> R.string.visibility_followers
TootVisibility.DirectSpecified -> R.string.visibility_direct
TootVisibility.DirectPrivate -> R.string.visibility_private
TootVisibility.WebSetting -> R.string.visibility_web_setting
TootVisibility.AccountSetting -> R.string.visibility_account_setting
TootVisibility.LocalPublic -> R.drawable.ic_local_ltl
TootVisibility.LocalHome -> R.drawable.ic_local_home
TootVisibility.LocalFollowers -> R.drawable.ic_local_lock_open
TootVisibility.LocalPublic -> R.string.visibility_local_public
TootVisibility.LocalHome -> R.string.visibility_local_home
TootVisibility.LocalFollowers -> R.string.visibility_local_followers
TootVisibility.Unknown -> R.drawable.ic_question
TootVisibility.Limited -> R.drawable.ic_account_circle
TootVisibility.Mutual -> R.drawable.ic_bidirectional
TootVisibility.Unknown -> R.string.visibility_unknown
TootVisibility.Limited -> R.string.visibility_limited
TootVisibility.Mutual -> R.string.visibility_mutual
}
else -> when (visibility) {
TootVisibility.Public -> R.drawable.ic_public
TootVisibility.UnlistedHome -> R.drawable.ic_lock_open
TootVisibility.PrivateFollowers -> R.drawable.ic_lock
TootVisibility.DirectSpecified -> R.drawable.ic_mail
TootVisibility.DirectPrivate -> R.drawable.ic_mail
TootVisibility.WebSetting -> R.drawable.ic_question
TootVisibility.AccountSetting -> R.drawable.ic_question
TootVisibility.Public -> R.string.visibility_public
TootVisibility.UnlistedHome -> R.string.visibility_unlisted
TootVisibility.PrivateFollowers -> R.string.visibility_followers
TootVisibility.DirectSpecified -> R.string.visibility_direct
TootVisibility.DirectPrivate -> R.string.visibility_direct
TootVisibility.WebSetting -> R.string.visibility_web_setting
TootVisibility.AccountSetting -> R.string.visibility_account_setting
TootVisibility.LocalPublic -> R.drawable.ic_local_ltl
TootVisibility.LocalHome -> R.drawable.ic_local_lock_open
TootVisibility.LocalFollowers -> R.drawable.ic_local_lock
TootVisibility.LocalPublic -> R.string.visibility_local_public
TootVisibility.LocalHome -> R.string.visibility_local_unlisted
TootVisibility.LocalFollowers -> R.string.visibility_local_followers
TootVisibility.Unknown -> R.drawable.ic_question
TootVisibility.Limited -> R.drawable.ic_account_circle
TootVisibility.Mutual -> R.drawable.ic_bidirectional
TootVisibility.Unknown -> R.string.visibility_unknown
TootVisibility.Limited -> R.string.visibility_limited
TootVisibility.Mutual -> R.string.visibility_mutual
}
}
}
)
}
fun getVisibilityString(
context: Context,
isMisskeyData: Boolean,
visibility: TootVisibility
): String {
val isMisskey = when (PrefI.ipVisibilityStyle()) {
PrefI.VS_MASTODON -> false
PrefI.VS_MISSKEY -> true
else -> isMisskeyData
}
return context.getString(
when {
isMisskey -> when (visibility) {
TootVisibility.Public -> R.string.visibility_public
TootVisibility.UnlistedHome -> R.string.visibility_home
TootVisibility.PrivateFollowers -> R.string.visibility_followers
TootVisibility.DirectSpecified -> R.string.visibility_direct
TootVisibility.DirectPrivate -> R.string.visibility_private
TootVisibility.WebSetting -> R.string.visibility_web_setting
TootVisibility.AccountSetting -> R.string.visibility_account_setting
// アイコン付きの装飾テキストを返す
fun getVisibilityCaption(
context: Context,
isMisskeyData: Boolean,
visibility: TootVisibility,
): CharSequence {
TootVisibility.LocalPublic -> R.string.visibility_local_public
TootVisibility.LocalHome -> R.string.visibility_local_home
TootVisibility.LocalFollowers -> R.string.visibility_local_followers
val icon_id = getVisibilityIconId(isMisskeyData, visibility)
val sv = getVisibilityString(context, isMisskeyData, visibility)
val color = context.attrColor(R.attr.colorVectorDrawable)
val sb = SpannableStringBuilder()
TootVisibility.Unknown -> R.string.visibility_unknown
TootVisibility.Limited -> R.string.visibility_limited
TootVisibility.Mutual -> R.string.visibility_mutual
}
else -> when (visibility) {
TootVisibility.Public -> R.string.visibility_public
TootVisibility.UnlistedHome -> R.string.visibility_unlisted
TootVisibility.PrivateFollowers -> R.string.visibility_followers
TootVisibility.DirectSpecified -> R.string.visibility_direct
TootVisibility.DirectPrivate -> R.string.visibility_direct
TootVisibility.WebSetting -> R.string.visibility_web_setting
TootVisibility.AccountSetting -> R.string.visibility_account_setting
TootVisibility.LocalPublic -> R.string.visibility_local_public
TootVisibility.LocalHome -> R.string.visibility_local_unlisted
TootVisibility.LocalFollowers -> R.string.visibility_local_followers
TootVisibility.Unknown -> R.string.visibility_unknown
TootVisibility.Limited -> R.string.visibility_limited
TootVisibility.Mutual -> R.string.visibility_mutual
}
}
)
}
// アイコン付きの装飾テキストを返す
fun getVisibilityCaption(
context: Context,
isMisskeyData: Boolean,
visibility: TootVisibility
): CharSequence {
val icon_id = getVisibilityIconId(isMisskeyData, visibility)
val sv = getVisibilityString(context, isMisskeyData, visibility)
val color = context.attrColor(R.attr.colorVectorDrawable)
val sb = SpannableStringBuilder()
// アイコン部分
val start = sb.length
sb.append(" ")
val end = sb.length
sb.setSpan(
EmojiImageSpan(
context,
icon_id,
useColorShader = true,
color = color
),
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
// 文字列部分
sb.append(' ')
sb.append(sv)
return sb
}
fun setFollowIcon(
context: Context,
ibFollow: ImageButton,
ivDot: ImageView,
relation: UserRelation,
who: TootAccount,
defaultColor: Int,
alphaMultiplier: Float
) {
fun colorAccent() =
PrefI.ipButtonFollowingColor(context.pref()).notZero()
?: context.attrColor(R.attr.colorButtonAccentFollow)
fun colorError() =
PrefI.ipButtonFollowRequestColor(context.pref()).notZero()
?: context.attrColor(R.attr.colorButtonAccentFollowRequest)
// 被フォロー状態
when {
relation.blocked_by -> {
ivDot.visibility = View.VISIBLE
setIconDrawableId(
context,
ivDot,
R.drawable.ic_blocked_by,
color = colorError(),
alphaMultiplier = alphaMultiplier
)
}
relation.requested_by -> {
ivDot.visibility = View.VISIBLE
setIconDrawableId(
context,
ivDot,
R.drawable.ic_requested_by,
color = colorError(),
alphaMultiplier = alphaMultiplier
)
}
relation.followed_by -> {
ivDot.visibility = View.VISIBLE
setIconDrawableId(
context,
ivDot,
R.drawable.ic_follow_dot,
color = colorAccent(),
alphaMultiplier = alphaMultiplier
)
// 被フォローリクエスト状態の時に followed_by が 真と偽の両方がありえるようなので
// Relationshipだけを見ても被フォローリクエスト状態は分からないっぽい
// 仕方ないので馬鹿正直に「 followed_byが真ならバッジをつける」しかできない
}
else -> {
ivDot.visibility = View.GONE
}
}
// フォローボタン
// follow button
val color: Int
val iconId: Int
val contentDescription: String
when {
relation.blocking -> {
iconId = R.drawable.ic_block
color = defaultColor
contentDescription = context.getString(R.string.follow)
}
relation.muting -> {
iconId = R.drawable.ic_volume_off
color = defaultColor
contentDescription = context.getString(R.string.follow)
}
relation.getFollowing(who) -> {
iconId = R.drawable.ic_follow_cross
color = colorAccent()
contentDescription = context.getString(R.string.unfollow)
}
relation.getRequested(who) -> {
iconId = R.drawable.ic_follow_wait
color = colorError()
contentDescription = context.getString(R.string.unfollow)
}
else -> {
iconId = R.drawable.ic_follow_plus
color = defaultColor
contentDescription = context.getString(R.string.follow)
}
}
setIconDrawableId(
// アイコン部分
val start = sb.length
sb.append(" ")
val end = sb.length
sb.setSpan(
EmojiImageSpan(
context,
ibFollow,
iconId,
color = color,
alphaMultiplier = alphaMultiplier
)
ibFollow.contentDescription = contentDescription
icon_id,
useColorShader = true,
color = color
),
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
// 文字列部分
sb.append(' ')
sb.append(sv)
return sb
}
fun setFollowIcon(
context: Context,
ibFollow: ImageButton,
ivDot: ImageView,
relation: UserRelation,
who: TootAccount,
defaultColor: Int,
alphaMultiplier: Float,
) {
fun colorAccent() =
PrefI.ipButtonFollowingColor(context.pref()).notZero()
?: context.attrColor(R.attr.colorButtonAccentFollow)
fun colorError() =
PrefI.ipButtonFollowRequestColor(context.pref()).notZero()
?: context.attrColor(R.attr.colorButtonAccentFollowRequest)
// 被フォロー状態
when {
relation.blocked_by -> {
ivDot.visibility = View.VISIBLE
setIconDrawableId(
context,
ivDot,
R.drawable.ic_blocked_by,
color = colorError(),
alphaMultiplier = alphaMultiplier
)
}
relation.requested_by -> {
ivDot.visibility = View.VISIBLE
setIconDrawableId(
context,
ivDot,
R.drawable.ic_requested_by,
color = colorError(),
alphaMultiplier = alphaMultiplier
)
}
relation.followed_by -> {
ivDot.visibility = View.VISIBLE
setIconDrawableId(
context,
ivDot,
R.drawable.ic_follow_dot,
color = colorAccent(),
alphaMultiplier = alphaMultiplier
)
// 被フォローリクエスト状態の時に followed_by が 真と偽の両方がありえるようなので
// Relationshipだけを見ても被フォローリクエスト状態は分からないっぽい
// 仕方ないので馬鹿正直に「 followed_byが真ならバッジをつける」しかできない
}
else -> {
ivDot.visibility = View.GONE
}
}
private fun getHorizontalPadding(v: View, dpDelta: Float): Int {
// Essential Phone PH-1は 短辺439dp
val formWidthMax = 460f
val dm = v.resources.displayMetrics
val screenW = dm.widthPixels
val contentW = (0.5f + formWidthMax * dm.density).toInt()
val padW = max(0, (screenW - contentW) / 2)
return padW + (0.5f + dpDelta * dm.density).toInt()
// フォローボタン
// follow button
val color: Int
val iconId: Int
val contentDescription: String
when {
relation.blocking -> {
iconId = R.drawable.ic_block
color = defaultColor
contentDescription = context.getString(R.string.follow)
}
relation.muting -> {
iconId = R.drawable.ic_volume_off
color = defaultColor
contentDescription = context.getString(R.string.follow)
}
relation.getFollowing(who) -> {
iconId = R.drawable.ic_follow_cross
color = colorAccent()
contentDescription = context.getString(R.string.unfollow)
}
relation.getRequested(who) -> {
iconId = R.drawable.ic_follow_wait
color = colorError()
contentDescription = context.getString(R.string.unfollow)
}
else -> {
iconId = R.drawable.ic_follow_plus
color = defaultColor
contentDescription = context.getString(R.string.follow)
}
}
private fun getOrientationString(orientation: Int?) = when (orientation) {
null -> "null"
Configuration.ORIENTATION_LANDSCAPE -> "landscape"
Configuration.ORIENTATION_PORTRAIT -> "portrait"
Configuration.ORIENTATION_UNDEFINED -> "undefined"
else -> orientation.toString()
setIconDrawableId(
context,
ibFollow,
iconId,
color = color,
alphaMultiplier = alphaMultiplier
)
ibFollow.contentDescription = contentDescription
}
private fun getHorizontalPadding(v: View, dpDelta: Float): Int {
// Essential Phone PH-1は 短辺439dp
val formWidthMax = 460f
val dm = v.resources.displayMetrics
val screenW = dm.widthPixels
val contentW = (0.5f + formWidthMax * dm.density).toInt()
val padW = max(0, (screenW - contentW) / 2)
return padW + (0.5f + dpDelta * dm.density).toInt()
}
private fun getOrientationString(orientation: Int?) = when (orientation) {
null -> "null"
Configuration.ORIENTATION_LANDSCAPE -> "landscape"
Configuration.ORIENTATION_PORTRAIT -> "portrait"
Configuration.ORIENTATION_UNDEFINED -> "undefined"
else -> orientation.toString()
}
fun fixHorizontalPadding(v: View, dpDelta: Float = 12f) {
val pad_t = v.paddingTop
val pad_b = v.paddingBottom
val dm = v.resources.displayMetrics
val widthDp = dm.widthPixels / dm.density
if (widthDp >= 640f && v.resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT) {
val pad_lr = (0.5f + dpDelta * dm.density).toInt()
when (PrefI.ipJustifyWindowContentPortrait()) {
PrefI.JWCP_START -> {
v.setPaddingRelative(pad_lr, pad_t, pad_lr + dm.widthPixels / 2, pad_b)
return
}
PrefI.JWCP_END -> {
v.setPaddingRelative(pad_lr + dm.widthPixels / 2, pad_t, pad_lr, pad_b)
return
}
}
}
fun fixHorizontalPadding(v: View, dpDelta: Float = 12f) {
val pad_t = v.paddingTop
val pad_b = v.paddingBottom
val pad_lr = getHorizontalPadding(v, dpDelta)
v.setPaddingRelative(pad_lr, pad_t, pad_lr, pad_b)
}
fun fixHorizontalPadding0(v: View) = fixHorizontalPadding(v, 0f)
fun fixHorizontalMargin(v: View) {
val lp = v.layoutParams
if (lp is ViewGroup.MarginLayoutParams) {
val dm = v.resources.displayMetrics
val orientationString = getOrientationString(v.resources?.configuration?.orientation)
val widthDp = dm.widthPixels / dm.density
log.d("fixHorizontalMargin: orientation=$orientationString, w=${widthDp}dp, h=${dm.heightPixels / dm.density}")
if (widthDp >= 640f && v.resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT) {
val pad_lr = (0.5f + dpDelta * dm.density).toInt()
when (PrefI.ipJustifyWindowContentPortrait()) {
PrefI.JWCP_START -> {
v.setPaddingRelative(pad_lr, pad_t, pad_lr + dm.widthPixels / 2, pad_b)
lp.marginStart = 0
lp.marginEnd = dm.widthPixels / 2
return
}
PrefI.JWCP_END -> {
v.setPaddingRelative(pad_lr + dm.widthPixels / 2, pad_t, pad_lr, pad_b)
lp.marginStart = dm.widthPixels / 2
lp.marginEnd = 0
return
}
}
}
val pad_lr = getHorizontalPadding(v, dpDelta)
v.setPaddingRelative(pad_lr, pad_t, pad_lr, pad_b)
val pad_lr = getHorizontalPadding(v, 0f)
lp.leftMargin = pad_lr
lp.rightMargin = pad_lr
}
fun fixHorizontalPadding0(v: View) = fixHorizontalPadding(v, 0f)
fun fixHorizontalMargin(v: View) {
val lp = v.layoutParams
if (lp is ViewGroup.MarginLayoutParams) {
val dm = v.resources.displayMetrics
val orientationString = getOrientationString(v.resources?.configuration?.orientation)
val widthDp = dm.widthPixels / dm.density
log.d("fixHorizontalMargin: orientation=$orientationString, w=${widthDp}dp, h=${dm.heightPixels / dm.density}")
if (widthDp >= 640f && v.resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT) {
when (PrefI.ipJustifyWindowContentPortrait()) {
PrefI.JWCP_START -> {
lp.marginStart = 0
lp.marginEnd = dm.widthPixels / 2
return
}
PrefI.JWCP_END -> {
lp.marginStart = dm.widthPixels / 2
lp.marginEnd = 0
return
}
}
}
val pad_lr = getHorizontalPadding(v, 0f)
lp.leftMargin = pad_lr
lp.rightMargin = pad_lr
}
}
// ActMainの初期化時に更新される
var round_ratio: Float = 0.33f * 0.5f
var boostAlpha: Float = 1f
fun calcIconRound(wh: Int) = wh.toFloat() * round_ratio
fun calcIconRound(lp: ViewGroup.LayoutParams) =
min(lp.width, lp.height).toFloat() * round_ratio
}
// ActMainの初期化時に更新される
var round_ratio: Float = 0.33f * 0.5f
var boostAlpha: Float = 1f
fun calcIconRound(wh: Int) = wh.toFloat() * round_ratio
fun calcIconRound(lp: ViewGroup.LayoutParams) =
min(lp.width, lp.height).toFloat() * round_ratio
fun SpannableStringBuilder.appendColorShadeIcon(
context: Context,
@DrawableRes drawableId: Int,
text: String,
color: Int? = null
color: Int? = null,
): SpannableStringBuilder {
val start = this.length
this.append(text)
@ -383,7 +387,7 @@ fun SpannableStringBuilder.appendColorShadeIcon(
fun SpannableStringBuilder.appendMisskeyReaction(
context: Context,
emojiUtf16: String,
text: String
text: String,
): SpannableStringBuilder {
val emoji = EmojiMap.unicodeMap[emojiUtf16]
@ -406,3 +410,89 @@ fun SpannableStringBuilder.appendMisskeyReaction(
}
return this
}
fun Context.setSwitchColor(root: View?) {
val colorBg = attrColor(R.attr.colorWindowBackground)
val colorOff = attrColor(R.attr.colorSwitchOff)
val colorOn = PrefI.ipSwitchOnColor()
val colorDisabled = mixColor(colorBg, colorOff)
val colorTrackDisabled = mixColor(colorBg, colorDisabled)
val colorTrackOn = mixColor(colorBg, colorOn)
val colorTrackOff = mixColor(colorBg, colorOff)
// https://stackoverflow.com/a/25635526/9134243
val thumbStates = ColorStateList(
arrayOf(
intArrayOf(-android.R.attr.state_enabled),
intArrayOf(android.R.attr.state_checked),
intArrayOf()
),
intArrayOf(
colorDisabled,
colorOn,
colorOff
)
)
val trackStates = ColorStateList(
arrayOf(
intArrayOf(-android.R.attr.state_enabled),
intArrayOf(android.R.attr.state_checked),
intArrayOf()
),
intArrayOf(
colorTrackDisabled,
colorTrackOn,
colorTrackOff
)
)
root?.scan {
(it as? SwitchCompat)?.apply {
thumbTintList = thumbStates
trackTintList = trackStates
}
}
}
fun ViewGroup.generateLayoutParamsEx(): ViewGroup.LayoutParams? =
try {
val parser = resources.getLayout(R.layout.generate_params)
// Skip everything until the view tag.
while (true) {
val token = parser.nextToken()
if (token == XmlPullParser.START_TAG) break
}
generateLayoutParams(parser)
} catch (ex: Throwable) {
log.e(ex, "generateLayoutParamsEx failed")
null
}
fun AppCompatActivity.setStatusBarColor(forceDark: Boolean = false) {
window?.apply {
if (Build.VERSION.SDK_INT < 30) {
@Suppress("DEPRECATION")
clearFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS or
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
)
}
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
var c = when {
forceDark -> Color.BLACK
else -> PrefI.ipStatusBarColor.invoke().notZero() ?: attrColor(R.attr.colorPrimaryDark)
}
setStatusBarColorCompat(c)
c = when {
forceDark -> Color.BLACK
else -> PrefI.ipNavigationBarColor()
}
setNavigationBarColorCompat(c)
}
}

View File

@ -7,10 +7,10 @@ import jp.juggler.subwaytooter.api.runApiTask
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.table.UserRelation
import jp.juggler.subwaytooter.util.matchHost
import jp.juggler.util.JsonObject
import jp.juggler.util.LogCategory
import jp.juggler.util.jsonObject
import jp.juggler.util.showToast
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.buildJsonObject
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
private val log = LogCategory("ActionUtils")
@ -43,7 +43,7 @@ internal suspend fun AppCompatActivity.addPseudoAccount(
?: getInstanceInfo()
?: return null
val accountInfo = jsonObject {
val accountInfo = buildJsonObject {
put("username", acct.username)
put("acct", acct.username) // ローカルから参照した場合なのでshort acct
}

View File

@ -5,6 +5,7 @@ import android.content.Context
import android.os.Build
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.net.toUri
import jp.juggler.subwaytooter.*
import jp.juggler.subwaytooter.actmain.addColumn
import jp.juggler.subwaytooter.actmain.afterAccountVerify
@ -18,11 +19,23 @@ import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.LinkHelper
import jp.juggler.subwaytooter.util.openBrowser
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchIO
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.buildJsonObject
import jp.juggler.util.data.encodePercent
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.network.toFormRequestBody
import jp.juggler.util.network.toPost
import jp.juggler.util.ui.dismissSafe
import kotlinx.coroutines.*
import ru.gildor.coroutines.okhttp.await
private val log = LogCategory("Action_Account")
// Androidでは \w や \d がUnicode文字にマッチしてしまうので、IDEの警告を無視する
@Suppress("RegExpSimplifiable")
private val mailRegex =
"""\A[a-z0-9_+&*-]+(?:\.[a-z0-9_+&*-]+)*@(?:[a-z0-9-]+\.)+[a-z]{2,12}\z""".toRegex(
RegexOption.IGNORE_CASE
@ -89,7 +102,7 @@ private fun ActMain.accountCreate(
}
}
val jsonObject = jsonObject {
val jsonObject = buildJsonObject {
put("id", EntityId.CONFIRMING.toString())
put("username", username)
put("acct", username)
@ -102,11 +115,13 @@ private fun ActMain.accountCreate(
r1
}?.let { result ->
val sa: SavedAccount? = null
if (activity.afterAccountVerify(result,
if (activity.afterAccountVerify(
result,
resultTootAccount,
sa,
apiHost,
resultApDomain)
resultApDomain
)
) {
dialogHost.dismissSafe()
dialog_create.dismissSafe()
@ -247,7 +262,7 @@ private fun appServerUnregister(context: Context, account: SavedAccount) {
)
val response = call.await()
if(!response.isSuccessful){
if (!response.isSuccessful) {
log.e("appServerUnregister: $response")
}
} catch (ex: Throwable) {

View File

@ -10,8 +10,8 @@ import jp.juggler.subwaytooter.actmain.handleOtherUri
import jp.juggler.subwaytooter.api.entity.TootApplication
import jp.juggler.subwaytooter.dialog.DlgOpenUrl
import jp.juggler.subwaytooter.table.MutedApp
import jp.juggler.util.dismissSafe
import jp.juggler.util.showToast
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.dismissSafe
// カラム一覧を開く
fun ActMain.openColumnList() =

View File

@ -4,7 +4,6 @@ import android.content.Context
import androidx.appcompat.app.AlertDialog
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.Styler
import jp.juggler.subwaytooter.actmain.addColumn
import jp.juggler.subwaytooter.actmain.reloadAccountSetting
import jp.juggler.subwaytooter.actmain.showColumnMatchAccount
@ -17,10 +16,15 @@ import jp.juggler.subwaytooter.column.ColumnType
import jp.juggler.subwaytooter.column.findStatus
import jp.juggler.subwaytooter.dialog.DlgConfirm.confirm
import jp.juggler.subwaytooter.dialog.pickAccount
import jp.juggler.subwaytooter.getVisibilityCaption
import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.emptyCallback
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.JsonObject
import jp.juggler.util.log.showToast
import jp.juggler.util.network.toPostRequestBuilder
import kotlin.math.max
private class BoostImpl(
@ -229,8 +233,10 @@ private class BoostImpl(
activity.showColumnMatchAccount(accessInfo)
val result =
activity.runApiTask(accessInfo,
progressStyle = ApiTask.PROGRESS_NONE) { client ->
activity.runApiTask(
accessInfo,
progressStyle = ApiTask.PROGRESS_NONE
) { client ->
try {
val targetStatus = syncStatus(client)
boostApi(client, targetStatus)
@ -347,7 +353,7 @@ fun ActMain.clickBoostWithVisibility(
)
}
val captionList = list
.map { Styler.getVisibilityCaption(this, accessInfo.isMisskey, it) }
.map { getVisibilityCaption(this, accessInfo.isMisskey, it) }
.toTypedArray()
AlertDialog.Builder(this)

View File

@ -1,6 +1,7 @@
package jp.juggler.subwaytooter.action
import android.content.Context
import androidx.core.net.toUri
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.actmain.addColumn
@ -14,7 +15,12 @@ import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.matchHost
import jp.juggler.subwaytooter.util.openCustomTab
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.notEmpty
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.network.toFormRequestBody
import jp.juggler.util.network.toPost
private val log = LogCategory("Action_Conversation")
@ -246,8 +252,12 @@ fun ActMain.conversationOtherInstance(
val hostOriginal = Host.parse(urlArg.toUri().authority ?: "")
// 選択肢:ブラウザで表示する
dialog.addAction(getString(R.string.open_web_on_host,
hostOriginal.pretty)) { openCustomTab(urlArg) }
dialog.addAction(
getString(
R.string.open_web_on_host,
hostOriginal.pretty
)
) { openCustomTab(urlArg) }
// トゥートの投稿元タンスにあるアカウント
val localAccountList = ArrayList<SavedAccount>()

View File

@ -9,8 +9,8 @@ import jp.juggler.subwaytooter.column.onFilterDeleted
import jp.juggler.subwaytooter.dialog.ActionsDialog
import jp.juggler.subwaytooter.dialog.DlgConfirm.confirm
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.launchAndShowError
import jp.juggler.util.showToast
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.log.showToast
import okhttp3.Request
// private val log = LogCategory("Action_Filter")

View File

@ -15,7 +15,13 @@ import jp.juggler.subwaytooter.dialog.pickAccount
import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.table.UserRelation
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.log.showToast
import jp.juggler.util.network.toFormRequestBody
import jp.juggler.util.network.toPost
import jp.juggler.util.network.toPostRequestBuilder
import jp.juggler.util.ui.dismissSafe
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
@ -50,10 +56,12 @@ fun ActMain.clickFollow(
relation.blocking || relation.muting ->
Unit // 何もしない
accessInfo.isMisskey && relation.getRequested(who) && !relation.getFollowing(who) ->
followRequestDelete(pos,
followRequestDelete(
pos,
accessInfo,
whoRef,
callback = cancelFollowRequestCompleteCallback)
callback = cancelFollowRequestCompleteCallback
)
relation.getFollowing(who) || relation.getRequested(who) ->
follow(pos, accessInfo, whoRef, bFollow = false, callback = unfollowCompleteCallback)
else ->
@ -100,7 +108,7 @@ fun ActMain.follow(
launchAndShowError {
if (!bConfirmMoved && bFollow && who.moved != null) {
val selected = suspendCancellableCoroutine<Int> { cont ->
val selected = suspendCancellableCoroutine { cont ->
try {
val dialog = AlertDialog.Builder(activity)
.setMessage(

View File

@ -17,7 +17,13 @@ import jp.juggler.subwaytooter.dialog.ActionsDialog
import jp.juggler.subwaytooter.dialog.DlgConfirm.confirm
import jp.juggler.subwaytooter.dialog.DlgTextInput
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.buildJsonObject
import jp.juggler.util.log.showToast
import jp.juggler.util.network.toPostRequestBuilder
import jp.juggler.util.network.toPutRequestBuilder
import jp.juggler.util.ui.dismissSafe
import okhttp3.Request
fun ActMain.clickListTl(pos: Int, accessInfo: SavedAccount, item: TimelineItem?) {
@ -83,10 +89,9 @@ fun ActMain.listCreate(
} else {
client.request(
"/api/v1/lists",
jsonObject {
buildJsonObject {
put("title", title)
}
.toPostRequestBuilder()
}.toPostRequestBuilder()
)
}?.also { result ->
client.publishApiProgress(getString(R.string.parsing_response))
@ -178,16 +183,14 @@ fun ActMain.listRename(
accessInfo.putMisskeyApiToken().apply {
put("listId", item.id)
put("title", text)
}
.toPostRequestBuilder()
}.toPostRequestBuilder()
)
} else {
client.request(
"/api/v1/lists/${item.id}",
jsonObject {
buildJsonObject {
put("title", text)
}
.toPutRequestBuilder()
}.toPutRequestBuilder()
)
}?.also { result ->
client.publishApiProgress(getString(R.string.parsing_response))

View File

@ -13,6 +13,13 @@ import jp.juggler.subwaytooter.column.onListMemberUpdated
import jp.juggler.subwaytooter.dialog.DlgConfirm.confirm
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.asciiPattern
import jp.juggler.util.data.buildJsonArray
import jp.juggler.util.data.buildJsonObject
import jp.juggler.util.log.showToast
import jp.juggler.util.network.*
import okhttp3.Request
import java.util.regex.Pattern
@ -83,10 +90,10 @@ fun ActMain.listMemberAdd(
client.request(
"/api/v1/lists/$listId/accounts",
jsonObject {
buildJsonObject {
put(
"account_ids",
jsonArray {
buildJsonArray {
add(userId.toString())
}
)

View File

@ -1,7 +1,8 @@
package jp.juggler.subwaytooter.action
import androidx.appcompat.app.AlertDialog
import jp.juggler.subwaytooter.*
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.actmain.addColumn
import jp.juggler.subwaytooter.api.entity.TootAccount
import jp.juggler.subwaytooter.api.entity.TootNotification
@ -11,10 +12,10 @@ import jp.juggler.subwaytooter.column.isNotificationColumn
import jp.juggler.subwaytooter.column.removeNotificationOne
import jp.juggler.subwaytooter.column.removeNotifications
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.launchMain
import jp.juggler.util.showToast
import jp.juggler.util.toFormRequestBody
import jp.juggler.util.toPost
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.log.showToast
import jp.juggler.util.network.toFormRequestBody
import jp.juggler.util.network.toPost
fun ActMain.clickNotificationFrom(
pos: Int,

View File

@ -1,6 +1,5 @@
package jp.juggler.subwaytooter.action
import android.annotation.TargetApi
import android.content.Intent
import android.os.Build
import android.util.DisplayMetrics
@ -21,15 +20,14 @@ import jp.juggler.subwaytooter.pref.PrefDevice
import jp.juggler.subwaytooter.pref.PrefS
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.matchHost
import jp.juggler.util.LogCategory
import jp.juggler.util.isLiveActivity
import jp.juggler.util.launchMain
import jp.juggler.util.showToast
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.isLiveActivity
import java.util.*
private val log = LogCategory("Action_OpenPost")
@TargetApi(24)
fun ActPost.saveWindowSize() {
// 最大化状態で起動することはできないので、最大化状態のサイズは覚えない

View File

@ -21,7 +21,11 @@ import jp.juggler.subwaytooter.emoji.UnicodeEmoji
import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.encodePercent
import jp.juggler.util.log.showToast
import jp.juggler.util.network.*
private val rePleromaStatusUrl = """/objects/""".toRegex()
@ -249,13 +253,17 @@ fun ActMain.reactionRemove(
else -> {
when (val newStatus = resultStatus) {
null ->
if (status.decreaseReactionMisskey(reaction.name,
if (status.decreaseReactionMisskey(
reaction.name,
true,
"removeReaction")
"removeReaction"
)
) {
// 1個だけ描画更新するのではなく、TLにある複数の要素をまとめて更新する
column.fireShowContent(reason = "removeReaction complete",
reset = true)
column.fireShowContent(
reason = "removeReaction complete",
reset = true
)
}
else ->

View File

@ -1,7 +1,8 @@
package jp.juggler.subwaytooter.action
import androidx.appcompat.app.AlertDialog
import jp.juggler.subwaytooter.*
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.actmain.addColumn
import jp.juggler.subwaytooter.actmain.defaultInsertPosition
import jp.juggler.subwaytooter.actmain.nextPosition
@ -14,7 +15,11 @@ import jp.juggler.subwaytooter.dialog.pickAccount
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.matchHost
import jp.juggler.subwaytooter.util.openBrowser
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.encodePercent
import jp.juggler.util.log.showToast
import jp.juggler.util.network.toFormRequestBody
import jp.juggler.util.network.toRequest
// profile directory を開く
private fun ActMain.serverProfileDirectory(

View File

@ -18,7 +18,13 @@ import jp.juggler.subwaytooter.dialog.pickAccount
import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.emptyCallback
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.notEmpty
import jp.juggler.util.log.showToast
import jp.juggler.util.network.toFormRequestBody
import jp.juggler.util.network.toPost
import jp.juggler.util.network.toPostRequestBuilder
import kotlinx.coroutines.CancellationException
import okhttp3.Request

View File

@ -12,12 +12,17 @@ import jp.juggler.subwaytooter.api.runApiTask
import jp.juggler.subwaytooter.column.ColumnType
import jp.juggler.subwaytooter.column.onTagFollowChanged
import jp.juggler.subwaytooter.dialog.ActionsDialog
import jp.juggler.subwaytooter.global.appDispatchers
import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.matchHost
import jp.juggler.subwaytooter.util.openCustomTab
import jp.juggler.util.*
import jp.juggler.util.coroutine.AppDispatchers
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.encodePercent
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.network.toFormRequestBody
import jp.juggler.util.network.toPost
import kotlinx.coroutines.withContext
private val log = LogCategory("Action_Tag")
@ -85,8 +90,12 @@ fun ActMain.tagDialog(
}
d.addAction(getString(R.string.open_in_browser)) { openCustomTab(url) }
.addAction(getString(R.string.quote_hashtag_of,
tagWithSharp)) { openPost("$tagWithSharp ") }
.addAction(
getString(
R.string.quote_hashtag_of,
tagWithSharp
)
) { openPost("$tagWithSharp ") }
if (tagList != null && tagList.size > 1) {
val sb = StringBuilder()
@ -265,7 +274,7 @@ fun ActMain.followHashTag(
// 成功時はTagオブジェクトが返る
// フォロー中のタグ一覧を更新する
TootParser(activity, accessInfo).tag(result.jsonObject)?.let { tag ->
withContext(appDispatchers.main.immediate) {
withContext(AppDispatchers.mainImmediate) {
for (column in appState.columnList) {
column.onTagFollowChanged(accessInfo, tag)
}

View File

@ -13,9 +13,8 @@ import jp.juggler.subwaytooter.column.ColumnType
import jp.juggler.subwaytooter.dialog.pickAccount
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.matchHost
import jp.juggler.util.launchMain
import jp.juggler.util.showToast
import java.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.log.showToast
// アカウントを選んでタイムラインカラムを追加
fun ActMain.timeline(
@ -29,7 +28,10 @@ fun ActMain.timeline(
bAllowMisskey = type.bAllowMisskey,
bAllowMastodon = type.bAllowMastodon,
bAuto = true,
message = getString(R.string.account_picker_add_timeline_of, type.name1(applicationContext))
message = getString(
R.string.account_picker_add_timeline_of,
type.name1(applicationContext)
)
)?.let { account ->
when (type) {
ColumnType.PROFILE ->
@ -201,7 +203,12 @@ fun ActMain.timelineAroundByStatusAnotherAccount(
}
}
fun ActMain.clickAroundAccountTL(accessInfo: SavedAccount, pos: Int, who: TootAccount, status: TootStatus?) =
fun ActMain.clickAroundAccountTL(
accessInfo: SavedAccount,
pos: Int,
who: TootAccount,
status: TootStatus?,
) =
timelineAroundByStatusAnotherAccount(
accessInfo,
pos,
@ -210,7 +217,12 @@ fun ActMain.clickAroundAccountTL(accessInfo: SavedAccount, pos: Int, who: TootAc
ColumnType.ACCOUNT_AROUND, allowPseudo = false
)
fun ActMain.clickAroundLTL(accessInfo: SavedAccount, pos: Int, who: TootAccount, status: TootStatus?) =
fun ActMain.clickAroundLTL(
accessInfo: SavedAccount,
pos: Int,
who: TootAccount,
status: TootStatus?,
) =
timelineAroundByStatusAnotherAccount(
accessInfo,
pos,
@ -219,7 +231,12 @@ fun ActMain.clickAroundLTL(accessInfo: SavedAccount, pos: Int, who: TootAccount,
ColumnType.LOCAL_AROUND
)
fun ActMain.clickAroundFTL(accessInfo: SavedAccount, pos: Int, who: TootAccount, status: TootStatus?) =
fun ActMain.clickAroundFTL(
accessInfo: SavedAccount,
pos: Int,
who: TootAccount,
status: TootStatus?,
) =
timelineAroundByStatusAnotherAccount(
accessInfo,
pos,

View File

@ -11,6 +11,7 @@ import jp.juggler.subwaytooter.actmain.addColumn
import jp.juggler.subwaytooter.api.*
import jp.juggler.subwaytooter.api.entity.*
import jp.juggler.subwaytooter.column.*
import jp.juggler.subwaytooter.dialog.DlgConfirm.confirm
import jp.juggler.subwaytooter.dialog.ReportForm
import jp.juggler.subwaytooter.dialog.pickAccount
import jp.juggler.subwaytooter.table.AcctColor
@ -20,6 +21,16 @@ import jp.juggler.subwaytooter.table.UserRelation
import jp.juggler.subwaytooter.util.matchHost
import jp.juggler.subwaytooter.util.openCustomTab
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.buildJsonArray
import jp.juggler.util.data.buildJsonObject
import jp.juggler.util.data.intoStringResource
import jp.juggler.util.data.jsonObjectOf
import jp.juggler.util.log.showToast
import jp.juggler.util.network.*
import jp.juggler.util.ui.dismissSafe
import jp.juggler.util.ui.vg
import kotlinx.coroutines.*
import okhttp3.Request
import java.util.*
@ -160,11 +171,10 @@ private fun ActMain.userMute(
when {
!bMute -> "".toFormRequestBody()
else ->
jsonObject {
buildJsonObject {
put("notifications", bMuteNotification)
if (duration != null) put("duration", duration)
}
.toRequestBody()
}.toRequestBody()
}.toPost()
)?.apply {
val jsonObject = jsonObject
@ -743,12 +753,12 @@ private fun ActMain.userReport(
} else {
client.request(
"/api/v1/reports",
JsonObject().apply {
buildJsonObject {
put("account_id", who.id.toString())
put("comment", comment)
put("forward", forward)
if (status != null) {
put("status_ids", jsonArray {
put("status_ids", buildJsonArray {
add(status.id.toString())
})
}
@ -808,25 +818,13 @@ fun ActMain.userSetShowBoosts(
fun ActMain.userSuggestionDelete(
accessInfo: SavedAccount,
who: TootAccount,
bConfirmed: Boolean = false,
) {
if (!bConfirmed) {
val name = who.decodeDisplayName(applicationContext)
AlertDialog.Builder(this)
.setMessage(
name.intoStringResource(
applicationContext,
R.string.delete_succeeded_confirm
)
)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok) { _, _ ->
userSuggestionDelete(accessInfo, who, bConfirmed = true)
}
.show()
return
}
launchMain {
val activity = this
launchAndShowError {
confirm(
who.decodeDisplayName(activity)
.intoStringResource(activity, R.string.delete_succeeded_confirm)
)
runApiTask(accessInfo) { client ->
client.request("/api/v1/suggestions/${who.id}", Request.Builder().delete())
}?.let { result ->
@ -853,9 +851,8 @@ fun ActMain.userSetStatusNotification(
runApiTask(accessInfo) { client ->
client.request(
"/api/v1/accounts/$whoId/follow",
jsonObject {
put("notify", enabled)
}.toPostRequestBuilder()
jsonObjectOf("notify" to enabled)
.toPostRequestBuilder()
)?.also { result ->
val relation = parseItem(
::TootRelationShip,

View File

@ -21,7 +21,11 @@ import jp.juggler.subwaytooter.pref.PrefB
import jp.juggler.subwaytooter.pref.PrefI
import jp.juggler.subwaytooter.span.MyClickableSpan
import jp.juggler.subwaytooter.util.openCustomTab
import jp.juggler.util.*
import jp.juggler.util.data.addTo
import jp.juggler.util.data.cast
import jp.juggler.util.data.notEmpty
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
private val log = LogCategory("ActMainActions")
@ -73,8 +77,10 @@ fun ActMain.onBackPressedImpl() {
else -> showToast(false, R.string.missing_closeable_column)
}
1 -> closeColumn(closeableColumnList.first())
else -> showToast(false,
R.string.cant_close_column_by_back_button_when_multiple_column_shown)
else -> showToast(
false,
R.string.cant_close_column_by_back_button_when_multiple_column_shown
)
}
}
else /* PrefI.BACK_ASK_ALWAYS */ -> {

View File

@ -7,8 +7,8 @@ import jp.juggler.subwaytooter.api.entity.Acct
import jp.juggler.subwaytooter.api.entity.EntityId
import jp.juggler.subwaytooter.column.*
import jp.juggler.subwaytooter.pref.PrefI
import jp.juggler.util.decodeJsonObject
import jp.juggler.util.isLiveActivity
import jp.juggler.util.data.decodeJsonObject
import jp.juggler.util.ui.isLiveActivity
// マルチウィンドウモードでは投稿画面から直接呼ばれる
// 通常モードでは activityResultHandler 経由で呼ばれる

View File

@ -19,6 +19,11 @@ import jp.juggler.subwaytooter.pref.PrefS
import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.*
import jp.juggler.util.data.clip
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.getAdaptiveRippleDrawableRound
import jp.juggler.util.ui.vg
import org.jetbrains.anko.backgroundDrawable
import kotlin.math.abs
import kotlin.math.min
@ -489,7 +494,7 @@ fun ActMain.updateColumnStripSelection(position: Int, positionOffset: Float) {
if (vr.first <= vr.last) {
val child = env.tabletLayoutManager.findViewByPosition(vr.first)
slideRatio =
clipRange(0f, 1f, abs((child?.left ?: 0) / nColumnWidth.toFloat()))
(abs((child?.left ?: 0) / nColumnWidth.toFloat())).clip(0f, 1f)
}
llColumnStrip.setVisibleRange(vr.first, vr.last, slideRatio)

View File

@ -10,10 +10,10 @@ import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.appsetting.AppDataExporter
import jp.juggler.subwaytooter.column.Column
import jp.juggler.subwaytooter.notification.setImportProtector
import jp.juggler.util.LogCategory
import jp.juggler.util.launchProgress
import jp.juggler.util.runOnMainLooper
import jp.juggler.util.showToast
import jp.juggler.util.coroutine.launchProgress
import jp.juggler.util.coroutine.runOnMainLooper
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
@ -51,7 +51,7 @@ fun ActMain.importAppData(uri: Uri) {
val cacheDir = cacheDir
cacheDir.mkdir()
val file = File(cacheDir, "SubwayTooter.${Process.myPid()}.${Process.myTid()}.tmp")
val copyBytes = contentResolver.openInputStream(uri)?.let { inStream ->
val copyBytes = contentResolver.openInputStream(uri)?.use { inStream ->
FileOutputStream(file).use { outStream ->
inStream.copyTo(outStream)
}

View File

@ -4,6 +4,7 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.action.conversationOtherInstance
@ -25,7 +26,15 @@ import jp.juggler.subwaytooter.pref.PrefDevice
import jp.juggler.subwaytooter.pref.PrefS
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.LinkHelper
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.decodePercent
import jp.juggler.util.data.groupEx
import jp.juggler.util.data.notBlank
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.log.withCaption
import jp.juggler.util.queryIntentActivitiesCompat
import java.util.concurrent.atomic.AtomicReference
private val log = LogCategory("ActMainIntent")

View File

@ -8,17 +8,17 @@ import androidx.core.view.GravityCompat
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.App1
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.Styler
import jp.juggler.subwaytooter.actpost.CompletionHelper
import jp.juggler.subwaytooter.api.entity.TootVisibility
import jp.juggler.subwaytooter.dialog.pickAccount
import jp.juggler.subwaytooter.getVisibilityIconId
import jp.juggler.subwaytooter.pref.PrefB
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.PostImpl
import jp.juggler.subwaytooter.util.PostResult
import jp.juggler.util.hideKeyboard
import jp.juggler.util.launchAndShowError
import jp.juggler.util.launchMain
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.ui.hideKeyboard
import org.jetbrains.anko.imageResource
// 簡易投稿入力のテキスト
@ -28,7 +28,7 @@ val ActMain.quickPostText: String
fun ActMain.initUIQuickPost() {
etQuickPost.typeface = ActMain.timelineFont
if (!PrefB.bpQuickPostBar(pref)) {
if (!PrefB.bpQuickPostBar.invoke(pref)) {
llQuickPostBar.visibility = View.GONE
}
@ -70,7 +70,7 @@ fun ActMain.initUIQuickPost() {
fun ActMain.showQuickPostVisibility() {
btnQuickPostMenu.imageResource =
when (val resId = Styler.getVisibilityIconId(false, quickPostVisibility)) {
when (val resId = getVisibilityIconId(false, quickPostVisibility)) {
R.drawable.ic_question -> R.drawable.ic_description
else -> resId
}

View File

@ -7,18 +7,24 @@ import android.view.ViewGroup
import android.widget.LinearLayout
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.Styler
import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.subwaytooter.boostAlpha
import jp.juggler.subwaytooter.itemviewholder.ItemViewHolder
import jp.juggler.subwaytooter.pref.PrefB
import jp.juggler.subwaytooter.pref.PrefF
import jp.juggler.subwaytooter.pref.PrefI
import jp.juggler.subwaytooter.pref.PrefS
import jp.juggler.subwaytooter.pref.impl.StringPref
import jp.juggler.subwaytooter.round_ratio
import jp.juggler.subwaytooter.span.MyClickableSpan
import jp.juggler.subwaytooter.util.CustomShare
import jp.juggler.subwaytooter.view.ListDivider
import jp.juggler.util.*
import jp.juggler.util.data.clip
import jp.juggler.util.data.notEmpty
import jp.juggler.util.data.notZero
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.attrColor
import jp.juggler.util.ui.getAdaptiveRippleDrawableRound
import org.jetbrains.anko.backgroundDrawable
import java.util.*
import kotlin.math.max
@ -92,12 +98,12 @@ fun ActMain.reloadRoundRatio() {
?.takeIf { it.isFinite() }
?: 33f
}
Styler.round_ratio = clipRange(0f, 1f, sizeDp / 100f) * 0.5f
round_ratio = (sizeDp / 100f).clip(0f, 1f) * 0.5f
}
// initUI から呼ばれる
fun ActMain.reloadBoostAlpha() {
Styler.boostAlpha = PrefS.spBoostAlpha(pref)
boostAlpha = PrefS.spBoostAlpha(pref)
.toIntOrNull()
?.toFloat()
?.let { (it + 0.5f) / 100f }
@ -118,7 +124,7 @@ private fun Float.clipFontSize(): Float =
if (isNaN()) this else max(1f, this)
fun ActMain.reloadTextSize() {
timelineFontSizeSp = PrefF.fpTimelineFontSize(pref).clipFontSize()
timelineFontSizeSp = PrefF.fpTimelineFontSize.invoke(pref).clipFontSize()
acctFontSizeSp = PrefF.fpAcctFontSize(pref).clipFontSize()
notificationTlFontSizeSp = PrefF.fpNotificationTlFontSize(pref).clipFontSize()
headerTextSizeSp = PrefF.fpHeaderTextSize(pref).clipFontSize()

View File

@ -6,7 +6,7 @@ import androidx.recyclerview.widget.RecyclerView
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.column.Column
import jp.juggler.subwaytooter.view.GravitySnapHelper
import jp.juggler.util.clipRange
import jp.juggler.util.data.clip
import kotlin.math.abs
import kotlin.math.min
@ -26,7 +26,7 @@ class ActMainTabletViews(val actMain: ActMain) {
val child = tabletLayoutManager.findViewByPosition(vs)
val slideRatio =
clipRange(0f, 1f, abs((child?.left ?: 0) / actMain.nColumnWidth.toFloat()))
abs((child?.left ?: 0) / actMain.nColumnWidth.toFloat()).clip(0f, 1f)
if (slideRatio >= 0.95f) {
++vs
++ve

View File

@ -10,8 +10,8 @@ import jp.juggler.subwaytooter.column.getColumnName
import jp.juggler.subwaytooter.columnviewholder.ColumnViewHolder
import jp.juggler.subwaytooter.columnviewholder.onPageCreate
import jp.juggler.subwaytooter.columnviewholder.onPageDestroy
import jp.juggler.subwaytooter.util.Benchmark
import jp.juggler.util.LogCategory
import jp.juggler.util.log.Benchmark
import jp.juggler.util.log.LogCategory
import java.util.*
internal class ColumnPagerAdapter(private val activity: ActMain) : PagerAdapter() {

View File

@ -30,8 +30,19 @@ import jp.juggler.subwaytooter.pref.PrefS
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.VersionString
import jp.juggler.subwaytooter.util.openBrowser
import jp.juggler.util.*
import kotlinx.coroutines.Dispatchers
import jp.juggler.util.coroutine.AppDispatchers
import jp.juggler.util.coroutine.launchIO
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.decodeJsonObject
import jp.juggler.util.data.decodeUTF8
import jp.juggler.util.data.notEmpty
import jp.juggler.util.getPackageInfoCompat
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.activity
import jp.juggler.util.ui.attrColor
import jp.juggler.util.ui.createColoredDrawable
import kotlinx.coroutines.withContext
import org.jetbrains.anko.backgroundColor
import java.lang.ref.WeakReference
@ -187,7 +198,7 @@ class SideMenuAdapter(
?: error("missing appVersion json")
releaseInfo = json
versionText = createVersionRow()
withContext(Dispatchers.Main) {
withContext(AppDispatchers.mainImmediate) {
lastVersionView?.get()?.text = versionText
}
} catch (ex: Throwable) {

View File

@ -7,7 +7,7 @@ import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import jp.juggler.subwaytooter.R
import jp.juggler.util.attrDrawable
import jp.juggler.util.ui.attrDrawable
class TabletColumnDivider(context: Context) : RecyclerView.ItemDecoration() {
@ -34,7 +34,7 @@ class TabletColumnDivider(context: Context) : RecyclerView.ItemDecoration() {
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
state: RecyclerView.State,
) {
outRect.set(0, 0, barWidth, 0)
}

View File

@ -7,7 +7,12 @@ import jp.juggler.subwaytooter.api.entity.TootVisibility
import jp.juggler.subwaytooter.dialog.pickAccount
import jp.juggler.subwaytooter.table.AcctColor
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.notZero
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.attrColor
import jp.juggler.util.ui.getAdaptiveRippleDrawableRound
import org.jetbrains.anko.textColor
import kotlin.math.max

View File

@ -6,11 +6,12 @@ import android.view.View
import androidx.appcompat.app.AlertDialog
import jp.juggler.subwaytooter.ActPost
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.Styler
import jp.juggler.subwaytooter.api.ApiTask
import jp.juggler.subwaytooter.api.TootApiResult
import jp.juggler.subwaytooter.api.entity.*
import jp.juggler.subwaytooter.api.runApiTask
import jp.juggler.subwaytooter.calcIconRound
import jp.juggler.subwaytooter.defaultColorIcon
import jp.juggler.subwaytooter.dialog.ActionsDialog
import jp.juggler.subwaytooter.dialog.DlgFocusPoint
import jp.juggler.subwaytooter.dialog.DlgTextInput
@ -18,7 +19,14 @@ import jp.juggler.subwaytooter.pref.PrefB
import jp.juggler.subwaytooter.util.AttachmentRequest
import jp.juggler.subwaytooter.util.PostAttachment
import jp.juggler.subwaytooter.view.MyNetworkImageView
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.log.withCaption
import jp.juggler.util.network.toPutRequestBuilder
import jp.juggler.util.ui.dismissSafe
import jp.juggler.util.ui.vg
private val log = LogCategory("ActPostAttachment")
@ -66,9 +74,9 @@ fun ActPost.showMediaAttachmentOne(iv: MyNetworkImageView, idx: Int) {
val a = pa.attachment
when {
a == null || pa.status != PostAttachment.Status.Ok -> {
iv.setDefaultImage(Styler.defaultColorIcon(this, R.drawable.ic_upload))
iv.setErrorImage(Styler.defaultColorIcon(this, R.drawable.ic_clip))
iv.setImageUrl(Styler.calcIconRound(iv.layoutParams.width), null)
iv.setDefaultImage(defaultColorIcon(this, R.drawable.ic_upload))
iv.setErrorImage(defaultColorIcon(this, R.drawable.ic_clip))
iv.setImageUrl(calcIconRound(iv.layoutParams.width), null)
}
else -> {
@ -80,9 +88,9 @@ fun ActPost.showMediaAttachmentOne(iv: MyNetworkImageView, idx: Int) {
TootAttachmentType.Audio -> R.drawable.ic_music_note
else -> R.drawable.ic_clip
}
iv.setDefaultImage(Styler.defaultColorIcon(this, defaultIconId))
iv.setErrorImage(Styler.defaultColorIcon(this, defaultIconId))
iv.setImageUrl(Styler.calcIconRound(iv.layoutParams.width), a.preview_url)
iv.setDefaultImage(defaultColorIcon(this, defaultIconId))
iv.setErrorImage(defaultColorIcon(this, defaultIconId))
iv.setImageUrl(calcIconRound(iv.layoutParams.width), a.preview_url)
}
}
}
@ -253,7 +261,7 @@ fun ActPost.sendFocusPoint(pa: PostAttachment, attachment: TootAttachment, x: Fl
try {
client.request(
"/api/v1/media/${attachment.id}",
jsonObject {
buildJsonObject {
put("focus", "%.2f,%.2f".format(x, y))
}.toPutRequestBuilder()
)?.also { result ->

View File

@ -7,9 +7,9 @@ import jp.juggler.subwaytooter.api.entity.TootAccount
import jp.juggler.subwaytooter.api.entity.TootInstance
import jp.juggler.subwaytooter.api.runApiTask
import jp.juggler.subwaytooter.util.EmojiDecoder
import jp.juggler.util.attrColor
import jp.juggler.util.launchMain
import jp.juggler.util.wrapWeakReference
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.wrapWeakReference
import jp.juggler.util.ui.attrColor
// 最大文字数を取得する
// 暫定で仮の値を返すことがある

View File

@ -13,7 +13,12 @@ import jp.juggler.subwaytooter.table.PostDraft
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.subwaytooter.util.PostAttachment
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchProgress
import jp.juggler.util.data.JsonException
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.decodeJsonObject
import jp.juggler.util.data.toJsonArray
import jp.juggler.util.log.LogCategory
import kotlinx.coroutines.isActive
import okhttp3.Request
import ru.gildor.coroutines.okhttp.await

View File

@ -1,7 +1,6 @@
package jp.juggler.subwaytooter.actpost
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import jp.juggler.subwaytooter.ActMain
@ -20,7 +19,14 @@ 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.*
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.data.CharacterGroup
import jp.juggler.util.getIntentExtra
import jp.juggler.util.getStreamUriExtra
import jp.juggler.util.getStreamUriListExtra
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.vg
private val log = LogCategory("ActPostExtra")
@ -243,7 +249,7 @@ fun ActPost.initializeFromSharedIntent(sharedIntent: Intent) {
Intent.ACTION_SEND_MULTIPLE -> {
val listUri = sharedIntent.getStreamUriListExtra()
?.filterNotNull()
?.filterNotNull()
if (listUri?.isNotEmpty() == true) {
for (uri in listUri) {
addAttachment(uri)
@ -261,7 +267,7 @@ fun ActPost.initializeFromSharedIntent(sharedIntent: Intent) {
appendContentText(sharedIntent)
}
} catch (ex: Throwable) {
log.e(ex,"initializeFromSharedIntent failed.")
log.e(ex, "initializeFromSharedIntent failed.")
}
}

View File

@ -12,9 +12,9 @@ import jp.juggler.subwaytooter.ActPost
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.subwaytooter.util.LinkHelper
import jp.juggler.util.LogCategory
import jp.juggler.util.decodeUTF8
import jp.juggler.util.loadRawResource
import jp.juggler.util.data.decodeUTF8
import jp.juggler.util.data.loadRawResource
import jp.juggler.util.log.LogCategory
private val log = LogCategory("ActPostMushroom")

View File

@ -1,8 +1,8 @@
package jp.juggler.subwaytooter.actpost
import jp.juggler.subwaytooter.ActPost
import jp.juggler.util.notEmpty
import jp.juggler.util.vg
import jp.juggler.util.data.notEmpty
import jp.juggler.util.ui.vg
private fun Double?.finiteOrZero(): Double = if (this?.isFinite() == true) this else 0.0

View File

@ -3,16 +3,20 @@ package jp.juggler.subwaytooter.actpost
import androidx.appcompat.app.AlertDialog
import jp.juggler.subwaytooter.ActPost
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.Styler
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.subwaytooter.api.entity.Acct
import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.subwaytooter.api.entity.TootVisibility
import jp.juggler.subwaytooter.api.runApiTask
import jp.juggler.subwaytooter.api.syncStatus
import jp.juggler.subwaytooter.calcIconRound
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.decodeJsonObject
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.ui.vg
private val log = LogCategory("ActPostReply")
@ -35,8 +39,10 @@ fun ActPost.showReplyTo() {
short = true,
decodeEmoji = true,
).decodeHTML(states.inReplyToText)
views.ivReply.setImageUrl(Styler.calcIconRound(views.ivReply.layoutParams),
states.inReplyToImage)
views.ivReply.setImageUrl(
calcIconRound(views.ivReply.layoutParams),
states.inReplyToImage
)
}
}

View File

@ -10,10 +10,10 @@ import jp.juggler.subwaytooter.api.entity.parseItem
import jp.juggler.subwaytooter.dialog.DlgDateTime
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.PostAttachment
import jp.juggler.util.LogCategory
import jp.juggler.util.cast
import jp.juggler.util.decodeJsonObject
import jp.juggler.util.notEmpty
import jp.juggler.util.data.cast
import jp.juggler.util.data.decodeJsonObject
import jp.juggler.util.data.notEmpty
import jp.juggler.util.log.LogCategory
private val log = LogCategory("ActPostSchedule")

View File

@ -7,9 +7,9 @@ import jp.juggler.subwaytooter.api.entity.*
import jp.juggler.subwaytooter.kJson
import jp.juggler.subwaytooter.util.AttachmentPicker
import jp.juggler.subwaytooter.util.PostAttachment
import jp.juggler.util.LogCategory
import jp.juggler.util.decodeJsonObject
import jp.juggler.util.toJsonArray
import jp.juggler.util.data.decodeJsonObject
import jp.juggler.util.data.toJsonArray
import jp.juggler.util.log.LogCategory
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString

View File

@ -3,14 +3,17 @@ package jp.juggler.subwaytooter.actpost
import androidx.appcompat.app.AlertDialog
import jp.juggler.subwaytooter.ActPost
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.Styler
import jp.juggler.subwaytooter.api.entity.InstanceCapability
import jp.juggler.subwaytooter.api.entity.TootInstance
import jp.juggler.subwaytooter.api.entity.TootVisibility
import jp.juggler.subwaytooter.getVisibilityCaption
import jp.juggler.subwaytooter.getVisibilityIconId
fun ActPost.showVisibility() {
val iconId = Styler.getVisibilityIconId(account?.isMisskey == true,
states.visibility ?: TootVisibility.Public)
val iconId = getVisibilityIconId(
account?.isMisskey == true,
states.visibility ?: TootVisibility.Public
)
views.btnVisibility.setImageResource(iconId)
}
@ -58,7 +61,7 @@ fun ActPost.openVisibilityPicker() {
)
}
val captionList = list
.map { Styler.getVisibilityCaption(this, account?.isMisskey == true, it) }
.map { getVisibilityCaption(this, account?.isMisskey == true, it) }
.toTypedArray()
AlertDialog.Builder(this)

View File

@ -24,6 +24,10 @@ import jp.juggler.subwaytooter.util.EmojiDecoder
import jp.juggler.subwaytooter.util.PopupAutoCompleteAcct
import jp.juggler.subwaytooter.view.MyEditText
import jp.juggler.util.*
import jp.juggler.util.data.asciiRegex
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.attrColor
import jp.juggler.util.ui.showKeyboard
import kotlin.math.min
// 入力補完機能

View File

@ -6,10 +6,10 @@ import jp.juggler.subwaytooter.api.ApiTask
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.subwaytooter.api.entity.TootTag
import jp.juggler.subwaytooter.api.runApiTask
import jp.juggler.util.jsonObject
import jp.juggler.util.launchMain
import jp.juggler.util.toPostRequestBuilder
import jp.juggler.util.wrapWeakReference
import jp.juggler.util.coroutine.launchMain
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.wrapWeakReference
import jp.juggler.util.network.toPostRequestBuilder
class FeaturedTagCache(val list: List<TootTag>, val time: Long)
@ -33,8 +33,7 @@ fun ActPost.updateFeaturedTags() {
if (account.isMisskey) {
client.request(
"/api/hashtags/trend",
jsonObject { }
.toPostRequestBuilder()
JsonObject().toPostRequestBuilder()
)?.also { result ->
val list = TootTag.parseList(
TootParser(this@runApiTask, account),

View File

@ -5,13 +5,13 @@ import android.content.Context
import android.os.SystemClock
import jp.juggler.subwaytooter.App1
import jp.juggler.subwaytooter.api.entity.Host
import jp.juggler.subwaytooter.dialog.ProgressDialogEx
import jp.juggler.subwaytooter.global.appDispatchers
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.clip
import jp.juggler.util.dismissSafe
import jp.juggler.util.isMainThread
import jp.juggler.util.withCaption
import jp.juggler.util.coroutine.AppDispatchers
import jp.juggler.util.coroutine.isMainThread
import jp.juggler.util.data.clip
import jp.juggler.util.log.withCaption
import jp.juggler.util.ui.ProgressDialogEx
import jp.juggler.util.ui.dismissSafe
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
@ -71,7 +71,7 @@ private class TootTaskRunner(
try {
openProgress()
supervisorScope {
async(appDispatchers.io) {
async(AppDispatchers.io) {
backgroundBlock(context, client)
}.also {
task = it
@ -224,13 +224,15 @@ suspend fun <A : Context> A.runApiTask(
progressPrefix: String? = null,
progressSetup: (progress: ProgressDialogEx) -> Unit = ApiTask.defaultProgressSetupCallback,
backgroundBlock: suspend A.(client: TootApiClient) -> TootApiResult?,
) = TootTaskRunner.runApiTask(this,
) = TootTaskRunner.runApiTask(
this,
accessInfo,
null,
progressStyle,
progressPrefix,
progressSetup,
backgroundBlock)
backgroundBlock
)
suspend fun <A : Context> A.runApiTask(
apiHost: Host,
@ -238,23 +240,27 @@ suspend fun <A : Context> A.runApiTask(
progressPrefix: String? = null,
progressSetup: (progress: ProgressDialogEx) -> Unit = ApiTask.defaultProgressSetupCallback,
backgroundBlock: suspend A.(client: TootApiClient) -> TootApiResult?,
) = TootTaskRunner.runApiTask(this,
) = TootTaskRunner.runApiTask(
this,
null,
apiHost,
progressStyle,
progressPrefix,
progressSetup,
backgroundBlock)
backgroundBlock
)
suspend fun <A : Context> A.runApiTask(
progressStyle: Int = ApiTask.PROGRESS_SPINNER,
progressPrefix: String? = null,
progressSetup: (progress: ProgressDialogEx) -> Unit = ApiTask.defaultProgressSetupCallback,
backgroundBlock: suspend A.(client: TootApiClient) -> TootApiResult?,
) = TootTaskRunner.runApiTask(this,
) = TootTaskRunner.runApiTask(
this,
null,
null,
progressStyle,
progressPrefix,
progressSetup,
backgroundBlock)
backgroundBlock
)

View File

@ -1,9 +1,8 @@
package jp.juggler.subwaytooter.api
import jp.juggler.subwaytooter.api.entity.*
import jp.juggler.util.LogCategory
import jp.juggler.util.cast
import java.util.*
import jp.juggler.util.data.cast
import jp.juggler.util.log.LogCategory
class DuplicateMap {

View File

@ -10,6 +10,13 @@ import jp.juggler.subwaytooter.table.ClientInfo
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.*
import jp.juggler.util.*
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.log.withCaption
import jp.juggler.util.network.toFormRequestBody
import jp.juggler.util.network.toPost
import jp.juggler.util.network.toPostRequestBuilder
import okhttp3.*
import okhttp3.internal.closeQuietly
import java.util.*
@ -61,7 +68,7 @@ class TootApiClient(
}
fun getScopeArrayMisskey(@Suppress("UNUSED_PARAMETER") ti: TootInstance) =
JsonArray().apply {
buildJsonArray {
if (ti.versionGE(TootInstance.MISSKEY_VERSION_11)) {
// https://github.com/syuilo/misskey/blob/master/src/server/api/kinds.ts
arrayOf(
@ -525,9 +532,7 @@ class TootApiClient(
val result = TootApiResult.makeWithCaption(apiHost?.pretty)
if (result.error != null) return result
if (sendRequest(result) {
JsonObject().apply {
put("appId", appId)
}
jsonObjectOf("appId" to appId)
.toPostRequestBuilder()
.url("https://${apiHost?.ascii}/api/app/show")
.build()

View File

@ -2,6 +2,8 @@ package jp.juggler.subwaytooter.api
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.util.*
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import okhttp3.Response
import okhttp3.WebSocket

View File

@ -4,9 +4,9 @@ import android.content.Context
import jp.juggler.subwaytooter.api.entity.*
import jp.juggler.subwaytooter.table.UserRelation
import jp.juggler.subwaytooter.util.LinkHelper
import jp.juggler.util.JsonArray
import jp.juggler.util.JsonObject
import jp.juggler.util.WordTrieTree
import jp.juggler.util.data.JsonArray
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.WordTrieTree
class TootParser(
val context: Context,

View File

@ -1,9 +1,9 @@
package jp.juggler.subwaytooter.api.entity
import jp.juggler.util.JsonArray
import jp.juggler.util.JsonObject
import jp.juggler.util.LogCategory
import jp.juggler.util.cast
import jp.juggler.util.data.JsonArray
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.cast
import jp.juggler.util.log.LogCategory
class APAttachment(jsonArray: JsonArray?) {

View File

@ -2,10 +2,10 @@ package jp.juggler.subwaytooter.api.entity
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.subwaytooter.emoji.CustomEmoji
import jp.juggler.util.JsonArray
import jp.juggler.util.JsonObject
import jp.juggler.util.LogCategory
import jp.juggler.util.cast
import jp.juggler.util.data.JsonArray
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.cast
import jp.juggler.util.log.LogCategory
class APTag(parser: TootParser, jsonArray: JsonArray?) {
@ -51,12 +51,14 @@ class APTag(parser: TootParser, jsonArray: JsonArray?) {
"Mention" ->
Acct.parse(it.string("name")!!)
.let { acct ->
mentions.add(TootMention(
id = EntityId.DEFAULT,
url = it.string("href")!!,
acct = acct, // may local
username = acct.username
))
mentions.add(
TootMention(
id = EntityId.DEFAULT,
url = it.string("href")!!,
acct = acct, // may local
username = acct.username
)
)
}
}
} catch (ex: Throwable) {

View File

@ -1,6 +1,6 @@
package jp.juggler.subwaytooter.api.entity
import jp.juggler.util.notZero
import jp.juggler.util.data.notZero
import java.net.IDN
import java.util.concurrent.ConcurrentHashMap

View File

@ -4,9 +4,9 @@ import android.content.ContentValues
import android.content.Intent
import android.database.Cursor
import android.os.Bundle
import jp.juggler.util.JsonObject
import jp.juggler.util.getStringOrNull
import jp.juggler.util.notZero
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.getStringOrNull
import jp.juggler.util.data.notZero
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor

View File

@ -1,10 +1,10 @@
package jp.juggler.subwaytooter.api.entity
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.util.JsonArray
import jp.juggler.util.JsonException
import jp.juggler.util.JsonObject
import jp.juggler.util.LogCategory
import jp.juggler.util.data.JsonArray
import jp.juggler.util.data.JsonException
import jp.juggler.util.data.JsonObject
import jp.juggler.util.log.LogCategory
object EntityUtil {
val log = LogCategory("EntityUtil")

View File

@ -1,7 +1,7 @@
package jp.juggler.subwaytooter.api.entity
import jp.juggler.util.JsonArray
import jp.juggler.util.JsonObject
import jp.juggler.util.data.JsonArray
import jp.juggler.util.data.JsonObject
class MisskeyAntenna(src: JsonObject) : TimelineItem() {

View File

@ -1,8 +1,8 @@
package jp.juggler.subwaytooter.api.entity
import jp.juggler.subwaytooter.emoji.CustomEmoji
import jp.juggler.util.JsonObject
import jp.juggler.util.LogCategory
import jp.juggler.util.data.JsonObject
import jp.juggler.util.log.LogCategory
class MisskeyNoteUpdate(apDomain: Host, apiHost: Host, src: JsonObject) {
companion object {

View File

@ -1,6 +1,6 @@
package jp.juggler.subwaytooter.api.entity
import jp.juggler.util.JsonObject
import jp.juggler.util.data.JsonObject
class NicoProfileEmoji(
val url: String,

View File

@ -17,6 +17,9 @@ import jp.juggler.subwaytooter.util.NetworkEmojiInvalidator
import jp.juggler.subwaytooter.util.matchHost
import jp.juggler.subwaytooter.view.MyLinkMovementMethod
import jp.juggler.util.*
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.vg
import java.util.*
import java.util.regex.Pattern
@ -203,7 +206,7 @@ open class TootAccount(parser: TootParser, src: JsonObject) : HostAndDomain {
if (parser.misskeyDecodeProfilePin) {
val list = parseList(::TootStatus, parser, src.jsonArray("pinnedNotes"))
list.forEach { it.pinned = true }
this.pinnedNotes = if (list.isNotEmpty()) list else null
this.pinnedNotes = list.ifEmpty { null }
}
val profile = src.jsonObject("profile")

View File

@ -4,9 +4,9 @@ import android.text.Spannable
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.subwaytooter.emoji.CustomEmoji
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.util.JsonObject
import jp.juggler.util.LogCategory
import jp.juggler.util.notEmpty
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.notEmpty
import jp.juggler.util.log.LogCategory
class TootAnnouncement(parser: TootParser, src: JsonObject) {

View File

@ -1,7 +1,7 @@
package jp.juggler.subwaytooter.api.entity
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.util.JsonObject
import jp.juggler.util.data.JsonObject
class TootApplication(parser: TootParser, src: JsonObject) {

View File

@ -4,6 +4,7 @@ import android.content.SharedPreferences
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.subwaytooter.pref.PrefB
import jp.juggler.util.*
import jp.juggler.util.data.*
class TootAttachment : TootAttachmentLike {
@ -11,7 +12,7 @@ class TootAttachment : TootAttachmentLike {
private fun parseFocusValue(parent: JsonObject?, key: String): Float {
if (parent != null) {
val dv = parent.double(key)
if (dv != null && dv.isFinite()) return clipRange(-1f, 1f, dv.toFloat())
if (dv != null && dv.isFinite()) return dv.toFloat().clip(-1f, 1f)
}
return 0f
}
@ -218,7 +219,7 @@ class TootAttachment : TootAttachmentLike {
}
}
fun encodeJson() = jsonObject {
fun encodeJson() = buildJsonObject {
put(KEY_IS_STRING_ID, true)
put(KEY_ID, id.toString())
put(KEY_TYPE, type.id)
@ -232,8 +233,8 @@ class TootAttachment : TootAttachmentLike {
put(KEY_BLURHASH, blurhash)
if (focusX != 0f || focusY != 0f) {
put(KEY_META, jsonObject {
put(KEY_FOCUS, jsonObject {
put(KEY_META, buildJsonObject {
put(KEY_FOCUS, buildJsonObject {
put(KEY_X, focusX)
put(KEY_Y, focusY)
})

View File

@ -1,8 +1,8 @@
package jp.juggler.subwaytooter.api.entity
import android.content.SharedPreferences
import jp.juggler.util.JsonArray
import jp.juggler.util.notBlank
import jp.juggler.util.data.JsonArray
import jp.juggler.util.data.notBlank
class TootAttachmentMSP(
val preview_url: String,

View File

@ -3,8 +3,8 @@ package jp.juggler.subwaytooter.api.entity
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.subwaytooter.pref.pref
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.util.JsonObject
import jp.juggler.util.filterNotEmpty
import jp.juggler.util.data.JsonObject
import jp.juggler.util.data.filterNotEmpty
class TootCard(

View File

@ -1,7 +1,7 @@
package jp.juggler.subwaytooter.api.entity
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.util.JsonObject
import jp.juggler.util.data.JsonObject
class TootContext(
// The ancestors of the status in the conversation, as a list of Statuses

View File

@ -1,7 +1,7 @@
package jp.juggler.subwaytooter.api.entity
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.util.JsonObject
import jp.juggler.util.data.JsonObject
class TootConversationSummary(parser: TootParser, src: JsonObject) : TimelineItem() {

View File

@ -1,7 +1,6 @@
package jp.juggler.subwaytooter.api.entity
import jp.juggler.util.JsonArray
import java.util.ArrayList
import jp.juggler.util.data.JsonArray
class TootDomainBlock(
val domain: Host,
@ -10,13 +9,13 @@ class TootDomainBlock(
companion object {
fun parseList(array: JsonArray?) =
ArrayList<TootDomainBlock>().also { result ->
array ?: return@also
result.ensureCapacity(array.size)
array.stringList().forEach {
if (it.isNotEmpty()) {
result.add(TootDomainBlock(Host.parse(it)))
}
}
array ?: return@also
result.ensureCapacity(array.size)
array.stringList().forEach {
if (it.isNotEmpty()) {
result.add(TootDomainBlock(Host.parse(it)))
}
}
}
}
}

View File

@ -3,6 +3,9 @@ package jp.juggler.subwaytooter.api.entity
import android.content.Context
import jp.juggler.subwaytooter.R
import jp.juggler.util.*
import jp.juggler.util.data.JsonArray
import jp.juggler.util.data.JsonObject
import jp.juggler.util.log.LogCategory
class TootFilter(src: JsonObject) : TimelineItem() {
@ -28,7 +31,7 @@ class TootFilter(src: JsonObject) : TimelineItem() {
FilterContext("account", CONTEXT_PROFILE, R.string.filter_profile)
)
private val CONTEXT_MAP = CONTEXT_LIST.map { Pair(it.name, it) }.toMap()
private val CONTEXT_MAP = CONTEXT_LIST.associateBy { it.name }
private fun parseFilterContext(src: JsonArray?): Int {
var n = 0

View File

@ -8,7 +8,11 @@ import jp.juggler.subwaytooter.pref.PrefB
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.LinkHelper
import jp.juggler.subwaytooter.util.VersionString
import jp.juggler.util.*
import jp.juggler.util.coroutine.launchDefault
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.withCaption
import jp.juggler.util.network.toPostRequestBuilder
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.withTimeout
@ -310,7 +314,7 @@ class TootInstance(parser: TootParser, src: JsonObject) {
if (result.error != null) return result
if (sendRequest(result) {
jsonObject {
buildJsonObject {
(forceAccessToken ?: account?.misskeyApiToken)
?.notEmpty()?.let { put("i", it) }
}.toPostRequestBuilder()
@ -331,7 +335,7 @@ class TootInstance(parser: TootParser, src: JsonObject) {
if (result.error != null) return result
if (sendRequest(result) {
jsonObject {
buildJsonObject {
put("dummy", 1)
(forceAccessToken ?: account?.misskeyApiToken)
?.notEmpty()?.let { put("i", it) }

Some files were not shown because too many files have changed in this diff Show More