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

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.ReportForm;
import jp.juggler.subwaytooter.table.SavedAccount;
import jp.juggler.subwaytooter.util.ActionsDialog;
import jp.juggler.subwaytooter.util.HTMLDecoder;
import jp.juggler.subwaytooter.util.LinkClickContext;
import jp.juggler.subwaytooter.util.LogCategory;
@ -112,7 +113,7 @@ public class ActMain extends AppCompatActivity
ArrayList< SavedAccount > done_list = new ArrayList<>();
for( Column column : pager_adapter.column_list ){
SavedAccount a = column.access_info;
if( a==null || done_list.contains( a ) ) continue;
if( a == null || done_list.contains( a ) ) continue;
done_list.add( a );
a.reloadSetting();
}
@ -337,7 +338,7 @@ public class ActMain extends AppCompatActivity
// taは使い捨てなので生成に使うLinkClickContextはダミーで問題ない
LinkClickContext lcc = new LinkClickContext() {
};
TootAccount ta = TootAccount.parse( log, lcc,result.object );
TootAccount ta = TootAccount.parse( log, lcc, result.object );
String user = ta.username + "@" + instance;
this.row_id = SavedAccount.insert( instance, user, result.object, result.token_info );
}
@ -449,36 +450,125 @@ public class ActMain extends AppCompatActivity
//////////////////////////////////////////////////////////////
public void openBrowser(SavedAccount account, String url ){
openChromeTab( account,url,false );
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 ){
openChromeTab( account, url, false );
}
Pattern reHashTag = Pattern.compile( "\\Ahttps://([^/]+)/tags/([^?#]+)\\z" );
Pattern reUserPage = Pattern.compile( "\\Ahttps://([^/]+)/@([^?#]+)\\z" );
public void openChromeTab( SavedAccount account, String url ,boolean noIntercept ){
public void openChromeTab( final SavedAccount access_info, final String url, boolean noIntercept ){
try{
log.d("openChromeTab url=%s",url);
log.d( "openChromeTab url=%s", url );
if(!noIntercept){
if( ! noIntercept ){
// ハッシュタグをアプリ内で開く
Matcher m = reHashTag.matcher( url );
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
String host = m.group( 1 );
String tag = m.group( 2 );
if( tag.length() > 0 ){
if( host.equalsIgnoreCase( account.host ) ){
openHashTag( account, Uri.decode( tag ) );
return;
}else{
openHashTagOtherInstance( account,url, host,Uri.decode(tag) );
return;
}
String tag = Uri.decode( m.group( 2 ) );
if( host.equalsIgnoreCase( access_info.host ) ){
openHashTag( access_info, tag );
return;
}else{
openHashTagOtherInstance( access_info, url, host, tag );
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,90 +585,76 @@ 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 ){
final ArrayList<Action> action_list = new ArrayList<>();
private void openHashTagOtherInstance( final SavedAccount access_info, final String url, String host, final String tag ){
ArrayList<SavedAccount> account_list = new ArrayList<>( );
for(SavedAccount a : SavedAccount.loadAccountList( log )){
if( a.host.equalsIgnoreCase( host )){
account_list.add(a);
ActionsDialog dialog = new ActionsDialog();
ArrayList< SavedAccount > account_list = new ArrayList<>();
for( SavedAccount a : SavedAccount.loadAccountList( log ) ){
if( a.host.equalsIgnoreCase( host ) ){
account_list.add( a );
}
}
Collections.sort( account_list,new Comparator< SavedAccount >() {
Collections.sort( account_list, new Comparator< SavedAccount >() {
@Override
public int compare( SavedAccount a, SavedAccount b ){
return String.CASE_INSENSITIVE_ORDER.compare( a.getFullAcct( a ), b.getFullAcct( b ) );
}
} );
for( SavedAccount a : account_list ){
Action action = new Action();
action.caption = getString(R.string.open_in_account,a.user);
final SavedAccount _a = a;
action.runnable = new Runnable() {
@Override
public void run(){
openHashTag( _a,tag );
dialog.addAction(
getString( R.string.open_in_account, a.user )
, new Runnable() {
@Override
public void run(){
openHashTag( _a, tag );
}
}
};
action_list.add( action);
);
}
if( account_list.isEmpty() ){
// TODO ログインなしアカウントで開く選択肢
}
// カラムのアカウントで開く
{
Action action = new Action();
action.caption = getString(R.string.open_in_account,access_info.user);
final SavedAccount _a = access_info;
action.runnable = new Runnable() {
@Override
public void run(){
openHashTag( _a,tag );
}
};
action_list.add( action);
}
// ブラウザで表示する
{
Action action = new Action();
action.caption = getString(R.string.open_web_on_host,host);
action.runnable = new Runnable() {
@Override
public void run(){
openChromeTab( access_info,url,true);
}
};
action_list.add( action);
}
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;
}
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();
dialog.addAction(
getString( R.string.open_in_account, access_info.user )
, new Runnable() {
@Override
public void run(){
openHashTag( _a, tag );
}
}
})
.show();
);
}
// ブラウザで表示する
{
dialog.addAction(
getString( R.string.open_web_on_host, host )
, new Runnable() {
@Override
public void run(){
openChromeTab( access_info, url, true );
}
}
);
}
dialog.show( this, "#" + tag );
}
final HTMLDecoder.LinkClickCallback link_click_listener = new HTMLDecoder.LinkClickCallback() {
@Override
public void onClickLink( LinkClickContext lcc,String url ){
openChromeTab( (SavedAccount)lcc,url ,false );
public void onClickLink( LinkClickContext lcc, String url ){
openChromeTab( (SavedAccount) lcc, url, false );
}
};
@ -659,7 +735,7 @@ public class ActMain extends AppCompatActivity
)
, request_builder );
if( result.object != null ){
new_status = TootStatus.parse( log,account, result.object );
new_status = TootStatus.parse( log, account, result.object );
}
return result;
@ -782,7 +858,7 @@ public class ActMain extends AppCompatActivity
// reblog,unreblog のレスポンスは信用ならんのでステータスを再取得する
result = client.request( "/api/v1/statuses/" + status.id );
if( result.object != null ){
new_status = TootStatus.parse( log, account,result.object );
new_status = TootStatus.parse( log, account, result.object );
}
}
@ -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 ),
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 ){
private void callFollow( final SavedAccount account, final TootAccount who, final boolean bFollow ){
new AsyncTask< Void, Void, TootApiResult >() {
@Override
protected TootApiResult doInBackground( Void... params ){
TootApiClient client = new TootApiClient( ActMain.this, new TootApiClient.Callback() {
@ -995,9 +1050,65 @@ public class ActMain extends AppCompatActivity
}.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 >() {
@Override
@ -1041,7 +1152,7 @@ public class ActMain extends AppCompatActivity
}.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 >() {
@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
){
new AsyncTask< Void, Void, TootApiResult >() {
@ -1139,11 +1250,11 @@ public class ActMain extends AppCompatActivity
}.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() {
@Override
public void startReport( final Dialog dialog, String comment ){
performReport( account, who, status, comment, new ReportCompleteCallback() {
callReport( account, who, status, comment, new ReportCompleteCallback() {
@Override
public void onReportComplete( TootApiResult result ){
if( result == null ){
@ -1162,100 +1273,111 @@ public class ActMain extends AppCompatActivity
} );
}
////////////////////////////////////////
////////////////////////////////////////////////
// ステータスのmoreメニュー
public void performStatusMore( final SavedAccount account, final TootStatus status ){
String[] caption_list = new String[]{
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
public void onClick( DialogInterface dialog, int which ){
switch( which ){
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;
}
}
} )
.show();
public void openStatusMoreMenu( final SavedAccount access_info, final TootStatus status ){
ActionsDialog dialog = new ActionsDialog();
dialog.addAction( getString( R.string. follow), new Runnable() {
@Override public void run(){
callFollow( access_info, status.account, true );
}
} );
dialog.addAction( getString( R.string. follow_from_another_account), new Runnable() {
@Override public void run(){
followFromAnotherAccount( access_info, status.account );
}
} );
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 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
public void onClick( DialogInterface dialog, int which ){
switch( which ){
case 0:
performMention( account, who );
break;
case 1:
performFollow( account, who, true );
break;
case 2:
performFollow( account, who, false );
break;
case 3:
performMute( account, who, true );
break;
case 4:
performMute( account, who, false );
break;
case 5:
performBlock( account, who, true );
break;
case 6:
performBlock( account, who, false );
break;
case 7:
performReport( account, who, null );
break;
}
}
} )
.show();
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
public void run(){
callFollow( access_info, who, false );
}
} );
dialog.addAction( getString( R.string.mute ), new Runnable() {
@Override public void run(){
callMute( access_info, who, true );
}
} );
dialog.addAction( getString( R.string.unmute ), new Runnable() {
@Override
public void run(){
callMute( access_info, who, false );
}
} );
dialog.addAction( getString( R.string.block ), new Runnable() {
@Override public void run(){
callBlock( access_info, who, true );
}
} );
dialog.addAction( getString( R.string.unblock ), new Runnable() {
@Override public void run(){
callBlock( access_info, who, false );
}
} );
dialog.addAction( getString( R.string.report ), new Runnable() {
@Override public void run(){
openReportForm( access_info, who, null );
}
} );
dialog.show( this, null );
}
}

View File

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