v1.1.1
This commit is contained in:
parent
9bc25e842e
commit
74b2f1173a
@ -9,8 +9,8 @@ android {
|
||||
applicationId "jp.juggler.subwaytooter"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 109
|
||||
versionName "1.0.9"
|
||||
versionCode 111
|
||||
versionName "1.1.1"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package jp.juggler.subwaytooter;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
@ -23,6 +24,7 @@ import android.widget.TextView;
|
||||
import jp.juggler.subwaytooter.api.TootApiClient;
|
||||
import jp.juggler.subwaytooter.api.TootApiResult;
|
||||
import jp.juggler.subwaytooter.api.entity.TootStatus;
|
||||
import jp.juggler.subwaytooter.dialog.DlgAccessToken;
|
||||
import jp.juggler.subwaytooter.table.AcctColor;
|
||||
import jp.juggler.subwaytooter.table.SavedAccount;
|
||||
import jp.juggler.subwaytooter.util.LogCategory;
|
||||
@ -93,6 +95,7 @@ public class ActAccountSetting extends AppCompatActivity
|
||||
TextView tvInstance;
|
||||
TextView tvUser;
|
||||
View btnAccessToken;
|
||||
View btnInputAccessToken;
|
||||
View btnAccountRemove;
|
||||
Button btnVisibility;
|
||||
Switch swNSFWOpen;
|
||||
@ -125,6 +128,7 @@ public class ActAccountSetting extends AppCompatActivity
|
||||
tvInstance = (TextView) findViewById( R.id.tvInstance );
|
||||
tvUser = (TextView) findViewById( R.id.tvUser );
|
||||
btnAccessToken = findViewById( R.id.btnAccessToken );
|
||||
btnInputAccessToken = findViewById( R.id.btnInputAccessToken );
|
||||
btnAccountRemove = findViewById( R.id.btnAccountRemove );
|
||||
btnVisibility = (Button) findViewById( R.id.btnVisibility );
|
||||
swNSFWOpen = (Switch) findViewById( R.id.swNSFWOpen );
|
||||
@ -145,6 +149,7 @@ public class ActAccountSetting extends AppCompatActivity
|
||||
|
||||
btnOpenBrowser.setOnClickListener( this );
|
||||
btnAccessToken.setOnClickListener( this );
|
||||
btnInputAccessToken.setOnClickListener( this );
|
||||
btnAccountRemove.setOnClickListener( this );
|
||||
btnVisibility.setOnClickListener( this );
|
||||
btnUserCustom.setOnClickListener( this );
|
||||
@ -200,6 +205,7 @@ public class ActAccountSetting extends AppCompatActivity
|
||||
|
||||
boolean enabled = ! a.isPseudo();
|
||||
btnAccessToken.setEnabled( enabled );
|
||||
btnInputAccessToken.setEnabled( enabled );
|
||||
btnVisibility.setEnabled( enabled );
|
||||
btnVisibility.setEnabled( enabled );
|
||||
btnVisibility.setEnabled( enabled );
|
||||
@ -258,6 +264,10 @@ public class ActAccountSetting extends AppCompatActivity
|
||||
case R.id.btnAccessToken:
|
||||
performAccessToken();
|
||||
break;
|
||||
case R.id.btnInputAccessToken:
|
||||
inputAccessToken();
|
||||
break;
|
||||
|
||||
case R.id.btnAccountRemove:
|
||||
performAccountRemove();
|
||||
break;
|
||||
@ -420,8 +430,6 @@ public class ActAccountSetting extends AppCompatActivity
|
||||
|
||||
final AsyncTask< Void, String, TootApiResult > task = new AsyncTask< Void, String, TootApiResult >() {
|
||||
|
||||
long row_id;
|
||||
|
||||
@Override
|
||||
protected TootApiResult doInBackground( Void... params ){
|
||||
TootApiClient api_client = new TootApiClient( ActAccountSetting.this, new TootApiClient.Callback() {
|
||||
@ -481,6 +489,16 @@ public class ActAccountSetting extends AppCompatActivity
|
||||
task.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
static final int RESULT_INPUT_ACCESS_TOKEN = RESULT_FIRST_USER + 10;
|
||||
static final String EXTRA_DB_ID = "db_id";
|
||||
private void inputAccessToken(){
|
||||
|
||||
Intent data = new Intent();
|
||||
data.putExtra( EXTRA_DB_ID,account.db_id );
|
||||
setResult( RESULT_INPUT_ACCESS_TOKEN, data );
|
||||
finish();
|
||||
}
|
||||
|
||||
private void openNotificationSoundPicker(){
|
||||
Intent intent = new Intent( RingtoneManager.ACTION_RINGTONE_PICKER );
|
||||
intent.putExtra( RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION );
|
||||
|
@ -71,6 +71,7 @@ import jp.juggler.subwaytooter.api.entity.TootStatus;
|
||||
import jp.juggler.subwaytooter.api.entity.TootStatusLike;
|
||||
import jp.juggler.subwaytooter.api_msp.entity.MSPToot;
|
||||
import jp.juggler.subwaytooter.dialog.AccountPicker;
|
||||
import jp.juggler.subwaytooter.dialog.DlgAccessToken;
|
||||
import jp.juggler.subwaytooter.dialog.DlgConfirm;
|
||||
import jp.juggler.subwaytooter.dialog.LoginForm;
|
||||
import jp.juggler.subwaytooter.dialog.ReportForm;
|
||||
@ -460,19 +461,6 @@ public class ActMain extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
}else if( requestCode == REQUEST_CODE_ACCOUNT_SETTING ){
|
||||
|
||||
updateColumnStrip();
|
||||
|
||||
for( Column column : app_state.column_list ){
|
||||
column.fireShowColumnHeader();
|
||||
}
|
||||
|
||||
if( data != null ){
|
||||
startAccessTokenUpdate( data );
|
||||
return;
|
||||
}
|
||||
|
||||
}else if( requestCode == REQUEST_APP_ABOUT ){
|
||||
if( data != null ){
|
||||
String search = data.getStringExtra( ActAbout.EXTRA_SEARCH );
|
||||
@ -507,8 +495,21 @@ public class ActMain extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( requestCode == REQUEST_CODE_APP_SETTING ){
|
||||
|
||||
if( requestCode == REQUEST_CODE_ACCOUNT_SETTING ){
|
||||
updateColumnStrip();
|
||||
|
||||
for( Column column : app_state.column_list ){
|
||||
column.fireShowColumnHeader();
|
||||
}
|
||||
|
||||
if( resultCode == RESULT_OK && data != null ){
|
||||
startAccessTokenUpdate( data );
|
||||
}else if( resultCode == ActAccountSetting.RESULT_INPUT_ACCESS_TOKEN && data != null){
|
||||
long db_id = data.getLongExtra( ActAccountSetting.EXTRA_DB_ID,-1L );
|
||||
checkAccessToken2( db_id );
|
||||
}
|
||||
}else if( requestCode == REQUEST_CODE_APP_SETTING ){
|
||||
showFooterColor();
|
||||
|
||||
if( resultCode == RESULT_APP_DATA_IMPORT ){
|
||||
@ -1033,7 +1034,12 @@ public class ActMain extends AppCompatActivity
|
||||
public void performAccountAdd(){
|
||||
LoginForm.showLoginForm( this, null, new LoginForm.LoginFormCallback() {
|
||||
@Override
|
||||
public void startLogin( final Dialog dialog, final String instance, final boolean bPseudoAccount ){
|
||||
public void startLogin(
|
||||
final Dialog dialog
|
||||
, final String instance
|
||||
, final boolean bPseudoAccount
|
||||
, final boolean bInputAccessToken
|
||||
){
|
||||
|
||||
final ProgressDialog progress = new ProgressDialog( ActMain.this );
|
||||
|
||||
@ -1061,7 +1067,6 @@ public class ActMain extends AppCompatActivity
|
||||
return api_client.checkInstance();
|
||||
}else{
|
||||
return api_client.authorize1( Pref.pref( ActMain.this ).getString( Pref.KEY_CLIENT_NAME, "" ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1088,11 +1093,21 @@ public class ActMain extends AppCompatActivity
|
||||
|
||||
// エラーはブラウザ用URLかもしれない
|
||||
if( sv.startsWith( "https" ) ){
|
||||
// OAuth認証が必要
|
||||
Intent data = new Intent();
|
||||
data.setData( Uri.parse( sv ) );
|
||||
startAccessTokenUpdate( data );
|
||||
dialog.dismiss();
|
||||
|
||||
if( bInputAccessToken ){
|
||||
// アクセストークンの手動入力
|
||||
DlgAccessToken.show( ActMain.this, new DlgAccessToken.Callback() {
|
||||
@Override public void startCheck( Dialog dialog_token, String access_token ){
|
||||
checkAccessToken( dialog,dialog_token,instance,access_token ,null);
|
||||
}
|
||||
} );
|
||||
}else{
|
||||
// OAuth認証が必要
|
||||
Intent data = new Intent();
|
||||
data.setData( Uri.parse( sv ) );
|
||||
startAccessTokenUpdate( data );
|
||||
dialog.dismiss();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1367,79 +1382,7 @@ public class ActMain extends AppCompatActivity
|
||||
// at android.app.Dialog.dismiss(Dialog.java:529)
|
||||
}
|
||||
|
||||
//noinspection StatementWithEmptyBody
|
||||
if( result == null ){
|
||||
// cancelled.
|
||||
}else if( result.error != null ){
|
||||
Utils.showToast( ActMain.this, true, result.error );
|
||||
}else if( ta == null ){
|
||||
// 自分のユーザネームを取れなかった
|
||||
// …普通はエラーメッセージが設定されてるはずだが
|
||||
Utils.showToast( ActMain.this, true, "missing TootAccount" );
|
||||
}else if( this.sa != null ){
|
||||
// アクセストークン更新時
|
||||
|
||||
// インスタンスは同じだと思うが、ユーザ名が異なる可能性がある
|
||||
if( ! sa.username.equals( ta.username ) ){
|
||||
Utils.showToast( ActMain.this, true, R.string.user_name_not_match );
|
||||
}else{
|
||||
Utils.showToast( ActMain.this, false, R.string.access_token_updated_for, sa.acct );
|
||||
|
||||
// DBの情報を更新する
|
||||
sa.updateTokenInfo( result.token_info );
|
||||
|
||||
// 各カラムの持つアカウント情報をリロードする
|
||||
reloadAccountSetting();
|
||||
|
||||
// 自動でリロードする
|
||||
for( Column c : app_state.column_list ){
|
||||
if( c.access_info.acct.equals( sa.acct ) ){
|
||||
c.startLoading();
|
||||
}
|
||||
}
|
||||
|
||||
// 通知の更新が必要かもしれない
|
||||
AlarmService.startCheck( ActMain.this );
|
||||
}
|
||||
}else{
|
||||
// アカウント追加時
|
||||
String user = ta.username + "@" + host;
|
||||
long row_id = SavedAccount.insert( host, user, result.object, result.token_info );
|
||||
SavedAccount account = SavedAccount.loadAccount( ActMain.this, log, row_id );
|
||||
if( account != null ){
|
||||
boolean bModified = false;
|
||||
if( account.locked ){
|
||||
bModified = true;
|
||||
account.visibility = TootStatus.VISIBILITY_PRIVATE;
|
||||
}
|
||||
if( ta != null && ta.source != null ){
|
||||
if( ta.source.privacy != null ){
|
||||
bModified = true;
|
||||
account.visibility = ta.source.privacy;
|
||||
}
|
||||
// FIXME ta.source.sensitive パラメータを読んで「添付画像をデフォルトでNSFWにする」を実現する
|
||||
}
|
||||
|
||||
if( bModified ){
|
||||
account.saveSetting();
|
||||
}
|
||||
Utils.showToast( ActMain.this, false, R.string.account_confirmed );
|
||||
|
||||
// 通知の更新が必要かもしれない
|
||||
AlarmService.startCheck( ActMain.this );
|
||||
|
||||
// 適当にカラムを追加する
|
||||
long count = SavedAccount.getCount();
|
||||
if( count > 1 ){
|
||||
addColumn( getDefaultInsertPosition(), account, Column.TYPE_HOME );
|
||||
}else{
|
||||
addColumn( getDefaultInsertPosition(), account, Column.TYPE_HOME );
|
||||
addColumn( getDefaultInsertPosition(), account, Column.TYPE_NOTIFICATIONS );
|
||||
addColumn( getDefaultInsertPosition(), account, Column.TYPE_LOCAL );
|
||||
addColumn( getDefaultInsertPosition(), account, Column.TYPE_FEDERATE );
|
||||
}
|
||||
}
|
||||
}
|
||||
afterAccountVerify( result,ta,sa,host );
|
||||
}
|
||||
};
|
||||
progress.setIndeterminate( true );
|
||||
@ -1454,6 +1397,180 @@ public class ActMain extends AppCompatActivity
|
||||
task.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
boolean afterAccountVerify( @Nullable TootApiResult result, @Nullable TootAccount ta, @Nullable SavedAccount sa, @Nullable String host){
|
||||
//noinspection StatementWithEmptyBody
|
||||
if( result == null ){
|
||||
// cancelled.
|
||||
}else if( result.error != null ){
|
||||
Utils.showToast( ActMain.this, true, result.error );
|
||||
}else if( ta == null ){
|
||||
// 自分のユーザネームを取れなかった
|
||||
// …普通はエラーメッセージが設定されてるはずだが
|
||||
Utils.showToast( ActMain.this, true, "missing TootAccount" );
|
||||
}else if( sa != null ){
|
||||
// アクセストークン更新時
|
||||
|
||||
// インスタンスは同じだと思うが、ユーザ名が異なる可能性がある
|
||||
if( ! sa.username.equals( ta.username ) ){
|
||||
Utils.showToast( ActMain.this, true, R.string.user_name_not_match );
|
||||
}else{
|
||||
Utils.showToast( ActMain.this, false, R.string.access_token_updated_for, sa.acct );
|
||||
|
||||
// DBの情報を更新する
|
||||
sa.updateTokenInfo( result.token_info );
|
||||
|
||||
// 各カラムの持つアカウント情報をリロードする
|
||||
reloadAccountSetting();
|
||||
|
||||
// 自動でリロードする
|
||||
for( Column c : app_state.column_list ){
|
||||
if( c.access_info.acct.equals( sa.acct ) ){
|
||||
c.startLoading();
|
||||
}
|
||||
}
|
||||
|
||||
// 通知の更新が必要かもしれない
|
||||
AlarmService.startCheck( ActMain.this );
|
||||
return true;
|
||||
}
|
||||
}else{
|
||||
// アカウント追加時
|
||||
String user = ta.username + "@" + host;
|
||||
long row_id = SavedAccount.insert( host, user, result.object, result.token_info );
|
||||
SavedAccount account = SavedAccount.loadAccount( ActMain.this, log, row_id );
|
||||
if( account != null ){
|
||||
boolean bModified = false;
|
||||
if( account.locked ){
|
||||
bModified = true;
|
||||
account.visibility = TootStatus.VISIBILITY_PRIVATE;
|
||||
}
|
||||
if( ta.source != null ){
|
||||
if( ta.source.privacy != null ){
|
||||
bModified = true;
|
||||
account.visibility = ta.source.privacy;
|
||||
}
|
||||
// FIXME ta.source.sensitive パラメータを読んで「添付画像をデフォルトでNSFWにする」を実現する
|
||||
}
|
||||
|
||||
if( bModified ){
|
||||
account.saveSetting();
|
||||
}
|
||||
Utils.showToast( ActMain.this, false, R.string.account_confirmed );
|
||||
|
||||
// 通知の更新が必要かもしれない
|
||||
AlarmService.startCheck( ActMain.this );
|
||||
|
||||
// 適当にカラムを追加する
|
||||
long count = SavedAccount.getCount();
|
||||
if( count > 1 ){
|
||||
addColumn( getDefaultInsertPosition(), account, Column.TYPE_HOME );
|
||||
}else{
|
||||
addColumn( getDefaultInsertPosition(), account, Column.TYPE_HOME );
|
||||
addColumn( getDefaultInsertPosition(), account, Column.TYPE_NOTIFICATIONS );
|
||||
addColumn( getDefaultInsertPosition(), account, Column.TYPE_LOCAL );
|
||||
addColumn( getDefaultInsertPosition(), account, Column.TYPE_FEDERATE );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// アクセストークンを手動で入力した場合
|
||||
void checkAccessToken(
|
||||
@Nullable final Dialog dialog_host
|
||||
, @Nullable final Dialog dialog_token
|
||||
, @NonNull final String host
|
||||
, @NonNull final String access_token
|
||||
, @Nullable final SavedAccount sa
|
||||
){
|
||||
|
||||
final ProgressDialog progress = new ProgressDialog( ActMain.this );
|
||||
|
||||
final AsyncTask< Void, Void, TootApiResult > task = new AsyncTask< Void, Void, TootApiResult >() {
|
||||
|
||||
TootAccount ta;
|
||||
|
||||
@Override
|
||||
protected TootApiResult doInBackground( Void... params ){
|
||||
TootApiClient client = new TootApiClient( ActMain.this, new TootApiClient.Callback() {
|
||||
@Override public boolean isApiCancelled(){
|
||||
return isCancelled();
|
||||
}
|
||||
|
||||
@Override public void publishApiProgress( final String s ){
|
||||
Utils.runOnMainThread( new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
progress.setMessage( s );
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
client.setInstance( host );
|
||||
|
||||
TootApiResult result = client.checkAccessToken( access_token );
|
||||
if( result != null && result.object != null ){
|
||||
// taは使い捨てなので、生成に使うLinkClickContextはダミーで問題ない
|
||||
LinkClickContext lcc = new LinkClickContext() {
|
||||
@Override public AcctColor findAcctColor( String url ){
|
||||
return null;
|
||||
}
|
||||
};
|
||||
this.ta = TootAccount.parse( ActMain.this, log, lcc, result.object );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute( TootApiResult result ){
|
||||
try{
|
||||
progress.dismiss();
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
// java.lang.IllegalArgumentException:
|
||||
// at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:451)
|
||||
// at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:377)
|
||||
// at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:122)
|
||||
// at android.app.Dialog.dismissDialog(Dialog.java:546)
|
||||
// at android.app.Dialog.dismiss(Dialog.java:529)
|
||||
}
|
||||
|
||||
if( afterAccountVerify( result,ta,sa,host ) ){
|
||||
if(dialog_host!=null ) dialog_host.dismiss();
|
||||
if(dialog_token!=null ) dialog_token.dismiss();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
progress.setIndeterminate( true );
|
||||
progress.setCancelable( true );
|
||||
progress.setOnCancelListener( new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel( DialogInterface dialog ){
|
||||
task.cancel( true );
|
||||
}
|
||||
} );
|
||||
progress.show();
|
||||
task.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
// アクセストークンの手動入力(更新)
|
||||
void checkAccessToken2(long db_id){
|
||||
|
||||
final SavedAccount sa = SavedAccount.loadAccount( this,log,db_id );
|
||||
if( sa == null ) return;
|
||||
|
||||
DlgAccessToken.show( this, new DlgAccessToken.Callback() {
|
||||
@Override public void startCheck( Dialog dialog_token, String access_token ){
|
||||
checkAccessToken( null, dialog_token, sa.host, access_token ,sa);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void reloadAccountSetting(){
|
||||
ArrayList< SavedAccount > done_list = new ArrayList<>();
|
||||
for( Column column : app_state.column_list ){
|
||||
@ -2662,8 +2779,8 @@ public class ActMain extends AppCompatActivity
|
||||
Request.Builder request_builder = new Request.Builder()
|
||||
.post( RequestBody.create( TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
|
||||
, "id=" + Long.toString( notification.id )
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
|
||||
return client.request(
|
||||
"/api/v1/notifications/dismiss"
|
||||
|
@ -26,6 +26,7 @@ import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
@ -61,6 +62,7 @@ import jp.juggler.subwaytooter.api.entity.TootAttachment;
|
||||
import jp.juggler.subwaytooter.api.entity.TootMention;
|
||||
import jp.juggler.subwaytooter.api.entity.TootResults;
|
||||
import jp.juggler.subwaytooter.api.entity.TootStatus;
|
||||
import jp.juggler.subwaytooter.dialog.AccountPicker;
|
||||
import jp.juggler.subwaytooter.dialog.DlgDraftPicker;
|
||||
import jp.juggler.subwaytooter.table.AcctColor;
|
||||
import jp.juggler.subwaytooter.table.PostDraft;
|
||||
@ -694,9 +696,28 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
||||
|
||||
void setAccount( SavedAccount a ){
|
||||
this.account = a;
|
||||
btnAccount.setText(
|
||||
( a == null ? getString( R.string.not_selected ) : a.getFullAcct( a ) )
|
||||
);
|
||||
SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
if( a == null ){
|
||||
btnAccount.setText( getString( R.string.not_selected ) );
|
||||
btnAccount.setTextColor( Styler.getAttributeColor( this, android.R.attr.textColorPrimary ) );
|
||||
btnAccount.setBackgroundResource( R.drawable.btn_bg_transparent );
|
||||
}else{
|
||||
String acct = a.getFullAcct( a );
|
||||
AcctColor ac = AcctColor.load( acct );
|
||||
String nickname = AcctColor.hasNickname( ac ) ? ac.nickname : acct;
|
||||
btnAccount.setText( nickname );
|
||||
|
||||
if( AcctColor.hasColorBackground( ac ) ){
|
||||
btnAccount.setBackgroundColor( ac.color_bg );
|
||||
}else{
|
||||
btnAccount.setBackgroundResource( R.drawable.btn_bg_transparent );
|
||||
}
|
||||
if( AcctColor.hasColorForeground( ac ) ){
|
||||
btnAccount.setTextColor( ac.color_fg );
|
||||
}else{
|
||||
btnAccount.setTextColor( Styler.getAttributeColor( this, android.R.attr.textColorPrimary ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void performAccountChooser(){
|
||||
@ -707,42 +728,59 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
||||
return;
|
||||
}
|
||||
|
||||
final ArrayList< SavedAccount > tmp_account_list = new ArrayList<>();
|
||||
tmp_account_list.addAll( account_list );
|
||||
|
||||
String[] caption_list = new String[ tmp_account_list.size() ];
|
||||
for( int i = 0, ie = tmp_account_list.size() ; i < ie ; ++ i ){
|
||||
caption_list[ i ] = tmp_account_list.get( i ).acct;
|
||||
}
|
||||
|
||||
new AlertDialog.Builder( this )
|
||||
.setTitle( R.string.choose_account )
|
||||
.setItems( caption_list, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( DialogInterface dialog, int which ){
|
||||
|
||||
if( which < 0 || which >= tmp_account_list.size() ){
|
||||
// 範囲外
|
||||
return;
|
||||
AccountPicker.pick( this, false, false, getString( R.string.choose_account ), new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( @NonNull SavedAccount ai ){
|
||||
|
||||
if( ! ai.host.equals( account.host ) ){
|
||||
// 別タンスへの移動
|
||||
if( in_reply_to_id != - 1L ){
|
||||
// 別タンスのアカウントならin_reply_toの変換が必要
|
||||
startReplyConversion( ai );
|
||||
|
||||
}
|
||||
|
||||
SavedAccount a = tmp_account_list.get( which );
|
||||
|
||||
if( ! a.host.equals( account.host ) ){
|
||||
// 別タンスへの移動
|
||||
if( in_reply_to_id != - 1L ){
|
||||
// 別タンスのアカウントならin_reply_toの変換が必要
|
||||
startReplyConversion( a );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// リプライがないか、同タンスへの移動
|
||||
setAccountWithVisibilityConversion( a );
|
||||
}
|
||||
} )
|
||||
.setNegativeButton( R.string.cancel, null )
|
||||
.show();
|
||||
|
||||
// リプライがないか、同タンスへの移動
|
||||
setAccountWithVisibilityConversion( ai );
|
||||
}
|
||||
} );
|
||||
|
||||
// final ArrayList< SavedAccount > tmp_account_list = new ArrayList<>();
|
||||
// tmp_account_list.addAll( account_list );
|
||||
//
|
||||
// String[] caption_list = new String[ tmp_account_list.size() ];
|
||||
// for( int i = 0, ie = tmp_account_list.size() ; i < ie ; ++ i ){
|
||||
// caption_list[ i ] = tmp_account_list.get( i ).acct;
|
||||
// }
|
||||
//
|
||||
// new AlertDialog.Builder( this )
|
||||
// .setTitle( R.string.choose_account )
|
||||
// .setItems( caption_list, new DialogInterface.OnClickListener() {
|
||||
// @Override
|
||||
// public void onClick( DialogInterface dialog, int which ){
|
||||
//
|
||||
// if( which < 0 || which >= tmp_account_list.size() ){
|
||||
// // 範囲外
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// SavedAccount ai = tmp_account_list.get( which );
|
||||
//
|
||||
// if( ! ai.host.equals( account.host ) ){
|
||||
// // 別タンスへの移動
|
||||
// if( in_reply_to_id != - 1L ){
|
||||
// // 別タンスのアカウントならin_reply_toの変換が必要
|
||||
// startReplyConversion( ai );
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // リプライがないか、同タンスへの移動
|
||||
// setAccountWithVisibilityConversion( ai );
|
||||
// }
|
||||
// } )
|
||||
// .setNegativeButton( R.string.cancel, null )
|
||||
// .show();
|
||||
}
|
||||
|
||||
void setAccountWithVisibilityConversion( @NonNull SavedAccount a ){
|
||||
|
@ -315,7 +315,7 @@ public class TootApiClient {
|
||||
return new TootApiResult( browser_url );
|
||||
}
|
||||
|
||||
public @Nullable TootApiResult authorize2( String code ){
|
||||
public @Nullable TootApiResult authorize2( String code ){
|
||||
|
||||
JSONObject client_info = ClientInfo.load( instance );
|
||||
if( client_info == null ){
|
||||
@ -424,4 +424,66 @@ public class TootApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable TootApiResult checkAccessToken( String access_token ){
|
||||
|
||||
JSONObject client_info = ClientInfo.load( instance );
|
||||
if( client_info == null ){
|
||||
return new TootApiResult( "missing client id" );
|
||||
}
|
||||
|
||||
JSONObject token_info;
|
||||
Response response;
|
||||
try{
|
||||
|
||||
// 指定されたアクセストークンを使って token_info を捏造する
|
||||
token_info = new JSONObject( );
|
||||
token_info.put("access_token",access_token);
|
||||
|
||||
// 認証されたアカウントのユーザ名を取得する
|
||||
String path = "/api/v1/accounts/verify_credentials";
|
||||
callback.publishApiProgress( context.getString( R.string.request_api, path ) );
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url( "https://" + instance + path )
|
||||
.header( "Authorization", "Bearer " + Utils.optStringX( token_info, "access_token" ) )
|
||||
.build();
|
||||
|
||||
Call call = ok_http_client.newCall( request );
|
||||
|
||||
response = call.execute();
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
return new TootApiResult( instance + ": " +Utils.formatError( ex, context.getResources(), R.string.network_error ) );
|
||||
}
|
||||
|
||||
if( callback.isApiCancelled() ) return null;
|
||||
|
||||
if( ! response.isSuccessful() ){
|
||||
return new TootApiResult( instance + ": " + context.getString( R.string.network_error_arg, response ) );
|
||||
}
|
||||
|
||||
try{
|
||||
//noinspection ConstantConditions
|
||||
String json = response.body().string();
|
||||
|
||||
if( TextUtils.isEmpty( json ) || json.startsWith( "<" ) ){
|
||||
return new TootApiResult( context.getString( R.string.response_not_json ) + "\n" + json );
|
||||
}else if( json.startsWith( "[" ) ){
|
||||
JSONArray array = new JSONArray( json );
|
||||
return new TootApiResult( log, response, token_info, json, array );
|
||||
}else{
|
||||
JSONObject object = new JSONObject( json );
|
||||
|
||||
String error = Utils.optStringX( object, "error" );
|
||||
if( ! TextUtils.isEmpty( error ) ){
|
||||
return new TootApiResult( context.getString( R.string.api_error, error ) );
|
||||
}
|
||||
return new TootApiResult( response, token_info, json, object );
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
return new TootApiResult( Utils.formatError( ex, "API data error" ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
@ -32,7 +33,7 @@ public class AccountPicker {
|
||||
|
||||
|
||||
public static void pick(
|
||||
@NonNull ActMain activity
|
||||
@NonNull AppCompatActivity activity
|
||||
, boolean bAllowPseudo
|
||||
, boolean bAuto
|
||||
, String message
|
||||
@ -44,7 +45,7 @@ public class AccountPicker {
|
||||
}
|
||||
|
||||
public static void pick(
|
||||
@NonNull ActMain activity
|
||||
@NonNull AppCompatActivity activity
|
||||
, boolean bAllowPseudo
|
||||
, boolean bAuto
|
||||
, String message
|
||||
@ -56,7 +57,7 @@ public class AccountPicker {
|
||||
}
|
||||
|
||||
public static void pick(
|
||||
@NonNull ActMain activity
|
||||
@NonNull AppCompatActivity activity
|
||||
, boolean bAllowPseudo
|
||||
, boolean bAuto
|
||||
, String message
|
||||
@ -67,7 +68,7 @@ public class AccountPicker {
|
||||
}
|
||||
|
||||
public static void pick(
|
||||
@NonNull ActMain activity
|
||||
@NonNull AppCompatActivity activity
|
||||
, boolean bAllowPseudo
|
||||
, boolean bAuto
|
||||
, String message
|
||||
@ -135,11 +136,12 @@ public class AccountPicker {
|
||||
} );
|
||||
|
||||
|
||||
float density = activity.getResources().getDisplayMetrics().density;
|
||||
|
||||
|
||||
LinearLayout llAccounts = (LinearLayout) viewRoot.findViewById( R.id.llAccounts );
|
||||
int pad_se = (int) ( 0.5f + 12f * activity.density );
|
||||
int pad_tb = (int) ( 0.5f + 6f * activity.density );
|
||||
int pad_se = (int) ( 0.5f + 12f * density );
|
||||
int pad_tb = (int) ( 0.5f + 6f * density );
|
||||
|
||||
for( SavedAccount a : account_list ){
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT );
|
||||
@ -161,7 +163,7 @@ public class AccountPicker {
|
||||
b.setGravity( Gravity.START | Gravity.CENTER_VERTICAL );
|
||||
b.setAllCaps( false );
|
||||
b.setLayoutParams( lp );
|
||||
b.setMinHeight( (int) ( 0.5f + 32f * activity.density ) );
|
||||
b.setMinHeight( (int) ( 0.5f + 32f * density ) );
|
||||
b.setText( AcctColor.hasNickname( ac ) ? ac.nickname : a.acct );
|
||||
|
||||
final SavedAccount _a = a;
|
||||
|
@ -0,0 +1,67 @@
|
||||
package jp.juggler.subwaytooter.dialog;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import jp.juggler.subwaytooter.R;
|
||||
import jp.juggler.subwaytooter.util.Utils;
|
||||
|
||||
public class DlgAccessToken {
|
||||
|
||||
public interface Callback {
|
||||
void startCheck( Dialog dialog, String access_token );
|
||||
}
|
||||
|
||||
public static void show( @NonNull final Activity activity ,@NonNull final Callback callback ){
|
||||
@SuppressLint("InflateParams") final View view = activity.getLayoutInflater().inflate( R.layout.dlg_access_token, null, false );
|
||||
final EditText etToken = (EditText) view.findViewById( R.id.etToken );
|
||||
final View btnOk = view.findViewById( R.id.btnOk );
|
||||
|
||||
etToken.setOnEditorActionListener( new TextView.OnEditorActionListener() {
|
||||
@Override public boolean onEditorAction( TextView v, int actionId, KeyEvent event ){
|
||||
if( actionId == EditorInfo.IME_ACTION_DONE ){
|
||||
btnOk.performClick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
|
||||
final Dialog dialog = new Dialog( activity );
|
||||
dialog.setContentView( view );
|
||||
btnOk.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ){
|
||||
final String token = etToken.getText().toString().trim();
|
||||
|
||||
if( TextUtils.isEmpty( token ) ){
|
||||
Utils.showToast( activity, true, R.string.token_not_specified );
|
||||
return;
|
||||
}
|
||||
callback.startCheck( dialog, token );
|
||||
}
|
||||
} );
|
||||
|
||||
view.findViewById( R.id.btnCancel ).setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ){
|
||||
dialog.cancel();
|
||||
}
|
||||
} );
|
||||
|
||||
//noinspection ConstantConditions
|
||||
dialog.getWindow().setLayout( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT );
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.Filter;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -27,7 +28,10 @@ import jp.juggler.subwaytooter.util.Utils;
|
||||
public class LoginForm {
|
||||
|
||||
public interface LoginFormCallback {
|
||||
void startLogin( Dialog dialog, String instance, boolean bPseudoAccount );
|
||||
void startLogin( Dialog dialog, String instance
|
||||
, boolean bPseudoAccount
|
||||
, boolean bInputAccessToken
|
||||
);
|
||||
}
|
||||
|
||||
private static class StringArray extends ArrayList< String > {
|
||||
@ -39,6 +43,13 @@ public class LoginForm {
|
||||
final AutoCompleteTextView etInstance = (AutoCompleteTextView) view.findViewById( R.id.etInstance );
|
||||
final View btnOk = view.findViewById( R.id.btnOk );
|
||||
final CheckBox cbPseudoAccount = (CheckBox) view.findViewById( R.id.cbPseudoAccount );
|
||||
final CheckBox cbInputAccessToken = (CheckBox) view.findViewById( R.id.cbInputAccessToken );
|
||||
|
||||
cbPseudoAccount.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override public void onCheckedChanged( CompoundButton buttonView, boolean isChecked ){
|
||||
cbInputAccessToken.setEnabled( ! cbPseudoAccount.isChecked() );
|
||||
}
|
||||
} );
|
||||
|
||||
if( ! TextUtils.isEmpty( instance ) ){
|
||||
etInstance.setText( instance );
|
||||
@ -70,7 +81,10 @@ public class LoginForm {
|
||||
Utils.showToast( activity, true, R.string.instance_not_need_slash );
|
||||
return;
|
||||
}
|
||||
callback.startLogin( dialog, instance, cbPseudoAccount.isChecked() );
|
||||
callback.startLogin( dialog, instance
|
||||
, cbPseudoAccount.isChecked()
|
||||
, cbInputAccessToken.isChecked()
|
||||
);
|
||||
}
|
||||
} );
|
||||
view.findViewById( R.id.btnCancel ).setOnClickListener( new View.OnClickListener() {
|
||||
|
@ -112,7 +112,17 @@
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnInputAccessToken"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
android:ellipsize="start"
|
||||
android:text="@string/input_access_token"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<Button
|
||||
|
54
app/src/main/res/layout/dlg_access_token.xml
Normal file
54
app/src/main/res/layout/dlg_access_token.xml
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:labelFor="@+id/etToken"
|
||||
android:text="@string/access_token"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etToken"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="text"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
style="?android:attr/buttonBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnCancel"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/cancel"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnOk"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/ok"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
@ -12,8 +12,8 @@
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/instance"
|
||||
android:labelFor="@+id/etInstance"
|
||||
android:text="@string/instance"
|
||||
/>
|
||||
|
||||
<AutoCompleteTextView
|
||||
@ -22,17 +22,27 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:inputType="textUri"
|
||||
android:hint="@string/instance_hint"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="textUri"
|
||||
/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbPseudoAccount"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/pseudo_account"
|
||||
android:id="@+id/cbPseudoAccount"
|
||||
/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbInputAccessToken"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/input_access_token"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
|
@ -397,10 +397,13 @@
|
||||
<string name="quote_url">Quote URL</string>
|
||||
<string name="actions_for_notification">Actions for notification</string>
|
||||
<string name="delete_this_notification">Delete this notification</string>
|
||||
<string name="mute_this_conversation">Mute more notification for this conversation</string>
|
||||
<string name="unmute_this_conversation">Unmute more notification for this conversation</string>
|
||||
<string name="mute_this_conversation">Mute more notifications for this conversation</string>
|
||||
<string name="unmute_this_conversation">Unmute more notifications for this conversation</string>
|
||||
<string name="input_access_token">Specify access token (for advanced users)</string>
|
||||
<string name="access_token">Access token</string>
|
||||
<string name="token_not_specified">Please input access token.</string>
|
||||
|
||||
<!--<string name="abc_action_bar_home_description">Revenir à l\'accueil</string>-->
|
||||
<!--<string name="abc_action_bar_home_description">Revenir à l\'accueil</string>-->
|
||||
<!--<string name="abc_action_bar_home_description_format">%1$s, %2$s</string>-->
|
||||
<!--<string name="abc_action_bar_home_subtitle_description_format">%1$s, %2$s, %3$s</string>-->
|
||||
<!--<string name="abc_action_bar_up_description">Revenir en haut de la page</string>-->
|
||||
|
@ -684,7 +684,10 @@
|
||||
<string name="quote_url">URLを引用…</string>
|
||||
<string name="actions_for_notification">通知へのアクション</string>
|
||||
<string name="delete_this_notification">この通知を削除</string>
|
||||
<string name="mute_this_conversation">この会話の通知をミュート</string>
|
||||
<string name="unmute_this_conversation">この会話の通知をミュート解除</string>
|
||||
<string name="mute_this_conversation">この会話の次回以降の通知をミュート</string>
|
||||
<string name="unmute_this_conversation">この会話の次回以降の通知をミュート解除</string>
|
||||
<string name="access_token">アクセストークン</string>
|
||||
<string name="input_access_token">アクセストークンを指定する(上級者向け)</string>
|
||||
<string name="token_not_specified">アクセストークンを入力してください</string>
|
||||
|
||||
</resources>
|
||||
|
@ -392,7 +392,10 @@
|
||||
<string name="quote_url">Quote URL</string>
|
||||
<string name="actions_for_notification">Actions for notification</string>
|
||||
<string name="delete_this_notification">Delete this notification</string>
|
||||
<string name="mute_this_conversation">Mute this conversation</string>
|
||||
<string name="unmute_this_conversation">Unmute this conversation</string>
|
||||
<string name="mute_this_conversation">Mute more notifications for this conversation</string>
|
||||
<string name="unmute_this_conversation">Unmute more notifications for this conversation</string>
|
||||
<string name="input_access_token">Specify access token (for advanced users)</string>
|
||||
<string name="access_token">Access token</string>
|
||||
<string name="token_not_specified">Please input access token.</string>
|
||||
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user