From 2135e62ef8b9b7d6f0670a7b37fbe9b9a0e0e2a4 Mon Sep 17 00:00:00 2001 From: tateisu Date: Fri, 8 Dec 2017 04:51:37 +0900 Subject: [PATCH] =?UTF-8?q?(=E8=A9=A6=E9=A8=93=E5=AE=9F=E8=A3=85)=E5=BC=95?= =?UTF-8?q?=E3=81=A3=E8=B6=8A=E3=81=97=E3=81=95=E3=82=8C=E3=81=9F=E3=82=A2?= =?UTF-8?q?=E3=82=AB=E3=82=A6=E3=83=B3=E3=83=88=E3=81=AE=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=83=95=E8=A1=A8=E7=A4=BA=E3=81=A8=E3=83=95=E3=82=A9=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=83=9C=E3=82=BF=E3=83=B3=E3=81=AE=E6=8C=99=E5=8B=95?= =?UTF-8?q?=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 +- .../java/jp/juggler/subwaytooter/ActMain.java | 87 +++++- .../java/jp/juggler/subwaytooter/Column.java | 293 ++++++++---------- .../juggler/subwaytooter/DlgContextMenu.java | 9 +- .../subwaytooter/HeaderViewHolderProfile.java | 112 ++++++- .../juggler/subwaytooter/ItemViewHolder.java | 2 +- .../juggler/subwaytooter/StatusButtons.java | 8 +- .../subwaytooter/api/entity/TootAccount.java | 15 +- app/src/main/res/layout/lv_header_account.xml | 99 +++++- app/src/main/res/values-fr/strings.xml | 3 + app/src/main/res/values-ja/strings.xml | 4 + app/src/main/res/values/strings.xml | 4 + 12 files changed, 444 insertions(+), 196 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 23bec48e..6fda4df8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "jp.juggler.subwaytooter" minSdkVersion 21 targetSdkVersion 26 - versionCode 178 - versionName "1.7.8" + versionCode 179 + versionName "1.7.9" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMain.java b/app/src/main/java/jp/juggler/subwaytooter/ActMain.java index 893af9ce..a2f2afee 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMain.java +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMain.java @@ -3329,11 +3329,23 @@ public class ActMain extends AppCompatActivity return rr; } - void callFollow( - @NonNull final SavedAccount access_info + public void callFollow( + int pos + , @NonNull final SavedAccount access_info , @NonNull final TootAccount who , final boolean bFollow - , boolean bConfirmed + , @Nullable final RelationChangedCallback callback + ){ + callFollow( pos ,access_info,who,bFollow,false,false,callback ); + } + + private void callFollow( + final int pos + , @NonNull final SavedAccount access_info + , @NonNull final TootAccount who + , final boolean bFollow + , final boolean bConfirmMoved + , final boolean bConfirmed , @Nullable final RelationChangedCallback callback ){ if( access_info.isMe( who ) ){ @@ -3341,6 +3353,27 @@ public class ActMain extends AppCompatActivity return; } + if( ! bConfirmMoved && bFollow && who.moved != null ){ + new AlertDialog.Builder( this ) + .setMessage( getString( R.string.jump_moved_user + , access_info.getFullAcct( who ) + , access_info.getFullAcct( who.moved ) + ) ) + .setPositiveButton( R.string.ok, new DialogInterface.OnClickListener() { + @Override public void onClick( DialogInterface dialog, int which ){ + openProfileFromAnotherAccount( pos,access_info,who.moved ); + } + } ) + .setNeutralButton( R.string.ignore_suggestion, new DialogInterface.OnClickListener() { + @Override public void onClick( DialogInterface dialog, int which ){ + callFollow( pos, access_info, who, true, true, false, callback ); + } + } ) + .setNegativeButton( android.R.string.cancel,null) + .show(); + return; + } + if( ! bConfirmed ){ if( bFollow && who.locked ){ DlgConfirm.open( this @@ -3358,7 +3391,7 @@ public class ActMain extends AppCompatActivity @Override public void onOK(){ //noinspection ConstantConditions - callFollow( access_info, who, bFollow, true, callback ); + callFollow( pos,access_info, who, bFollow, bConfirmMoved, true, callback ); } } ); @@ -3384,7 +3417,7 @@ public class ActMain extends AppCompatActivity @Override public void onOK(){ //noinspection ConstantConditions - callFollow( access_info, who, bFollow, true, callback ); + callFollow( pos, access_info, who, bFollow, bConfirmMoved, true, callback ); } } ); @@ -3405,7 +3438,7 @@ public class ActMain extends AppCompatActivity @Override public void onOK(){ //noinspection ConstantConditions - callFollow( access_info, who, bFollow, true, callback ); + callFollow( pos, access_info, who, bFollow, bConfirmMoved,true, callback ); } } ); @@ -3515,7 +3548,17 @@ public class ActMain extends AppCompatActivity } // acct で指定したユーザをリモートフォローする - void callRemoteFollow( + private void callRemoteFollow( + @NonNull final SavedAccount access_info + , @NonNull final String acct + , final boolean locked + , @Nullable final RelationChangedCallback callback + ){ + callRemoteFollow( access_info, acct,locked,false,callback); + } + + // acct で指定したユーザをリモートフォローする + private void callRemoteFollow( @NonNull final SavedAccount access_info , @NonNull final String acct , final boolean locked @@ -4391,18 +4434,42 @@ public class ActMain extends AppCompatActivity // if( status == null ) return; // openFollowFromAnotherAccount( access_info, status.account ); // } + void openFollowFromAnotherAccount( int pos,@NonNull SavedAccount access_info, @Nullable final TootAccount account ){ + openFollowFromAnotherAccount( pos,access_info, account ,false); + } - void openFollowFromAnotherAccount( @NonNull SavedAccount access_info, @Nullable final TootAccount account ){ + void openFollowFromAnotherAccount( final int pos,@NonNull final SavedAccount access_info, @Nullable final TootAccount account ,final boolean bConfirmMoved ){ if( account == null ) return; - String who_host = access_info.getAccountHost( account ); + if( ! bConfirmMoved && account.moved != null ){ + new AlertDialog.Builder( this ) + .setMessage( getString( R.string.jump_moved_user + , access_info.getFullAcct( account ) + , access_info.getFullAcct( account.moved ) + ) ) + .setPositiveButton( R.string.ok, new DialogInterface.OnClickListener() { + @Override public void onClick( DialogInterface dialog, int which ){ + openProfileFromAnotherAccount( pos,access_info,account.moved ); + } + } ) + .setNeutralButton( R.string.ignore_suggestion, new DialogInterface.OnClickListener() { + @Override public void onClick( DialogInterface dialog, int which ){ + openFollowFromAnotherAccount( pos,access_info, account ,true); + } + } ) + .setNegativeButton( android.R.string.cancel,null) + .show(); + return; + } + + final String who_host = access_info.getAccountHost( account ); final String who_acct = access_info.getFullAcct( account ); AccountPicker.pick( this, false, false , getString( R.string.account_picker_follow ) , makeAccountList( log, false, who_host ) , new AccountPicker.AccountPickerCallback() { @Override public void onAccountPicked( @NonNull SavedAccount ai ){ - callRemoteFollow( ai, who_acct, account.locked, false, follow_complete_callback ); + callRemoteFollow( ai, who_acct, account.locked, follow_complete_callback ); } } ); } diff --git a/app/src/main/java/jp/juggler/subwaytooter/Column.java b/app/src/main/java/jp/juggler/subwaytooter/Column.java index dff67812..14633fa3 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Column.java +++ b/app/src/main/java/jp/juggler/subwaytooter/Column.java @@ -60,7 +60,6 @@ import jp.juggler.subwaytooter.util.Utils; @SuppressWarnings("WeakerAccess") public class Column implements StreamReader.Callback { private static final LogCategory log = new LogCategory( "Column" ); - interface Callback { boolean isActivityStart(); } @@ -749,7 +748,7 @@ import jp.juggler.subwaytooter.util.Utils; if( item.status.reblog != null && item.status.reblog.account != null && item.status.reblog.account.id == who_id ) continue; } - }else if( o instanceof TootAccount ){ + }else if( o instanceof TootAccount ){ TootAccount item = (TootAccount) o; if( item.id == who_id ) continue; } @@ -1749,7 +1748,7 @@ import jp.juggler.subwaytooter.util.Utils; } }finally{ try{ - updateRelation( client, list_tmp ); + updateRelation( client, list_tmp, who_account ); }catch( Throwable ex ){ log.trace( ex ); } @@ -1850,164 +1849,132 @@ import jp.juggler.subwaytooter.util.Utils; return path; } - private void updateRelation( TootApiClient client, ArrayList< Object > list_tmp ){ - if( list_tmp == null || list_tmp.isEmpty() ) return; - if( access_info.isPseudo() ) return; - + private class UpdateRelationEnv { HashSet< Long > who_set = new HashSet<>(); HashSet< String > acct_set = new HashSet<>(); HashSet< String > tag_set = new HashSet<>(); - { - TootAccount a; - TootStatus s; - TootNotification n; + + void add( @Nullable TootAccount a ){ + if( a == null ) return; + who_set.add( a.id ); + acct_set.add( "@" + access_info.getFullAcct( a ) ); + // + add( a.moved ); + } + + void add( @Nullable TootStatus s ){ + if( s==null) return; + add( s.account ); + add( s.reblog ); + // + if( s.tags != null ){ + for( TootTag tag : s.tags ){ + tag_set.add( tag.name ); + } + } + } + + void add( @Nullable TootNotification n ){ + if( n == null ) return; + add( n.account ); + add( n.status ); + } + + void update(@NonNull TootApiClient client){ + int size = who_set.size(); + if( size > 0 ){ + long[] who_list = new long[ size ]; + { + int n = 0; + for( Long l : who_set ){ + who_list[ n++ ] = l; + } + } + + long now = System.currentTimeMillis(); + int n = 0; + while( n < size ){ + StringBuilder sb = new StringBuilder(); + sb.append( "/api/v1/accounts/relationships" ); + for( int i = 0 ; i < RELATIONSHIP_LOAD_STEP ; ++ i ){ + if( n >= size ) break; + sb.append( i == 0 ? '?' : '&' ); + sb.append( "id[]=" ); + sb.append( Long.toString( who_list[ n++ ] ) ); + } + TootApiResult result = client.request( sb.toString() ); + if( result == null ){ + // cancelled. + break; + }else if( result.array != null ){ + TootRelationShip.List list = TootRelationShip.parseList( result.array ); + UserRelation.saveList( now, access_info.db_id, list ); + } + } + log.d( "updateRelation: update %d relations.", n ); + + } + size = acct_set.size(); + if( size > 0 ){ + String[] acct_list = new String[ size ]; + { + int n = 0; + for( String l : acct_set ){ + acct_list[ n++ ] = l; + } + } + long now = System.currentTimeMillis(); + int n = 0; + while( n < size ){ + int length = size - n; + if( length > ACCT_DB_STEP ) length = ACCT_DB_STEP; + AcctSet.saveList( now, acct_list, n, length ); + n += length; + } + log.d( "updateRelation: update %d acct.", n ); + + } + size = tag_set.size(); + if( size > 0 ){ + String[] tag_list = new String[ size ]; + { + int n = 0; + for( String l : tag_set ){ + tag_list[ n++ ] = l; + } + } + long now = System.currentTimeMillis(); + int n = 0; + while( n < size ){ + int length = size - n; + if( length > ACCT_DB_STEP ) length = ACCT_DB_STEP; + TagSet.saveList( now, tag_list, n, length ); + n += length; + } + log.d( "updateRelation: update %d tag.", n ); + } + } + } + + private void updateRelation( @NonNull TootApiClient client, @Nullable ArrayList< Object > list_tmp, @Nullable TootAccount who ){ + if( access_info.isPseudo() ) return; + + UpdateRelationEnv env = new UpdateRelationEnv(); + + env.add( who ); + + if( list_tmp != null ){ for( Object o : list_tmp ){ if( o instanceof TootAccount ){ - a = (TootAccount) o; - who_set.add( a.id ); - acct_set.add( "@" + access_info.getFullAcct( a ) ); + env.add( (TootAccount) o ); }else if( o instanceof TootStatus ){ - s = (TootStatus) o; - if( s.tags != null ){ - for( TootTag tag : s.tags ){ - tag_set.add( tag.name ); - } - } - a = s.account; - if( a != null ){ - who_set.add( a.id ); - acct_set.add( "@" + access_info.getFullAcct( a ) ); - } - s = s.reblog; - if( s != null ){ - - if( s.tags != null ){ - for( TootTag tag : s.tags ){ - tag_set.add( tag.name ); - } - } - - a = s.account; - if( a != null ){ - who_set.add( a.id ); - acct_set.add( "@" + access_info.getFullAcct( a ) ); - } - } + env.add( (TootStatus) o ); }else if( o instanceof TootNotification ){ - n = (TootNotification) o; - // - a = n.account; - if( a != null ){ - who_set.add( a.id ); - acct_set.add( "@" + access_info.getFullAcct( a ) ); - } - // - s = n.status; - if( s != null ){ - - if( s.tags != null ){ - for( TootTag tag : s.tags ){ - tag_set.add( tag.name ); - } - } - - a = s.account; - if( a != null ){ - who_set.add( a.id ); - acct_set.add( "@" + access_info.getFullAcct( a ) ); - } - s = s.reblog; - if( s != null ){ - - if( s.tags != null ){ - for( TootTag tag : s.tags ){ - tag_set.add( tag.name ); - } - } - - a = s.account; - if( a != null ){ - who_set.add( a.id ); - acct_set.add( "@" + access_info.getFullAcct( a ) ); - } - } - } + env.add( (TootNotification) o ); } } } - int size = who_set.size(); - if( size > 0 ){ - long[] who_list = new long[ size ]; - { - int n = 0; - for( Long l : who_set ){ - who_list[ n++ ] = l; - } - } - - long now = System.currentTimeMillis(); - int n = 0; - while( n < size ){ - StringBuilder sb = new StringBuilder(); - sb.append( "/api/v1/accounts/relationships" ); - for( int i = 0 ; i < RELATIONSHIP_LOAD_STEP ; ++ i ){ - if( n >= size ) break; - sb.append( i == 0 ? '?' : '&' ); - sb.append( "id[]=" ); - sb.append( Long.toString( who_list[ n++ ] ) ); - } - TootApiResult result = client.request( sb.toString() ); - if( result == null ){ - // cancelled. - break; - }else if( result.array != null ){ - TootRelationShip.List list = TootRelationShip.parseList( result.array ); - UserRelation.saveList( now, access_info.db_id, list ); - } - } - log.d( "updateRelation: update %d relations.", n ); - - } - size = acct_set.size(); - if( size > 0 ){ - String[] acct_list = new String[ size ]; - { - int n = 0; - for( String l : acct_set ){ - acct_list[ n++ ] = l; - } - } - long now = System.currentTimeMillis(); - int n = 0; - while( n < size ){ - int length = size - n; - if( length > ACCT_DB_STEP ) length = ACCT_DB_STEP; - AcctSet.saveList( now, acct_list, n, length ); - n += length; - } - log.d( "updateRelation: update %d acct.", n ); - - } - size = tag_set.size(); - if( size > 0 ){ - String[] tag_list = new String[ size ]; - { - int n = 0; - for( String l : tag_set ){ - tag_list[ n++ ] = l; - } - } - long now = System.currentTimeMillis(); - int n = 0; - while( n < size ){ - int length = size - n; - if( length > ACCT_DB_STEP ) length = ACCT_DB_STEP; - TagSet.saveList( now, tag_list, n, length ); - n += length; - } - log.d( "updateRelation: update %d tag.", n ); - - } + env.update(client); } void startRefreshForPost( long status_id, int refresh_after_toot ){ @@ -2072,7 +2039,8 @@ import jp.juggler.subwaytooter.util.Utils; @SuppressLint("StaticFieldLeak") AsyncTask< Void, Void, TootApiResult > task = this.last_task = new AsyncTask< Void, Void, TootApiResult >() { - void parseAccount1( TootApiResult result ){ + void parseAccount1( TootApiClient client, String path ){ + TootApiResult result = client.request( path ); if( result != null ){ who_account = TootAccount.parse( context, access_info, result.object ); } @@ -2085,7 +2053,6 @@ import jp.juggler.subwaytooter.util.Utils; } } - TootApiResult getAccountList( TootApiClient client, String path_base ){ long time_start = SystemClock.elapsedRealtime(); char delimiter = ( - 1 != path_base.indexOf( '?' ) ? '&' : '?' ); @@ -2584,10 +2551,9 @@ import jp.juggler.subwaytooter.util.Utils; case TYPE_PROFILE: if( who_account == null ){ - parseAccount1( client.request( - String.format( Locale.JAPAN, PATH_ACCOUNT, profile_id ) ) ); - + parseAccount1( client, String.format( Locale.JAPAN, PATH_ACCOUNT, profile_id ) ); client.callback.publishApiProgress( "" ); + } switch( profile_tab ){ @@ -2688,7 +2654,7 @@ import jp.juggler.subwaytooter.util.Utils; } }finally{ try{ - updateRelation( client, list_tmp ); + updateRelation( client, list_tmp, who_account ); }catch( Throwable ex ){ log.trace( ex ); } @@ -3104,7 +3070,7 @@ import jp.juggler.subwaytooter.util.Utils; } }finally{ try{ - updateRelation( client, list_tmp ); + updateRelation( client, list_tmp, who_account ); }catch( Throwable ex ){ log.trace( ex ); } @@ -3649,20 +3615,21 @@ import jp.juggler.subwaytooter.util.Utils; } public @NonNull String getListTitle(){ - switch(column_type){ + switch( column_type ){ default: return "?"; - + case TYPE_LIST_MEMBER: case TYPE_LIST_TL: String sv = list_info == null ? null : list_info.title; - return !TextUtils.isEmpty( sv ) ? sv : Long.toString( profile_id ); + return ! TextUtils.isEmpty( sv ) ? sv : Long.toString( profile_id ); } } + public long getListId(){ - switch(column_type){ + switch( column_type ){ default: - return -1L; + return - 1L; case TYPE_LIST_MEMBER: case TYPE_LIST_TL: diff --git a/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.java b/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.java index 039ec308..e3b6ba0b 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.java +++ b/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.java @@ -414,14 +414,13 @@ class DlgContextMenu implements View.OnClickListener, View.OnLongClickListener { if( who == null ){ // サーバのバグで誰のことか分からないので何もできない }else if( access_info.isPseudo() ){ - activity.openFollowFromAnotherAccount( access_info, who ); + activity.openFollowFromAnotherAccount( pos, access_info, who ); }else{ boolean bSet = ! ( relation.getFollowing( who ) || relation.getRequested( who ) ); activity.callFollow( - access_info + pos,access_info , who , bSet - , false , bSet ? activity.follow_complete_callback : activity.unfollow_complete_callback ); } @@ -507,7 +506,7 @@ class DlgContextMenu implements View.OnClickListener, View.OnLongClickListener { break; case R.id.btnFollowFromAnotherAccount: - activity.openFollowFromAnotherAccount( access_info, who ); + activity.openFollowFromAnotherAccount( pos,access_info, who ); break; case R.id.btnSendMessageFromAnotherAccount: @@ -674,7 +673,7 @@ class DlgContextMenu implements View.OnClickListener, View.OnLongClickListener { }catch( Throwable ignored ){ // IllegalArgumentException がたまに出る } - activity.openFollowFromAnotherAccount( access_info, who ); + activity.openFollowFromAnotherAccount( activity.nextPosition( column),access_info, who ); return true; } diff --git a/app/src/main/java/jp/juggler/subwaytooter/HeaderViewHolderProfile.java b/app/src/main/java/jp/juggler/subwaytooter/HeaderViewHolderProfile.java index 58dea2ff..1b365ba5 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/HeaderViewHolderProfile.java +++ b/app/src/main/java/jp/juggler/subwaytooter/HeaderViewHolderProfile.java @@ -1,5 +1,7 @@ package jp.juggler.subwaytooter; +import android.support.annotation.NonNull; +import android.support.v4.view.ViewCompat; import android.text.Spannable; import android.view.View; import android.widget.Button; @@ -10,11 +12,13 @@ import android.widget.TextView; import jp.juggler.subwaytooter.api.entity.TootAccount; import jp.juggler.subwaytooter.api.entity.TootStatus; +import jp.juggler.subwaytooter.table.AcctColor; import jp.juggler.subwaytooter.table.UserRelation; import jp.juggler.subwaytooter.util.DecodeOptions; import jp.juggler.subwaytooter.util.EmojiDecoder; import jp.juggler.subwaytooter.util.EmojiMap201709; import jp.juggler.subwaytooter.util.NetworkEmojiInvalidator; +import jp.juggler.subwaytooter.util.Utils; import jp.juggler.subwaytooter.view.MyLinkMovementMethod; import jp.juggler.subwaytooter.view.MyNetworkImageView; @@ -38,6 +42,19 @@ class HeaderViewHolderProfile extends HeaderViewHolderBase implements View.OnCli private TootAccount who; + private TootAccount who_moved; + + private final View llMoved; + private final TextView tvMoved; + private final MyNetworkImageView ivMoved; + private final TextView tvMovedName; + private final TextView tvMovedAcct; + private final ImageButton btnMoved; + private final ImageView ivMovedBy; + private final NetworkEmojiInvalidator moved_caption_invalidator; + private final NetworkEmojiInvalidator moved_name_invalidator; + + HeaderViewHolderProfile( ActMain arg_activity, Column column, ListView parent ){ super( arg_activity, column , arg_activity.getLayoutInflater().inflate( R.layout.lv_header_account, parent, false ) @@ -58,6 +75,15 @@ class HeaderViewHolderProfile extends HeaderViewHolderBase implements View.OnCli ivFollowedBy = viewRoot.findViewById( R.id.ivFollowedBy ); tvRemoteProfileWarning = viewRoot.findViewById( R.id.tvRemoteProfileWarning ); + llMoved = viewRoot.findViewById( R.id.llMoved ); + tvMoved = viewRoot.findViewById( R.id.tvMoved ); + ivMoved = viewRoot.findViewById( R.id.ivMoved ); + tvMovedName = viewRoot.findViewById( R.id.tvMovedName ); + tvMovedAcct = viewRoot.findViewById( R.id.tvMovedAcct ); + btnMoved = viewRoot.findViewById( R.id.btnMoved ); + ivMovedBy = viewRoot.findViewById( R.id.ivMovedBy ); + + ivBackground.setOnClickListener( this ); btnFollowing.setOnClickListener( this ); btnFollowers.setOnClickListener( this ); @@ -65,13 +91,29 @@ class HeaderViewHolderProfile extends HeaderViewHolderBase implements View.OnCli btnMore.setOnClickListener( this ); btnFollow.setOnClickListener( this ); tvRemoteProfileWarning.setOnClickListener( this ); + + btnMoved.setOnClickListener( this ); + llMoved.setOnClickListener( this ); + btnMoved.setOnLongClickListener( this ); btnFollow.setOnLongClickListener( this ); tvNote.setMovementMethod( MyLinkMovementMethod.getInstance() ); - name_invalidator = new NetworkEmojiInvalidator( activity.handler, tvAcct ); + name_invalidator = new NetworkEmojiInvalidator( activity.handler, tvDisplayName ); note_invalidator = new NetworkEmojiInvalidator( activity.handler, tvNote ); + moved_caption_invalidator = new NetworkEmojiInvalidator( activity.handler, tvMoved ); + moved_name_invalidator = new NetworkEmojiInvalidator( activity.handler, tvMovedName ); + + if( ! Float.isNaN( activity.timeline_font_size_sp ) ){ + tvMovedName.setTextSize( activity.timeline_font_size_sp ); + tvMoved.setTextSize( activity.timeline_font_size_sp ); + } + + if( ! Float.isNaN( activity.acct_font_size_sp ) ){ + tvMovedAcct.setTextSize( activity.acct_font_size_sp ); + tvCreated.setTextSize( activity.acct_font_size_sp ); + } } void showColor(){ @@ -89,6 +131,9 @@ class HeaderViewHolderProfile extends HeaderViewHolderBase implements View.OnCli showColor(); + llMoved.setVisibility( View.GONE ); + tvMovedAcct.setVisibility( View.GONE ); + if( who == null ){ tvCreated.setText( "" ); ivBackground.setImageDrawable( null ); @@ -114,6 +159,8 @@ class HeaderViewHolderProfile extends HeaderViewHolderBase implements View.OnCli ivAvatar.setImageUrl( activity.pref, 16f, access_info.supplyBaseUrl( who.avatar_static ), access_info.supplyBaseUrl( who.avatar ) ); + tvAcct.setText( access_info.getFullAcct( who ) ); + Spannable name =who.decoded_display_name ; tvDisplayName.setText( name ); name_invalidator.register( name ); @@ -135,9 +182,52 @@ class HeaderViewHolderProfile extends HeaderViewHolderBase implements View.OnCli UserRelation relation = UserRelation.load( access_info.db_id, who.id ); Styler.setFollowIcon( activity, btnFollow, ivFollowedBy, relation ,who ); + + if( who.moved != null ){ + showMoved(who, who.moved); + } } } + private void showMoved( @NonNull TootAccount who, @NonNull TootAccount who_moved ){ + this.who_moved = who_moved; + + llMoved.setVisibility( View.VISIBLE ); + tvMoved.setVisibility( View.VISIBLE ); + + Spannable caption = Utils.formatSpannable1( activity, R.string.account_moved_to , who.decodeDisplayName( activity )); + tvMoved.setText( caption); + moved_caption_invalidator.register( caption ); + + ivMoved.getLayoutParams().width = activity.mAvatarIconSize; + ivMoved.setImageUrl( activity.pref, 16f, access_info.supplyBaseUrl( who_moved.avatar_static ) ); + + tvMovedName.setText( who_moved.decoded_display_name ); + moved_name_invalidator.register( who_moved.decoded_display_name ); + + setAcct( tvMovedAcct, access_info.getFullAcct( who_moved ), who_moved.acct ); + + UserRelation relation = UserRelation.load( access_info.db_id, who_moved.id ); + Styler.setFollowIcon( activity, btnMoved, ivMovedBy, relation, who_moved ); + } + + private void setAcct( @NonNull TextView tv, @NonNull String acctLong, @NonNull String acctShort ){ + AcctColor ac = AcctColor.load( acctLong ); + tv.setText( AcctColor.hasNickname( ac ) ? ac.nickname : activity.mShortAcctLocalUser ? "@" + acctShort : acctLong ); + + int acct_color = column.acct_color != 0 ? column.acct_color : Styler.getAttributeColor( activity, R.attr.colorTimeSmall ); + tv.setTextColor( AcctColor.hasColorForeground( ac ) ? ac.color_fg : acct_color ); + + if( AcctColor.hasColorBackground( ac ) ){ + tv.setBackgroundColor( ac.color_bg ); + }else{ + ViewCompat.setBackground( tv, null ); + } + tv.setPaddingRelative( activity.acct_pad_lr, 0, activity.acct_pad_lr, 0 ); + + } + + @Override public void onClick( View v ){ @@ -181,13 +271,31 @@ class HeaderViewHolderProfile extends HeaderViewHolderBase implements View.OnCli } break; + case R.id.btnMoved: + if( who_moved != null ){ + new DlgContextMenu( activity, column, who_moved, null, null ).show(); + } + break; + + case R.id.llMoved: + if( access_info.isPseudo() ){ + new DlgContextMenu( activity, column, who_moved, null, null ).show(); + }else{ + activity.openProfile( activity.nextPosition( column ), access_info, who_moved ); + } + break; } } @Override public boolean onLongClick( View v ){ switch( v.getId() ){ + case R.id.btnFollow: - activity.openFollowFromAnotherAccount( access_info, who ); + activity.openFollowFromAnotherAccount( activity.nextPosition( column),access_info, who ); + return true; + + case R.id.btnMoved: + activity.openFollowFromAnotherAccount( activity.nextPosition( column),access_info, who_moved ); return true; } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.java b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.java index 367befc2..78539252 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.java +++ b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.java @@ -882,7 +882,7 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener { return true; case R.id.btnFollow: - activity.openFollowFromAnotherAccount( access_info, account_follow ); + activity.openFollowFromAnotherAccount( activity.nextPosition( column),access_info, account_follow ); return true; case R.id.llBoosted: diff --git a/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.java b/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.java index 4b25902a..b2c86cf1 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.java +++ b/app/src/main/java/jp/juggler/subwaytooter/StatusButtons.java @@ -189,13 +189,13 @@ class StatusButtons implements View.OnClickListener, View.OnLongClickListener { if( status == null || status.account == null ){ // 何もしない }else if( access_info.isPseudo() ){ - activity.openFollowFromAnotherAccount( access_info, status.account ); + activity.openFollowFromAnotherAccount( activity.nextPosition( column ), access_info, status.account ); }else if( relation.blocking || relation.muting ){ // 何もしない }else if( relation.getFollowing( status.account ) || relation.getRequested( status.account ) ){ - activity.callFollow( access_info, status.account, false, false, activity.unfollow_complete_callback ); + activity.callFollow( activity.nextPosition( column ), access_info, status.account, false, activity.unfollow_complete_callback ); }else{ - activity.callFollow( access_info, status.account, true, false, activity.follow_complete_callback ); + activity.callFollow( activity.nextPosition( column ), access_info, status.account, true, activity.follow_complete_callback ); } break; } @@ -219,7 +219,7 @@ class StatusButtons implements View.OnClickListener, View.OnLongClickListener { case R.id.btnFollow2: if( status != null ){ - activity.openFollowFromAnotherAccount( access_info, status.account ); + activity.openFollowFromAnotherAccount( activity.nextPosition( column ), access_info, status.account ); } break; diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.java b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.java index e5ffbe68..c9c6c8ea 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.java +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootAccount.java @@ -96,6 +96,8 @@ public class TootAccount { @Nullable public NicoProfileEmoji.Map profile_emojis; + @Nullable public TootAccount moved; + public TootAccount(){ } @@ -106,6 +108,11 @@ public class TootAccount { this.username = username; } + public static TootAccount parse( Context context, LinkClickContext account, JSONObject src ){ + return parse( context, account, src, new TootAccount() ); + } + + @Nullable public static TootAccount parse( Context context, LinkClickContext account, JSONObject src, TootAccount dst ){ if( src == null ) return null; @@ -146,6 +153,10 @@ public class TootAccount { dst.source = parseSource( src.optJSONObject( "source" ) ); + JSONObject o = src.optJSONObject( "moved" ); + if( o != null ){ + dst.moved = TootAccount.parse( context, account, o); + } return dst; @@ -167,9 +178,7 @@ public class TootAccount { return dst; } - public static TootAccount parse( Context context, LinkClickContext account, JSONObject src ){ - return parse( context, account, src, new TootAccount() ); - } + @NonNull public static List parseList( Context context, LinkClickContext account, JSONArray array ){ diff --git a/app/src/main/res/layout/lv_header_account.xml b/app/src/main/res/layout/lv_header_account.xml index ad0bcc2d..0b0f61cc 100644 --- a/app/src/main/res/layout/lv_header_account.xml +++ b/app/src/main/res/layout/lv_header_account.xml @@ -8,6 +8,94 @@ android:orientation="vertical" > + + + + + + + + + + + + + + + + + + + + + + - - + \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index b7f32f1a..ef1600a7 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -558,6 +558,9 @@ Can\'t add user to list:\nfollow operation failed. User has been added to the list. Mute notification from this user + %1$s has moved to: + %1$s has been moved. Would you like to check %2$s ? + ignore suggestion diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 94a6b7e9..c87abf82 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -845,4 +845,8 @@ リストに追加できません:\nフォロー操作に失敗しました 追加できました Mute notification from this user + %1$s は引っ越しました: + + %1$s は引っ越しました。%2$s を確認しますか? + 提案を無視 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a43b86b2..713bd0ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -549,4 +549,8 @@ Can\'t add user to list:\nfollow operation failed. User has been added to the list. Mute notification from this user + %1$s has moved to: + %1$s has been moved. Would you like to check %2$s ? + ignore suggestion +