「別アカウントからフォロー」を追加

This commit is contained in:
tateisu 2017-04-24 06:12:11 +09:00
parent e312790992
commit caa07564a2
5 changed files with 604 additions and 203 deletions

228
.idea/codeStyleSettings.xml Normal file
View File

@ -0,0 +1,228 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value />
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="android" withSubpackages="true" static="false" />
<emptyLine />
<package name="com" withSubpackages="true" static="false" />
<emptyLine />
<package name="junit" withSubpackages="true" static="false" />
<emptyLine />
<package name="net" withSubpackages="true" static="false" />
<emptyLine />
<package name="org" withSubpackages="true" static="false" />
<emptyLine />
<package name="java" withSubpackages="true" static="false" />
<emptyLine />
<package name="javax" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="true" />
<emptyLine />
</value>
</option>
<option name="RIGHT_MARGIN" value="100" />
<AndroidXmlCodeStyleSettings>
<option name="USE_CUSTOM_SETTINGS" value="true" />
</AndroidXmlCodeStyleSettings>
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" />
<pair source="c" header="h" />
</extensions>
</Objective-C-extensions>
<XML>
<option name="XML_KEEP_LINE_BREAKS" value="false" />
<option name="XML_ALIGN_ATTRIBUTES" value="false" />
<option name="XML_SPACE_INSIDE_EMPTY_TAG" value="true" />
</XML>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_width</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_height</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:width</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:height</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</value>
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
</component>
</project>

View File

