アプリ設定/タブレットモード/投稿画面を別ウィンドウで表示する」を追加
This commit is contained in:
parent
60224dc3f8
commit
18c355715c
|
@ -197,7 +197,18 @@
|
|||
android:name=".ActPost"
|
||||
android:label="@string/act_post"
|
||||
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
android:windowSoftInputMode="adjustResize" >
|
||||
|
||||
<!--suppress AndroidElementNotAllowed -->
|
||||
<layout
|
||||
android:defaultWidth="320dp"
|
||||
android:defaultHeight="480dp"
|
||||
android:gravity="center"
|
||||
android:minWidth="64dp"
|
||||
android:minHeight="64dp"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ActAccountSetting"
|
||||
|
|
|
@ -33,6 +33,7 @@ import jp.juggler.subwaytooter.dialog.*
|
|||
import jp.juggler.subwaytooter.notification.PollingWorker
|
||||
import jp.juggler.subwaytooter.notification.PushSubscriptionHelper
|
||||
import jp.juggler.subwaytooter.span.MyClickableSpan
|
||||
import jp.juggler.subwaytooter.span.MyClickableSpanHandler
|
||||
import jp.juggler.subwaytooter.table.AcctColor
|
||||
import jp.juggler.subwaytooter.table.SavedAccount
|
||||
import jp.juggler.subwaytooter.util.*
|
||||
|
@ -54,8 +55,11 @@ import kotlin.math.abs
|
|||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class ActMain : AppCompatActivity(), View.OnClickListener,
|
||||
ViewPager.OnPageChangeListener, DrawerLayout.DrawerListener {
|
||||
class ActMain : AppCompatActivity(),
|
||||
View.OnClickListener,
|
||||
ViewPager.OnPageChangeListener,
|
||||
DrawerLayout.DrawerListener,
|
||||
MyClickableSpanHandler {
|
||||
|
||||
class PhoneEnv {
|
||||
|
||||
|
@ -79,17 +83,20 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
const val RESULT_APP_DATA_IMPORT = Activity.RESULT_FIRST_USER
|
||||
|
||||
// リクエスト
|
||||
const val REQUEST_CODE_COLUMN_LIST = 1
|
||||
const val REQUEST_APP_ABOUT = 3
|
||||
const val REQUEST_CODE_NICKNAME = 4
|
||||
const val REQUEST_CODE_POST = 5
|
||||
const val REQUEST_CODE_TEXT = 8
|
||||
const val REQUEST_CODE_LANGUAGE_FILTER = 9
|
||||
// const val REQUEST_CODE_COLUMN_LIST = 1
|
||||
// const val REQUEST_APP_ABOUT = 3
|
||||
// const val REQUEST_CODE_NICKNAME = 4
|
||||
// const val REQUEST_CODE_POST = 5
|
||||
// const val REQUEST_CODE_TEXT = 8
|
||||
// const val REQUEST_CODE_LANGUAGE_FILTER = 9
|
||||
|
||||
const val COLUMN_WIDTH_MIN_DP = 300
|
||||
|
||||
const val STATE_CURRENT_PAGE = "current_page"
|
||||
|
||||
// ActPostから参照される
|
||||
var refActMain: WeakReference<ActMain>? = null
|
||||
|
||||
// 外部からインテントを受信した後、アカウント選択中に画面回転したらアカウント選択からやり直す
|
||||
internal var sent_intent2: Intent? = null
|
||||
|
||||
|
@ -117,6 +124,9 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
var avatarIconSize: Int = 0
|
||||
var notificationTlIconSize: Int = 0
|
||||
|
||||
// マルチウィンドウモードで子ウィンドウを閉じるのに使う
|
||||
val closeList = LinkedList<WeakReference<AppCompatActivity>>()
|
||||
|
||||
// onResume() .. onPause() の間なら真
|
||||
private var isResumed = false
|
||||
|
||||
|
@ -223,7 +233,7 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
}
|
||||
}
|
||||
|
||||
private val link_click_listener: (View, MyClickableSpan) -> Unit = { viewClicked, span ->
|
||||
override fun onMyClickableSpanClicked(viewClicked: View, span: MyClickableSpan) {
|
||||
|
||||
// ビュー階層を下から辿って文脈を取得する
|
||||
var column: Column? = null
|
||||
|
@ -496,6 +506,7 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
log.d("onCreate")
|
||||
super.onCreate(savedInstanceState)
|
||||
refActMain = WeakReference(this)
|
||||
|
||||
arColumnColor.register(this, log)
|
||||
arLanguageFilter.register(this, log)
|
||||
|
@ -560,8 +571,19 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
override fun onDestroy() {
|
||||
log.d("onDestroy")
|
||||
super.onDestroy()
|
||||
refActMain = null
|
||||
post_helper.onDestroy()
|
||||
|
||||
// 子画面を全て閉じる
|
||||
closeList.forEach {
|
||||
try {
|
||||
it.get()?.finish()
|
||||
} catch (ex: Throwable) {
|
||||
log.e(ex, "close failed?")
|
||||
}
|
||||
}
|
||||
closeList.clear()
|
||||
|
||||
// このアクティビティに関連する ColumnViewHolder への参照を全カラムから除去する
|
||||
app_state.columnList.forEach {
|
||||
it.removeColumnViewHolderByActivity(this)
|
||||
|
@ -807,7 +829,7 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
at android.os.Binder.execTransact (Binder.java:739)
|
||||
*/
|
||||
|
||||
MyClickableSpan.link_callback = WeakReference(link_click_listener)
|
||||
// TODO MyClickableSpan.link_callback = WeakReference(link_click_listener)
|
||||
|
||||
if (Pref.bpDontScreenOff(pref)) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
|
@ -826,7 +848,6 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
if (intent != null) {
|
||||
handleSentIntent(intent)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
@ -937,6 +958,31 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
dlgQuickTootMenu.toggle()
|
||||
}
|
||||
|
||||
private fun updatePostedStatus(data: Intent) {
|
||||
posted_acct = data.getStringExtra(ActPost.EXTRA_POSTED_ACCT)?.let { Acct.parse(it) }
|
||||
if (data.extras?.containsKey(ActPost.EXTRA_POSTED_STATUS_ID) == true) {
|
||||
posted_status_id = EntityId.from(data, ActPost.EXTRA_POSTED_STATUS_ID)
|
||||
posted_reply_id = EntityId.from(data, ActPost.EXTRA_POSTED_REPLY_ID)
|
||||
posted_redraft_id = EntityId.from(data, ActPost.EXTRA_POSTED_REDRAFT_ID)
|
||||
} else {
|
||||
posted_status_id = null
|
||||
}
|
||||
}
|
||||
|
||||
val arActPost = activityResultHandler { ar ->
|
||||
val data = ar?.data
|
||||
if (data != null && ar.resultCode == Activity.RESULT_OK) {
|
||||
etQuickToot.setText("")
|
||||
updatePostedStatus(data)
|
||||
}
|
||||
}
|
||||
|
||||
fun onMultiWindowPostComplete(data: Intent) {
|
||||
if (!isLiveActivity) return
|
||||
updatePostedStatus(data)
|
||||
if (isStart_) refreshAfterPost()
|
||||
}
|
||||
|
||||
private fun refreshAfterPost() {
|
||||
val posted_acct = this.posted_acct
|
||||
val posted_status_id = this.posted_status_id
|
||||
|
@ -949,11 +995,8 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
) {
|
||||
column.startLoading()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (posted_acct != null && posted_status_id != null) {
|
||||
|
||||
val posted_redraft_id = this.posted_redraft_id
|
||||
if (posted_redraft_id != null) {
|
||||
val host = posted_acct.host
|
||||
|
@ -1074,20 +1117,6 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
return false
|
||||
}
|
||||
|
||||
val arActPost = activityResultHandler { ar ->
|
||||
val data = ar?.data
|
||||
if (data != null && ar.resultCode == Activity.RESULT_OK) {
|
||||
etQuickToot.setText("")
|
||||
posted_acct = data.getStringExtra(ActPost.EXTRA_POSTED_ACCT)?.let { Acct.parse(it) }
|
||||
if (data.extras?.containsKey(ActPost.EXTRA_POSTED_STATUS_ID) == true) {
|
||||
posted_status_id = EntityId.from(data, ActPost.EXTRA_POSTED_STATUS_ID)
|
||||
posted_reply_id = EntityId.from(data, ActPost.EXTRA_POSTED_REPLY_ID)
|
||||
posted_redraft_id = EntityId.from(data, ActPost.EXTRA_POSTED_REDRAFT_ID)
|
||||
} else {
|
||||
posted_status_id = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val arActText = activityResultHandler { ar ->
|
||||
when (ar?.resultCode) {
|
||||
|
@ -1704,7 +1733,7 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
userProfile(
|
||||
defaultInsertPosition,
|
||||
null,
|
||||
Acct.parse(user,instance),
|
||||
Acct.parse(user, instance),
|
||||
userUrl = "https://$instance/@$user",
|
||||
original_url = url
|
||||
)
|
||||
|
@ -1712,7 +1741,7 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
userProfile(
|
||||
defaultInsertPosition,
|
||||
null,
|
||||
acct = Acct.parse(user,host),
|
||||
acct = Acct.parse(user, host),
|
||||
userUrl = url,
|
||||
)
|
||||
}
|
||||
|
@ -1728,7 +1757,7 @@ class ActMain : AppCompatActivity(), View.OnClickListener,
|
|||
userProfile(
|
||||
defaultInsertPosition,
|
||||
null,
|
||||
acct = Acct.parse(user,host),
|
||||
acct = Acct.parse(user, host),
|
||||
userUrl = url,
|
||||
)
|
||||
return
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -485,6 +485,15 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
R.string.start,
|
||||
R.string.end
|
||||
)
|
||||
|
||||
sw(
|
||||
Pref.bpMultiWindowPost,
|
||||
R.string.multi_window_post
|
||||
)
|
||||
sw(
|
||||
Pref.bpManyWindowPost,
|
||||
R.string.many_window_post
|
||||
)
|
||||
}
|
||||
|
||||
section(R.string.media_attachment) {
|
||||
|
|
|
@ -450,6 +450,15 @@ object Pref {
|
|||
false
|
||||
)
|
||||
|
||||
val bpMultiWindowPost = BooleanPref(
|
||||
"MultiWindowPost",
|
||||
false
|
||||
)
|
||||
val bpManyWindowPost = BooleanPref(
|
||||
"ManyWindowPost",
|
||||
false
|
||||
)
|
||||
|
||||
// int
|
||||
|
||||
val ipBackButtonAction = IntPref("back_button_action", 0)
|
||||
|
|
|
@ -275,7 +275,9 @@ internal class ViewHolderHeaderProfile(
|
|||
append(tagWithSharp)
|
||||
val end = length
|
||||
tag.url?.notEmpty()?.let { url ->
|
||||
val span = MyClickableSpan(LinkInfo(url = url, tag = tag.name, caption = tagWithSharp))
|
||||
val span = MyClickableSpan(
|
||||
LinkInfo(url = url, tag = tag.name, caption = tagWithSharp)
|
||||
)
|
||||
setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package jp.juggler.subwaytooter.action
|
|||
import android.content.Intent
|
||||
import jp.juggler.subwaytooter.ActMain
|
||||
import jp.juggler.subwaytooter.ActPost
|
||||
import jp.juggler.subwaytooter.Pref
|
||||
import jp.juggler.subwaytooter.R
|
||||
import jp.juggler.subwaytooter.api.entity.TootAccount
|
||||
import jp.juggler.subwaytooter.api.entity.TootScheduled
|
||||
|
@ -12,6 +13,7 @@ import jp.juggler.subwaytooter.api.syncStatus
|
|||
import jp.juggler.subwaytooter.dialog.pickAccount
|
||||
import jp.juggler.subwaytooter.table.SavedAccount
|
||||
import jp.juggler.subwaytooter.util.matchHost
|
||||
import jp.juggler.util.isLiveActivity
|
||||
import jp.juggler.util.launchMain
|
||||
import jp.juggler.util.showToast
|
||||
|
||||
|
@ -35,8 +37,12 @@ fun ActMain.openActPostImpl(
|
|||
|
||||
//(Mastodon) 予約投稿の編集
|
||||
scheduledStatus: TootScheduled? = null
|
||||
) = arActPost.launch(
|
||||
ActPost.createIntent(
|
||||
) {
|
||||
|
||||
val useManyWindow = Pref.bpManyWindowPost(pref)
|
||||
val useMultiWindow = useManyWindow || Pref.bpMultiWindowPost(pref)
|
||||
|
||||
val intent = ActPost.createIntent(
|
||||
activity = this,
|
||||
account_db_id = account_db_id,
|
||||
redraft_status = redraft_status,
|
||||
|
@ -45,8 +51,27 @@ fun ActMain.openActPostImpl(
|
|||
sent_intent = sent_intent,
|
||||
quote = quote,
|
||||
scheduledStatus = scheduledStatus,
|
||||
multiWindowMode = useMultiWindow
|
||||
)
|
||||
)
|
||||
|
||||
if (!useMultiWindow) {
|
||||
arActPost.launch(intent)
|
||||
} else {
|
||||
|
||||
if (!useManyWindow)
|
||||
ActPost.refActPost?.get()
|
||||
?.takeIf { it.isLiveActivity }
|
||||
?.let {
|
||||
it.updateText(intent)
|
||||
return
|
||||
}
|
||||
|
||||
// fall thru
|
||||
arActPost.launch(intent.apply{
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK )
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 投稿画面を開く。初期テキストを指定する
|
||||
fun ActMain.openPost(
|
||||
|
|
|
@ -5,9 +5,13 @@ import android.text.style.ClickableSpan
|
|||
import android.view.View
|
||||
import jp.juggler.subwaytooter.api.entity.TootMention
|
||||
import jp.juggler.subwaytooter.table.AcctColor
|
||||
import jp.juggler.util.activity
|
||||
import jp.juggler.util.cast
|
||||
import jp.juggler.util.notZero
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
interface MyClickableSpanHandler{
|
||||
fun onMyClickableSpanClicked(viewClicked:View,span:MyClickableSpan)
|
||||
}
|
||||
|
||||
class LinkInfo(
|
||||
var url : String,
|
||||
|
@ -23,11 +27,10 @@ class LinkInfo(
|
|||
class MyClickableSpan(val linkInfo : LinkInfo) : ClickableSpan() {
|
||||
|
||||
companion object {
|
||||
var link_callback : WeakReference<(View, MyClickableSpan) -> Unit>? = null
|
||||
var defaultLinkColor : Int = 0
|
||||
var showLinkUnderline = true
|
||||
}
|
||||
|
||||
|
||||
val color_fg : Int
|
||||
val color_bg : Int
|
||||
|
||||
|
@ -43,7 +46,9 @@ class MyClickableSpan(val linkInfo : LinkInfo) : ClickableSpan() {
|
|||
}
|
||||
|
||||
override fun onClick(view : View) {
|
||||
link_callback?.get()?.invoke(view, this)
|
||||
view.activity
|
||||
?.cast<MyClickableSpanHandler>()
|
||||
?.onMyClickableSpanClicked(view,this)
|
||||
}
|
||||
|
||||
override fun updateDrawState(ds : TextPaint) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import androidx.activity.ComponentActivity
|
|||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import jp.juggler.subwaytooter.R
|
||||
import java.util.*
|
||||
|
@ -384,3 +385,6 @@ class ActivityResultHandler<A : ComponentActivity>(
|
|||
@Suppress("unused")
|
||||
fun <A : ComponentActivity> A.activityResultHandler(callback: A.(ActivityResult?) -> Unit) =
|
||||
ActivityResultHandler(callback)
|
||||
|
||||
val AppCompatActivity.isLiveActivity: Boolean
|
||||
get() = !(isFinishing || isDestroyed)
|
||||
|
|
|
@ -1,35 +1,46 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
android:orientation="vertical">
|
||||
|
||||
<DatePicker
|
||||
android:id="@+id/datePicker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:datePickerMode="spinner"
|
||||
android:calendarViewShown="false"
|
||||
android:spinnersShown="true"
|
||||
android:layout_gravity="center_horizontal"
|
||||
/>
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:fadeScrollbars="false"
|
||||
android:fillViewport="true"
|
||||
android:scrollbarStyle="outsideOverlay">
|
||||
|
||||
<TimePicker
|
||||
android:id="@+id/timePicker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:timePickerMode="spinner"
|
||||
android:layout_gravity="center_horizontal"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<DatePicker
|
||||
android:id="@+id/datePicker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:calendarViewShown="false"
|
||||
android:datePickerMode="spinner"
|
||||
android:spinnersShown="true" />
|
||||
|
||||
<TimePicker
|
||||
android:id="@+id/timePicker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:timePickerMode="spinner" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<LinearLayout
|
||||
style="?android:attr/buttonBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnCancel"
|
||||
|
@ -37,8 +48,7 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/cancel"
|
||||
/>
|
||||
android:text="@string/cancel" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnOk"
|
||||
|
@ -46,7 +56,6 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/ok"
|
||||
/>
|
||||
android:text="@string/ok" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -1093,4 +1093,8 @@
|
|||
<string name="not_available_for_current_accounts">この機能を利用できるアカウントがありません</string>
|
||||
<string name="confirm_reaction">%2$s から %1$s でリアクションしますか?</string>
|
||||
<string name="confirm_reaction_to_pleroma">%2$s からカスタム絵文字 %1$s でリアクションしようとしていますが、送り先 %3$s はカスタム絵文字のリアクションに対応してないかもしれません。続けますか?</string>
|
||||
|
||||
<string name="multi_window_post">投稿画面を別ウィンドウで表示する</string>
|
||||
<string name="many_window_post">投稿画面を多くのウィンドウで表示する</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1106,4 +1106,6 @@
|
|||
<string name="not_available_for_current_accounts">Unavailable for current accounts</string>
|
||||
<string name="confirm_reaction">Reaction %1$s from %2$s?</string>
|
||||
<string name="confirm_reaction_to_pleroma">Reaction custom emoji %1$s from %2$s to server %3$s that may not support custom emoji reaction. Continue?</string>
|
||||
<string name="multi_window_post">Multi window for post activity</string>
|
||||
<string name="many_window_post">Many window for post activity</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue