package jp.juggler.subwaytooter.action import android.app.Dialog import android.content.Intent import android.os.Build import androidx.appcompat.app.AlertDialog import jp.juggler.subwaytooter.* import jp.juggler.subwaytooter.api.* import jp.juggler.subwaytooter.api.entity.* import jp.juggler.subwaytooter.dialog.AccountPicker import jp.juggler.subwaytooter.dialog.DlgCreateAccount import jp.juggler.subwaytooter.dialog.DlgTextInput import jp.juggler.subwaytooter.dialog.LoginForm import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.subwaytooter.table.UserRelation import jp.juggler.subwaytooter.util.LinkHelper import jp.juggler.util.* object Action_Account { @Suppress("unused") private val log = LogCategory("Action_Account") // アカウントの追加 fun add(activity : ActMain) { LoginForm.showLoginForm( activity, null ) { dialog, instance, action -> TootTaskRunner(activity).run(instance, object : TootTask { override fun background(client : TootApiClient) : TootApiResult? { return when(action) { LoginForm.Action.Existing -> client.authentication1(Pref.spClientName(activity)) LoginForm.Action.Create -> client.createUser1(Pref.spClientName(activity)) LoginForm.Action.Pseudo, LoginForm.Action.Token -> { val (ti, ri) = TootInstance.get(client) if(ti != null) ri?.data = ti ri } } } override fun handleResult(result : TootApiResult?) { result ?: return // cancelled. val data = result.data if(result.error == null && data != null) { when(action) { LoginForm.Action.Existing -> if(data is String) { // ブラウザ用URLが生成された val intent = Intent() intent.data = data.toUri() activity.startAccessTokenUpdate(intent) dialog.dismissSafe() return } LoginForm.Action.Create -> if(data is JsonObject) { // インスタンスを確認できた createAccount( activity, instance, data, dialog ) return } LoginForm.Action.Pseudo -> if(data is TootInstance) { addPseudoAccount( activity, instance, instanceInfo = data ) { a -> showToast(activity, false, R.string.server_confirmed) val pos = App1.getAppState(activity).column_list.size activity.addColumn(pos, a, ColumnType.LOCAL) dialog.dismissSafe() } } LoginForm.Action.Token -> if(data is TootInstance) { DlgTextInput.show( activity, activity.getString(R.string.access_token_or_api_token), null, callback = object : DlgTextInput.Callback { @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") override fun onOK( dialog_token : Dialog, text : String ) { // dialog引数が二つあるのに注意 activity.checkAccessToken( dialog, dialog_token, instance, text, null ) } override fun onEmptyError() { showToast(activity, true, R.string.token_not_specified) } } ) } } } val errorText = result.error ?: "(no error information)" if(errorText.contains("SSLHandshakeException") && (Build.VERSION.RELEASE.startsWith("7.0") || Build.VERSION.RELEASE.startsWith("7.1") && ! Build.VERSION.RELEASE.startsWith("7.1.") ) ) { AlertDialog.Builder(activity) .setMessage(errorText + "\n\n" + activity.getString(R.string.ssl_bug_7_0)) .setNeutralButton(R.string.close, null) .show() } else { showToast(activity, true, "$errorText ${result.requestInfo}".trim()) } } }) } } private fun createAccount( activity : ActMain, instance : Host, client_info : JsonObject, dialog_host : Dialog ) { DlgCreateAccount( activity, instance ) { dialog_create, username, email, password, agreement, reason -> // dialog引数が二つあるのに注意 TootTaskRunner(activity).run(instance, object : TootTask { var ta : TootAccount? = null var ti : TootInstance? = null override fun background(client : TootApiClient) : TootApiResult? { val r1 = client.createUser2Mastodon( client_info, username, email, password, agreement, reason ) val ti = r1?.jsonObject ?: return r1 val misskeyVersion = TootInstance.parseMisskeyVersion(ti) val linkHelper = LinkHelper.newLinkHelper(instance, misskeyVersion = misskeyVersion) val parser =TootParser(activity, linkHelper) this.ti = TootInstance(parser,ti) val access_token = ti.string("access_token") ?: return TootApiResult("can't get user access token") val r2 = client.getUserCredential(access_token, misskeyVersion = misskeyVersion) this.ta = parser.account(r2?.jsonObject) if(this.ta != null) return r2 val jsonObject = jsonObject { put("id", EntityId.CONFIRMING.toString()) put("username", username) put("acct", username) put("acct", username) put("url", "https://$instance/@$username") } this.ta = TootParser(activity, linkHelper).account(jsonObject) r1.data = jsonObject r1.tokenInfo = ti return r1 } override fun handleResult(result : TootApiResult?) { val sa : SavedAccount? = null if(activity.afterAccountVerify(result, ta, sa, ti,instance)) { dialog_host.dismissSafe() dialog_create.dismissSafe() } } }) }.show() } // アカウント設定 fun setting(activity : ActMain) { AccountPicker.pick( activity, bAllowPseudo = true, bAuto = true, message = activity.getString(R.string.account_picker_open_setting) ) { ai -> ActAccountSetting.open(activity, ai, ActMain.REQUEST_CODE_ACCOUNT_SETTING) } } // アカウントを選んでタイムラインカラムを追加 fun timeline( activity : ActMain, pos : Int, type : ColumnType, args : Array = emptyArray() ) { AccountPicker.pick( activity, bAllowPseudo = type.bAllowPseudo, bAllowMisskey = type.bAllowMisskey, bAllowMastodon = type.bAllowMastodon, bAuto = true, message = activity.getString( R.string.account_picker_add_timeline_of, type.name1(activity) ) ) { ai -> when(type) { ColumnType.PROFILE -> { val id = ai.loginAccount?.id if(id != null) activity.addColumn(pos, ai, type, id) } ColumnType.PROFILE_DIRECTORY -> activity.addColumn(pos, ai, type, ai.apiHost) else -> activity.addColumn(pos, ai, type, *args) } } } // 投稿画面を開く。初期テキストを指定する fun openPost( activity : ActMain, initial_text : String? = activity.quickTootText ) { activity.post_helper.closeAcctPopup() val db_id = activity.currentPostTarget?.db_id ?: - 1L if(db_id != - 1L) { ActPost.open(activity, ActMain.REQUEST_CODE_POST, db_id, initial_text = initial_text) } else { AccountPicker.pick( activity, bAllowPseudo = false, bAuto = true, message = activity.getString(R.string.account_picker_toot) ) { ai -> ActPost.open( activity, ActMain.REQUEST_CODE_POST, ai.db_id, initial_text = initial_text ) } } } fun endorse( activity : ActMain, access_info : SavedAccount, who : TootAccount, bSet : Boolean ) { if(access_info.isMisskey) { showToast(activity, false, "This feature is not provided on Misskey account.") return } TootTaskRunner(activity).run(access_info, object : TootTask { var relation : UserRelation? = null override fun background(client : TootApiClient) : TootApiResult? { val result = client.request( "/api/v1/accounts/${who.id}/" + when(bSet) { true -> "pin" false -> "unpin" }, "".toFormRequestBody().toPost() ) val jsonObject = result?.jsonObject if(jsonObject != null) { val tr = parseItem( ::TootRelationShip, TootParser(client.context, access_info), jsonObject ) if(tr != null) { this.relation = saveUserRelation(access_info, tr) } } return result } override fun handleResult(result : TootApiResult?) { result ?: return if(result.error != null) { showToast(activity, true, result.error) } else { showToast( activity, false, when(bSet) { true -> R.string.endorse_succeeded else -> R.string.remove_endorse_succeeded } ) } } }) } }