@ -47,6 +47,7 @@ import jp.juggler.subwaytooter.dialog.AccountPicker;
import jp.juggler.subwaytooter.dialog.LoginForm; import jp.juggler.subwaytooter.dialog.LoginForm;
import jp.juggler.subwaytooter.dialog.ReportForm; import jp.juggler.subwaytooter.dialog.ReportForm;
import jp.juggler.subwaytooter.table.SavedAccount; import jp.juggler.subwaytooter.table.SavedAccount;
import jp.juggler.subwaytooter.util.ActionsDialog;
import jp.juggler.subwaytooter.util.HTMLDecoder; import jp.juggler.subwaytooter.util.HTMLDecoder;
import jp.juggler.subwaytooter.util.LinkClickContext; import jp.juggler.subwaytooter.util.LinkClickContext;
import jp.juggler.subwaytooter.util.LogCategory; import jp.juggler.subwaytooter.util.LogCategory;
@ -449,14 +450,89 @@ public class ActMain extends AppCompatActivity
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
public interface GetAccountCallback {
// return account information
// if failed, account is null.
void onGetAccount( TootAccount account );
}
void startGetAccount( final SavedAccount access_info, final String host, final String user, final GetAccountCallback callback ){
final ProgressDialog progress = new ProgressDialog( this );
final AsyncTask< Void, Void, TootAccount > task = new AsyncTask< Void, Void, TootAccount >() {
@Override
protected TootAccount doInBackground( Void... params ){
TootApiClient client = new TootApiClient( ActMain.this, new TootApiClient.Callback() {
@Override
public boolean isApiCancelled(){
return isCancelled();
}
@Override
public void publishApiProgress( final String s ){
Utils.runOnMainThread( new Runnable() {
@Override
public void run(){
progress.setMessage( s );
}
} );
}
} );
client.setAccount( access_info );
String path = "/api/v1/accounts/search" + "?q=" + Uri.encode( user );
TootApiResult result = client.request( path );
if( result.array != null ){
for( int i = 0, ie = result.array.length() ; i < ie ; ++ i ){
TootAccount item = TootAccount.parse( log, access_info, result.array.optJSONObject( i ) );
if( ! item.username.equals( user ) ) continue;
if( ! item.acct.contains( "@" )
|| item.acct.equalsIgnoreCase( user + "@" + host ) )
return item;
}
}
return null;
}
@Override
protected void onCancelled( TootAccount result ){
super.onPostExecute( result );
}
@Override
protected void onPostExecute( TootAccount result ){
progress.dismiss();
callback.onGetAccount( result );
}
};
progress.setIndeterminate( true );
progress.setCancelable( true );
progress.setOnCancelListener( new DialogInterface.OnCancelListener() {
@Override
public void onCancel( DialogInterface dialog ){
task.cancel( true );
}
} );
progress.show();
AsyncTaskCompat.executeParallel( task );
}
public void openBrowser( SavedAccount account, String url ){ public void openBrowser( SavedAccount account, String url ){
openChromeTab( account, url, false ); openChromeTab( account, url, false );
} }
Pattern reHashTag = Pattern.compile( "\\Ahttps://([^/]+)/tags/([^?#]+)\\z" ); Pattern reHashTag = Pattern.compile( "\\Ahttps://([^/]+)/tags/([^?#]+)\\z" );
Pattern reUserPage = Pattern.compile( "\\Ahttps://([^/]+)/@([^?#]+)\\z" );
public void openChromeTab( final SavedAccount access_info, final String url, boolean noIntercept ){
public void openChromeTab( SavedAccount account, String url ,boolean noIntercept ){
try{ try{
log.d( "openChromeTab url=%s", url ); log.d( "openChromeTab url=%s", url );
@ -466,18 +542,32 @@ public class ActMain extends AppCompatActivity
if( m.find() ){ if( m.find() ){
// https://mastodon.juggler.jp/tags/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%B0 // https://mastodon.juggler.jp/tags/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%B0
String host = m.group( 1 ); String host = m.group( 1 );
String tag = m.group( 2 ); String tag = Uri.decode( m.group( 2 ) );
if( tag.length() > 0 ){ if( host.equalsIgnoreCase( access_info.host ) ){
if( host.equalsIgnoreCase( account.host ) ){ openHashTag( access_info, tag );
openHashTag( account, Uri.decode( tag ) );
return; return;
}else{ }else{
openHashTagOtherInstance( account,url, host,Uri.decode(tag) ); openHashTagOtherInstance( access_info, url, host, tag );
return; return;
} }
} }
m = reUserPage.matcher( url );
if( m.find() ){
// https://mastodon.juggler.jp/@SubwayTooter
final String host = m.group( 1 );
final String user = Uri.decode( m.group( 2 ) );
startGetAccount( access_info, host, user, new GetAccountCallback() {
@Override
public void onGetAccount( TootAccount who ){
if( who != null ){
performOpenUser( access_info, who );
return;
}
openChromeTab( access_info, url, true );
}
} );
return;
} }
} }
@ -495,14 +585,10 @@ public class ActMain extends AppCompatActivity
} }
} }
static class Action{
String caption;
Runnable runnable;
}
// 他インスタンスのハッシュタグの表示 // 他インスタンスのハッシュタグの表示
private void openHashTagOtherInstance( final SavedAccount access_info, final String url, String host, final String tag ){ private void openHashTagOtherInstance( final SavedAccount access_info, final String url, String host, final String tag ){
final ArrayList<Action> action_list = new ArrayList<>();
ActionsDialog dialog = new ActionsDialog();
ArrayList< SavedAccount > account_list = new ArrayList<>(); ArrayList< SavedAccount > account_list = new ArrayList<>();
for( SavedAccount a : SavedAccount.loadAccountList( log ) ){ for( SavedAccount a : SavedAccount.loadAccountList( log ) ){
@ -517,62 +603,52 @@ public class ActMain extends AppCompatActivity
} }
} ); } );
for( SavedAccount a : account_list ){ for( SavedAccount a : account_list ){
Action action = new Action();
action.caption = getString(R.string.open_in_account,a.user);
final SavedAccount _a = a; final SavedAccount _a = a;
action.runnable = new Runnable() { dialog.addAction(
getString( R.string.open_in_account, a.user )
, new Runnable() {
@Override @Override
public void run(){ public void run(){
openHashTag( _a, tag ); openHashTag( _a, tag );
} }
}; }
action_list.add( action); );
} }
if( account_list.isEmpty() ){ if( account_list.isEmpty() ){
// TODO ログインなしアカウントで開く選択肢 // TODO ログインなしアカウントで開く選択肢
} }
// カラムのアカウントで開く // カラムのアカウントで開く
{ {
Action action = new Action();
action.caption = getString(R.string.open_in_account,access_info.user);
final SavedAccount _a = access_info; final SavedAccount _a = access_info;
action.runnable = new Runnable() { dialog.addAction(
getString( R.string.open_in_account, access_info.user )
, new Runnable() {
@Override @Override
public void run(){ public void run(){
openHashTag( _a, tag ); openHashTag( _a, tag );
} }
};
action_list.add( action);
} }
);
}
// ブラウザで表示する // ブラウザで表示する
{ {
Action action = new Action(); dialog.addAction(
action.caption = getString(R.string.open_web_on_host,host); getString( R.string.open_web_on_host, host )
action.runnable = new Runnable() { , new Runnable() {
@Override @Override
public void run(){ public void run(){
openChromeTab( access_info, url, true ); openChromeTab( access_info, url, true );
} }
}; }
action_list.add( action); );
} }
String[] caption_list = new String[action_list.size()]; dialog.show( this, "#" + tag );
for(int i=0,ie=caption_list.length;i<ie;++i){
caption_list[i] = action_list.get(i).caption;
}
new AlertDialog.Builder( this )
.setTitle( "#"+tag)
.setNegativeButton( R.string.cancel,null )
.setItems( caption_list, new DialogInterface.OnClickListener() {
@Override
public void onClick( DialogInterface dialog, int which ){
if( which >= 0 && which < action_list.size()){
action_list.get(which).runnable.run();
}
}
})
.show();
} }
final HTMLDecoder.LinkClickCallback link_click_listener = new HTMLDecoder.LinkClickCallback() { final HTMLDecoder.LinkClickCallback link_click_listener = new HTMLDecoder.LinkClickCallback() {
@ -922,32 +998,11 @@ public class ActMain extends AppCompatActivity
} }
} }
public void performFollow( final SavedAccount account, final TootAccount who ){ ////////////////////////////////////////////////////////////////////////////
String[] caption_list = new String[]{
getString( R.string.follow ), private void callFollow( final SavedAccount account, final TootAccount who, final boolean bFollow ){
getString( R.string.unfollow ),
};
new AlertDialog.Builder( this )
.setNegativeButton( R.string.cancel, null )
.setItems( caption_list, new DialogInterface.OnClickListener() {
@Override
public void onClick( DialogInterface dialog, int which ){
switch( which ){
case 0:
performFollow( account, who, true );
break;
case 1:
performFollow( account, who, false );
break;
}
}
} )
.show();
}
private void performFollow( final SavedAccount account, final TootAccount who, final boolean bFollow ){
new AsyncTask< Void, Void, TootApiResult >() { new AsyncTask< Void, Void, TootApiResult >() {
@Override @Override
protected TootApiResult doInBackground( Void... params ){ protected TootApiResult doInBackground( Void... params ){
TootApiClient client = new TootApiClient( ActMain.this, new TootApiClient.Callback() { TootApiClient client = new TootApiClient( ActMain.this, new TootApiClient.Callback() {
@ -995,9 +1050,65 @@ public class ActMain extends AppCompatActivity
}.execute(); }.execute();
} }
// acct で指定したユーザをリモートフォローする
void callRemoteFollow( final SavedAccount access_info, final String acct, final boolean locked ){
new AsyncTask< Void, Void, TootApiResult >() {
@Override
protected TootApiResult doInBackground( Void... params ){
TootApiClient client = new TootApiClient( ActMain.this, new TootApiClient.Callback() {
@Override
public boolean isApiCancelled(){
return isCancelled();
}
@Override
public void publishApiProgress( String s ){
}
} );
client.setAccount( access_info );
Request.Builder request_builder = new Request.Builder().post(
RequestBody.create(
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
, "uri=" + Uri.encode( acct )
) );
TootApiResult result = client.request( "/api/v1/follows", request_builder );
if( result != null ){
if( result.object != null ){
Utils.showToast( ActMain.this, false, R.string.follow_succeeded );
}else if( locked && result.response.code() == 422 ){
Utils.showToast( ActMain.this, false, R.string.cant_follow_locked_user );
}else{
Utils.showToast( ActMain.this, false, result.error );
}
}
return result;
}
}.execute();
}
// アカウントを選択してからユーザをフォローする
void followFromAnotherAccount( final SavedAccount access_info, final TootAccount who ){
AccountPicker.pick( ActMain.this, new AccountPicker.AccountPickerCallback() {
@Override
public void onAccountPicked( SavedAccount ai ){
String acct = who.acct;
if( ! acct.contains( "@" ) ){
acct = acct + "@" + access_info.host;
}
callRemoteFollow( ai, acct, who.locked );
}
} );
}
//////////////////////////////////////// ////////////////////////////////////////
private void performMute( final SavedAccount account, final TootAccount who, final boolean bMute ){ private void callMute( final SavedAccount account, final TootAccount who, final boolean bMute ){
new AsyncTask< Void, Void, TootApiResult >() { new AsyncTask< Void, Void, TootApiResult >() {
@Override @Override
@ -1041,7 +1152,7 @@ public class ActMain extends AppCompatActivity
}.execute(); }.execute();
} }
private void performBlock( final SavedAccount account, final TootAccount who, final boolean bBlock ){ private void callBlock( final SavedAccount account, final TootAccount who, final boolean bBlock ){
new AsyncTask< Void, Void, TootApiResult >() { new AsyncTask< Void, Void, TootApiResult >() {
@Override @Override
@ -1090,7 +1201,7 @@ public class ActMain extends AppCompatActivity
} }
private void performReport( final SavedAccount account, final TootAccount who, final TootStatus status private void callReport( final SavedAccount account, final TootAccount who, final TootStatus status
, final String comment, final ReportCompleteCallback callback , final String comment, final ReportCompleteCallback callback
){ ){
new AsyncTask< Void, Void, TootApiResult >() { new AsyncTask< Void, Void, TootApiResult >() {
@ -1139,11 +1250,11 @@ public class ActMain extends AppCompatActivity
}.execute(); }.execute();
} }
private void performReport( final SavedAccount account, final TootAccount who, final TootStatus status ){ private void openReportForm( final SavedAccount account, final TootAccount who, final TootStatus status ){
ReportForm.showReportForm( this, who, status, new ReportForm.ReportFormCallback() { ReportForm.showReportForm( this, who, status, new ReportForm.ReportFormCallback() {
@Override @Override
public void startReport( final Dialog dialog, String comment ){ public void startReport( final Dialog dialog, String comment ){
performReport( account, who, status, comment, new ReportCompleteCallback() { callReport( account, who, status, comment, new ReportCompleteCallback() {
@Override @Override
public void onReportComplete( TootApiResult result ){ public void onReportComplete( TootApiResult result ){
if( result == null ){ if( result == null ){
@ -1162,100 +1273,111 @@ public class ActMain extends AppCompatActivity
} ); } );
} }
//////////////////////////////////////// ////////////////////////////////////////////////
// ステータスのmoreメニュー // ステータスのmoreメニュー
public void performStatusMore( final SavedAccount account, final TootStatus status ){ public void openStatusMoreMenu( final SavedAccount access_info, final TootStatus status ){
String[] caption_list = new String[]{ ActionsDialog dialog = new ActionsDialog();
getString( R.string.follow ), dialog.addAction( getString( R.string. follow), new Runnable() {
getString( R.string.unfollow ), @Override public void run(){
getString( R.string.mute ), callFollow( access_info, status.account, true );
getString( R.string.unmute ), }
getString( R.string.block ), } );
getString( R.string.unblock ), dialog.addAction( getString( R.string. follow_from_another_account), new Runnable() {
getString( R.string.report ), @Override public void run(){
}; followFromAnotherAccount( access_info, status.account );
new AlertDialog.Builder( this ) }
.setNegativeButton( R.string.cancel, null ) } );
.setItems( caption_list, new DialogInterface.OnClickListener() { dialog.addAction( getString( R.string.unfollow ), new Runnable() {
@Override public void run(){
callFollow( access_info, status.account, false );
}
} );
dialog.addAction( getString( R.string. mute), new Runnable() {
@Override public void run(){
callMute( access_info, status.account, true );
}
} );
dialog.addAction( getString( R.string.unmute ), new Runnable() {
@Override public void run(){
callMute( access_info, status.account, false );
}
} );
dialog.addAction( getString( R.string.block ), new Runnable() {
@Override public void run(){
callBlock( access_info, status.account, true );
}
} );
dialog.addAction( getString( R.string. unblock), new Runnable() {
@Override public void run(){
callBlock( access_info, status.account, false );
}
} );
dialog.addAction( getString( R.string. report), new Runnable() {
@Override public void run(){
openReportForm( access_info, status.account, status );
}
} );
dialog.addAction( getString( R.string. open_web_page), new Runnable() {
@Override public void run(){
// 強制的にブラウザで開く
openChromeTab( access_info, status.url, true );
}
} );
dialog.show(this, null );
}
public void openAccountMoreMenu( final SavedAccount access_info, final TootAccount who ){
ActionsDialog dialog = new ActionsDialog();
dialog.addAction( getString( R.string.mention ), new Runnable() {
@Override public void run(){
performMention( access_info, who );
}
} );
dialog.addAction( getString( R.string.follow ), new Runnable() {
@Override public void run(){
callFollow( access_info, who, true );
}
} );
dialog.addAction( getString( R.string.follow_from_another_account ), new Runnable() {
@Override public void run(){
followFromAnotherAccount( access_info, who );
}
} );
dialog.addAction( getString( R.string.unfollow ), new Runnable() {
@Override @Override
public void onClick( DialogInterface dialog, int which ){ public void run(){
switch( which ){ callFollow( access_info, who, false );
case 0:
performFollow( account, status.account, true );
break;
case 1:
performFollow( account, status.account, false );
break;
case 2:
performMute( account, status.account, true );
break;
case 3:
performMute( account, status.account, false );
break;
case 4:
performBlock( account, status.account, true );
break;
case 5:
performBlock( account, status.account, false );
break;
case 6:
performReport( account, status.account, status );
break;
} }
} );
dialog.addAction( getString( R.string.mute ), new Runnable() {
@Override public void run(){
callMute( access_info, who, true );
} }
} ) } );
.show(); dialog.addAction( getString( R.string.unmute ), new Runnable() {
}
public void performAccountMore( final SavedAccount account, final TootAccount who ){
String[] caption_list = new String[]{
getString( R.string.mention ),
getString( R.string.follow ),
getString( R.string.unfollow ),
getString( R.string.mute ),
getString( R.string.unmute ),
getString( R.string.block ),
getString( R.string.unblock ),
getString( R.string.report ),
};
new AlertDialog.Builder( this )
.setNegativeButton( R.string.cancel, null )
.setItems( caption_list, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick( DialogInterface dialog, int which ){ public void run(){
switch( which ){ callMute( access_info, who, false );
case 0: }
performMention( account, who ); } );
break; dialog.addAction( getString( R.string.block ), new Runnable() {
case 1: @Override public void run(){
performFollow( account, who, true ); callBlock( access_info, who, true );
break; }
case 2: } );
performFollow( account, who, false ); dialog.addAction( getString( R.string.unblock ), new Runnable() {
break; @Override public void run(){
case 3: callBlock( access_info, who, false );
performMute( account, who, true ); }
break; } );
case 4: dialog.addAction( getString( R.string.report ), new Runnable() {
performMute( account, who, false ); @Override public void run(){
break; openReportForm( access_info, who, null );
case 5: }
performBlock( account, who, true ); } );
break; dialog.show( this, null );
case 6:
performBlock( account, who, false );
break;
case 7:
performReport( account, who, null );
break;
} }
} }
} )
.show();
}
}

View File

@ -371,7 +371,8 @@ public class ColumnViewHolder implements View.OnClickListener, Column.VisualCall
switch( v.getId() ){ switch( v.getId() ){
case R.id.ivBackground: case R.id.ivBackground:
if( who != null ){ if( who != null ){
activity.openBrowser( access_info,who.url ); // 強制的にブラウザで開く
activity.openChromeTab( access_info,who.url ,true);
} }
break; break;
case R.id.btnFollowing: case R.id.btnFollowing:
@ -384,7 +385,7 @@ public class ColumnViewHolder implements View.OnClickListener, Column.VisualCall
Utils.showToast( activity, false, "not implemented" ); Utils.showToast( activity, false, "not implemented" );
break; break;
case R.id.btnMore: case R.id.btnMore:
activity.performAccountMore( access_info,who ); activity.openAccountMoreMenu( access_info,who );
break; break;
} }
@ -735,7 +736,7 @@ public class ColumnViewHolder implements View.OnClickListener, Column.VisualCall
activity.performFavourite( access_info, status ); activity.performFavourite( access_info, status );
break; break;
case R.id.btnMore: case R.id.btnMore:
activity.performStatusMore( access_info, status ); activity.openStatusMoreMenu( access_info, status );
break; break;
case R.id.ivThumbnail: case R.id.ivThumbnail:
activity.performOpenUser( access_info, account_thumbnail ); activity.performOpenUser( access_info, account_thumbnail );
@ -747,7 +748,7 @@ public class ColumnViewHolder implements View.OnClickListener, Column.VisualCall
activity.performOpenUser( access_info, account_follow ); activity.performOpenUser( access_info, account_follow );
break; break;
case R.id.btnFollow: case R.id.btnFollow:
activity.performAccountMore( access_info,account_follow); activity.openAccountMoreMenu( access_info,account_follow);
} }
} }

View File

@ -0,0 +1,48 @@
package jp.juggler.subwaytooter.util;
import android.content.Context;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import java.util.ArrayList;
import jp.juggler.subwaytooter.R;
public class ActionsDialog {
static class Action {
String caption;
Runnable r;
}
final ArrayList< Action > action_list = new ArrayList<>();
public void addAction( String caption, Runnable r ){
Action action = new Action();
action.caption = caption;
action.r = r;
action_list.add( action );
}
public void show( Context context, String title ){
String[] caption_list = new String[ action_list.size() ];
for( int i = 0, ie = caption_list.length ; i < ie ; ++ i ){
caption_list[ i ] = action_list.get( i ).caption;
}
AlertDialog.Builder b = new AlertDialog.Builder( context )
.setNegativeButton( R.string.cancel, null )
.setItems( caption_list, new DialogInterface.OnClickListener() {
@Override public void onClick( DialogInterface dialog, int which ){
if( which >= 0 && which < action_list.size() ){
action_list.get( which ).r.run();
}
}
} );
if( ! TextUtils.isEmpty( title ) ) b.setTitle( title );
b.show();
}
}

View File

@ -154,4 +154,6 @@
<string name="open_in_browser"/> <string name="open_in_browser"/>
<string name="open_web_page">open web page</string> <string name="open_web_page">open web page</string>
<string name="open_web_on_host">open web page on %1$s</string> <string name="open_web_on_host">open web page on %1$s</string>
<string name="follow_from_another_account">follow_from_another_account</string>
<string name="menu">menu</string>
</resources> </resources>