diff --git a/.idea/dictionaries/tateisu.xml b/.idea/dictionaries/tateisu.xml index b6dd600b..86b253ea 100644 --- a/.idea/dictionaries/tateisu.xml +++ b/.idea/dictionaries/tateisu.xml @@ -8,6 +8,7 @@ favourited hashtag hashtags + idempotency noto nsfw reblog diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMain.java b/app/src/main/java/jp/juggler/subwaytooter/ActMain.java index 9bc03365..1a953e37 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMain.java +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMain.java @@ -10,6 +10,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.customtabs.CustomTabsIntent; import android.support.design.widget.FloatingActionButton; import android.support.v4.os.AsyncTaskCompat; @@ -141,6 +142,7 @@ public class ActMain extends AppCompatActivity } ColumnViewHolder.ListItemPopup list_item_popup; + void closeListItemPopup(){ if( list_item_popup != null ){ list_item_popup.dismiss(); @@ -328,7 +330,7 @@ public class ActMain extends AppCompatActivity }else if( id == R.id.nav_add_blocks ){ performAddTimeline( Column.TYPE_BLOCKS ); - + }else if( id == R.id.nav_follow_requests ){ performAddTimeline( Column.TYPE_FOLLOW_REQUESTS ); @@ -1660,7 +1662,7 @@ public class ActMain extends AppCompatActivity ) ); return client.request( - "/api/v1/follow_requests/" + who.id+ ( bAllow ? "/authorize" : "/reject" ) + "/api/v1/follow_requests/" + who.id + ( bAllow ? "/authorize" : "/reject" ) , request_builder ); } @@ -1680,7 +1682,7 @@ public class ActMain extends AppCompatActivity column.removeFollowRequest( access_info, who.id ); } - Utils.showToast( ActMain.this, false,( bAllow ? R.string.follow_request_authorized : R.string.follow_request_rejected),who.display_name ); + Utils.showToast( ActMain.this, false, ( bAllow ? R.string.follow_request_authorized : R.string.follow_request_rejected ), who.display_name ); }else{ Utils.showToast( ActMain.this, false, result.error ); } @@ -1739,7 +1741,9 @@ public class ActMain extends AppCompatActivity } private void callReport( - @NonNull final SavedAccount account + @NonNull final SavedAccount access_info + + , @NonNull final TootAccount who , @NonNull final TootStatus status , @NonNull final String comment , final ReportCompleteCallback callback @@ -1756,16 +1760,20 @@ public class ActMain extends AppCompatActivity } } ); - client.setAccount( account ); + client.setAccount( access_info ); + StringBuilder sb = new StringBuilder(); + sb.append( "account_id=" ) + .append( Long.toString( who.id ) ) + .append( "&comment=" ) + .append( Uri.encode( comment ) ); - String sb = "account_id=" + Long.toString( status.account.id ) - + "&comment=" + Uri.encode( comment ) - + "&status_ids[]=" + Long.toString( status.id ); + sb.append( "&status_ids[]=" ) + .append( Long.toString( status.id ) ); Request.Builder request_builder = new Request.Builder().post( RequestBody.create( TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED - , sb + , sb.toString() ) ); return client.request( "/api/v1/reports", request_builder ); @@ -1789,13 +1797,13 @@ public class ActMain extends AppCompatActivity }.execute(); } - private void openReportForm( final SavedAccount account, final TootAccount who, final TootStatus status ){ + private void openReportForm( @NonNull final SavedAccount account, @NonNull final TootAccount who, @NonNull final TootStatus status ){ ReportForm.showReportForm( this, who, status, new ReportForm.ReportFormCallback() { @Override public void startReport( final Dialog dialog, String comment ){ // レポートの送信を開始する - callReport( account, status, comment, new ReportCompleteCallback() { + callReport( account, who, status, comment, new ReportCompleteCallback() { @Override public void onReportComplete( TootApiResult result ){ // 成功したらダイアログを閉じる @@ -1957,17 +1965,19 @@ public class ActMain extends AppCompatActivity callBlock( access_info, status.account, false, null ); } } ); - dialog.addAction( getString( R.string.report ), new Runnable() { - @Override public void run(){ - openReportForm( access_info, status.account, status ); - } - } ); + if( access_info.isMe( status.account ) ){ dialog.addAction( getString( R.string.delete ), new Runnable() { @Override public void run(){ deleteStatus( access_info, status.id ); } } ); + }else{ + dialog.addAction( getString( R.string.report ), new Runnable() { + @Override public void run(){ + openReportForm( access_info, status.account, status ); + } + } ); } if( column_type == Column.TYPE_CONVERSATION && status.application != null ){ @@ -1991,12 +2001,12 @@ public class ActMain extends AppCompatActivity if( column_type == Column.TYPE_FOLLOW_REQUESTS ){ dialog.addAction( getString( R.string.follow_request_ok ), new Runnable() { @Override public void run(){ - callFollowRequestAuthorize( access_info, who ,true); + callFollowRequestAuthorize( access_info, who, true ); } } ); dialog.addAction( getString( R.string.follow_request_ng ), new Runnable() { @Override public void run(){ - callFollowRequestAuthorize( access_info, who ,false); + callFollowRequestAuthorize( access_info, who, false ); } } ); @@ -2044,15 +2054,14 @@ public class ActMain extends AppCompatActivity callBlock( access_info, who, false, null ); } } ); - dialog.addAction( getString( R.string.report ), new Runnable() { - @Override public void run(){ - openReportForm( access_info, who, null ); - } - } ); +// dialog.addAction( getString( R.string.report ), new Runnable() { +// @Override public void run(){ +// openReportForm( access_info, who, null ); +// } +// } ); dialog.show( this, null ); } - private void openOSSLicense(){ startActivity( new Intent( this, ActOSSLicense.class ) ); } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActPost.java b/app/src/main/java/jp/juggler/subwaytooter/ActPost.java index 640627d4..ea7cf484 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActPost.java +++ b/app/src/main/java/jp/juggler/subwaytooter/ActPost.java @@ -940,19 +940,14 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener { TootStatus status; - @Override - protected TootApiResult doInBackground( Void... params ){ + @Override protected TootApiResult doInBackground( Void... params ){ TootApiClient client = new TootApiClient( ActPost.this, new TootApiClient.Callback() { - @Override - public boolean isApiCancelled(){ + @Override public boolean isApiCancelled(){ return isCancelled(); } - - @Override - public void publishApiProgress( final String s ){ + @Override public void publishApiProgress( final String s ){ Utils.runOnMainThread( new Runnable() { - @Override - public void run(){ + @Override public void run(){ progress.setMessage( s ); } } ); @@ -960,12 +955,16 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener { } ); client.setAccount( target_account ); + String post_content = sb.toString(); + String digest = Utils.digestSHA256( post_content + target_account.acct ); Request.Builder request_builder = new Request.Builder() .post( RequestBody.create( TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED - , sb.toString() - ) ); + , post_content + ) ) + .header( "Idempotency-Key" ,digest) + ; TootApiResult result = client.request( "/api/v1/statuses", request_builder ); if( result.object != null ){ @@ -986,7 +985,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener { if( status != null ){ ActMain.update_at_resume = true; - ActPost.this.finish(); + //DEBUG ActPost.this.finish(); }else{ if( result != null ){ Utils.showToast( ActPost.this, true, result.error ); diff --git a/app/src/main/java/jp/juggler/subwaytooter/App1.java b/app/src/main/java/jp/juggler/subwaytooter/App1.java index b494ec62..8b0ba4ff 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/App1.java +++ b/app/src/main/java/jp/juggler/subwaytooter/App1.java @@ -17,6 +17,9 @@ import com.android.volley.RequestQueue; import com.android.volley.toolbox.ImageLoader; import com.android.volley.toolbox.Volley; +import java.util.ArrayList; +import java.util.Collections; + import jp.juggler.subwaytooter.table.AcctSet; import jp.juggler.subwaytooter.table.MutedApp; import jp.juggler.subwaytooter.table.ClientInfo; @@ -26,7 +29,11 @@ import jp.juggler.subwaytooter.table.MediaShown; import jp.juggler.subwaytooter.table.NotificationTracking; import jp.juggler.subwaytooter.table.SavedAccount; import jp.juggler.subwaytooter.table.UserRelation; +import okhttp3.CipherSuite; +import okhttp3.ConnectionSpec; import okhttp3.OkHttpClient; +import okhttp3.TlsVersion; +import okhttp3.internal.Util; import uk.co.chrisjenx.calligraphy.CalligraphyConfig; import uk.co.chrisjenx.calligraphy.TypefaceUtils; @@ -153,7 +160,8 @@ public class App1 extends Application { } - public static final OkHttpClient ok_http_client = new OkHttpClient(); + public static OkHttpClient ok_http_client ; + public static Typeface typeface_emoji ; @@ -179,6 +187,28 @@ public class App1 extends Application { typeface_emoji = TypefaceUtils.load(getAssets(), "emojione_android.ttf"); } + if( ok_http_client == null ){ +// ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS) +// .tlsVersions( TlsVersion.TLS_1_2) +// .cipherSuites( +// CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, +// CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, +// CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) +// .build(); +// +// ArrayList spec_list = new ArrayList<>( ); +// spec_list.add(ConnectionSpec.MODERN_TLS ); +// // spec_list.add(ConnectionSpec.COMPATIBLE_TLS ); +// spec_list.add(ConnectionSpec.CLEARTEXT ); +// ok_http_client = new OkHttpClient.Builder() +// .connectionSpecs( spec_list ) +// .build(); + + ok_http_client = new OkHttpClient(); + } + + + if( db_open_helper == null ){ db_open_helper = new DBOpenHelper( getApplicationContext() ); diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.java b/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.java index 6f2cf59b..b8792792 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.java +++ b/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.java @@ -111,6 +111,7 @@ public class TootApiClient { try{ response = call.execute(); }catch( Throwable ex ){ + ex.printStackTrace( ); return new TootApiResult( Utils.formatError( ex, context.getResources(), R.string.network_error ) ); @@ -183,6 +184,7 @@ public class TootApiClient { try{ response = call.execute(); }catch( Throwable ex ){ + ex.printStackTrace( ); return new TootApiResult( Utils.formatError( ex, context.getResources(), R.string.network_error ) ); } if( callback.isApiCancelled() ) return null; @@ -266,6 +268,7 @@ public class TootApiClient { try{ response = call.execute(); }catch( Throwable ex ){ + ex.printStackTrace( ); return new TootApiResult( Utils.formatError( ex, context.getResources(), R.string.network_error ) ); } if( callback.isApiCancelled() ) return null; @@ -306,6 +309,7 @@ public class TootApiClient { try{ response = call.execute(); }catch( Throwable ex ){ + ex.printStackTrace( ); return new TootApiResult( Utils.formatError( ex, context.getResources(), R.string.network_error ) ); } diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAttachment.java b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAttachment.java index 248ffcd7..ab21ee8d 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAttachment.java +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAttachment.java @@ -74,3 +74,47 @@ public class TootAttachment { } } + +// v1.3 から 添付ファイルの画像のピクセルサイズが取得できるようになった +// https://github.com/tootsuite/mastodon/issues/1985 +// "media_attachments" : [ +// { +// "id" : 4, +// "type" : "image", +// "remote_url" : "", +// "meta" : { +// "original" : { +// "width" : 600, +// "size" : "600x400", +// "height" : 400, +// "aspect" : 1.5 +// }, +// "small" : { +// "aspect" : 1.49812734082397, +// "height" : 267, +// "size" : "400x267", +// "width" : 400 +// } +// }, +// "url" : "http://127.0.0.1:3000/system/media_attachments/files/000/000/004/original/3416fc5188c656da.jpg?1493138517", +// "preview_url" : "http://127.0.0.1:3000/system/media_attachments/files/000/000/004/small/3416fc5188c656da.jpg?1493138517", +// "text_url" : "http://127.0.0.1:3000/media/4hfW3Kt4U9UxDvV_xug" +// }, +// { +// "text_url" : "http://127.0.0.1:3000/media/0vTH_B1kjvIvlUBhGBw", +// "preview_url" : "http://127.0.0.1:3000/system/media_attachments/files/000/000/003/small/23519a5e64064e32.png?1493138030", +// "meta" : { +// "fps" : 15, +// "duration" : 5.06, +// "width" : 320, +// "size" : "320x180", +// "height" : 180, +// "length" : "0:00:05.06", +// "aspect" : 1.77777777777778 +// }, +// "url" : "http://127.0.0.1:3000/system/media_attachments/files/000/000/003/original/23519a5e64064e32.mp4?1493138030", +// "remote_url" : "", +// "type" : "gifv", +// "id" : 3 +// } +// ], \ No newline at end of file diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/Utils.java b/app/src/main/java/jp/juggler/subwaytooter/util/Utils.java index ae31e9f6..3c713fc4 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/Utils.java +++ b/app/src/main/java/jp/juggler/subwaytooter/util/Utils.java @@ -134,7 +134,7 @@ public class Utils { try{ return str.getBytes( "UTF-8" ); }catch( Throwable ex ){ - return new byte[0]; // 入力がnullの場合のみ発生 + return new byte[ 0 ]; // 入力がnullの場合のみ発生 } } @@ -156,39 +156,38 @@ public class Utils { } } - public static String optStringX( JSONObject src, String key){ - return src.isNull( key ) ? null : src.optString( key ); + public static String optStringX( JSONObject src, String key ){ + return src.isNull( key ) ? null : src.optString( key ); } - - public static String optStringX( JSONArray src, int key){ - return src.isNull( key ) ? null : src.optString( key ); + + public static String optStringX( JSONArray src, int key ){ + return src.isNull( key ) ? null : src.optString( key ); } public static ArrayList< String > parseStringArray( LogCategory log, JSONArray array ){ - ArrayList< String > dst_list = new ArrayList<>( ); + ArrayList< String > dst_list = new ArrayList<>(); if( array != null ){ - for(int i=0,ie=array.length();i boolean equalsNullable(T a,T b){ + public static < T > boolean equalsNullable( T a, T b ){ return a == null ? b == null : a.equals( b ); } - public static CharSequence dumpCodePoints(String str){ + public static CharSequence dumpCodePoints( String str ){ StringBuilder sb = new StringBuilder(); - for(int i=0,ie=str.length(),cp;i taisaku_map = new HashMap<>(); @@ -555,11 +566,11 @@ public class Utils { String s = context.getString( string_id ); int end = s.length(); int pos = s.indexOf( "%1$s" ); - if( pos == -1 ) return s; - SpannableStringBuilder sb = new SpannableStringBuilder( ); - if( pos > 0 ) sb.append(s.substring( 0,pos )); - sb.append( display_name); - if( pos +4 < end ) sb.append(s.substring( pos+4,end )); + if( pos == - 1 ) return s; + SpannableStringBuilder sb = new SpannableStringBuilder(); + if( pos > 0 ) sb.append( s.substring( 0, pos ) ); + sb.append( display_name ); + if( pos + 4 < end ) sb.append( s.substring( pos + 4, end ) ); return sb; } @@ -814,14 +825,13 @@ public class Utils { return null; } - - public static Activity getActivityFromView( View view) { + public static Activity getActivityFromView( View view ){ Context context = view.getContext(); - while (context instanceof ContextWrapper ) { - if (context instanceof Activity) { - return (Activity)context; + while( context instanceof ContextWrapper ){ + if( context instanceof Activity ){ + return (Activity) context; } - context = ((ContextWrapper)context).getBaseContext(); + context = ( (ContextWrapper) context ).getBaseContext(); } return null; }