リファクタ

This commit is contained in:
tateisu 2018-01-03 13:00:49 +09:00
parent 941bbab4f2
commit d22125cd98
22 changed files with 585 additions and 787 deletions

View File

@ -3,7 +3,6 @@ package jp.juggler.subwaytooter;
import android.Manifest;
import android.app.Activity;
import android.app.NotificationChannel;
import android.app.ProgressDialog;
import android.content.ClipData;
import android.content.ContentValues;
import android.content.DialogInterface;
@ -49,6 +48,8 @@ import java.io.InputStream;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootAccount;
import jp.juggler.subwaytooter.api.entity.TootStatus;
import jp.juggler.subwaytooter.dialog.ActionsDialog;
@ -92,7 +93,7 @@ public class ActAccountSetting extends AppCompatActivity
this.pref = App1.pref;
initUI();
account = SavedAccount.loadAccount( this, getIntent().getLongExtra( KEY_ACCOUNT_DB_ID, - 1L ) );
account = SavedAccount.loadAccount( this, getIntent().getLongExtra( KEY_ACCOUNT_DB_ID, - 1L ) );
if( account == null ) finish();
loadUIFromData( account );
@ -522,6 +523,7 @@ public class ActAccountSetting extends AppCompatActivity
.setMessage( R.string.confirm_account_remove )
.setNegativeButton( R.string.cancel, null )
.setPositiveButton( R.string.ok, new DialogInterface.OnClickListener() {
@Override public void onClick( DialogInterface dialog, int which ){
account.delete();
@ -590,40 +592,15 @@ public class ActAccountSetting extends AppCompatActivity
///////////////////////////////////////////////////
private void performAccessToken(){
//noinspection deprecation
final ProgressDialog progress = new ProgressDialog( ActAccountSetting.this );
final AsyncTask< Void, String, TootApiResult > task = new AsyncTask< Void, String, TootApiResult >() {
@Override
protected TootApiResult doInBackground( Void... params ){
TootApiClient api_client = new TootApiClient( ActAccountSetting.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 );
}
} );
}
} );
api_client.setAccount( account );
return api_client.authorize1( Pref.pref( ActAccountSetting.this ).getString( Pref.KEY_CLIENT_NAME, "" ) );
new TootTaskRunner( ActAccountSetting.this, true ).run( account, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
return client.authorize1( Pref.pref( ActAccountSetting.this ).getString( Pref.KEY_CLIENT_NAME, "" ) );
}
@Override protected void onPostExecute( TootApiResult result ){
progress.dismiss();
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( result == null ){
// cancelled.
}else if( result.error != null ){
if( result.error != null ){
// エラー
String sv = result.error;
if( sv.startsWith( "https" ) ){
@ -642,16 +619,8 @@ public class ActAccountSetting extends AppCompatActivity
Utils.showToast( ActAccountSetting.this, false, R.string.access_token_updated_for );
}
}
};
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 );
}
static final int RESULT_INPUT_ACCESS_TOKEN = RESULT_FIRST_USER + 10;
@ -707,24 +676,8 @@ public class ActAccountSetting extends AppCompatActivity
void loadProfile(){
// サーバから情報をロードする
//noinspection deprecation
final ProgressDialog progress = new ProgressDialog( this );
final AsyncTask< Void, Void, TootApiResult > task = new AsyncTask< Void, Void, TootApiResult >() {
TootAccount data;
@Override protected TootApiResult doInBackground( Void... params ){
TootApiClient client = new TootApiClient( ActAccountSetting.this, new TootApiClient.Callback() {
@Override public boolean isApiCancelled(){
return isCancelled();
}
@Override public void publishApiProgress( final String s ){
}
} );
client.setAccount( account );
new TootTaskRunner( this, true ).run( account, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
TootApiResult result = client.request( "/api/v1/accounts/verify_credentials" );
if( result != null && result.object != null ){
data = TootAccount.parse( ActAccountSetting.this, account, result.object );
@ -733,35 +686,19 @@ public class ActAccountSetting extends AppCompatActivity
return result;
}
@Override
protected void onCancelled( TootApiResult result ){
super.onPostExecute( result );
}
TootAccount data;
@Override
protected void onPostExecute( TootApiResult result ){
try{
progress.dismiss();
}catch( Throwable ignored ){
}
if( result == null ){
// cancelled.
}else if( data != null ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( data != null ){
showProfile( data );
}else{
Utils.showToast( ActAccountSetting.this, true, result.error );
}
}
};
task.executeOnExecutor( App1.task_executor );
progress.setIndeterminate( true );
progress.setOnDismissListener( new DialogInterface.OnDismissListener() {
@Override public void onDismiss( DialogInterface dialog ){
task.cancel( true );
}
} );
progress.show();
}
void showProfile( TootAccount src ){
@ -794,24 +731,8 @@ public class ActAccountSetting extends AppCompatActivity
void updateCredential( final String form_data ){
//noinspection deprecation
final ProgressDialog progress = new ProgressDialog( this );
final AsyncTask< Void, Void, TootApiResult > task = new AsyncTask< Void, Void, TootApiResult >() {
TootAccount data;
@Override protected TootApiResult doInBackground( Void... params ){
TootApiClient client = new TootApiClient( ActAccountSetting.this, new TootApiClient.Callback() {
@Override public boolean isApiCancelled(){
return isCancelled();
}
@Override public void publishApiProgress( final String s ){
}
} );
client.setAccount( account );
new TootTaskRunner( this, true ).run( account, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
Request.Builder request_builder = new Request.Builder()
.patch( RequestBody.create(
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
@ -826,36 +747,20 @@ public class ActAccountSetting extends AppCompatActivity
return result;
}
@Override
protected void onCancelled( TootApiResult result ){
super.onPostExecute( result );
}
TootAccount data;
@Override
protected void onPostExecute( TootApiResult result ){
try{
progress.dismiss();
}catch( Throwable ignored ){
}
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( result == null ){
// cancelled.
}else if( data != null ){
if( data != null ){
showProfile( data );
}else{
Utils.showToast( ActAccountSetting.this, true, result.error );
}
}
};
task.executeOnExecutor( App1.task_executor );
progress.setIndeterminate( true );
progress.setOnDismissListener( new DialogInterface.OnDismissListener() {
@Override public void onDismiss( DialogInterface dialog ){
task.cancel( true );
}
} );
progress.show();
}
static final int max_length_display_name = 30;

View File

@ -68,8 +68,10 @@ import jp.juggler.subwaytooter.action.Action_HashTag;
import jp.juggler.subwaytooter.action.Action_Toot;
import jp.juggler.subwaytooter.action.Action_User;
import jp.juggler.subwaytooter.action.RelationChangedCallback;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootAccount;
import jp.juggler.subwaytooter.api.entity.TootStatus;
import jp.juggler.subwaytooter.api.entity.TootStatusLike;
@ -88,7 +90,6 @@ import jp.juggler.subwaytooter.view.ColumnStripLinearLayout;
import jp.juggler.subwaytooter.view.GravitySnapHelper;
import jp.juggler.subwaytooter.view.MyEditText;
@SuppressLint("StaticFieldLeak")
public class ActMain extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, View.OnClickListener, ViewPager.OnPageChangeListener, Column.Callback, DrawerLayout.DrawerListener
{
@ -1254,14 +1255,13 @@ public class ActMain extends AppCompatActivity
// OAuth2 認証コールバック
// subwaytooter://oauth/?...
new TootApiTask( ActMain.this, true ) {
new TootTaskRunner( ActMain.this, true ).run( new TootTask() {
TootAccount ta;
SavedAccount sa;
String host;
@Override
protected TootApiResult doInBackground( Void... params ){
@Override public TootApiResult background( @NonNull TootApiClient client ){
// エラー時
// subwaytooter://oauth
@ -1324,11 +1324,11 @@ public class ActMain extends AppCompatActivity
return result;
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( TootApiResult result ){
afterAccountVerify( result, ta, sa, host );
}
}.executeOnExecutor( App1.task_executor );
});
}
boolean afterAccountVerify( @Nullable TootApiResult result, @Nullable TootAccount ta, @Nullable SavedAccount sa, @Nullable String host ){
@ -1430,13 +1430,8 @@ public class ActMain extends AppCompatActivity
, @Nullable final SavedAccount sa
){
new TootApiTask( ActMain.this, host, true ) {
TootAccount ta;
@Override
protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( ActMain.this, true ) .run( host,new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
TootApiResult result = client.checkAccessToken( access_token );
if( result != null && result.object != null ){
// taは使い捨てなので生成に使うLinkClickContextはダミーで問題ない
@ -1450,7 +1445,9 @@ public class ActMain extends AppCompatActivity
return result;
}
@Override protected void handleResult( TootApiResult result ){
TootAccount ta;
@Override public void handleResult( @Nullable TootApiResult result ){
if( afterAccountVerify( result, ta, sa, host ) ){
try{
@ -1464,9 +1461,8 @@ public class ActMain extends AppCompatActivity
// IllegalArgumentException がたまに出る
}
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
// アクセストークンの手動入力(更新)
@ -2020,6 +2016,7 @@ public class ActMain extends AppCompatActivity
//noinspection deprecation
final ProgressDialog progress = new ProgressDialog( this );
@SuppressLint("StaticFieldLeak")
final AsyncTask< Void, String, ArrayList< Column > > task = new AsyncTask< Void, String, ArrayList< Column > >() {
void setProgressMessage( final String sv ){

View File

@ -51,8 +51,10 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootAttachment;
import jp.juggler.subwaytooter.dialog.ActionsDialog;
import jp.juggler.subwaytooter.util.LogCategory;
@ -174,7 +176,7 @@ public class ActMediaViewer extends AppCompatActivity implements View.OnClickLis
@Override public void run(){
if( isDestroyed() ) return;
if( tvStatus.getVisibility() == View.VISIBLE ){
tvStatus.setText( getString( R.string.zooming_of,(int) bitmap_w, (int)bitmap_h, scale ) );
tvStatus.setText( getString( R.string.zooming_of, (int) bitmap_w, (int) bitmap_h, scale ) );
}
}
} );
@ -291,7 +293,7 @@ public class ActMediaViewer extends AppCompatActivity implements View.OnClickLis
pbvImage.setVisibility( View.VISIBLE );
pbvImage.setBitmap( null );
new TootApiTask( this, TootApiTask.PROGRESS_HORIZONTAL ) {
new TootTaskRunner( this, TootTaskRunner.PROGRESS_HORIZONTAL ).run( new TootTask() {
private final BitmapFactory.Options options = new BitmapFactory.Options();
@ -318,7 +320,8 @@ public class ActMediaViewer extends AppCompatActivity implements View.OnClickLis
return BitmapFactory.decodeByteArray( data, 0, data.length, options );
}
@NonNull TootApiResult getHttpCached( @NonNull String url ){
@NonNull
TootApiResult getHttpCached( @NonNull final TootApiClient client, @NonNull String url ){
Response response;
try{
@ -327,7 +330,7 @@ public class ActMediaViewer extends AppCompatActivity implements View.OnClickLis
.cacheControl( App1.CACHE_5MIN )
.build();
publishApiProgress( getString( R.string.request_api, request.method(), url ) );
client.publishApiProgress( getString( R.string.request_api, request.method(), url ) );
Call call = App1.ok_http_client2.newCall( request );
response = call.execute();
}catch( Throwable ex ){
@ -346,7 +349,7 @@ public class ActMediaViewer extends AppCompatActivity implements View.OnClickLis
if( Math.max( bytesRead, bytesTotal ) >= 50000000 ){
throw new RuntimeException( "media attachment is larger than 50000000" );
}
publishApiProgressRatio( (int) bytesRead, (int) bytesTotal );
client.publishApiProgressRatio( (int) bytesRead, (int) bytesTotal );
}
} );
@ -359,23 +362,23 @@ public class ActMediaViewer extends AppCompatActivity implements View.OnClickLis
byte[] data;
Bitmap bitmap;
@Override protected TootApiResult doInBackground( Void... voids ){
TootApiResult result = getHttpCached( url );
@Override public TootApiResult background( @NonNull TootApiClient client ){
TootApiResult result = getHttpCached( client, url );
if( data == null ) return result;
publishApiProgress( "image decoding.." );
client.publishApiProgress( "decoding image…" );
this.bitmap = decodeBitmap( data, 2048 );
if( bitmap == null ) return new TootApiResult( "image decode failed." );
return result;
}
@Override protected void handleResult( @Nullable TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( bitmap != null ){
pbvImage.setBitmap( bitmap );
return;
}
if( result != null ) Utils.showToast( ActMediaViewer.this, true, result.error );
}
}.executeOnExecutor( App1.task_executor );
} );
}

View File

@ -58,7 +58,8 @@ import java.util.Locale;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootAttachment;
import jp.juggler.subwaytooter.api.entity.TootMention;
import jp.juggler.subwaytooter.api.entity.TootResults;
@ -863,41 +864,40 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
return;
}
new TootApiTask( this, access_info, true ) {
TootStatus target_status;
@Override protected TootApiResult doInBackground( Void... params ){
// 検索APIに他タンスのステータスのURLを投げると自タンスのステータスを得られる
String path = String.format( Locale.JAPAN, Column.PATH_SEARCH, Uri.encode( in_reply_to_url ) );
path = path + "&resolve=1";
TootApiResult result = client.request( path );
if( result != null && result.object != null ){
TootResults tmp = TootResults.parse( ActPost.this, access_info, result.object );
if( tmp != null && tmp.statuses != null && ! tmp.statuses.isEmpty() ){
target_status = tmp.statuses.get( 0 );
new TootTaskRunner( this, true )
.progressPrefix( getString( R.string.progress_synchronize_toot ) )
.run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
// 検索APIに他タンスのステータスのURLを投げると自タンスのステータスを得られる
String path = String.format( Locale.JAPAN, Column.PATH_SEARCH, Uri.encode( in_reply_to_url ) );
path = path + "&resolve=1";
TootApiResult result = client.request( path );
if( result != null && result.object != null ){
TootResults tmp = TootResults.parse( ActPost.this, access_info, result.object );
if( tmp != null && tmp.statuses != null && ! tmp.statuses.isEmpty() ){
target_status = tmp.statuses.get( 0 );
}
if( target_status == null ){
return new TootApiResult( getString( R.string.status_id_conversion_failed ) );
}
}
if( target_status == null ){
return new TootApiResult( getString( R.string.status_id_conversion_failed ) );
return result;
}
TootStatus target_status;
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( target_status != null ){
in_reply_to_id = target_status.id;
setAccountWithVisibilityConversion( access_info );
}else{
Utils.showToast( ActPost.this, true, getString( R.string.in_reply_to_id_conversion_failed ) + "\n" + result.error );
}
}
return result;
}
@Override protected void handleResult( TootApiResult result ){
if( isCancelled() ) return;
if( result == null ){
// cancelled.
}else if( target_status != null ){
in_reply_to_id = target_status.id;
setAccountWithVisibilityConversion( access_info );
}else{
Utils.showToast( ActPost.this, true, getString( R.string.in_reply_to_id_conversion_failed ) + "\n" + result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
@ -993,10 +993,8 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
@SuppressLint("StaticFieldLeak")
private void setAttachmentDescription( final PostAttachment pa, final Dialog dialog, final String text ){
final SavedAccount target_account = account;
new TootApiTask( this, target_account, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( this, true ).run( account, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
JSONObject json = new JSONObject();
try{
json.put( "description", text );
@ -1021,25 +1019,24 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
TootAttachment attachment;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( result == null ){
// cancelled.
}else if( attachment != null ){
if( attachment != null ){
pa.attachment = attachment;
showMediaAttachment();
try{
dialog.dismiss();
}catch( Throwable ignored ){
}
}else{
Utils.showToast( ActPost.this, true, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
void openAttachment(){
@ -1244,10 +1241,8 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
Utils.showToast( this, false, R.string.attachment_uploading );
final SavedAccount target_account = account;
new TootApiTask( this, target_account, false ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( this ).run( target_account, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
if( TextUtils.isEmpty( mime_type ) ){
return new TootApiResult( "mime_type is null." );
}
@ -1318,10 +1313,9 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
}catch( Throwable ex ){
return new TootApiResult( Utils.formatError( ex, "read failed." ) );
}
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( pa.attachment == null ){
pa.status = PostAttachment.STATUS_UPLOAD_FAILED;
if( result != null ){
@ -1333,8 +1327,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
// 投稿中に画面回転があった場合新しい画面のコールバックを呼び出す必要がある
pa.callback.onPostAttachmentComplete( pa );
}
}.executeOnExecutor( App1.task_executor );
} );
}
// 添付メディア投稿が完了したら呼ばれる
@ -1748,7 +1741,8 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
final ProgressDialog progress = new ProgressDialog( this );
@SuppressLint("StaticFieldLeak") final AsyncTask< Void, String, String > task = new AsyncTask< Void, String, String >() {
@SuppressLint("StaticFieldLeak")
final AsyncTask< Void, String, String > task = new AsyncTask< Void, String, String >() {
final ArrayList< String > list_warning = new ArrayList<>();
SavedAccount account;
@ -1780,13 +1774,14 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
}
return "OK";
}
// アカウントがあるなら基本的にはすべての情報を復元できるはずだがいくつか確認が必要だ
TootApiClient api_client = new TootApiClient( ActPost.this, new TootApiClient.Callback() {
@Override public boolean isApiCancelled(){
return isCancelled();
}
@Override public void publishApiProgress( final String s ){
@Override public void publishApiProgress( @NonNull final String s ){
Utils.runOnMainThread( new Runnable() {
@Override public void run(){
progress.setMessage( s );
@ -1794,6 +1789,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
} );
}
} );
api_client.setAccount( account );
if( in_reply_to_id != - 1L ){
@ -1835,11 +1831,15 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
}
@Override protected void onCancelled( String result ){
super.onCancelled( result );
onPostExecute( result );
}
@Override protected void onPostExecute( String result ){
progress.dismiss();
try{
progress.dismiss();
}catch(Throwable ignored){
}
if( isCancelled() || result == null ){
// cancelled.

View File

@ -1337,7 +1337,7 @@ import jp.juggler.subwaytooter.util.Utils;
TootAccount data = TootAccount.parse( context, access_info, result.object );
if( data != null ){
this.who_account = data;
client.callback.publishApiProgress( "" ); // カラムヘッダの再表示
client.publishApiProgress( "" ); // カラムヘッダの再表示
}
}
}
@ -1350,7 +1350,7 @@ import jp.juggler.subwaytooter.util.Utils;
TootList data = TootList.parse( result.object );
if( data != null ){
this.list_info = data;
client.callback.publishApiProgress( "" ); // カラムヘッダの再表示
client.publishApiProgress( "" ); // カラムヘッダの再表示
}
}
}
@ -1618,19 +1618,15 @@ import jp.juggler.subwaytooter.util.Utils;
return result;
}
@Override
protected TootApiResult doInBackground( Void... params ){
@Override protected TootApiResult doInBackground( Void... params ){
TootApiClient client = new TootApiClient( context, new TootApiClient.Callback() {
@Override
public boolean isApiCancelled(){
@Override public boolean isApiCancelled(){
return isCancelled() || is_dispose.get();
}
@Override
public void publishApiProgress( final String s ){
@Override public void publishApiProgress( @NonNull final String s ){
Utils.runOnMainThread( new Runnable() {
@Override
public void run(){
@Override public void run(){
if( isCancelled() ) return;
task_progress = s;
fireShowContent();
@ -2647,16 +2643,13 @@ import jp.juggler.subwaytooter.util.Utils;
@Override
protected TootApiResult doInBackground( Void... params ){
TootApiClient client = new TootApiClient( context, new TootApiClient.Callback() {
@Override
public boolean isApiCancelled(){
@Override public boolean isApiCancelled(){
return isCancelled() || is_dispose.get();
}
@Override
public void publishApiProgress( final String s ){
@Override public void publishApiProgress( @NonNull final String s ){
Utils.runOnMainThread( new Runnable() {
@Override
public void run(){
@Override public void run(){
if( isCancelled() ) return;
task_progress = s;
fireShowContent();
@ -3159,7 +3152,7 @@ import jp.juggler.subwaytooter.util.Utils;
return isCancelled() || is_dispose.get();
}
@Override public void publishApiProgress( final String s ){
@Override public void publishApiProgress( @NonNull final String s ){
Utils.runOnMainThread( new Runnable() {
@Override
public void run(){

View File

@ -838,9 +838,6 @@ public class PollingWorker {
@Override public boolean isApiCancelled(){
return job.isJobCancelled();
}
@Override public void publishApiProgress( String s ){
}
} );
@Override public void run(){

View File

@ -2,9 +2,9 @@ package jp.juggler.subwaytooter;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import org.json.JSONObject;
@ -19,6 +19,8 @@ import java.util.regex.Pattern;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootNotification;
import jp.juggler.subwaytooter.api.entity.TootStatus;
import jp.juggler.subwaytooter.table.SavedAccount;
@ -251,19 +253,8 @@ import okhttp3.WebSocketListener;
}
bListening.set( true );
new AsyncTask< Void, Void, TootApiResult >() {
@Override protected TootApiResult doInBackground( Void... params ){
TootApiClient client = new TootApiClient( context, new TootApiClient.Callback() {
@Override public boolean isApiCancelled(){
return isCancelled();
}
@Override public void publishApiProgress( String s ){
}
} );
client.setAccount( access_info );
new TootTaskRunner( context ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
TootApiResult result = client.webSocket( end_point, new Request.Builder(), Reader.this );
if( result == null ){
log.d( "startRead: cancelled." );
@ -273,7 +264,11 @@ import okhttp3.WebSocketListener;
}
return result;
}
}.executeOnExecutor( App1.task_executor );
@Override public void handleResult( @Nullable TootApiResult result ){
}
} );
}
}

View File

@ -1,6 +1,5 @@
package jp.juggler.subwaytooter.action;
import android.annotation.SuppressLint;
import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
@ -11,10 +10,10 @@ import org.json.JSONObject;
import java.util.ArrayList;
import jp.juggler.subwaytooter.ActMain;
import jp.juggler.subwaytooter.App1;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootAccount;
import jp.juggler.subwaytooter.api.entity.TootRelationShip;
import jp.juggler.subwaytooter.table.SavedAccount;
@ -22,27 +21,25 @@ import jp.juggler.subwaytooter.table.UserRelation;
import jp.juggler.subwaytooter.util.LogCategory;
import jp.juggler.subwaytooter.util.Utils;
@SuppressWarnings("WeakerAccess") @SuppressLint("StaticFieldLeak")
public class ActionUtils {
private static final LogCategory log = new LogCategory( "ActionUtils" );
public interface FindAccountCallback {
interface FindAccountCallback {
// return account information
// if failed, account is null.
void onFindAccount( @Nullable TootAccount account );
}
// ユーザ名からアカウントIDを取得する
public static void findAccountByName(
static void findAccountByName(
@NonNull final ActMain activity
, @NonNull final SavedAccount access_info
, @NonNull final String host
, @NonNull final String user
, @NonNull final FindAccountCallback callback
){
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... voids ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
String path = "/api/v1/accounts/search" + "?q=" + Uri.encode( user );
TootApiResult result = client.request( path );
@ -63,19 +60,17 @@ public class ActionUtils {
}
TootAccount who;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
callback.onFindAccount( who );
}
}.executeOnExecutor( App1.task_executor );
} );
}
// 疑似アカウントを作成する
// 既に存在する場合は再利用する
@Nullable
public static SavedAccount addPseudoAccount(
@Nullable static SavedAccount addPseudoAccount(
@NonNull Context context
, @NonNull String host
){
@ -157,10 +152,10 @@ public class ActionUtils {
// 別アカ操作と別タンスの関係
public static final int NOT_CROSS_ACCOUNT = 1;
public static final int CROSS_ACCOUNT_SAME_INSTANCE = 2;
public static final int CROSS_ACCOUNT_REMOTE_INSTANCE = 3;
private static final int CROSS_ACCOUNT_SAME_INSTANCE = 2;
static final int CROSS_ACCOUNT_REMOTE_INSTANCE = 3;
public static int calcCrossAccountMode( @NonNull final SavedAccount timeline_account, @NonNull final SavedAccount action_account ){
static int calcCrossAccountMode( @NonNull final SavedAccount timeline_account, @NonNull final SavedAccount action_account ){
if( ! timeline_account.host.equalsIgnoreCase( action_account.host ) ){
return CROSS_ACCOUNT_REMOTE_INSTANCE;
}else if( ! timeline_account.acct.equalsIgnoreCase( action_account.acct ) ){

View File

@ -1,6 +1,5 @@
package jp.juggler.subwaytooter.action;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Intent;
import android.net.Uri;
@ -16,8 +15,10 @@ import jp.juggler.subwaytooter.App1;
import jp.juggler.subwaytooter.Column;
import jp.juggler.subwaytooter.Pref;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.dialog.AccountPicker;
import jp.juggler.subwaytooter.dialog.DlgTextInput;
import jp.juggler.subwaytooter.dialog.LoginForm;
@ -25,9 +26,8 @@ import jp.juggler.subwaytooter.table.SavedAccount;
import jp.juggler.subwaytooter.util.LogCategory;
import jp.juggler.subwaytooter.util.Utils;
@SuppressWarnings("WeakerAccess") @SuppressLint("StaticFieldLeak")
public class Action_Account {
static final LogCategory log = new LogCategory( "Action_Account" );
private static final LogCategory log = new LogCategory( "Action_Account" );
// アカウントの追加
public static void add( @NonNull final ActMain activity ){
@ -43,9 +43,8 @@ public class Action_Account {
, final boolean bPseudoAccount
, final boolean bInputAccessToken
){
new TootApiTask( activity, instance, true ) {
@Override protected TootApiResult doInBackground( Void... voids ){
new TootTaskRunner( activity, true ).run( instance, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
if( bPseudoAccount ){
return client.checkInstance();
}else{
@ -54,7 +53,7 @@ public class Action_Account {
}
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( result.error != null ){
@ -120,8 +119,9 @@ public class Action_Account {
}
}
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
}
);

View File

@ -1,6 +1,5 @@
package jp.juggler.subwaytooter.action;
import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.net.Uri;
import android.support.annotation.NonNull;
@ -13,7 +12,8 @@ import jp.juggler.subwaytooter.Column;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootAccount;
import jp.juggler.subwaytooter.api.entity.TootRelationShip;
import jp.juggler.subwaytooter.dialog.AccountPicker;
@ -25,7 +25,6 @@ import jp.juggler.subwaytooter.util.Utils;
import okhttp3.Request;
import okhttp3.RequestBody;
@SuppressWarnings("WeakerAccess") @SuppressLint("StaticFieldLeak")
public class Action_Follow {
public static void follow(
@ -147,10 +146,8 @@ public class Action_Follow {
}
}
new TootApiTask( activity, access_info, false ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, false ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
TootApiResult result;
if( bFollow & who.acct.contains( "@" ) ){
@ -196,7 +193,7 @@ public class Action_Follow {
UserRelation relation;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
@ -219,8 +216,9 @@ public class Action_Follow {
}else{
Utils.showToast( activity, false, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
// acct で指定したユーザをリモートフォローする
@ -294,9 +292,8 @@ public class Action_Follow {
}
}
new TootApiTask( activity, access_info, false ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, false ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
Request.Builder request_builder = new Request.Builder().post(
RequestBody.create(
@ -323,7 +320,7 @@ public class Action_Follow {
TootAccount remote_who;
UserRelation relation;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
@ -338,8 +335,9 @@ public class Action_Follow {
}else{
Utils.showToast( activity, false, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
public static void followFromAnotherAccount(
@ -351,7 +349,7 @@ public class Action_Follow {
followFromAnotherAccount( activity, pos, access_info, account, false );
}
public static void followFromAnotherAccount(
private static void followFromAnotherAccount(
@NonNull final ActMain activity
, final int pos
, @NonNull final SavedAccount access_info
@ -404,10 +402,8 @@ public class Action_Follow {
return;
}
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
Request.Builder request_builder = new Request.Builder().post(
RequestBody.create(
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
@ -419,8 +415,7 @@ public class Action_Follow {
, request_builder );
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( result.object != null ){
@ -433,6 +428,6 @@ public class Action_Follow {
Utils.showToast( activity, false, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
}

View File

@ -1,8 +1,8 @@
package jp.juggler.subwaytooter.action;
import android.annotation.SuppressLint;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.util.ArrayList;
@ -12,14 +12,14 @@ import jp.juggler.subwaytooter.Column;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.dialog.AccountPicker;
import jp.juggler.subwaytooter.table.SavedAccount;
import jp.juggler.subwaytooter.util.Utils;
import okhttp3.Request;
import okhttp3.RequestBody;
@SuppressWarnings("WeakerAccess") @SuppressLint("StaticFieldLeak")
public class Action_Instance {
// インスタンス情報カラムを開く
@ -74,9 +74,8 @@ public class Action_Instance {
return;
}
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ) .run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
RequestBody body = RequestBody.create(
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
@ -89,8 +88,7 @@ public class Action_Instance {
return client.request( "/api/v1/domain_blocks", request_builder );
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( result.object != null ){
@ -105,7 +103,7 @@ public class Action_Instance {
Utils.showToast( activity, false, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
}

View File

@ -1,29 +1,27 @@
package jp.juggler.subwaytooter.action;
import android.annotation.SuppressLint;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.json.JSONObject;
import jp.juggler.subwaytooter.ActMain;
import jp.juggler.subwaytooter.App1;
import jp.juggler.subwaytooter.Column;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootList;
import jp.juggler.subwaytooter.table.SavedAccount;
import jp.juggler.subwaytooter.util.Utils;
import okhttp3.Request;
import okhttp3.RequestBody;
@SuppressWarnings("WeakerAccess") @SuppressLint("StaticFieldLeak")
public class Action_List {
public interface CreateCallback {
void onCreated(@NonNull TootList list);
void onCreated( @NonNull TootList list );
}
// リストを作成する
@ -31,11 +29,10 @@ public class Action_List {
@NonNull final ActMain activity
, @NonNull final SavedAccount access_info
, @NonNull final String title
,@Nullable final CreateCallback callback
, @Nullable final CreateCallback callback
){
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
JSONObject content = new JSONObject();
try{
@ -52,7 +49,7 @@ public class Action_List {
TootApiResult result = client.request( "/api/v1/lists", request_builder );
publishApiProgress( activity.getString( R.string.parsing_response ) );
client.publishApiProgress( activity.getString( R.string.parsing_response ) );
if( result != null ){
if( result.object != null ){
@ -66,7 +63,7 @@ public class Action_List {
TootList list;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( list != null ){
@ -77,12 +74,12 @@ public class Action_List {
Utils.showToast( activity, false, R.string.list_created );
if( callback != null ) callback.onCreated(list);
if( callback != null ) callback.onCreated( list );
}else{
Utils.showToast( activity, false, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
// リストを削除する
@ -91,13 +88,12 @@ public class Action_List {
, @NonNull final SavedAccount access_info
, final long list_id
){
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
return client.request( "/api/v1/lists/" + list_id, new Request.Builder().delete() );
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( result.object != null ){
@ -112,6 +108,6 @@ public class Action_List {
Utils.showToast( activity, false, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
}

View File

@ -1,6 +1,5 @@
package jp.juggler.subwaytooter.action;
import android.annotation.SuppressLint;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -16,7 +15,8 @@ import jp.juggler.subwaytooter.Column;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootAccount;
import jp.juggler.subwaytooter.api.entity.TootRelationShip;
import jp.juggler.subwaytooter.dialog.DlgConfirm;
@ -25,7 +25,6 @@ import jp.juggler.subwaytooter.util.Utils;
import okhttp3.Request;
import okhttp3.RequestBody;
@SuppressWarnings("WeakerAccess") @SuppressLint("StaticFieldLeak")
public class Action_ListMember {
public interface Callback {
@ -42,9 +41,8 @@ public class Action_ListMember {
, final boolean bFollow
, @Nullable final Callback callback
){
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
if( access_info.isMe( local_who ) ){
return new TootApiResult( activity.getString( R.string.it_is_you ) );
@ -125,7 +123,7 @@ public class Action_ListMember {
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
boolean bSuccess = false;
try{
@ -177,9 +175,9 @@ public class Action_ListMember {
}finally{
if( callback != null ) callback.onListMemberUpdated( true, bSuccess );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
public static void delete(
@ -189,18 +187,15 @@ public class Action_ListMember {
, @NonNull final TootAccount local_who
, @Nullable final Callback callback
){
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ) .run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
return client.request(
"/api/v1/lists/" + list_id + "/accounts?account_ids[]=" + local_who.id
, new Request.Builder().delete()
);
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
boolean bSuccess = false;
try{
@ -223,7 +218,8 @@ public class Action_ListMember {
}finally{
if( callback != null ) callback.onListMemberUpdated( false, bSuccess );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
}

View File

@ -1,8 +1,8 @@
package jp.juggler.subwaytooter.action;
import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import jp.juggler.subwaytooter.ActMain;
@ -11,14 +11,14 @@ import jp.juggler.subwaytooter.Column;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootNotification;
import jp.juggler.subwaytooter.table.SavedAccount;
import jp.juggler.subwaytooter.util.Utils;
import okhttp3.Request;
import okhttp3.RequestBody;
@SuppressWarnings("WeakerAccess") @SuppressLint("StaticFieldLeak")
public class Action_Notification {
public static void deleteAll(
@ -39,9 +39,8 @@ public class Action_Notification {
.show();
return;
}
new TootApiTask( activity, target_account, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( target_account, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
Request.Builder request_builder = new Request.Builder().post(
RequestBody.create(
@ -51,7 +50,7 @@ public class Action_Notification {
return client.request( "/api/v1/notifications/clear", request_builder );
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( result.object != null ){
@ -67,9 +66,9 @@ public class Action_Notification {
}else{
Utils.showToast( activity, false, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
public static void deleteOne(
@ -77,10 +76,8 @@ public class Action_Notification {
, @NonNull final SavedAccount access_info
, @NonNull final TootNotification notification
){
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
Request.Builder request_builder = new Request.Builder()
.post( RequestBody.create( TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
, "id=" + Long.toString( notification.id )
@ -92,8 +89,7 @@ public class Action_Notification {
, request_builder );
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ){
// cancelled.
}else if( result.object != null ){
@ -105,8 +101,9 @@ public class Action_Notification {
}else{
Utils.showToast( activity, true, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
}

View File

@ -1,6 +1,5 @@
package jp.juggler.subwaytooter.action;
import android.annotation.SuppressLint;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -17,7 +16,8 @@ import jp.juggler.subwaytooter.Column;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootResults;
import jp.juggler.subwaytooter.api.entity.TootStatus;
import jp.juggler.subwaytooter.api.entity.TootStatusLike;
@ -33,10 +33,9 @@ import jp.juggler.subwaytooter.util.Utils;
import okhttp3.Request;
import okhttp3.RequestBody;
@SuppressWarnings("WeakerAccess") @SuppressLint("StaticFieldLeak")
public class Action_Toot {
static final LogCategory log = new LogCategory( "Action_Favourite" );
private static final LogCategory log = new LogCategory( "Action_Favourite" );
// アカウントを選んでお気に入り
public static void favouriteFromAnotherAccount(
@ -81,9 +80,8 @@ public class Action_Toot {
App1.app_state.setBusyFav( access_info, arg_status );
//
new TootApiTask( activity, access_info, false ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, false ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
TootApiResult result;
TootStatusLike target_status;
@ -136,7 +134,7 @@ public class Action_Toot {
TootStatus new_status;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
App1.app_state.resetBusyFav( access_info, arg_status );
@ -177,9 +175,9 @@ public class Action_Toot {
}
// 結果に関わらず更新中状態から復帰させる
activity.showColumnMatchAccount( access_info );
}
}.executeOnExecutor( App1.task_executor );
} );
// ファボ表示を更新中にする
activity.showColumnMatchAccount( access_info );
@ -264,9 +262,8 @@ public class Action_Toot {
App1.app_state.setBusyBoost( access_info, arg_status );
new TootApiTask( activity, access_info, false ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, false ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
TootApiResult result;
@ -323,13 +320,11 @@ public class Action_Toot {
}
return result;
}
TootStatus new_status;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
App1.app_state.resetBusyBoost( access_info, arg_status );
//noinspection StatementWithEmptyBody
@ -370,10 +365,11 @@ public class Action_Toot {
// 結果に関わらず更新中状態から復帰させる
activity.showColumnMatchAccount( access_info );
}
}.executeOnExecutor( App1.task_executor );
} );
// ブースト表示を更新中にする
activity.showColumnMatchAccount( access_info );
}
@ -383,17 +379,14 @@ public class Action_Toot {
, final long status_id
){
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
Request.Builder request_builder = new Request.Builder().delete(); // method is delete
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
Request.Builder request_builder = new Request.Builder().delete();
return client.request( "/api/v1/statuses/" + status_id, request_builder );
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( result.object != null ){
@ -404,8 +397,9 @@ public class Action_Toot {
}else{
Utils.showToast( activity, false, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
/////////////////////////////////////////////////////////////////////////////////////
@ -424,7 +418,7 @@ public class Action_Toot {
conversationLocal( activity, pos, access_info, status.id );
}
}
// ローカルから見える会話の流れを表示する
public static void conversationLocal(
@NonNull final ActMain activity
@ -434,7 +428,7 @@ public class Action_Toot {
){
activity.addColumn( pos, access_info, Column.TYPE_CONVERSATION, status_id );
}
// リモートかもしれない会話の流れを表示する
public static void conversationOtherInstance(
@NonNull final ActMain activity
@ -584,69 +578,67 @@ public class Action_Toot {
dialog.show( activity, activity.getString( R.string.open_status_from ) );
}
static final Pattern reDetailedStatusTime = Pattern.compile( "<a\\b[^>]*?\\bdetailed-status__datetime\\b[^>]*href=\"https://[^/]+/@[^/]+/(\\d+)\"" );
private static final Pattern reDetailedStatusTime = Pattern.compile( "<a\\b[^>]*?\\bdetailed-status__datetime\\b[^>]*href=\"https://[^/]+/@[^/]+/(\\d+)\"" );
public static void conversationRemote(
private static void conversationRemote(
@NonNull final ActMain activity
, final int pos
, final SavedAccount access_info
, final String remote_status_url
){
new TootApiTask( activity, access_info, true ) {
long local_status_id = - 1L;
@Override protected TootApiResult doInBackground( Void... params ){
TootApiResult result;
if( access_info.isPseudo() ){
result = client.getHttp( remote_status_url );
if( result != null && result.json != null ){
try{
Matcher m = reDetailedStatusTime.matcher( result.json );
if( m.find() ){
local_status_id = Long.parseLong( m.group( 1 ), 10 );
new TootTaskRunner( activity, true )
.progressPrefix( activity.getString( R.string.progress_synchronize_toot ) )
.run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
TootApiResult result;
if( access_info.isPseudo() ){
result = client.getHttp( remote_status_url );
if( result != null && result.json != null ){
try{
Matcher m = reDetailedStatusTime.matcher( result.json );
if( m.find() ){
local_status_id = Long.parseLong( m.group( 1 ), 10 );
}
}catch( Throwable ex ){
log.e( ex, "openStatusRemote: can't parse status id from HTML data." );
}
if( local_status_id == - 1L ){
result = new TootApiResult( activity.getString( R.string.status_id_conversion_failed ) );
}
}catch( Throwable ex ){
log.e( ex, "openStatusRemote: can't parse status id from HTML data." );
}
if( local_status_id == - 1L ){
result = new TootApiResult( activity.getString( R.string.status_id_conversion_failed ) );
}
}
}else{
// 検索APIに他タンスのステータスのURLを投げると自タンスのステータスを得られる
String path = String.format( Locale.JAPAN, Column.PATH_SEARCH, Uri.encode( remote_status_url ) );
path = path + "&resolve=1";
result = client.request( path );
if( result != null && result.object != null ){
TootResults tmp = TootResults.parse( activity, access_info, result.object );
if( tmp != null && tmp.statuses != null && ! tmp.statuses.isEmpty() ){
TootStatus status = tmp.statuses.get( 0 );
local_status_id = status.id;
log.d( "status id conversion %s => %s", remote_status_url, status.id );
}
if( local_status_id == - 1L ){
result = new TootApiResult( activity.getString( R.string.status_id_conversion_failed ) );
}else{
// 検索APIに他タンスのステータスのURLを投げると自タンスのステータスを得られる
String path = String.format( Locale.JAPAN, Column.PATH_SEARCH, Uri.encode( remote_status_url ) );
path = path + "&resolve=1";
result = client.request( path );
if( result != null && result.object != null ){
TootResults tmp = TootResults.parse( activity, access_info, result.object );
if( tmp != null && tmp.statuses != null && ! tmp.statuses.isEmpty() ){
TootStatus status = tmp.statuses.get( 0 );
local_status_id = status.id;
log.d( "status id conversion %s => %s", remote_status_url, status.id );
}
if( local_status_id == - 1L ){
result = new TootApiResult( activity.getString( R.string.status_id_conversion_failed ) );
}
}
}
return result;
}
return result;
}
@Override protected void handleResult( TootApiResult result ){
if( result == null ){
// cancelled.
}else if( local_status_id != - 1L ){
conversationLocal( activity, pos, access_info, local_status_id );
}else{
Utils.showToast( activity, true, result.error );
long local_status_id = - 1L;
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ){
// cancelled.
}else if( local_status_id != - 1L ){
conversationLocal( activity, pos, access_info, local_status_id );
}else{
Utils.showToast( activity, true, result.error );
}
}
}
}
.setProgressPrefix( activity.getString( R.string.progress_synchronize_toot ) )
.executeOnExecutor( App1.task_executor );
} );
}
@ -660,59 +652,59 @@ public class Action_Toot {
, final boolean bSet
){
new TootApiTask( activity, access_info, true ) {
TootStatus new_status;
new TootTaskRunner( activity, true )
.progressPrefix( activity.getString( R.string.profile_pin_progress ) )
@Override protected TootApiResult doInBackground( Void... params ){
TootApiResult result;
Request.Builder request_builder = new Request.Builder()
.post( RequestBody.create(
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
, ""
) );
result = client.request(
( bSet
? "/api/v1/statuses/" + status.id + "/pin"
: "/api/v1/statuses/" + status.id + "/unpin"
)
, request_builder );
if( result != null && result.object != null ){
new_status = TootStatus.parse( activity, access_info, result.object );
}
return result;
}
@Override protected void handleResult( TootApiResult result ){
//noinspection StatementWithEmptyBody
if( result == null ){
// cancelled.
}else if( new_status != null ){
.run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
TootApiResult result;
for( Column column : App1.app_state.column_list ){
column.findStatus( access_info.host, new_status.id, new Column.StatusEntryCallback() {
@Override
public boolean onIterate( SavedAccount account, TootStatus status ){
status.pinned = bSet;
return true;
}
} );
Request.Builder request_builder = new Request.Builder()
.post( RequestBody.create(
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
, ""
) );
result = client.request(
( bSet
? "/api/v1/statuses/" + status.id + "/pin"
: "/api/v1/statuses/" + status.id + "/unpin"
)
, request_builder );
if( result != null && result.object != null ){
new_status = TootStatus.parse( activity, access_info, result.object );
}
}else{
Utils.showToast( activity, true, result.error );
return result;
}
// 結果に関わらず更新中状態から復帰させる
activity.showColumnMatchAccount( access_info );
}
}
.setProgressPrefix( activity.getString( R.string.profile_pin_progress ) )
.executeOnExecutor( App1.task_executor );
TootStatus new_status;
@Override public void handleResult( @Nullable TootApiResult result ){
//noinspection StatementWithEmptyBody
if( result == null ){
// cancelled.
}else if( new_status != null ){
for( Column column : App1.app_state.column_list ){
column.findStatus( access_info.host, new_status.id, new Column.StatusEntryCallback() {
@Override
public boolean onIterate( SavedAccount account, TootStatus status ){
status.pinned = bSet;
return true;
}
} );
}
}else{
Utils.showToast( activity, true, result.error );
}
// 結果に関わらず更新中状態から復帰させる
activity.showColumnMatchAccount( access_info );
}
} );
}
/////////////////////////////////////////////////////////////////////////////////
@ -751,48 +743,48 @@ public class Action_Toot {
} );
}
public static void replyRemote(
private static void replyRemote(
@NonNull final ActMain activity
, @NonNull final SavedAccount access_info
, @NonNull final String remote_status_url
){
new TootApiTask( activity, access_info, true ) {
new TootTaskRunner( activity, true )
.progressPrefix( activity.getString( R.string.progress_synchronize_toot ) )
TootStatus local_status;
@Override protected TootApiResult doInBackground( Void... params ){
// 検索APIに他タンスのステータスのURLを投げると自タンスのステータスを得られる
String path = String.format( Locale.JAPAN, Column.PATH_SEARCH, Uri.encode( remote_status_url ) );
path = path + "&resolve=1";
TootApiResult result = client.request( path );
if( result != null && result.object != null ){
TootResults tmp = TootResults.parse( activity, access_info, result.object );
if( tmp != null && tmp.statuses != null && ! tmp.statuses.isEmpty() ){
local_status = tmp.statuses.get( 0 );
log.d( "status id conversion %s => %s", remote_status_url, local_status.id );
}
if( local_status == null ){
return new TootApiResult( activity.getString( R.string.status_id_conversion_failed ) );
.run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
// 検索APIに他タンスのステータスのURLを投げると自タンスのステータスを得られる
String path = String.format( Locale.JAPAN, Column.PATH_SEARCH, Uri.encode( remote_status_url ) );
path = path + "&resolve=1";
TootApiResult result = client.request( path );
if( result != null && result.object != null ){
TootResults tmp = TootResults.parse( activity, access_info, result.object );
if( tmp != null && tmp.statuses != null && ! tmp.statuses.isEmpty() ){
local_status = tmp.statuses.get( 0 );
log.d( "status id conversion %s => %s", remote_status_url, local_status.id );
}
if( local_status == null ){
return new TootApiResult( activity.getString( R.string.status_id_conversion_failed ) );
}
}
return result;
}
return result;
}
@Override protected void handleResult( TootApiResult result ){
if( result == null ){
// cancelled.
}else if( local_status != null ){
reply( activity, access_info, local_status );
}else{
Utils.showToast( activity, true, result.error );
TootStatus local_status;
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ){
// cancelled.
}else if( local_status != null ){
reply( activity, access_info, local_status );
}else{
Utils.showToast( activity, true, result.error );
}
}
}
}
.setProgressPrefix( activity.getString( R.string.progress_synchronize_toot ) )
.executeOnExecutor( App1.task_executor );
} );
}
////////////////////////////////////////
@ -802,12 +794,11 @@ public class Action_Toot {
, @NonNull final SavedAccount access_info
, @NonNull final TootStatusLike status
){
// toggle change
final boolean bMute = ! status.muted;
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
Request.Builder request_builder = new Request.Builder()
.post( RequestBody.create( TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, "" ) );
@ -817,21 +808,20 @@ public class Action_Toot {
);
if( result != null && result.object != null ){
new_status = TootStatus.parse( activity, access_info, result.object );
local_status = TootStatus.parse( activity, access_info, result.object );
}
return result;
}
TootStatus new_status;
TootStatus local_status;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ){
// cancelled.
}else if( new_status != null ){
}else if( local_status != null ){
for( Column column : App1.app_state.column_list ){
column.findStatus( access_info.host, new_status.id, new Column.StatusEntryCallback() {
column.findStatus( access_info.host, local_status.id, new Column.StatusEntryCallback() {
@Override
public boolean onIterate( SavedAccount account, TootStatus status ){
if( access_info.acct.equalsIgnoreCase( account.acct ) ){
@ -846,7 +836,7 @@ public class Action_Toot {
Utils.showToast( activity, true, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
}

View File

@ -1,6 +1,5 @@
package jp.juggler.subwaytooter.action;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.net.Uri;
import android.support.annotation.NonNull;
@ -17,7 +16,8 @@ import jp.juggler.subwaytooter.Column;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootAccount;
import jp.juggler.subwaytooter.api.entity.TootRelationShip;
import jp.juggler.subwaytooter.api.entity.TootResults;
@ -31,7 +31,6 @@ import jp.juggler.subwaytooter.util.Utils;
import okhttp3.Request;
import okhttp3.RequestBody;
@SuppressWarnings("WeakerAccess") @SuppressLint("StaticFieldLeak")
public class Action_User {
// ユーザをミュート/ミュート解除する
@ -48,9 +47,8 @@ public class Action_User {
return;
}
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
Request.Builder request_builder = new Request.Builder().post(
! bMute ? RequestBody.create( TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, "" )
@ -68,8 +66,7 @@ public class Action_User {
UserRelation relation;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( relation != null ){
@ -95,8 +92,8 @@ public class Action_User {
Utils.showToast( activity, false, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
// ユーザをブロック/ブロック解除する
@ -111,9 +108,8 @@ public class Action_User {
return;
}
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
Request.Builder request_builder = new Request.Builder().post(
RequestBody.create(
@ -138,7 +134,7 @@ public class Action_User {
UserRelation relation;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
@ -164,7 +160,8 @@ public class Action_User {
Utils.showToast( activity, false, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
// アカウントを選んでユーザプロフを開く
@ -217,10 +214,8 @@ public class Action_User {
, final SavedAccount access_info
, final String who_url
){
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
// 検索APIに他タンスのユーザのURLを投げると自タンスのURLを得られる
String path = String.format( Locale.JAPAN, Column.PATH_SEARCH, Uri.encode( who_url ) );
path = path + "&resolve=1";
@ -242,12 +237,11 @@ public class Action_User {
}
return result;
}
TootAccount who_local;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ){
// cancelled.
@ -260,8 +254,8 @@ public class Action_User {
App1.openCustomTab( activity, who_url );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
// Intent-FilterからUser URL で指定されたユーザのプロフを開く
@ -347,7 +341,7 @@ public class Action_User {
}
// 通報する
static void report(
private static void report(
@NonNull final ActMain activity
, @NonNull final SavedAccount access_info
, @NonNull final TootAccount who
@ -360,9 +354,8 @@ public class Action_User {
return;
}
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
String sb = "account_id=" + Long.toString( who.id )
+ "&comment=" + Uri.encode( comment )
+ "&status_ids[]=" + Long.toString( status.id );
@ -376,7 +369,7 @@ public class Action_User {
return client.request( "/api/v1/reports", request_builder );
}
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
@ -388,8 +381,7 @@ public class Action_User {
Utils.showToast( activity, true, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
// show/hide boosts from (following) user
@ -404,9 +396,8 @@ public class Action_User {
return;
}
new TootApiTask( activity, access_info, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
JSONObject content = new JSONObject();
try{
@ -430,7 +421,7 @@ public class Action_User {
TootRelationShip relation;
@Override protected void handleResult( TootApiResult result ){
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
@ -441,12 +432,11 @@ public class Action_User {
Utils.showToast( activity, true, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}
// メンションを含むトゥートを作る
public static void mention(
private static void mention(
@NonNull final ActMain activity
, @NonNull final SavedAccount account
, @NonNull final String initial_text
@ -478,7 +468,10 @@ public class Action_User {
String who_host = access_info.getAccountHost( who );
final String initial_text = "@" + access_info.getFullAcct( who ) + " ";
AccountPicker.pick( activity, false, false
AccountPicker.pick(
activity
, false
, false
, activity.getString( R.string.account_picker_toot )
, ActionUtils.makeAccountListNonPseudo( activity, who_host )
, new AccountPicker.AccountPickerCallback() {

View File

@ -30,21 +30,37 @@ public class TootApiClient {
private static final OkHttpClient ok_http_client = App1.ok_http_client;
public interface Callback {
boolean isApiCancelled();
public static abstract class Callback {
void publishApiProgress( String s );
public abstract boolean isApiCancelled();
public void publishApiProgress( @NonNull String s ){
}
public void publishApiProgressRatio( int value, int max ){
}
}
private final Context context;
public final Callback callback;
@NonNull private final Context context;
@NonNull private final Callback callback;
public TootApiClient( @NonNull Context context, @NonNull Callback callback ){
this.context = context;
this.callback = callback;
}
@SuppressWarnings("unused") public boolean isApiCancelled(){
return callback.isApiCancelled();
}
public void publishApiProgress( @NonNull final String s ){
callback.publishApiProgress( s );
}
public void publishApiProgressRatio( final int value, final int max ){
callback.publishApiProgressRatio( value, max );
}
public interface CurrentCallCallback {
void onCallCreated( Call call );
}

View File

@ -0,0 +1,15 @@
package jp.juggler.subwaytooter.api;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
public interface TootTask {
// 非同期処理をここに実装する
TootApiResult background( @NonNull TootApiClient client );
// 非同期処理が終わったらメインスレッドから実行される
// 処理がキャンセルされた場合 resultはnullになるかもしれない
void handleResult( @Nullable TootApiResult result );
}

View File

@ -2,6 +2,7 @@ package jp.juggler.subwaytooter.api;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Handler;
@ -13,22 +14,27 @@ import android.text.TextUtils;
import java.lang.ref.WeakReference;
import java.text.NumberFormat;
import jp.juggler.subwaytooter.App1;
import jp.juggler.subwaytooter.table.SavedAccount;
/*
AsyncTask customized version:
- avoid warning from android lint.
- has ProgressDialog.
- has TootApiClient.
- pass progress message from TootApiClient to ProgressDialog.
非同期タスク(TootTask)を実行します
- 内部でAsyncTaskを使いますAndroid Lintの警告を抑制します
- ProgressDialogを表示します抑制することも可能です
- TootApiClientの初期化を行います
- TootApiClientからの進捗イベントをProgressDialogに伝達します
*/
@SuppressWarnings({"FieldCanBeLocal", "WeakerAccess"})
public abstract class TootApiTask extends AsyncTask< Void, Void, TootApiResult > implements TootApiClient.Callback {
public class TootTaskRunner extends TootApiClient.Callback {
@SuppressWarnings("WeakerAccess") public static final int PROGRESS_NONE = - 1;
@SuppressWarnings("WeakerAccess") public static final int PROGRESS_SPINNER = ProgressDialog.STYLE_SPINNER;
@SuppressWarnings("WeakerAccess") public static final int PROGRESS_HORIZONTAL = ProgressDialog.STYLE_HORIZONTAL;
private static int getDefaultProgressStyle( boolean bShowProgress ){
return bShowProgress ? PROGRESS_SPINNER : PROGRESS_NONE;
}
private static class ProgressInfo {
// HORIZONTALスタイルの場合初期メッセージがないと後からメッセージを指定しても表示されない
@ -39,15 +45,17 @@ public abstract class TootApiTask extends AsyncTask< Void, Void, TootApiResult >
int max = 1;
}
@NonNull private WeakReference< Activity > refActivity;
@NonNull protected Handler handler;
@NonNull protected final Handler handler;
@NonNull protected final TootApiClient client;
@NonNull private final ProgressInfo info = new ProgressInfo();
@NonNull private final MyTask task;
@NonNull protected final ProgressInfo info = new ProgressInfo();
@Nullable private ProgressDialog progress;
@Nullable private String progress_prefix;
@NonNull private final WeakReference<Context> refContext;
private final int progress_style;
private boolean isAlive = true;
private TootTask callback;
private long last_message_shown;
private static final NumberFormat percent_format;
@ -57,99 +65,119 @@ public abstract class TootApiTask extends AsyncTask< Void, Void, TootApiResult >
percent_format.setMaximumFractionDigits( 0 );
}
public TootApiTask( @NonNull Activity _activity, int progress_style ){
this.refActivity = new WeakReference<>( _activity );
this.handler = new Handler();
this.client = new TootApiClient( _activity, this );
public TootTaskRunner( @NonNull Context context ){
this( context,PROGRESS_NONE);
}
public TootTaskRunner( @NonNull Context context, boolean bShowProgress ){
this( context, getDefaultProgressStyle( bShowProgress ) );
}
public TootTaskRunner( @NonNull Context context, int progress_style ){
this.refContext = new WeakReference<>( context );
this.progress_style = progress_style;
if( progress_style != PROGRESS_NONE ){
// ダイアログの遅延表示を実装したけどすぐにダイアログを出した方が下のUIのタッチ判定を隠せて良いので使わないんだ
// handler.postDelayed( proc_progress_opener ,1000L );
proc_progress_opener.run();
}
this.handler = new Handler();
this.client = new TootApiClient( context, this );
this.task = new MyTask(this);
}
public TootApiTask( @NonNull Activity _activity, SavedAccount access_info, int progress_style ){
this( _activity, progress_style );
public void run( @NonNull TootTask callback){
openProgress();
this.callback = callback;
task.executeOnExecutor( App1.task_executor );
}
public void run( @NonNull SavedAccount access_info,@NonNull TootTask callback){
client.setAccount( access_info );
run(callback);
}
public TootApiTask( @NonNull Activity _activity, String instance, int progress_style ){
this( _activity, progress_style );
public void run( @NonNull String instance,@NonNull TootTask callback){
client.setInstance( instance );
run(callback);
}
private static int getDefaultProgressStyle( boolean bShowProgress ){
return bShowProgress ? PROGRESS_SPINNER : PROGRESS_NONE;
}
public TootApiTask( @NonNull Activity _activity, boolean bShowProgress ){
this( _activity, getDefaultProgressStyle( bShowProgress ) );
}
public TootApiTask( @NonNull Activity _activity, SavedAccount access_info, boolean bShowProgress ){
this( _activity, access_info, getDefaultProgressStyle( bShowProgress ) );
}
public TootApiTask( @NonNull Activity _activity, String instance, boolean bShowProgress ){
this( _activity, instance, getDefaultProgressStyle( bShowProgress ) );
}
public TootApiTask setProgressPrefix( String s ){
public TootTaskRunner progressPrefix( String s ){
this.progress_prefix = s;
return this;
}
//////////////////////////////////////////////////////
// implements AsyncTask
@Override protected abstract TootApiResult doInBackground( Void... voids );
protected abstract void handleResult( @Nullable TootApiResult result );
@Override protected final void onCancelled( TootApiResult result ){
onPostExecute( result );
}
@Override protected final void onPostExecute( TootApiResult result ){
dismissProgress();
handleResult( result );
// has AsyncTask
protected static class MyTask extends AsyncTask< Void, Void, TootApiResult >{
private TootTaskRunner runner;
MyTask(TootTaskRunner runner){
this.runner = runner;
}
@Override protected TootApiResult doInBackground( Void... voids ){
return runner.callback.background( runner.client );
}
@Override protected final void onCancelled( TootApiResult result ){
onPostExecute( result );
}
@Override protected final void onPostExecute( TootApiResult result ){
runner.dismissProgress();
runner.callback.handleResult( result );
}
}
//////////////////////////////////////////////////////
// implements TootApiClient.Callback
@Override public boolean isApiCancelled(){
return isCancelled();
return task.isCancelled();
}
@Override public void publishApiProgress( final String s ){
@Override public void publishApiProgress( @NonNull final String s ){
synchronized( this ){
info.message = s;
info.isIndeterminate = true;
}
requestShowMessage();
delayProgressMessage();
}
//////////////////////////////////////////////////////
// 内蔵メディアビューアのローディング進捗の表示に使う
public void publishApiProgressRatio( final int value, final int max ){
@Override public void publishApiProgressRatio( final int value, final int max ){
synchronized( this ){
info.isIndeterminate = false;
info.value = value;
info.max = max;
}
requestShowMessage();
delayProgressMessage();
}
//////////////////////////////////////////////////////
// ProgressDialog
private void openProgress(){
// open progress
if( progress_style != PROGRESS_NONE ){
Context context = refContext.get();
if( context != null && context instanceof Activity ){
//noinspection deprecation
progress = new ProgressDialog( context );
progress.setCancelable( true );
progress.setOnCancelListener( new DialogInterface.OnCancelListener() {
@Override public void onCancel( DialogInterface dialog ){
task.cancel( true );
}
} );
progress.setProgressStyle( progress_style );
showProgressMessage();
progress.show();
}
}
}
// ダイアログを閉じる
private void dismissProgress(){
synchronized( this ){
isAlive = false;
}
if( progress != null ){
try{
progress.dismiss();
@ -160,41 +188,14 @@ public abstract class TootApiTask extends AsyncTask< Void, Void, TootApiResult >
// at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:116)
// at android.app.Dialog.dismissDialog(Dialog.java:341)
// at android.app.Dialog.dismiss(Dialog.java:324)
// at jp.juggler.subwaytooter.ActMain$10$1.onPostExecute(ActMain.java:867)
// at jp.juggler.subwaytooter.ActMain$10$1.onPostExecute(ActMain.java:837)
}finally{
progress = null;
}
}
}
// ダイアログを開く
private final Runnable proc_progress_opener = new Runnable() {
@Override public void run(){
synchronized( this ){
Activity activity = refActivity.get();
if( isAlive
&& activity != null
&& progress == null
&& progress_style != PROGRESS_NONE
){
//noinspection deprecation
progress = new ProgressDialog( activity );
progress.setCancelable( true );
progress.setOnCancelListener( new DialogInterface.OnCancelListener() {
@Override public void onCancel( DialogInterface dialog ){
TootApiTask.this.cancel( true );
}
} );
progress.setProgressStyle( progress_style );
showProgressMessage();
progress.show();
}
}
}
};
// ダイアログのメッセージを更新する
// 初期化時とメッセージ更新時に呼ばれる
private void showProgressMessage(){
if( progress == null ) return;
@ -220,11 +221,15 @@ public abstract class TootApiTask extends AsyncTask< Void, Void, TootApiResult >
// 少し後にダイアログのメッセージを更新する
// あまり頻繁に更新せずしかし繰り返し呼ばれ続けても時々は更新したい
private void requestShowMessage(){
// どのスレッドから呼ばれるか分からない
private void delayProgressMessage(){
long wait = 100L + last_message_shown - SystemClock.elapsedRealtime();
wait = wait < 0L ? 0L : wait > 100L ? 100L : wait;
handler.removeCallbacks( proc_progress_message );
handler.postDelayed( proc_progress_message, wait );
synchronized( this ){
handler.removeCallbacks( proc_progress_message );
handler.postDelayed( proc_progress_message, wait );
}
}
private final Runnable proc_progress_message = new Runnable() {

View File

@ -1,9 +1,6 @@
package jp.juggler.subwaytooter.api.entity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Spannable;
@ -19,10 +16,11 @@ import java.util.ArrayList;
import java.util.regex.Pattern;
import jp.juggler.subwaytooter.ActMain;
import jp.juggler.subwaytooter.App1;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.table.SavedAccount;
import jp.juggler.subwaytooter.util.DecodeOptions;
import jp.juggler.subwaytooter.util.LogCategory;
@ -32,7 +30,6 @@ import jp.juggler.subwaytooter.view.EnqueteTimerView;
import okhttp3.Request;
import okhttp3.RequestBody;
@SuppressWarnings("WeakerAccess")
public class NicoEnquete {
static final LogCategory log = new LogCategory( "NicoEnquete" );
@ -43,7 +40,7 @@ public class NicoEnquete {
public ArrayList< Spannable > items;
// 結果の数値 // null or array of number
public ArrayList< Float > ratios;
@SuppressWarnings("unused") private ArrayList< Float > ratios;
// 結果の数値のテキスト // null or array of string
// public ArrayList< CharSequence > ratios_text;
@ -55,8 +52,8 @@ public class NicoEnquete {
private static final Pattern reWhitespace = Pattern.compile( "[\\s\\t\\x0d\\x0a]+" );
long time_start;
long status_id;
private long time_start;
private long status_id;
public static NicoEnquete parse(
@NonNull Context context,
@ -116,7 +113,7 @@ public class NicoEnquete {
return null;
}
private static ArrayList< String > parseStringArray( JSONObject src, String name ){
private static ArrayList< String > parseStringArray( JSONObject src, @SuppressWarnings("SameParameterValue") String name ){
JSONArray array = src.optJSONArray( name );
if( array != null ){
ArrayList< String > dst = new ArrayList<>();
@ -129,7 +126,7 @@ public class NicoEnquete {
return null;
}
private static ArrayList< Float > parseFloatArray( JSONObject src, String name ){
private static ArrayList< Float > parseFloatArray( JSONObject src, @SuppressWarnings("SameParameterValue") String name ){
JSONArray array = src.optJSONArray( name );
if( array != null ){
ArrayList< Float > dst = new ArrayList<>();
@ -142,7 +139,7 @@ public class NicoEnquete {
return null;
}
static final long ENQUETE_EXPIRE = 30000L;
private static final long ENQUETE_EXPIRE = 30000L;
public void makeChoiceView(
final ActMain activity
@ -190,7 +187,7 @@ public class NicoEnquete {
llExtra.addView( view );
}
void enquete_click( @NonNull final Context context, @NonNull final SavedAccount access_info, final int idx ){
private void enquete_click( @NonNull final Context context, @NonNull final SavedAccount access_info, final int idx ){
long now = System.currentTimeMillis();
long remain = time_start + ENQUETE_EXPIRE - now;
@ -199,21 +196,8 @@ public class NicoEnquete {
return;
}
final ProgressDialog progress = new ProgressDialog( context );
final AsyncTask< Void, Void, TootApiResult > task = new AsyncTask< Void, Void, TootApiResult >() {
@Override protected TootApiResult doInBackground( Void... params ){
TootApiClient client = new TootApiClient( context, new TootApiClient.Callback() {
@Override public boolean isApiCancelled(){
return isCancelled();
}
@Override public void publishApiProgress( final String s ){
}
} );
client.setAccount( access_info );
new TootTaskRunner( context ).run( access_info, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
JSONObject form = new JSONObject();
try{
form.put( "item_index", Integer.toString( idx ) );
@ -231,21 +215,10 @@ public class NicoEnquete {
return result;
}
@Override
protected void onCancelled( TootApiResult result ){
super.onPostExecute( result );
}
@Override
protected void onPostExecute( TootApiResult result ){
try{
progress.dismiss();
}catch( Throwable ignored ){
}
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
if( result == null ){
// cancelled.
}else if( result.object != null ){
if( result.object != null ){
String message = Utils.optStringX( result.object, "message" );
boolean valid = result.object.optBoolean( "valid" );
if( valid ){
@ -256,18 +229,8 @@ public class NicoEnquete {
}else{
Utils.showToast( context, true, result.error );
}
}
};
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 );
}
}

View File

@ -28,8 +28,10 @@ import jp.juggler.subwaytooter.Styler;
import jp.juggler.subwaytooter.action.ActionUtils;
import jp.juggler.subwaytooter.action.Action_List;
import jp.juggler.subwaytooter.action.Action_ListMember;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootApiTask;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootAccount;
import jp.juggler.subwaytooter.api.entity.TootList;
import jp.juggler.subwaytooter.api.entity.TootResults;
@ -40,7 +42,6 @@ import jp.juggler.subwaytooter.util.Utils;
import jp.juggler.subwaytooter.view.MyListView;
import jp.juggler.subwaytooter.view.MyNetworkImageView;
@SuppressLint({ "StaticFieldLeak", "InflateParams" })
public class DlgListMember implements View.OnClickListener {
@NonNull private final ActMain activity;
@ -66,7 +67,7 @@ public class DlgListMember implements View.OnClickListener {
this.list_owner = _list_owner;
}
final View view = activity.getLayoutInflater().inflate( R.layout.dlg_list_member, null, false );
@SuppressLint("InflateParams") final View view = activity.getLayoutInflater().inflate( R.layout.dlg_list_member, null, false );
MyNetworkImageView ivUser = view.findViewById( R.id.ivUser );
TextView tvUserName = view.findViewById( R.id.tvUserName );
@ -180,10 +181,8 @@ public class DlgListMember implements View.OnClickListener {
return;
}
new TootApiTask( activity, list_owner, true ) {
@Override protected TootApiResult doInBackground( Void... params ){
new TootTaskRunner( activity, true ).run( list_owner, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
// リストに追加したいアカウントの自タンスでのアカウントIDを取得する
local_who = null;
TootApiResult result = client.request( "/api/v1/search?resolve=true&q=" + Uri.encode( target_user_full_acct ) );
@ -222,22 +221,21 @@ public class DlgListMember implements View.OnClickListener {
if( result == null || result.array == null ){
return result;
}
list_list = TootList.parseList( result.array );
Collections.sort( list_list );
new_list = TootList.parseList( result.array );
Collections.sort( new_list );
// isRegistered を設定する
for( TootList a : list_list ){
for( TootList a : new_list ){
if( set_registered.contains( a.id ) ) a.isRegistered = true;
}
return result;
}
TootList.List list_list;
TootList.List new_list;
@Override protected void handleResult( TootApiResult result ){
showList( list_list );
@Override public void handleResult( @Nullable TootApiResult result ){
showList( new_list );
//noinspection StatementWithEmptyBody
if( result != null
@ -246,8 +244,9 @@ public class DlgListMember implements View.OnClickListener {
){
Utils.showToast( activity, true, result.error );
}
}
}.executeOnExecutor( App1.task_executor );
} );
}

View File

@ -1,13 +1,11 @@
package jp.juggler.subwaytooter.util;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
@ -31,6 +29,8 @@ import jp.juggler.subwaytooter.Pref;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.CustomEmoji;
import jp.juggler.subwaytooter.api.entity.TootAccount;
import jp.juggler.subwaytooter.api.entity.TootInstance;
@ -45,7 +45,6 @@ import jp.juggler.subwaytooter.view.MyEditText;
import okhttp3.Request;
import okhttp3.RequestBody;
@SuppressWarnings("WeakerAccess")
public class PostHelper implements CustomEmojiLister.Callback, EmojiPicker.Callback {
private static final LogCategory log = new LogCategory( "PostHelper" );
@ -93,7 +92,7 @@ public class PostHelper implements CustomEmojiLister.Callback, EmojiPicker.Callb
public ArrayList< PostAttachment > attachment_list;
public ArrayList< String > enquete_items;
static final VersionString version_1_6 = new VersionString( "1.6" );
private static final VersionString version_1_6 = new VersionString( "1.6" );
public void post( final SavedAccount account, final boolean bConfirmTag, final boolean bConfirmAccount, final Callback callback ){
if( TextUtils.isEmpty( content ) ){
@ -170,11 +169,8 @@ public class PostHelper implements CustomEmojiLister.Callback, EmojiPicker.Callb
}
}
//noinspection deprecation
final ProgressDialog progress = new ProgressDialog( activity );
@SuppressLint("StaticFieldLeak")
final AsyncTask< Void, Void, TootApiResult > task = new AsyncTask< Void, Void, TootApiResult >() {
new TootTaskRunner( activity, true ).run( account, new TootTask() {
final SavedAccount target_account = account;
TootStatus status;
@ -203,23 +199,7 @@ public class PostHelper implements CustomEmojiLister.Callback, EmojiPicker.Callb
return result;
}
@Override protected TootApiResult doInBackground( Void... params ){
TootApiClient client = new TootApiClient( activity, 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.setAccount( target_account );
@Override public TootApiResult background( @NonNull TootApiClient client ){
if( TextUtils.isEmpty( visibility ) ){
visibility = TootStatus.VISIBILITY_PUBLIC;
}
@ -367,48 +347,18 @@ public class PostHelper implements CustomEmojiLister.Callback, EmojiPicker.Callb
}
@Override
protected void onCancelled(){
onPostExecute( null );
}
@Override
protected void onPostExecute( TootApiResult result ){
try{
progress.dismiss();
}catch( Throwable ignored ){
// java.lang.IllegalArgumentException:
// at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:396)
// at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:322)
// at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:116)
// at android.app.Dialog.dismissDialog(Dialog.java:341)
// at android.app.Dialog.dismiss(Dialog.java:324)
// at jp.juggler.subwaytooter.ActMain$10$1.onPostExecute(ActMain.java:867)
// at jp.juggler.subwaytooter.ActMain$10$1.onPostExecute(ActMain.java:837)
}
@Override public void handleResult( @Nullable TootApiResult result ){
if( result == null ) return; // cancelled.
//noinspection StatementWithEmptyBody
if( result == null ){
// cancelled.
}else if( status != null ){
if( status != null ){
// 連投してIdempotency が同じだった場合もエラーにはならずここを通る
callback.onPostComplete( target_account, status );
}else{
Utils.showToast( activity, true, result.error );
}
}
};
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 );
}
public interface Callback2 {