diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 060755b1..d7b67786 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -4,10 +4,19 @@
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2b0aec11..ef15f5e4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -87,6 +87,7 @@
(null)
- internal val sent_intent = AtomicReference(null)
+ internal val lastUri = AtomicReference(null)
+ internal val sharedIntent = AtomicReference(null)
private fun String?.isMediaMimeType() = when {
this == null -> false
@@ -47,10 +47,10 @@ class ActCallback : AppCompatActivity() {
}
override fun onCreate(savedInstanceState: Bundle?) {
- log.d("onCreate flags=0x${intent.flags.toString(radix = 16)}")
+ var intent = this.intent
+ log.d("onCreate flags=0x${intent?.flags?.toString(radix = 16)}")
super.onCreate(savedInstanceState)
- var intent: Intent? = intent
when {
intent == null -> {
// 多分起きないと思う
@@ -65,29 +65,31 @@ class ActCallback : AppCompatActivity() {
val type = intent.type
// ACTION_SEND か ACTION_SEND_MULTIPLE
// ACTION_VIEW かつ type が 画像かビデオか音声
- if (
+ when {
Intent.ACTION_SEND == action ||
- Intent.ACTION_SEND_MULTIPLE == action ||
- (Intent.ACTION_VIEW == action && type.isMediaMimeType())
- ) {
+ Intent.ACTION_SEND_MULTIPLE == action ||
+ (Intent.ACTION_VIEW == action && type.isMediaMimeType()) -> {
- // Google Photo などから送られるIntentに含まれるuriの有効期間はActivityが閉じられるまで
- // http://qiita.com/pside/items/a821e2fe9ae6b7c1a98c
+ // Google Photo などから送られるIntentに含まれるuriの有効期間はActivityが閉じられるまで
+ // http://qiita.com/pside/items/a821e2fe9ae6b7c1a98c
- // 有効期間を延長する
- intent = remake(intent)
- if (intent != null) {
- sent_intent.set(intent)
+ // 有効期間を延長する
+ intent = remake(intent)
+ if (intent != null) {
+ sharedIntent.set(intent)
+ }
}
- } else if (forbidUriFromApp(intent)) {
- // last_uriをクリアする
- last_uri.set(null)
- // ダイアログを閉じるまで画面遷移しない
- return
- } else {
- val uri = intent.data
- if (uri != null) {
- last_uri.set(uri)
+ forbidUriFromApp(intent) -> {
+ // last_uriをクリアする
+ lastUri.set(null)
+ // ダイアログを閉じるまで画面遷移しない
+ return
+ }
+ else -> {
+ val uri = intent.data
+ if (uri != null) {
+ lastUri.set(uri)
+ }
}
}
}
@@ -105,13 +107,11 @@ class ActCallback : AppCompatActivity() {
}
private fun copyExtraTexts(dst: Intent, src: Intent) {
- var sv: String?
+ src.string(Intent.EXTRA_TEXT)
+ ?.let { dst.putExtra(Intent.EXTRA_TEXT, it) }
//
- sv = src.string(Intent.EXTRA_TEXT)
- if (sv != null) dst.putExtra(Intent.EXTRA_TEXT, sv)
- //
- sv = src.string(Intent.EXTRA_SUBJECT)
- if (sv != null) dst.putExtra(Intent.EXTRA_SUBJECT, sv)
+ src.string(Intent.EXTRA_SUBJECT)
+ ?.let { dst.putExtra(Intent.EXTRA_SUBJECT, it) }
}
private fun remake(src: Intent): Intent? {
@@ -123,52 +123,56 @@ class ActCallback : AppCompatActivity() {
val type = src.type
if (type.isMediaMimeType()) {
- if (Intent.ACTION_VIEW == action) {
- src.data?.let { uriOriginal ->
+ when (action){
+ Intent.ACTION_VIEW -> {
+ src.data?.let { uriOriginal ->
+ try {
+ val uri = saveToCache(uriOriginal)
+ val dst = Intent(action)
+ dst.setDataAndType(uri, type)
+ copyExtraTexts(dst, src)
+ return dst
+ } catch (ex: Throwable) {
+ log.e(ex, "remake failed. src=$src")
+ }
+ }
+ }
+ Intent.ACTION_SEND -> {
+ var uri = src.getStreamUriExtra()
+ ?: return src // text/plainの場合
try {
- val uri = saveToCache(uriOriginal)
+ uri = saveToCache(uri)
+
val dst = Intent(action)
- dst.setDataAndType(uri, type)
+ dst.type = type
+ dst.putExtra(Intent.EXTRA_STREAM, uri)
copyExtraTexts(dst, src)
return dst
} catch (ex: Throwable) {
log.e(ex, "remake failed. src=$src")
}
}
- } else if (Intent.ACTION_SEND == action) {
- var uri = src.getStreamUriExtra()
- ?: return src // text/plainの場合
- try {
- uri = saveToCache(uri)
-
- val dst = Intent(action)
- dst.type = type
- dst.putExtra(Intent.EXTRA_STREAM, uri)
- copyExtraTexts(dst, src)
- return dst
- } catch (ex: Throwable) {
- log.e(ex, "remake failed. src=$src")
- }
- } else if (Intent.ACTION_SEND_MULTIPLE == action) {
- val listUri = src.getStreamUriListExtra()
- ?: return null
- val listDst = ArrayList()
- for (uriOriginal in listUri) {
- if (uriOriginal != null) {
- try {
- val uri = saveToCache(uriOriginal)
- listDst.add(uri)
- } catch (ex: Throwable) {
- log.e(ex, "remake failed. src=$src")
+ Intent.ACTION_SEND_MULTIPLE -> {
+ val listUri = src.getStreamUriListExtra()
+ ?: return null
+ val listDst = ArrayList()
+ for (uriOriginal in listUri) {
+ if (uriOriginal != null) {
+ try {
+ val uri = saveToCache(uriOriginal)
+ listDst.add(uri)
+ } catch (ex: Throwable) {
+ log.e(ex, "remake failed. src=$src")
+ }
}
}
+ if (listDst.isEmpty()) return null
+ val dst = Intent(action)
+ dst.type = type
+ dst.putParcelableArrayListExtra(Intent.EXTRA_STREAM, listDst)
+ copyExtraTexts(dst, src)
+ return dst
}
- if (listDst.isEmpty()) return null
- val dst = Intent(action)
- dst.type = type
- dst.putParcelableArrayListExtra(Intent.EXTRA_STREAM, listDst)
- copyExtraTexts(dst, src)
- return dst
}
} else if (Intent.ACTION_SEND == action) {
diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt
index 21712168..ce7d1159 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/ActMain.kt
@@ -657,13 +657,13 @@ class ActMain : AppCompatActivity(),
}
// 外部から受け取ったUriの処理
- val uri = ActCallback.last_uri.getAndSet(null)
+ val uri = ActCallback.lastUri.getAndSet(null)
if (uri != null) {
handleIntentUri(uri)
}
// 外部から受け取ったUriの処理
- val intent = ActCallback.sent_intent.getAndSet(null)
+ val intent = ActCallback.sharedIntent.getAndSet(null)
if (intent != null) {
handleSharedIntent(intent)
}
diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMediaViewer.kt b/app/src/main/java/jp/juggler/subwaytooter/ActMediaViewer.kt
index c04a17ed..ffe0dcc5 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/ActMediaViewer.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/ActMediaViewer.kt
@@ -13,6 +13,7 @@ import android.os.Environment
import android.os.SystemClock
import android.view.View
import android.view.Window
+import androidx.annotation.OptIn
import androidx.appcompat.app.AppCompatActivity
import androidx.core.net.toUri
import androidx.media3.common.MediaItem
@@ -20,6 +21,7 @@ import androidx.media3.common.PlaybackException
import androidx.media3.common.Player
import androidx.media3.common.Timeline
import androidx.media3.common.util.RepeatModeUtil
+import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.source.LoadEventInfo
import androidx.media3.exoplayer.source.MediaLoadData
@@ -60,7 +62,6 @@ import javax.net.ssl.HttpsURLConnection
import kotlin.math.max
import kotlin.math.min
-@androidx.annotation.OptIn(markerClass = [androidx.media3.common.util.UnstableApi::class])
class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
companion object {
@@ -226,6 +227,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
}
}
+ @UnstableApi
private val mediaSourceEventListener = object : MediaSourceEventListener {
override fun onLoadStarted(
windowIndex: Int,
@@ -306,7 +308,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
this.showDescription = intent.getBooleanExtra(EXTRA_SHOW_DESCRIPTION, showDescription)
- this.serviceType = ServiceType.values()[
+ this.serviceType = ServiceType.entries[
savedInstanceState?.int(EXTRA_SERVICE_TYPE)
?: intent.int(EXTRA_SERVICE_TYPE) ?: 0
]
@@ -349,7 +351,8 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
)
}
- internal fun initUI() {
+ @OptIn(UnstableApi::class)
+ private fun initUI() {
setContentView(views.root)
views.pbvImage.background = MediaBackgroundDrawable(
@@ -409,6 +412,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
exoPlayer = ExoPlayer.Builder(this).build()
exoPlayer.addListener(playerListener)
+
views.pvVideo.run {
player = exoPlayer
controllerAutoShow = false
@@ -916,7 +920,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
private fun mediaBackgroundDialog() {
launchAndShowError {
actionsDialog(getString(R.string.background_pattern)) {
- for (k in MediaBackgroundDrawable.Kind.values()) {
+ for (k in MediaBackgroundDrawable.Kind.entries) {
if (!k.isMediaBackground) continue
action(k.name) {
val idx = k.toIndex()
diff --git a/app/src/main/java/jp/juggler/subwaytooter/AppState.kt b/app/src/main/java/jp/juggler/subwaytooter/AppState.kt
index 4d9028bb..630fd8d7 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/AppState.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/AppState.kt
@@ -10,6 +10,7 @@ import android.os.SystemClock
import android.speech.tts.TextToSpeech
import android.speech.tts.Voice
import android.text.Spannable
+import androidx.core.content.ContextCompat
import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.subwaytooter.column.Column
import jp.juggler.subwaytooter.column.ColumnEncoder
@@ -411,7 +412,7 @@ class AppState(
} catch (ignored: Throwable) {
null
}
- if (voiceSet == null || voiceSet.isEmpty()) {
+ if (voiceSet.isNullOrEmpty()) {
log.d("TextToSpeech.getVoices returns null or empty set.")
} else {
val lang = defaultLocale(context).toLanguageTag()
@@ -427,9 +428,10 @@ class AppState(
handler.post(procFlushSpeechQueue)
- context.registerReceiver(
- ttsReceiver,
- IntentFilter(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED)
+ ContextCompat.registerReceiver(
+ context,
+ IntentFilter(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED),
+ ContextCompat.RECEIVER_NOT_EXPORTED,
)
// tts.setOnUtteranceProgressListener( new UtteranceProgressListener() {
diff --git a/app/src/main/java/jp/juggler/subwaytooter/actpost/ActPostAttachment.kt b/app/src/main/java/jp/juggler/subwaytooter/actpost/ActPostAttachment.kt
index 9cb56f85..c905bc27 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/actpost/ActPostAttachment.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/actpost/ActPostAttachment.kt
@@ -21,7 +21,7 @@ import jp.juggler.subwaytooter.calcIconRound
import jp.juggler.subwaytooter.defaultColorIcon
import jp.juggler.subwaytooter.dialog.actionsDialog
import jp.juggler.subwaytooter.dialog.decodeAttachmentBitmap
-import jp.juggler.subwaytooter.dialog.dialogArrachmentRearrange
+import jp.juggler.subwaytooter.dialog.dialogAttachmentRearrange
import jp.juggler.subwaytooter.dialog.focusPointDialog
import jp.juggler.subwaytooter.dialog.showTextInputDialog
import jp.juggler.subwaytooter.pref.PrefB
@@ -454,7 +454,7 @@ fun ActPost.onPickCustomThumbnailImpl(pa: PostAttachment, src: GetContentResultE
fun ActPost.rearrangeAttachments() = lifecycleScope.launch {
try {
- val rearranged = dialogArrachmentRearrange(attachmentList)
+ val rearranged = dialogAttachmentRearrange(attachmentList)
// 入れ替え中にアップロード失敗などで要素が消えることがあるので
// 最新のattachmentListを指定順に並べ替える
val remain = ArrayList(attachmentList)
diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAttachmentRearrange.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAttachmentRearrange.kt
index 2a1d9903..68e184b4 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAttachmentRearrange.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgAttachmentRearrange.kt
@@ -31,7 +31,7 @@ private val log = LogCategory("DlgAttachmentRearrange")
* 投稿画面で添付メディアを並べ替えるダイアログを開き、OKボタンが押されるまで非同期待機する。
* OK以外の方法で閉じたらCancellationExceptionを投げる。
*/
-suspend fun AppCompatActivity.dialogArrachmentRearrange(
+suspend fun AppCompatActivity.dialogAttachmentRearrange(
initialList: List,
): List = suspendCancellableCoroutine { cont ->
val views = AttachmentRearrangeDialogBinding.inflate(layoutInflater)
diff --git a/app/src/main/res/xml/backup_spec.xml b/app/src/main/res/xml/backup_spec.xml
index 1b3de7a5..52a06cac 100644
--- a/app/src/main/res/xml/backup_spec.xml
+++ b/app/src/main/res/xml/backup_spec.xml
@@ -1,4 +1,6 @@
-
+
diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 00000000..f463f518
--- /dev/null
+++ b/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+