アカウント追加時に「疑似アカウント(ログインなし、公開データのみ読める)」を選択可能
This commit is contained in:
parent
dad9a200a4
commit
0ac0f90d54
|
@ -9,8 +9,8 @@ android {
|
|||
applicationId "jp.juggler.subwaytooter"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 27
|
||||
versionName "0.2.7"
|
||||
versionCode 28
|
||||
versionName "0.2.8"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public class ActAccountSetting extends AppCompatActivity implements View.OnClick
|
|||
@Override
|
||||
protected void onCreate( @Nullable Bundle savedInstanceState ){
|
||||
super.onCreate( savedInstanceState );
|
||||
App1.setActivityTheme(this,false);
|
||||
App1.setActivityTheme( this, false );
|
||||
initUI();
|
||||
account = SavedAccount.loadAccount( log, getIntent().getLongExtra( KEY_ACCOUNT_DB_ID, - 1L ) );
|
||||
if( account == null ) finish();
|
||||
|
@ -113,11 +113,20 @@ public class ActAccountSetting extends AppCompatActivity implements View.OnClick
|
|||
|
||||
loading = false;
|
||||
|
||||
boolean enabled = ! a.isPseudo();
|
||||
btnAccessToken.setEnabled( enabled );
|
||||
btnVisibility.setEnabled( enabled );
|
||||
swConfirmBeforeBoost.setEnabled( enabled );
|
||||
cbNotificationMention.setEnabled( enabled );
|
||||
cbNotificationBoost.setEnabled( enabled );
|
||||
cbNotificationFavourite.setEnabled( enabled );
|
||||
cbNotificationFollow.setEnabled( enabled );
|
||||
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
@Override protected void onStop(){
|
||||
AlarmService.startCheck(this);
|
||||
AlarmService.startCheck( this );
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ public class ActMain extends AppCompatActivity
|
|||
if( data != null ){
|
||||
String search = data.getStringExtra( ActAbout.EXTRA_SEARCH );
|
||||
if( ! TextUtils.isEmpty( search ) ){
|
||||
performAddTimeline( Column.TYPE_SEARCH, search, true );
|
||||
performAddTimeline( true, Column.TYPE_SEARCH, search, true );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -291,20 +291,22 @@ public class ActMain extends AppCompatActivity
|
|||
if( id == R.id.nav_account_add ){
|
||||
performAccountAdd();
|
||||
}else if( id == R.id.nav_add_tl_home ){
|
||||
performAddTimeline( Column.TYPE_HOME );
|
||||
|
||||
performAddTimeline( false, Column.TYPE_HOME );
|
||||
}else if( id == R.id.nav_add_tl_local ){
|
||||
performAddTimeline( Column.TYPE_LOCAL );
|
||||
performAddTimeline( true, Column.TYPE_LOCAL );
|
||||
}else if( id == R.id.nav_add_tl_federate ){
|
||||
performAddTimeline( Column.TYPE_FEDERATE );
|
||||
performAddTimeline( true, Column.TYPE_FEDERATE );
|
||||
|
||||
}else if( id == R.id.nav_add_favourites ){
|
||||
performAddTimeline( Column.TYPE_FAVOURITES );
|
||||
performAddTimeline( false, Column.TYPE_FAVOURITES );
|
||||
|
||||
// }else if( id == R.id.nav_add_reports ){
|
||||
// performAddTimeline(Column.TYPE_REPORTS );
|
||||
}else if( id == R.id.nav_add_statuses ){
|
||||
performAddTimeline( Column.TYPE_PROFILE );
|
||||
performAddTimeline( false, Column.TYPE_PROFILE );
|
||||
}else if( id == R.id.nav_add_notifications ){
|
||||
performAddTimeline( Column.TYPE_NOTIFICATIONS );
|
||||
performAddTimeline( false, Column.TYPE_NOTIFICATIONS );
|
||||
|
||||
}else if( id == R.id.nav_app_setting ){
|
||||
performAppSetting();
|
||||
|
@ -314,7 +316,7 @@ public class ActMain extends AppCompatActivity
|
|||
performColumnList();
|
||||
|
||||
}else if( id == R.id.nav_add_tl_search ){
|
||||
performAddTimeline( Column.TYPE_SEARCH, "", false );
|
||||
performAddTimeline( true, Column.TYPE_SEARCH, "", false );
|
||||
|
||||
}else if( id == R.id.nav_app_about ){
|
||||
openAppAbout();
|
||||
|
@ -326,13 +328,13 @@ public class ActMain extends AppCompatActivity
|
|||
finish();
|
||||
|
||||
}else if( id == R.id.nav_add_mutes ){
|
||||
performAddTimeline( Column.TYPE_MUTES );
|
||||
performAddTimeline( false, Column.TYPE_MUTES );
|
||||
|
||||
}else if( id == R.id.nav_add_blocks ){
|
||||
performAddTimeline( Column.TYPE_BLOCKS );
|
||||
performAddTimeline( false, Column.TYPE_BLOCKS );
|
||||
|
||||
}else if( id == R.id.nav_follow_requests ){
|
||||
performAddTimeline( Column.TYPE_FOLLOW_REQUESTS );
|
||||
performAddTimeline( false, Column.TYPE_FOLLOW_REQUESTS );
|
||||
|
||||
}else if( id == R.id.nav_muted_app ){
|
||||
startActivity( new Intent( this, ActMutedApp.class ) );
|
||||
|
@ -404,22 +406,19 @@ public class ActMain extends AppCompatActivity
|
|||
public void performAccountAdd(){
|
||||
LoginForm.showLoginForm( this, null, new LoginForm.LoginFormCallback() {
|
||||
@Override
|
||||
public void startLogin( final Dialog dialog, final String instance ){
|
||||
public void startLogin( final Dialog dialog, final String instance, final boolean bPseudoAccount ){
|
||||
|
||||
final ProgressDialog progress = new ProgressDialog( ActMain.this );
|
||||
|
||||
final AsyncTask< Void, String, TootApiResult > task = new AsyncTask< Void, String, TootApiResult >() {
|
||||
|
||||
@Override
|
||||
protected TootApiResult doInBackground( Void... params ){
|
||||
@Override protected TootApiResult doInBackground( Void... params ){
|
||||
TootApiClient api_client = new TootApiClient( ActMain.this, new TootApiClient.Callback() {
|
||||
@Override
|
||||
public boolean isApiCancelled(){
|
||||
@Override public boolean isApiCancelled(){
|
||||
return isCancelled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishApiProgress( final String s ){
|
||||
@Override public void publishApiProgress( final String s ){
|
||||
Utils.runOnMainThread( new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
|
@ -430,7 +429,13 @@ public class ActMain extends AppCompatActivity
|
|||
} );
|
||||
|
||||
api_client.setInstance( instance );
|
||||
return api_client.authorize1();
|
||||
|
||||
if( bPseudoAccount ){
|
||||
return api_client.checkInstance();
|
||||
}else{
|
||||
return api_client.authorize1();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -441,8 +446,9 @@ public class ActMain extends AppCompatActivity
|
|||
if( result == null ){
|
||||
// cancelled.
|
||||
}else if( result.error != null ){
|
||||
// エラー?
|
||||
String sv = result.error;
|
||||
|
||||
// エラーはブラウザ用URLかもしれない
|
||||
if( sv.startsWith( "https" ) ){
|
||||
// OAuth認証が必要
|
||||
Intent data = new Intent();
|
||||
|
@ -451,12 +457,36 @@ public class ActMain extends AppCompatActivity
|
|||
dialog.dismiss();
|
||||
return;
|
||||
}
|
||||
|
||||
// 他のエラー
|
||||
Utils.showToast( ActMain.this, true, sv );
|
||||
log.e( result.error );
|
||||
}else{
|
||||
// 多分ここは通らないはず
|
||||
Utils.showToast( ActMain.this, false, R.string.access_token_updated_for );
|
||||
// 疑似アカウントが追加された
|
||||
try{
|
||||
String username = "?";
|
||||
String full_acct = username + "@" + instance;
|
||||
|
||||
JSONObject account_info = new JSONObject();
|
||||
account_info.put( "username", username );
|
||||
account_info.put( "acct", username );
|
||||
|
||||
long row_id = SavedAccount.insert( instance, full_acct, account_info, new JSONObject() );
|
||||
SavedAccount account = SavedAccount.loadAccount( log, row_id );
|
||||
if( account != null ){
|
||||
account.notification_follow = false;
|
||||
account.notification_favourite = false;
|
||||
account.notification_boost = false;
|
||||
account.notification_mention = false;
|
||||
account.saveSetting();
|
||||
|
||||
Utils.showToast( ActMain.this, false, R.string.server_confirmed );
|
||||
addColumn( account, Column.TYPE_LOCAL );
|
||||
dialog.dismiss();
|
||||
}
|
||||
}catch( JSONException ex ){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -513,7 +543,6 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
final AsyncTask< Void, Void, TootApiResult > task = new AsyncTask< Void, Void, TootApiResult >() {
|
||||
|
||||
long row_id;
|
||||
TootAccount ta;
|
||||
SavedAccount sa;
|
||||
String host;
|
||||
|
@ -629,7 +658,7 @@ public class ActMain extends AppCompatActivity
|
|||
}else{
|
||||
// アカウント追加時
|
||||
String user = ta.username + "@" + host;
|
||||
this.row_id = SavedAccount.insert( host, user, result.object, result.token_info );
|
||||
long row_id = SavedAccount.insert( host, user, result.object, result.token_info );
|
||||
SavedAccount account = SavedAccount.loadAccount( log, row_id );
|
||||
if( account != null ){
|
||||
if( account.locked ){
|
||||
|
@ -717,15 +746,19 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
|
||||
void performOpenUser( SavedAccount access_info, TootAccount user ){
|
||||
addColumn( access_info, Column.TYPE_PROFILE, user.id );
|
||||
if( access_info.isPseudo() ){
|
||||
Utils.showToast( this,false,R.string.not_available_for_pseudo_account );
|
||||
}else{
|
||||
addColumn( access_info, Column.TYPE_PROFILE, user.id );
|
||||
}
|
||||
}
|
||||
|
||||
public void performConversation( SavedAccount access_info, TootStatus status ){
|
||||
addColumn( access_info, Column.TYPE_CONVERSATION, status.id );
|
||||
}
|
||||
|
||||
private void performAddTimeline( final int type, final Object... args ){
|
||||
AccountPicker.pick( this, true, new AccountPicker.AccountPickerCallback() {
|
||||
private void performAddTimeline( boolean bAllowPseudo, final int type, final Object... args ){
|
||||
AccountPicker.pick( this, bAllowPseudo, true, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
switch( type ){
|
||||
default:
|
||||
|
@ -1191,9 +1224,8 @@ public class ActMain extends AppCompatActivity
|
|||
////////////////////////////////////////
|
||||
|
||||
private void performAccountSetting(){
|
||||
AccountPicker.pick( this, true, new AccountPicker.AccountPickerCallback() {
|
||||
@Override
|
||||
public void onAccountPicked( SavedAccount ai ){
|
||||
AccountPicker.pick( this, true, true, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
ActAccountSetting.open( ActMain.this, ai, REQUEST_CODE_ACCOUNT_SETTING );
|
||||
}
|
||||
} );
|
||||
|
@ -1490,7 +1522,7 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
// アカウントを選択してからユーザをフォローする
|
||||
void followFromAccount( final SavedAccount access_info, final TootAccount who, final RelationChangedCallback callback ){
|
||||
AccountPicker.pick( ActMain.this, true, new AccountPicker.AccountPickerCallback() {
|
||||
AccountPicker.pick( ActMain.this, false, true, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
String acct = who.acct;
|
||||
if( ! acct.contains( "@" ) ){
|
||||
|
@ -1761,19 +1793,14 @@ public class ActMain extends AppCompatActivity
|
|||
} );
|
||||
|
||||
client.setAccount( access_info );
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( "account_id=" )
|
||||
.append( Long.toString( who.id ) )
|
||||
.append( "&comment=" )
|
||||
.append( Uri.encode( comment ) );
|
||||
|
||||
sb.append( "&status_ids[]=" )
|
||||
.append( Long.toString( status.id ) );
|
||||
String sb = "account_id=" + Long.toString( who.id )
|
||||
+ "&comment=" + Uri.encode( comment )
|
||||
+ "&status_ids[]=" + Long.toString( status.id );
|
||||
|
||||
Request.Builder request_builder = new Request.Builder().post(
|
||||
RequestBody.create(
|
||||
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
|
||||
, sb.toString()
|
||||
, sb
|
||||
) );
|
||||
|
||||
return client.request( "/api/v1/reports", request_builder );
|
||||
|
@ -1900,6 +1927,7 @@ public class ActMain extends AppCompatActivity
|
|||
} );
|
||||
final ArrayList< SavedAccount > tmp_list = new ArrayList<>();
|
||||
for( SavedAccount a : SavedAccount.loadAccountList( log ) ){
|
||||
if( a.isPseudo() ) continue;
|
||||
if( a.host.equalsIgnoreCase( access_info.host ) ){
|
||||
// 同じホストを収集
|
||||
tmp_list.add( a );
|
||||
|
@ -1908,7 +1936,7 @@ public class ActMain extends AppCompatActivity
|
|||
if( ! tmp_list.isEmpty() ){
|
||||
dialog.addAction( getString( R.string.favourite_from_another_account ), new Runnable() {
|
||||
@Override public void run(){
|
||||
AccountPicker.pick( ActMain.this, false, tmp_list, new AccountPicker.AccountPickerCallback() {
|
||||
AccountPicker.pick( ActMain.this, false, false, tmp_list, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
if( ai != null )
|
||||
performFavourite( ai, status, favourite_complete_callback );
|
||||
|
@ -1918,7 +1946,7 @@ public class ActMain extends AppCompatActivity
|
|||
} );
|
||||
dialog.addAction( getString( R.string.boost_from_another_account ), new Runnable() {
|
||||
@Override public void run(){
|
||||
AccountPicker.pick( ActMain.this, false, tmp_list, new AccountPicker.AccountPickerCallback() {
|
||||
AccountPicker.pick( ActMain.this, false, false, tmp_list, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
if( ai != null )
|
||||
performBoost( ai, status, false, boost_complete_callback );
|
||||
|
@ -1934,50 +1962,53 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
} );
|
||||
|
||||
dialog.addAction( getString( R.string.follow ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callFollow( access_info, status.account, true, follow_complete_callback );
|
||||
}
|
||||
} );
|
||||
|
||||
dialog.addAction( getString( R.string.unfollow ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callFollow( access_info, status.account, false, unfollow_complete_callback );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.mute ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callMute( access_info, status.account, true, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unmute ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callMute( access_info, status.account, false, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.block ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, status.account, true, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unblock ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, status.account, false, null );
|
||||
}
|
||||
} );
|
||||
|
||||
if( access_info.isMe( status.account ) ){
|
||||
dialog.addAction( getString( R.string.delete ), new Runnable() {
|
||||
if( ! access_info.isPseudo() ){
|
||||
dialog.addAction( getString( R.string.follow ), new Runnable() {
|
||||
@Override public void run(){
|
||||
deleteStatus( access_info, status.id );
|
||||
callFollow( access_info, status.account, true, follow_complete_callback );
|
||||
}
|
||||
} );
|
||||
}else{
|
||||
dialog.addAction( getString( R.string.report ), new Runnable() {
|
||||
|
||||
dialog.addAction( getString( R.string.unfollow ), new Runnable() {
|
||||
@Override public void run(){
|
||||
openReportForm( access_info, status.account, status );
|
||||
callFollow( access_info, status.account, false, unfollow_complete_callback );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.mute ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callMute( access_info, status.account, true, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unmute ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callMute( access_info, status.account, false, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.block ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, status.account, true, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unblock ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, status.account, false, null );
|
||||
}
|
||||
} );
|
||||
|
||||
if( access_info.isMe( status.account ) ){
|
||||
dialog.addAction( getString( R.string.delete ), new Runnable() {
|
||||
@Override public void run(){
|
||||
deleteStatus( access_info, status.id );
|
||||
}
|
||||
} );
|
||||
}else{
|
||||
dialog.addAction( getString( R.string.report ), new Runnable() {
|
||||
@Override public void run(){
|
||||
openReportForm( access_info, status.account, status );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( column_type == Column.TYPE_CONVERSATION && status.application != null ){
|
||||
|
@ -1998,67 +2029,68 @@ public class ActMain extends AppCompatActivity
|
|||
public void openAccountMoreMenu( final SavedAccount access_info, final TootAccount who, int column_type ){
|
||||
ActionsDialog dialog = new ActionsDialog();
|
||||
|
||||
if( column_type == Column.TYPE_FOLLOW_REQUESTS ){
|
||||
dialog.addAction( getString( R.string.follow_request_ok ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callFollowRequestAuthorize( access_info, who, true );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.follow_request_ng ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callFollowRequestAuthorize( access_info, who, false );
|
||||
}
|
||||
} );
|
||||
|
||||
if( ! access_info.isPseudo() ){
|
||||
if( column_type == Column.TYPE_FOLLOW_REQUESTS ){
|
||||
dialog.addAction( getString( R.string.follow_request_ok ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callFollowRequestAuthorize( access_info, who, true );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.follow_request_ng ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callFollowRequestAuthorize( access_info, who, false );
|
||||
}
|
||||
} );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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, follow_complete_callback );
|
||||
}
|
||||
} );
|
||||
if( ! access_info.isPseudo() ){
|
||||
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, follow_complete_callback );
|
||||
}
|
||||
} );
|
||||
}
|
||||
dialog.addAction( getString( R.string.follow_from_another_account ), new Runnable() {
|
||||
@Override public void run(){
|
||||
followFromAccount( access_info, who, follow_complete_callback );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unfollow ), new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
callFollow( access_info, who, false, unfollow_complete_callback );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.mute ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callMute( access_info, who, true, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unmute ), new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
callMute( access_info, who, false, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.block ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, who, true, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unblock ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, who, false, null );
|
||||
}
|
||||
} );
|
||||
// dialog.addAction( getString( R.string.report ), new Runnable() {
|
||||
// @Override public void run(){
|
||||
// openReportForm( access_info, who, null );
|
||||
// }
|
||||
// } );
|
||||
if( ! access_info.isPseudo() ){
|
||||
dialog.addAction( getString( R.string.unfollow ), new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
callFollow( access_info, who, false, unfollow_complete_callback );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.mute ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callMute( access_info, who, true, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unmute ), new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
callMute( access_info, who, false, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.block ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, who, true, null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unblock ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, who, false, null );
|
||||
}
|
||||
} );
|
||||
}
|
||||
dialog.show( this, null );
|
||||
}
|
||||
|
||||
|
@ -2106,8 +2138,7 @@ public class ActMain extends AppCompatActivity
|
|||
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
|
||||
, "" // 空データ
|
||||
) );
|
||||
TootApiResult result = client.request( "/api/v1/notifications/clear", request_builder );
|
||||
return result;
|
||||
return client.request( "/api/v1/notifications/clear", request_builder );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2117,6 +2148,7 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
@Override
|
||||
protected void onPostExecute( TootApiResult result ){
|
||||
//noinspection StatementWithEmptyBody
|
||||
if( result == null ){
|
||||
//cancelled.
|
||||
}else if( result.object != null ){
|
||||
|
|
|
@ -78,6 +78,7 @@ class Column {
|
|||
private static final String PATH_STATUSES = "/api/v1/statuses/%d"; // 1:status_id
|
||||
private static final String PATH_STATUSES_CONTEXT = "/api/v1/statuses/%d/context"; // 1:status_id
|
||||
private static final String PATH_SEARCH = "/api/v1/search?q=%s"; // 1: query(urlencoded) , also, append "&resolve=1" if resolve non-local accounts
|
||||
private static final String PATH_INSTANCE="/api/v1/instance";
|
||||
|
||||
private static final String KEY_ACCOUNT_ROW_ID = "account_id";
|
||||
private static final String KEY_TYPE = "type";
|
||||
|
@ -852,9 +853,16 @@ class Column {
|
|||
|
||||
default:
|
||||
case TAB_STATUS:
|
||||
String s = String.format( Locale.JAPAN, PATH_ACCOUNT_STATUSES, profile_id );
|
||||
if( with_attachment ) s = s + "&only_media=1";
|
||||
return getStatuses( client, s );
|
||||
if( access_info.isPseudo()){
|
||||
return client.request(PATH_INSTANCE );
|
||||
|
||||
}else{
|
||||
String s = String.format( Locale.JAPAN, PATH_ACCOUNT_STATUSES, profile_id );
|
||||
if( with_attachment ) s = s + "&only_media=1";
|
||||
return getStatuses( client, s );
|
||||
|
||||
}
|
||||
|
||||
|
||||
case TAB_FOLLOWING:
|
||||
return parseAccountList( client,
|
||||
|
@ -1387,10 +1395,13 @@ class Column {
|
|||
|
||||
default:
|
||||
case TAB_STATUS:
|
||||
String s = String.format( Locale.JAPAN, PATH_ACCOUNT_STATUSES, profile_id );
|
||||
if( with_attachment ) s = s + "&only_media=1";
|
||||
return getStatusList( client, s );
|
||||
|
||||
if( access_info.isPseudo()){
|
||||
return client.request(PATH_INSTANCE );
|
||||
}else{
|
||||
String s = String.format( Locale.JAPAN, PATH_ACCOUNT_STATUSES, profile_id );
|
||||
if( with_attachment ) s = s + "&only_media=1";
|
||||
return getStatusList( client, s );
|
||||
}
|
||||
case TAB_FOLLOWING:
|
||||
return getAccountList( client,
|
||||
String.format( Locale.JAPAN, PATH_ACCOUNT_FOLLOWING, profile_id ) );
|
||||
|
@ -1765,9 +1776,16 @@ class Column {
|
|||
|
||||
default:
|
||||
case TAB_STATUS:
|
||||
String s = String.format( Locale.JAPAN, PATH_ACCOUNT_STATUSES, profile_id );
|
||||
if( with_attachment ) s = s + "&only_media=1";
|
||||
return getStatusList( client, s );
|
||||
|
||||
if( access_info.isPseudo()){
|
||||
return client.request(PATH_INSTANCE );
|
||||
|
||||
}else{
|
||||
String s = String.format( Locale.JAPAN, PATH_ACCOUNT_STATUSES, profile_id );
|
||||
if( with_attachment ) s = s + "&only_media=1";
|
||||
return getStatusList( client, s );
|
||||
|
||||
}
|
||||
|
||||
case TAB_FOLLOWING:
|
||||
return getAccountList( client,
|
||||
|
|
|
@ -81,32 +81,26 @@ public class TootApiClient {
|
|||
|
||||
private TootApiResult request_sub( String path, Request.Builder request_builder ){
|
||||
|
||||
if( callback.isApiCancelled() ) return null;
|
||||
|
||||
// アクセストークンを使ってAPIを呼び出す
|
||||
callback.publishApiProgress( context.getString( R.string.request_api, path ) );
|
||||
|
||||
if( account == null ){
|
||||
return new TootApiResult( "account is null" );
|
||||
}
|
||||
|
||||
JSONObject token_info = account.token_info;
|
||||
// if( token_info != null && token_info.optInt( KEY_AUTH_VERSION, 0 ) < AUTH_VERSION ){
|
||||
// // このトークンは形式が古くて使えないよ
|
||||
// token_info = null;
|
||||
// }
|
||||
|
||||
if( callback.isApiCancelled() ) return null;
|
||||
|
||||
if( token_info == null ){
|
||||
// アクセストークンの更新が必要
|
||||
return new TootApiResult( context.getString( R.string.login_required ) );
|
||||
request_builder.url( "https://" + instance + path );
|
||||
|
||||
String access_token = Utils.optStringX( token_info, "access_token" );
|
||||
if( !TextUtils.isEmpty( access_token ) ){
|
||||
request_builder.header( "Authorization", "Bearer " + access_token );
|
||||
}
|
||||
|
||||
// アクセストークンを使ってAPIを呼び出す
|
||||
callback.publishApiProgress( context.getString( R.string.request_api, path ) );
|
||||
|
||||
Request request = request_builder
|
||||
.url( "https://" + instance + path )
|
||||
.header( "Authorization", "Bearer " + Utils.optStringX( token_info, "access_token" ) )
|
||||
.build();
|
||||
|
||||
Call call = ok_http_client.newCall( request );
|
||||
Call call = ok_http_client.newCall( request_builder.build() );
|
||||
Response response;
|
||||
try{
|
||||
response = call.execute();
|
||||
|
@ -119,8 +113,6 @@ public class TootApiClient {
|
|||
|
||||
if( callback.isApiCancelled() ) return null;
|
||||
|
||||
// TODO: アクセストークンが無効な場合はどうなる?
|
||||
|
||||
if( ! response.isSuccessful() ){
|
||||
return new TootApiResult( context.getString( R.string.network_error_arg, response ) );
|
||||
}
|
||||
|
@ -148,6 +140,58 @@ public class TootApiClient {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// 疑似アカウントの追加時に、インスタンスの検証を行う
|
||||
public TootApiResult checkInstance(){
|
||||
|
||||
// サーバ情報APIを使う
|
||||
String path = "/api/v1/instance";
|
||||
callback.publishApiProgress( context.getString( R.string.request_api, path ) );
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url( "https://" + instance + path )
|
||||
.build();
|
||||
|
||||
Call call = ok_http_client.newCall( request );
|
||||
|
||||
Response response;
|
||||
try{
|
||||
response = call.execute();
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace( );
|
||||
return new TootApiResult( Utils.formatError( ex, context.getResources(), R.string.network_error ) );
|
||||
}
|
||||
|
||||
if( callback.isApiCancelled() ) return null;
|
||||
|
||||
if( ! response.isSuccessful() ){
|
||||
return new TootApiResult( context.getString( R.string.network_error_arg, response ) );
|
||||
}
|
||||
|
||||
try{
|
||||
String json = response.body().string();
|
||||
|
||||
if( TextUtils.isEmpty( json ) || json.startsWith( "<" ) ){
|
||||
return new TootApiResult( context.getString( R.string.response_not_json ) + "\n" + json );
|
||||
}else if( json.startsWith( "[" ) ){
|
||||
JSONArray array = new JSONArray( json );
|
||||
return new TootApiResult( log,response, null, json, array );
|
||||
}else{
|
||||
JSONObject object = new JSONObject( json );
|
||||
|
||||
String error = Utils.optStringX( object, "error" );
|
||||
if( ! TextUtils.isEmpty( error ) ){
|
||||
return new TootApiResult( context.getString( R.string.api_error, error ) );
|
||||
}
|
||||
return new TootApiResult( response, null, json, object );
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
return new TootApiResult( Utils.formatError( ex, "API data error" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public TootApiResult authorize1(){
|
||||
|
||||
JSONObject client_info = null;
|
||||
|
@ -341,4 +385,7 @@ public class TootApiClient {
|
|||
return new TootApiResult( Utils.formatError( ex, "API data error" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import jp.juggler.subwaytooter.util.Utils;
|
|||
|
||||
public class TootAccount {
|
||||
|
||||
|
||||
public static class List extends ArrayList< TootAccount > {
|
||||
|
||||
}
|
||||
|
@ -72,10 +73,20 @@ public class TootAccount {
|
|||
|
||||
public long time_created_at;
|
||||
|
||||
public TootAccount(){
|
||||
|
||||
}
|
||||
|
||||
// 疑似アカウントの作成
|
||||
public TootAccount( String username ){
|
||||
this.acct = username;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public static TootAccount parse( LogCategory log, LinkClickContext account, JSONObject src, TootAccount dst ){
|
||||
if( src == null ) return null;
|
||||
try{
|
||||
dst.id = src.optLong( "id" );
|
||||
dst.id = src.optLong( "id",-1L );
|
||||
dst.username = Utils.optStringX( src, "username" );
|
||||
dst.acct = Utils.optStringX( src, "acct" );
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ public class TootStatus extends TootId {
|
|||
return date_format_utc.parse( strTime ).getTime();
|
||||
}catch( ParseException ex ){
|
||||
ex.printStackTrace();
|
||||
log.e( ex, "TootStatus.parseTime failed." );
|
||||
log.e( ex, "TootStatus.parseTime failed. src=%s",strTime );
|
||||
}
|
||||
}
|
||||
return 0L;
|
||||
|
|
|
@ -2,6 +2,7 @@ package jp.juggler.subwaytooter.dialog;
|
|||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -14,48 +15,67 @@ import jp.juggler.subwaytooter.util.Utils;
|
|||
|
||||
public class AccountPicker {
|
||||
|
||||
public interface AccountPickerCallback{
|
||||
void onAccountPicked(SavedAccount ai);
|
||||
}
|
||||
public static void pick( ActMain activity, boolean bAuto,final AccountPickerCallback callback){
|
||||
|
||||
final ArrayList< SavedAccount > account_list = SavedAccount.loadAccountList( ActMain.log );
|
||||
pick( activity,bAuto,account_list,callback);
|
||||
public interface AccountPickerCallback {
|
||||
void onAccountPicked( SavedAccount ai );
|
||||
}
|
||||
|
||||
public static void pick( ActMain activity, boolean bAuto,final ArrayList<SavedAccount > account_list,final AccountPickerCallback callback){
|
||||
|
||||
if( account_list == null || account_list.isEmpty() ){
|
||||
Utils.showToast(activity,false,R.string.account_empty);
|
||||
public static void pick( @NonNull ActMain activity, boolean bAllowPseudo, boolean bAuto
|
||||
, @NonNull final AccountPickerCallback callback
|
||||
){
|
||||
|
||||
ArrayList< SavedAccount > account_list = SavedAccount.loadAccountList( ActMain.log );
|
||||
pick( activity, bAllowPseudo, bAuto, account_list, callback );
|
||||
}
|
||||
|
||||
public static void pick( @NonNull ActMain activity, boolean bAllowPseudo, boolean bAuto
|
||||
, @NonNull final ArrayList< SavedAccount > account_list
|
||||
, @NonNull final AccountPickerCallback callback
|
||||
){
|
||||
if( account_list.isEmpty() ){
|
||||
Utils.showToast( activity, false, R.string.account_empty );
|
||||
return;
|
||||
}
|
||||
|
||||
if( ! bAllowPseudo ){
|
||||
ArrayList< SavedAccount > tmp_list = new ArrayList<>();
|
||||
for( SavedAccount a : account_list ){
|
||||
if( a.isPseudo() ) continue;
|
||||
tmp_list.add( a );
|
||||
}
|
||||
account_list.clear();
|
||||
account_list.addAll( tmp_list );
|
||||
if( account_list.isEmpty() ){
|
||||
Utils.showToast( activity, false, R.string.not_available_for_pseudo_account );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( bAuto && account_list.size() == 1 ){
|
||||
callback.onAccountPicked(account_list.get(0));
|
||||
callback.onAccountPicked( account_list.get( 0 ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Collections.sort( account_list, new Comparator< SavedAccount >() {
|
||||
@Override
|
||||
public int compare( SavedAccount o1, SavedAccount o2 ){
|
||||
return String.CASE_INSENSITIVE_ORDER.compare( o1.acct, o2.acct );
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
String[] caption_list = new String[ account_list.size() ];
|
||||
|
||||
for(int i=0,ie=account_list.size();i<ie;++i){
|
||||
SavedAccount ai = account_list.get(i);
|
||||
caption_list[i] = ai.acct;
|
||||
|
||||
for( int i = 0, ie = account_list.size() ; i < ie ; ++ i ){
|
||||
SavedAccount ai = account_list.get( i );
|
||||
caption_list[ i ] = ai.acct;
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(activity)
|
||||
.setNegativeButton( R.string.cancel,null )
|
||||
|
||||
new AlertDialog.Builder( activity )
|
||||
.setNegativeButton( R.string.cancel, null )
|
||||
.setItems( caption_list, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( DialogInterface dialog, int which ){
|
||||
if( which >= 0 && which < account_list.size() ){
|
||||
callback.onAccountPicked(account_list.get(which));
|
||||
callback.onAccountPicked( account_list.get( which ) );
|
||||
dialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import android.view.WindowManager;
|
|||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
@ -23,14 +24,15 @@ import jp.juggler.subwaytooter.util.Utils;
|
|||
public class LoginForm {
|
||||
|
||||
public interface LoginFormCallback{
|
||||
void startLogin(Dialog dialog,String instance);
|
||||
void startLogin(Dialog dialog,String instance,boolean bPseudoAccount);
|
||||
}
|
||||
|
||||
public static void showLoginForm( final Activity activity, String instance , final LoginFormCallback callback){
|
||||
final View view = activity.getLayoutInflater().inflate( R.layout.dlg_account_add, null, false );
|
||||
final AutoCompleteTextView etInstance = (AutoCompleteTextView) view.findViewById( R.id.etInstance );
|
||||
final View btnOk = view.findViewById( R.id.btnOk );
|
||||
|
||||
final CheckBox cbPseudoAccount = (CheckBox) view.findViewById( R.id.cbPseudoAccount );
|
||||
|
||||
if( !TextUtils.isEmpty( instance ) ){
|
||||
etInstance.setText(instance);
|
||||
etInstance.setInputType( InputType.TYPE_NULL );
|
||||
|
@ -61,7 +63,7 @@ public class LoginForm {
|
|||
Utils.showToast( activity, true, R.string.instance_not_need_slash );
|
||||
return;
|
||||
}
|
||||
callback.startLogin( dialog,instance );
|
||||
callback.startLogin( dialog,instance ,cbPseudoAccount.isChecked() );
|
||||
}
|
||||
} );
|
||||
view.findViewById( R.id.btnCancel ).setOnClickListener( new View.OnClickListener() {
|
||||
|
|
|
@ -268,4 +268,8 @@ public class SavedAccount extends TootAccount implements LinkClickContext {
|
|||
if( url.charAt( 0 )=='/') return "https://"+host+url;
|
||||
return url;
|
||||
}
|
||||
|
||||
public boolean isPseudo(){
|
||||
return "?".equals( username );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,29 +213,29 @@ public class HTMLDecoder {
|
|||
}
|
||||
|
||||
public static SpannableStringBuilder decodeHTML( LinkClickContext account, String src ){
|
||||
SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
try{
|
||||
TokenParser tracker = new TokenParser( src );
|
||||
Node rootNode = new Node();
|
||||
rootNode.parseChild( tracker, "" );
|
||||
|
||||
SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
|
||||
rootNode.encodeSpan( account, sb );
|
||||
int end = sb.length();
|
||||
while( end > 0 && isWhitespace( sb.charAt( end - 1 ) ) ) -- end;
|
||||
if( end < sb.length() ){
|
||||
sb.delete( end, sb.length() );
|
||||
}
|
||||
if( src != null ){
|
||||
TokenParser tracker = new TokenParser( src );
|
||||
Node rootNode = new Node();
|
||||
rootNode.parseChild( tracker, "" );
|
||||
|
||||
rootNode.encodeSpan( account, sb );
|
||||
int end = sb.length();
|
||||
while( end > 0 && isWhitespace( sb.charAt( end - 1 ) ) ) -- end;
|
||||
if( end < sb.length() ){
|
||||
sb.delete( end, sb.length() );
|
||||
}
|
||||
|
||||
// sb.append( "\n" );
|
||||
// sb.append( src );
|
||||
|
||||
return sb;
|
||||
|
||||
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
// public static Spannable decodeTags( final LinkClickContext account, TootTag.List src_list ){
|
||||
|
|
|
@ -163,7 +163,7 @@ public class Utils {
|
|||
public static String optStringX( JSONArray src, int key ){
|
||||
return src.isNull( key ) ? null : src.optString( key );
|
||||
}
|
||||
|
||||
|
||||
public static ArrayList< String > parseStringArray( LogCategory log, JSONArray array ){
|
||||
ArrayList< String > dst_list = new ArrayList<>();
|
||||
if( array != null ){
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
android:text="@string/confirm_before_boost"
|
||||
/>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
<LinearLayout style="@style/setting_row_form" >
|
||||
|
||||
<Switch
|
||||
android:id="@+id/swConfirmBeforeBoost"
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/instance"
|
||||
|
@ -23,13 +21,19 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:inputType="textUri"
|
||||
android:hint="@string/instance_hint"
|
||||
android:imeOptions="actionDone"
|
||||
/>
|
||||
<CheckBox
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/pseudo_account"
|
||||
android:id="@+id/cbPseudoAccount"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
style="?android:attr/buttonBarStyle"
|
||||
|
|
|
@ -206,5 +206,8 @@
|
|||
<string name="sound">sound</string>
|
||||
<string name="vibration">vibration</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="not_available_for_pseudo_account">not available for pseudo account</string>
|
||||
<string name="pseudo_account">pseudo account (non-login,only reading public data)</string>
|
||||
<string name="server_confirmed">server confirmed.</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -202,4 +202,7 @@
|
|||
<string name="sound">音</string>
|
||||
<string name="vibration">振動</string>
|
||||
<string name="close">閉じる</string>
|
||||
<string name="not_available_for_pseudo_account">疑似アカウントでは利用できません</string>
|
||||
<string name="pseudo_account">疑似アカウント(ログインなし、公開データを読めるだけ)</string>
|
||||
<string name="server_confirmed">サーバを確認しました</string>
|
||||
</resources>
|
||||
|
|
|
@ -203,4 +203,7 @@
|
|||
<string name="follow_request_rejected">%1$s\'s follow request is rejected.</string>
|
||||
<string name="follow_request_authorized">%1$s\'s follow request is authorized.</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="pseudo_account">pseudo account (non-login,only reading public data)</string>
|
||||
<string name="server_confirmed">server confirmed.</string>
|
||||
<string name="not_available_for_pseudo_account">not available for pseudo account</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue