mirror of
https://github.com/tateisu/SubwayTooter
synced 2025-02-01 19:36:48 +01:00
「別アカウントからフォロー」を追加
This commit is contained in:
parent
e312790992
commit
caa07564a2
228
.idea/codeStyleSettings.xml
generated
Normal file
228
.idea/codeStyleSettings.xml
generated
Normal 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>
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user