v0.0.7: フォロー一覧/フォロワー一覧。アプリ情報。OSSライセンス。
@ -4,6 +4,7 @@
|
||||
<w>dont</w>
|
||||
<w>emoji</w>
|
||||
<w>emojione</w>
|
||||
<w>enty</w>
|
||||
<w>favourited</w>
|
||||
<w>hashtag</w>
|
||||
<w>noto</w>
|
||||
|
@ -9,8 +9,8 @@ android {
|
||||
applicationId "jp.juggler.subwaytooter"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 6
|
||||
versionName "0.0.6"
|
||||
versionCode 7
|
||||
versionName "0.0.7"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
|
@ -5,19 +5,19 @@
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application
|
||||
android:name=".App1"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:name=".App1"
|
||||
>
|
||||
|
||||
<activity
|
||||
android:name=".ActMain"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:windowSoftInputMode="adjustPan|stateAlwaysHidden"
|
||||
>
|
||||
<intent-filter>
|
||||
@ -53,8 +53,20 @@
|
||||
android:theme="@style/AppTheme"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
/>
|
||||
<activity
|
||||
android:name=".ActAbout"
|
||||
android:label="@string/app_about"
|
||||
android:theme="@style/AppTheme"
|
||||
/>
|
||||
<activity
|
||||
android:name=".ActOSSLicense"
|
||||
android:label="@string/oss_license"
|
||||
android:theme="@style/AppTheme"
|
||||
/>
|
||||
|
||||
<meta-data android:name="android.max_aspect" android:value="ratio_float"/>
|
||||
<meta-data
|
||||
android:name="android.max_aspect"
|
||||
android:value="ratio_float"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
55
app/src/main/java/jp/juggler/subwaytooter/ActAbout.java
Normal file
@ -0,0 +1,55 @@
|
||||
package jp.juggler.subwaytooter;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class ActAbout extends AppCompatActivity {
|
||||
|
||||
static final String url_store = "https://play.google.com/store/apps/details?id=jp.juggler.subwaytooter";
|
||||
static final String url_enty = "https://enty.jp/3WtlzHG10wZv";
|
||||
|
||||
@Override protected void onCreate( @Nullable Bundle savedInstanceState ){
|
||||
super.onCreate( savedInstanceState );
|
||||
setContentView( R.layout.act_about );
|
||||
|
||||
try{
|
||||
PackageInfo pInfo = getPackageManager().getPackageInfo( getPackageName(), 0 );
|
||||
( (TextView) findViewById( R.id.tvVersion ) ).setText( getString( R.string.version_is, pInfo.versionName ) );
|
||||
}catch( PackageManager.NameNotFoundException ex ){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
Button b = (Button) findViewById( R.id.btnRate );
|
||||
b.setText( url_store );
|
||||
b.setOnClickListener( new View.OnClickListener() {
|
||||
@Override public void onClick( View v ){
|
||||
open_browser( url_store );
|
||||
}
|
||||
} );
|
||||
|
||||
b = (Button) findViewById( R.id.btnDonate );
|
||||
b.setText( url_enty );
|
||||
b.setOnClickListener( new View.OnClickListener() {
|
||||
@Override public void onClick( View v ){
|
||||
open_browser( url_enty );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
void open_browser( String url ){
|
||||
try{
|
||||
Intent intent = new Intent( Intent.ACTION_VIEW, Uri.parse( url ) );
|
||||
startActivity( intent );
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -77,7 +77,7 @@ public class ActAccountSetting extends AppCompatActivity implements View.OnClick
|
||||
|
||||
private void loadUIFromData( SavedAccount a ){
|
||||
tvInstance.setText( a.host );
|
||||
tvUser.setText( a.user );
|
||||
tvUser.setText( a.acct );
|
||||
|
||||
String sv = a.visibility;
|
||||
if( sv != null ){
|
||||
|
@ -42,6 +42,7 @@ import java.util.regex.Pattern;
|
||||
import jp.juggler.subwaytooter.api.TootApiClient;
|
||||
import jp.juggler.subwaytooter.api.TootApiResult;
|
||||
import jp.juggler.subwaytooter.api.entity.TootAccount;
|
||||
import jp.juggler.subwaytooter.api.entity.TootRelationShip;
|
||||
import jp.juggler.subwaytooter.api.entity.TootStatus;
|
||||
import jp.juggler.subwaytooter.dialog.AccountPicker;
|
||||
import jp.juggler.subwaytooter.dialog.LoginForm;
|
||||
@ -238,7 +239,12 @@ public class ActMain extends AppCompatActivity
|
||||
}else if( id == R.id.nav_add_tl_search ){
|
||||
performAddTimeline( Column.TYPE_SEARCH );
|
||||
|
||||
}else if( id == R.id.nav_app_about ){
|
||||
openAppAbout();
|
||||
|
||||
}else if( id == R.id.nav_oss_license ){
|
||||
openOSSLicense( );
|
||||
|
||||
// Handle the camera action
|
||||
// }else if( id == R.id.nav_gallery ){
|
||||
//
|
||||
@ -257,6 +263,7 @@ public class ActMain extends AppCompatActivity
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ViewPager pager;
|
||||
ColumnPagerAdapter pager_adapter;
|
||||
View llEmpty;
|
||||
@ -442,12 +449,12 @@ public class ActMain extends AppCompatActivity
|
||||
AccountPicker.pick( this, new AccountPicker.AccountPickerCallback() {
|
||||
@Override
|
||||
public void onAccountPicked( SavedAccount ai ){
|
||||
switch(type){
|
||||
switch( type ){
|
||||
default:
|
||||
addColumn( ai, type, ai.id );
|
||||
break;
|
||||
case Column.TYPE_SEARCH:
|
||||
addColumn( ai,type, "",false);
|
||||
addColumn( ai, type, "", false );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -615,7 +622,7 @@ public class ActMain extends AppCompatActivity
|
||||
for( SavedAccount a : account_list ){
|
||||
final SavedAccount _a = a;
|
||||
dialog.addAction(
|
||||
getString( R.string.open_in_account, a.user )
|
||||
getString( R.string.open_in_account, a.acct )
|
||||
, new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
@ -632,7 +639,7 @@ public class ActMain extends AppCompatActivity
|
||||
{
|
||||
final SavedAccount _a = access_info;
|
||||
dialog.addAction(
|
||||
getString( R.string.open_in_account, access_info.user )
|
||||
getString( R.string.open_in_account, access_info.acct )
|
||||
, new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
@ -687,7 +694,7 @@ public class ActMain extends AppCompatActivity
|
||||
|
||||
private void showColumnMatchAccount( SavedAccount account ){
|
||||
for( Column column : pager_adapter.column_list ){
|
||||
if( account.user.equals( column.access_info.user ) ){
|
||||
if( account.acct.equals( column.access_info.acct ) ){
|
||||
column.fireVisualCallback();
|
||||
}
|
||||
}
|
||||
@ -1010,7 +1017,12 @@ public class ActMain extends AppCompatActivity
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void callFollow( final SavedAccount account, final TootAccount who, final boolean bFollow ){
|
||||
public interface RelationChangedCallback {
|
||||
// void onRelationChanged( TootRelationShip relationship );
|
||||
void onRelationChanged( );
|
||||
}
|
||||
|
||||
private void callFollow( final SavedAccount access_info, final TootAccount who, final boolean bFollow, final RelationChangedCallback callback ){
|
||||
|
||||
new AsyncTask< Void, Void, TootApiResult >() {
|
||||
@Override
|
||||
@ -1026,7 +1038,7 @@ public class ActMain extends AppCompatActivity
|
||||
|
||||
}
|
||||
} );
|
||||
client.setAccount( account );
|
||||
client.setAccount( access_info );
|
||||
|
||||
TootApiResult result;
|
||||
if( bFollow & who.acct.contains( "@" ) ){
|
||||
@ -1036,6 +1048,17 @@ public class ActMain extends AppCompatActivity
|
||||
, "uri=" + Uri.encode( who.acct )
|
||||
) );
|
||||
result = client.request( "/api/v1/follows", request_builder );
|
||||
if( result != null ){
|
||||
if( result.object != null ){
|
||||
remote_who = TootAccount.parse( log, access_info, result.object );
|
||||
|
||||
Utils.showToast( ActMain.this, false, bFollow ? R.string.follow_succeeded : R.string.unfollow_succeeded );
|
||||
}else if( bFollow && who.locked && result.response.code() == 422 ){
|
||||
Utils.showToast( ActMain.this, false, R.string.cant_follow_locked_user );
|
||||
}else{
|
||||
Utils.showToast( ActMain.this, false, result.error );
|
||||
}
|
||||
}
|
||||
}else{
|
||||
Request.Builder request_builder = new Request.Builder().post(
|
||||
RequestBody.create(
|
||||
@ -1044,24 +1067,53 @@ public class ActMain extends AppCompatActivity
|
||||
) );
|
||||
result = client.request( "/api/v1/accounts/" + who.id + ( bFollow ? "/follow" : "/unfollow" )
|
||||
, request_builder );
|
||||
}
|
||||
if( result != null ){
|
||||
if( result.object != null ){
|
||||
Utils.showToast( ActMain.this, false, bFollow ? R.string.follow_succeeded : R.string.unfollow_succeeded );
|
||||
}else if( bFollow && who.locked && result.response.code() == 422 ){
|
||||
Utils.showToast( ActMain.this, false, R.string.cant_follow_locked_user );
|
||||
}else{
|
||||
Utils.showToast( ActMain.this, false, result.error );
|
||||
if( result != null ){
|
||||
if( result.object != null ){
|
||||
relation = TootRelationShip.parse( log, result.object );
|
||||
|
||||
Utils.showToast( ActMain.this, false, bFollow ? R.string.follow_succeeded : R.string.unfollow_succeeded );
|
||||
}else if( bFollow && who.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;
|
||||
}
|
||||
|
||||
TootRelationShip relation;
|
||||
TootAccount remote_who;
|
||||
|
||||
@Override
|
||||
protected void onCancelled( TootApiResult result ){
|
||||
onPostExecute( null );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute( TootApiResult result ){
|
||||
// if( relation != null ){
|
||||
// App1.relationship_map.put( access_info, relation );
|
||||
// if( callback != null ) callback.onRelationChanged( relation );
|
||||
// }else if( remote_who != null ){
|
||||
// App1.relationship_map.addFollowing( access_info, remote_who.id );
|
||||
// if( callback != null )
|
||||
// callback.onRelationChanged( App1.relationship_map.get( access_info, remote_who.id ) );
|
||||
// }
|
||||
|
||||
if( relation != null ){
|
||||
if( callback != null ) callback.onRelationChanged( );
|
||||
}else if( remote_who != null ){
|
||||
if( callback != null )
|
||||
callback.onRelationChanged( );
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
// acct で指定したユーザをリモートフォローする
|
||||
void callRemoteFollow( final SavedAccount access_info, final String acct, final boolean locked ){
|
||||
void callRemoteFollow( final SavedAccount access_info, final String acct, final boolean locked, final RelationChangedCallback callback ){
|
||||
|
||||
new AsyncTask< Void, Void, TootApiResult >() {
|
||||
|
||||
@ -1089,6 +1141,7 @@ public class ActMain extends AppCompatActivity
|
||||
|
||||
if( result != null ){
|
||||
if( result.object != null ){
|
||||
who = TootAccount.parse( log, access_info, result.object );
|
||||
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 );
|
||||
@ -1099,11 +1152,31 @@ public class ActMain extends AppCompatActivity
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TootAccount who;
|
||||
|
||||
@Override
|
||||
protected void onCancelled( TootApiResult result ){
|
||||
onPostExecute( null );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute( TootApiResult result ){
|
||||
if( who != null ){
|
||||
// App1.relationship_map.addFollowing( access_info, who.id );
|
||||
// if( callback != null )
|
||||
// callback.onRelationChanged( App1.relationship_map.get( access_info, who.id ) );
|
||||
|
||||
if( callback != null )
|
||||
callback.onRelationChanged( );
|
||||
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
// アカウントを選択してからユーザをフォローする
|
||||
void followFromAnotherAccount( final SavedAccount access_info, final TootAccount who ){
|
||||
void followFromAnotherAccount( final SavedAccount access_info, final TootAccount who, final RelationChangedCallback callback ){
|
||||
AccountPicker.pick( ActMain.this, new AccountPicker.AccountPickerCallback() {
|
||||
@Override
|
||||
public void onAccountPicked( SavedAccount ai ){
|
||||
@ -1111,14 +1184,14 @@ public class ActMain extends AppCompatActivity
|
||||
if( ! acct.contains( "@" ) ){
|
||||
acct = acct + "@" + access_info.host;
|
||||
}
|
||||
callRemoteFollow( ai, acct, who.locked );
|
||||
callRemoteFollow( ai, acct, who.locked, callback );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
private void callMute( final SavedAccount account, final TootAccount who, final boolean bMute ){
|
||||
private void callMute( final SavedAccount access_info, final TootAccount who, final boolean bMute, final RelationChangedCallback callback ){
|
||||
new AsyncTask< Void, Void, TootApiResult >() {
|
||||
|
||||
@Override
|
||||
@ -1134,7 +1207,7 @@ public class ActMain extends AppCompatActivity
|
||||
|
||||
}
|
||||
} );
|
||||
client.setAccount( account );
|
||||
client.setAccount( access_info );
|
||||
|
||||
Request.Builder request_builder = new Request.Builder().post(
|
||||
RequestBody.create(
|
||||
@ -1145,24 +1218,44 @@ public class ActMain extends AppCompatActivity
|
||||
, request_builder );
|
||||
if( result != null ){
|
||||
if( result.object != null ){
|
||||
relation = TootRelationShip.parse( log, result.object );
|
||||
Utils.showToast( ActMain.this, false, bMute ? R.string.mute_succeeded : R.string.unmute_succeeded );
|
||||
if( bMute ){
|
||||
for( Column column : pager_adapter.column_list ){
|
||||
column.removeStatusByAccount( account, who.id );
|
||||
}
|
||||
showColumnMatchAccount( account );
|
||||
}
|
||||
|
||||
}else{
|
||||
Utils.showToast( ActMain.this, false, result.error );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TootRelationShip relation;
|
||||
|
||||
@Override
|
||||
protected void onCancelled( TootApiResult result ){
|
||||
onPostExecute( null );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute( TootApiResult result ){
|
||||
if( relation != null ){
|
||||
// App1.relationship_map.put( access_info, relation );
|
||||
// if( callback != null ) callback.onRelationChanged( relation );
|
||||
|
||||
if( callback != null ) callback.onRelationChanged( );
|
||||
|
||||
if( bMute ){
|
||||
for( Column column : pager_adapter.column_list ){
|
||||
column.removeStatusByAccount( access_info, who.id );
|
||||
}
|
||||
}
|
||||
showColumnMatchAccount( access_info );
|
||||
}
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void callBlock( final SavedAccount account, final TootAccount who, final boolean bBlock ){
|
||||
private void callBlock( final SavedAccount access_info, final TootAccount who, final boolean bBlock, final RelationChangedCallback callback ){
|
||||
new AsyncTask< Void, Void, TootApiResult >() {
|
||||
|
||||
@Override
|
||||
@ -1178,7 +1271,7 @@ public class ActMain extends AppCompatActivity
|
||||
|
||||
}
|
||||
} );
|
||||
client.setAccount( account );
|
||||
client.setAccount( access_info );
|
||||
|
||||
Request.Builder request_builder = new Request.Builder().post(
|
||||
RequestBody.create(
|
||||
@ -1189,13 +1282,8 @@ public class ActMain extends AppCompatActivity
|
||||
, request_builder );
|
||||
if( result != null ){
|
||||
if( result.object != null ){
|
||||
relation = TootRelationShip.parse( log, result.object );
|
||||
Utils.showToast( ActMain.this, false, bBlock ? R.string.block_succeeded : R.string.unblock_succeeded );
|
||||
if( bBlock ){
|
||||
for( Column column : pager_adapter.column_list ){
|
||||
column.removeStatusByAccount( account, who.id );
|
||||
}
|
||||
showColumnMatchAccount( account );
|
||||
}
|
||||
}else{
|
||||
Utils.showToast( ActMain.this, false, result.error );
|
||||
}
|
||||
@ -1203,6 +1291,40 @@ public class ActMain extends AppCompatActivity
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TootRelationShip relation;
|
||||
TootAccount remote_who;
|
||||
|
||||
@Override
|
||||
protected void onCancelled( TootApiResult result ){
|
||||
onPostExecute( null );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute( TootApiResult result ){
|
||||
boolean bOK = false;
|
||||
if( relation != null ){
|
||||
bOK = true;
|
||||
// App1.relationship_map.put( access_info, relation );
|
||||
// if( callback != null ) callback.onRelationChanged( relation );
|
||||
if( callback != null ) callback.onRelationChanged( );
|
||||
}else if( remote_who != null ){
|
||||
bOK = true;
|
||||
// App1.relationship_map.addFollowing( access_info, remote_who.id );
|
||||
// if( callback != null )
|
||||
// callback.onRelationChanged( App1.relationship_map.get( access_info, remote_who.id ) );
|
||||
if( callback != null )
|
||||
callback.onRelationChanged( );
|
||||
}
|
||||
if( bOK ){
|
||||
if( bBlock ){
|
||||
for( Column column : pager_adapter.column_list ){
|
||||
column.removeStatusByAccount( access_info, who.id );
|
||||
}
|
||||
}
|
||||
showColumnMatchAccount( access_info );
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
@ -1285,88 +1407,95 @@ public class ActMain extends AppCompatActivity
|
||||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
final RelationChangedCallback follow_comolete_callback = new RelationChangedCallback() {
|
||||
// @Override public void onRelationChanged( TootRelationShip relationship ){
|
||||
// Utils.showToast( ActMain.this,false,R.string.follow_succeeded );
|
||||
// }
|
||||
@Override public void onRelationChanged( ){
|
||||
Utils.showToast( ActMain.this,false,R.string.follow_succeeded );
|
||||
}
|
||||
};
|
||||
|
||||
// ステータスのmoreメニュー
|
||||
public void openStatusMoreMenu( final SavedAccount access_info, final TootStatus status ){
|
||||
|
||||
ActionsDialog dialog = new ActionsDialog();
|
||||
|
||||
|
||||
final ArrayList<SavedAccount> tmp_list = new ArrayList<>();
|
||||
for( SavedAccount a : SavedAccount.loadAccountList( log )){
|
||||
if( a.host.equalsIgnoreCase( access_info.host )){
|
||||
final ArrayList< SavedAccount > tmp_list = new ArrayList<>();
|
||||
for( SavedAccount a : SavedAccount.loadAccountList( log ) ){
|
||||
if( a.host.equalsIgnoreCase( access_info.host ) ){
|
||||
tmp_list.add( a );
|
||||
}
|
||||
}
|
||||
if( ! tmp_list.isEmpty() ){
|
||||
dialog.addAction( getString( R.string. favourite_from_another_account), new Runnable() {
|
||||
dialog.addAction( getString( R.string.favourite_from_another_account ), new Runnable() {
|
||||
@Override public void run(){
|
||||
AccountPicker.pick( ActMain.this, tmp_list, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
if(ai!= null) performFavourite( ai,status );
|
||||
if( ai != null ) performFavourite( ai, status );
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string. boost_from_another_account), new Runnable() {
|
||||
dialog.addAction( getString( R.string.boost_from_another_account ), new Runnable() {
|
||||
@Override public void run(){
|
||||
AccountPicker.pick( ActMain.this, tmp_list, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
if(ai!= null) performBoost( ai,status ,false);
|
||||
if( ai != null ) performBoost( ai, status, false );
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
dialog.addAction( getString( R.string. follow), new Runnable() {
|
||||
|
||||
dialog.addAction( getString( R.string.follow ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callFollow( access_info, status.account, true );
|
||||
callFollow( access_info, status.account, true ,null);
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
dialog.addAction( getString( R.string. follow_from_another_account), new Runnable() {
|
||||
dialog.addAction( getString( R.string.follow_from_another_account ), new Runnable() {
|
||||
@Override public void run(){
|
||||
followFromAnotherAccount( access_info, status.account );
|
||||
followFromAnotherAccount( access_info, status.account ,follow_comolete_callback);
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unfollow ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callFollow( access_info, status.account, false );
|
||||
callFollow( access_info, status.account, false,null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string. mute), new Runnable() {
|
||||
dialog.addAction( getString( R.string.mute ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callMute( access_info, status.account, true );
|
||||
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 );
|
||||
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 );
|
||||
callBlock( access_info, status.account, true ,null);
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string. unblock), new Runnable() {
|
||||
dialog.addAction( getString( R.string.unblock ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, status.account, false );
|
||||
callBlock( access_info, status.account, false ,null);
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string. report), new Runnable() {
|
||||
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() {
|
||||
dialog.addAction( getString( R.string.open_web_page ), new Runnable() {
|
||||
@Override public void run(){
|
||||
// 強制的にブラウザで開く
|
||||
openChromeTab( access_info, status.url, true );
|
||||
}
|
||||
} );
|
||||
dialog.show(this, null );
|
||||
dialog.show( this, null );
|
||||
|
||||
}
|
||||
|
||||
@ -1380,39 +1509,39 @@ public class ActMain extends AppCompatActivity
|
||||
} );
|
||||
dialog.addAction( getString( R.string.follow ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callFollow( access_info, who, true );
|
||||
callFollow( access_info, who, true ,null);
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.follow_from_another_account ), new Runnable() {
|
||||
@Override public void run(){
|
||||
followFromAnotherAccount( access_info, who );
|
||||
followFromAnotherAccount( access_info, who,follow_comolete_callback );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unfollow ), new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
callFollow( access_info, who, false );
|
||||
callFollow( access_info, who, false ,null);
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.mute ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callMute( access_info, who, true );
|
||||
callMute( access_info, who, true ,null);
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unmute ), new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
callMute( access_info, who, false );
|
||||
callMute( access_info, who, false,null );
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.block ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, who, true );
|
||||
callBlock( access_info, who, true ,null);
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.unblock ), new Runnable() {
|
||||
@Override public void run(){
|
||||
callBlock( access_info, who, false );
|
||||
callBlock( access_info, who, false ,null);
|
||||
}
|
||||
} );
|
||||
dialog.addAction( getString( R.string.report ), new Runnable() {
|
||||
@ -1422,4 +1551,14 @@ public class ActMain extends AppCompatActivity
|
||||
} );
|
||||
dialog.show( this, null );
|
||||
}
|
||||
|
||||
private void openOSSLicense(){
|
||||
startActivity( new Intent(this,ActOSSLicense.class) );
|
||||
}
|
||||
|
||||
private void openAppAbout(){
|
||||
startActivity( new Intent(this,ActAbout.class) );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
38
app/src/main/java/jp/juggler/subwaytooter/ActOSSLicense.java
Normal file
@ -0,0 +1,38 @@
|
||||
package jp.juggler.subwaytooter;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import jp.juggler.subwaytooter.util.Utils;
|
||||
|
||||
public class ActOSSLicense extends AppCompatActivity{
|
||||
@Override protected void onCreate( @Nullable Bundle savedInstanceState ){
|
||||
super.onCreate( savedInstanceState );
|
||||
setContentView( R.layout.act_oss_license);
|
||||
|
||||
try{
|
||||
InputStream is = getResources().openRawResource( R.raw.oss_license );
|
||||
try{
|
||||
ByteArrayOutputStream bao = new ByteArrayOutputStream( );
|
||||
IOUtils.copy( is,bao );
|
||||
String text = Utils.decodeUTF8(bao.toByteArray());
|
||||
TextView tv = (TextView) findViewById( R.id.tvText );
|
||||
tv.setText(text);
|
||||
}finally{
|
||||
IOUtils.closeQuietly( is );
|
||||
}
|
||||
|
||||
}catch(Throwable ex){
|
||||
ex.printStackTrace( );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -445,7 +445,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener {
|
||||
}
|
||||
String[] caption_list = new String[ tmp_account_list.size() ];
|
||||
for( int i = 0, ie = tmp_account_list.size() ; i < ie ; ++ i ){
|
||||
caption_list[ i ] = tmp_account_list.get( i ).user;
|
||||
caption_list[ i ] = tmp_account_list.get( i ).acct;
|
||||
}
|
||||
|
||||
new AlertDialog.Builder( this )
|
||||
|
@ -151,4 +151,7 @@ public class App1 extends Application {
|
||||
public static final OkHttpClient ok_http_client = new OkHttpClient();
|
||||
|
||||
public static Typeface typeface_emoji ;
|
||||
|
||||
// public static final RelationshipMap relationship_map = new RelationshipMap();
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package jp.juggler.subwaytooter;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.os.AsyncTaskCompat;
|
||||
import android.text.TextUtils;
|
||||
|
||||
@ -21,7 +22,6 @@ import jp.juggler.subwaytooter.api.TootApiClient;
|
||||
import jp.juggler.subwaytooter.api.TootApiResult;
|
||||
import jp.juggler.subwaytooter.api.entity.TootAccount;
|
||||
import jp.juggler.subwaytooter.api.entity.TootContext;
|
||||
import jp.juggler.subwaytooter.api.entity.TootId;
|
||||
import jp.juggler.subwaytooter.api.entity.TootNotification;
|
||||
import jp.juggler.subwaytooter.api.entity.TootReport;
|
||||
import jp.juggler.subwaytooter.api.entity.TootResults;
|
||||
@ -40,9 +40,29 @@ class Column {
|
||||
return params[ idx ];
|
||||
}
|
||||
|
||||
private static final String PATH_HOME = "/api/v1/timelines/home?limit=80";
|
||||
private static final String PATH_LOCAL = "/api/v1/timelines/public?limit=80&local=1";
|
||||
private static final String PATH_FEDERATE = "/api/v1/timelines/public?limit=80";
|
||||
private static final String PATH_FAVOURITES = "/api/v1/favourites?limit=80";
|
||||
private static final String PATH_REPORTS = "/api/v1/reports?limit=80";
|
||||
private static final String PATH_NOTIFICATIONS = "/api/v1/notifications?limit=80";
|
||||
|
||||
private static final String PATH_ACCOUNT = "/api/v1/accounts/%d?limit=80"; // 1:account_id
|
||||
private static final String PATH_ACCOUNT_STATUSES = "/api/v1/accounts/%d/statuses?limit=80"; // 1:account_id
|
||||
private static final String PATH_ACCOUNT_FOLLOWING = "/api/v1/accounts/%d/following?limit=80"; // 1:account_id
|
||||
private static final String PATH_ACCOUNT_FOLLOWERS = "/api/v1/accounts/%d/followers?limit=80"; // 1:account_id
|
||||
|
||||
private static final String PATH_HASHTAG = "/api/v1/timelines/tag/%s?limit=80"; // 1: hashtag(url encoded)
|
||||
|
||||
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?limit=80&q=%s"; // 1: query(urlencoded) , also, append "&resolve=1" if resolve non-local accounts
|
||||
|
||||
private static final String KEY_ACCOUNT_ROW_ID = "account_id";
|
||||
private static final String KEY_TYPE = "type";
|
||||
private static final String KEY_WHO_ID = "who_id";
|
||||
private static final String KEY_PROFILE_ID = "profile_id";
|
||||
private static final String KEY_PROFILE_TAB = "tab";
|
||||
private static final String KEY_STATUS_ID = "status_id";
|
||||
private static final String KEY_HASHTAG = "hashtag";
|
||||
private static final String KEY_SEARCH_QUERY = "search_query";
|
||||
@ -68,7 +88,12 @@ class Column {
|
||||
static final int TYPE_HASHTAG = 9;
|
||||
static final int TYPE_SEARCH = 10;
|
||||
|
||||
private long who_id;
|
||||
private long profile_id;
|
||||
volatile TootAccount who_account;
|
||||
int profile_tab = TAB_STATUS;
|
||||
static final int TAB_STATUS = 0;
|
||||
static final int TAB_FOLLOWING = 1;
|
||||
static final int TAB_FOLLOWERS = 2;
|
||||
|
||||
private long status_id;
|
||||
|
||||
@ -77,12 +102,11 @@ class Column {
|
||||
String search_query;
|
||||
boolean search_resolve;
|
||||
|
||||
int profile_tab = 0;
|
||||
|
||||
int scroll_pos;
|
||||
int scroll_y;
|
||||
|
||||
Column( ActMain activity, SavedAccount access_info, int type, Object... params ){
|
||||
Column( ActMain activity, @NonNull SavedAccount access_info, int type, Object... params ){
|
||||
this.activity = activity;
|
||||
this.access_info = access_info;
|
||||
this.type = type;
|
||||
@ -91,7 +115,7 @@ class Column {
|
||||
this.status_id = (Long) getParamAt( params, 0 );
|
||||
break;
|
||||
case TYPE_PROFILE:
|
||||
this.who_id = (Long) getParamAt( params, 0 );
|
||||
this.profile_id = (Long) getParamAt( params, 0 );
|
||||
break;
|
||||
case TYPE_HASHTAG:
|
||||
this.hashtag = (String) getParamAt( params, 0 );
|
||||
@ -113,7 +137,8 @@ class Column {
|
||||
item.put( KEY_STATUS_ID, status_id );
|
||||
break;
|
||||
case TYPE_PROFILE:
|
||||
item.put( KEY_WHO_ID, who_id );
|
||||
item.put( KEY_PROFILE_ID, profile_id );
|
||||
item.put( KEY_PROFILE_TAB, profile_tab );
|
||||
break;
|
||||
case TYPE_HASHTAG:
|
||||
item.put( KEY_HASHTAG, hashtag );
|
||||
@ -121,10 +146,11 @@ class Column {
|
||||
case TYPE_SEARCH:
|
||||
item.put( KEY_SEARCH_QUERY, search_query );
|
||||
item.put( KEY_SEARCH_RESOLVE, search_resolve );
|
||||
break;
|
||||
}
|
||||
|
||||
// 以下は保存には必要ないが、カラムリスト画面で使う
|
||||
item.put( KEY_COLUMN_ACCESS, access_info.user );
|
||||
item.put( KEY_COLUMN_ACCESS, access_info.acct );
|
||||
item.put( KEY_COLUMN_NAME, getColumnName( true ) );
|
||||
item.put( KEY_OLD_INDEX, old_index );
|
||||
}
|
||||
@ -139,7 +165,8 @@ class Column {
|
||||
this.status_id = src.optLong( KEY_STATUS_ID );
|
||||
break;
|
||||
case TYPE_PROFILE:
|
||||
this.who_id = src.optLong( KEY_WHO_ID );
|
||||
this.profile_id = src.optLong( KEY_PROFILE_ID );
|
||||
this.profile_tab = src.optInt( KEY_PROFILE_TAB );
|
||||
break;
|
||||
case TYPE_HASHTAG:
|
||||
this.hashtag = src.optString( KEY_HASHTAG );
|
||||
@ -174,7 +201,7 @@ class Column {
|
||||
|
||||
case TYPE_PROFILE:
|
||||
return activity.getString( R.string.statuses_of
|
||||
, who_account != null ? access_info.getFullAcct( who_account ) : Long.toString( who_id )
|
||||
, who_account != null ? access_info.getFullAcct( who_account ) : Long.toString( profile_id )
|
||||
);
|
||||
|
||||
case TYPE_FAVOURITES:
|
||||
@ -201,7 +228,7 @@ class Column {
|
||||
}
|
||||
|
||||
boolean isSameSpec( SavedAccount ai, int type, Object[] params ){
|
||||
if( type != this.type || ! Utils.equalsNullable( ai.user, access_info.user ) ) return false;
|
||||
if( type != this.type || ! Utils.equalsNullable( ai.acct, access_info.acct ) ) return false;
|
||||
switch( type ){
|
||||
default:
|
||||
return true;
|
||||
@ -209,7 +236,7 @@ class Column {
|
||||
case TYPE_PROFILE:
|
||||
try{
|
||||
long who_id = (Long) getParamAt( params, 0 );
|
||||
return who_id == this.who_id;
|
||||
return who_id == this.profile_id;
|
||||
}catch( Throwable ex ){
|
||||
return false;
|
||||
}
|
||||
@ -249,18 +276,26 @@ class Column {
|
||||
|
||||
// ブーストやお気に入りの更新に使う。ステータスを列挙する。
|
||||
void findStatus( SavedAccount target_account, long target_status_id, StatusEntryCallback callback ){
|
||||
if( target_account.user.equals( access_info.user ) ){
|
||||
for( int i = 0, ie = status_list.size() ; i < ie ; ++ i ){
|
||||
if( target_account.acct.equals( access_info.acct ) ){
|
||||
for( int i = 0, ie = list_data.size() ; i < ie ; ++ i ){
|
||||
Object data = list_data.get( i );
|
||||
//
|
||||
TootStatus status = status_list.get( i );
|
||||
if( target_status_id == status.id ){
|
||||
callback.onIterate( status );
|
||||
if( data instanceof TootNotification ){
|
||||
data = ( (TootNotification) data ).status;
|
||||
}
|
||||
//
|
||||
TootStatus reblog = status.reblog;
|
||||
if( reblog != null ){
|
||||
if( target_status_id == reblog.id ){
|
||||
callback.onIterate( reblog );
|
||||
if( data instanceof TootStatus ){
|
||||
//
|
||||
TootStatus status = (TootStatus) data;
|
||||
if( target_status_id == status.id ){
|
||||
callback.onIterate( status );
|
||||
}
|
||||
//
|
||||
TootStatus reblog = status.reblog;
|
||||
if( reblog != null ){
|
||||
if( target_status_id == reblog.id ){
|
||||
callback.onIterate( reblog );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -269,35 +304,33 @@ class Column {
|
||||
|
||||
// ミュート、ブロックが成功した時に呼ばれる
|
||||
void removeStatusByAccount( SavedAccount target_account, long who_id ){
|
||||
if( ! target_account.user.equals( access_info.user ) ) return;
|
||||
if( ! target_account.acct.equals( access_info.acct ) ) return;
|
||||
{
|
||||
// remove from status_list
|
||||
TootStatus.List tmp_list = new TootStatus.List( status_list.size() );
|
||||
for( TootStatus status : status_list ){
|
||||
if( status.account.id == who_id
|
||||
|| ( status.reblog != null && status.reblog.account.id == who_id )
|
||||
){
|
||||
continue;
|
||||
}
|
||||
tmp_list.add( status );
|
||||
}
|
||||
status_list.clear();
|
||||
status_list.addAll( tmp_list );
|
||||
}
|
||||
{
|
||||
// remove from notification_list
|
||||
TootNotification.List tmp_list = new TootNotification.List( notification_list.size() );
|
||||
for( TootNotification item : notification_list ){
|
||||
if( item.account.id == who_id ) continue;
|
||||
if( item.status != null ){
|
||||
if( item.status.account.id == who_id ) continue;
|
||||
if( item.status.reblog != null && item.status.reblog.account.id == who_id )
|
||||
ArrayList< Object > tmp_list = new ArrayList<>( list_data.size() );
|
||||
for( Object o : list_data ){
|
||||
if( o instanceof TootStatus ){
|
||||
TootStatus item = (TootStatus) o;
|
||||
if( item.account.id == who_id
|
||||
|| ( item.reblog != null && item.reblog.account.id == who_id )
|
||||
){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
tmp_list.add( item );
|
||||
if( o instanceof TootNotification ){
|
||||
TootNotification item = (TootNotification) o;
|
||||
if( item.account.id == who_id ) continue;
|
||||
if( item.status != null ){
|
||||
if( item.status.account.id == who_id ) continue;
|
||||
if( item.status.reblog != null && item.status.reblog.account.id == who_id )
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
tmp_list.add( o );
|
||||
}
|
||||
notification_list.clear();
|
||||
notification_list.addAll( tmp_list );
|
||||
list_data.clear();
|
||||
list_data.addAll( tmp_list );
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,36 +391,14 @@ class Column {
|
||||
|
||||
String task_progress;
|
||||
|
||||
final TootStatus.List status_list = new TootStatus.List();
|
||||
final TootNotification.List notification_list = new TootNotification.List();
|
||||
final TootReport.List report_list = new TootReport.List();
|
||||
final ArrayList< Object > result_list = new ArrayList<>();
|
||||
|
||||
volatile TootAccount who_account;
|
||||
final ArrayList< Object > list_data = new ArrayList<>();
|
||||
|
||||
|
||||
void reload(){
|
||||
status_list.clear();
|
||||
notification_list.clear();
|
||||
report_list.clear();
|
||||
result_list.clear();
|
||||
list_data.clear();
|
||||
startLoading();
|
||||
}
|
||||
|
||||
private static final String PATH_HOME = "/api/v1/timelines/home?limit=80";
|
||||
private static final String PATH_LOCAL = "/api/v1/timelines/public?limit=80&local=1";
|
||||
private static final String PATH_FEDERATE = "/api/v1/timelines/public?limit=80";
|
||||
private static final String PATH_FAVOURITES = "/api/v1/favourites?limit=80";
|
||||
private static final String PATH_REPORTS = "/api/v1/reports?limit=80";
|
||||
private static final String PATH_NOTIFICATIONS = "/api/v1/notifications?limit=80";
|
||||
private static final String PATH_PROFILE1_FORMAT = "/api/v1/accounts/%d?limit=80"; // 1:account_id
|
||||
private static final String PATH_PROFILE2_FORMAT = "/api/v1/accounts/%d/statuses?limit=80"; // 1:account_id
|
||||
private static final String PATH_HASHTAG_FORMAT = "/api/v1/timelines/tag/%s?limit=80"; // 1: tashtag(url encoded)
|
||||
|
||||
private static final String PATH_CONVERSATION1_FORMAT = "/api/v1/statuses/%d"; // 1:status_id
|
||||
private static final String PATH_CONVERSATION2_FORMAT = "/api/v1/statuses/%d/context"; // 1:status_id
|
||||
|
||||
private static final String PATH_SEARCH_FORMAT = "/api/v1/search?limit=80&q=%s"; // 1: query(urlencoded) , also, append "&resolve=1" if resolve non-local accounts
|
||||
|
||||
private void startLoading(){
|
||||
cancelLastTask();
|
||||
|
||||
@ -402,23 +413,29 @@ class Column {
|
||||
|
||||
AsyncTask< Void, Void, TootApiResult > task = this.last_task = new AsyncTask< Void, Void, TootApiResult >() {
|
||||
|
||||
TootStatus.List tmp_list_status;
|
||||
TootReport.List tmp_list_report;
|
||||
TootNotification.List tmp_list_notification;
|
||||
ArrayList< Object > tmp_list_result;
|
||||
|
||||
TootApiResult parseStatuses( TootApiResult result ){
|
||||
TootApiResult parseAccount1( TootApiResult result ){
|
||||
if( result != null ){
|
||||
saveRange( result, true, true );
|
||||
tmp_list_status = TootStatus.parseList( log, access_info, result.array );
|
||||
who_account = TootAccount.parse( log, access_info, result.object );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TootApiResult parseAccount( TootApiResult result ){
|
||||
ArrayList< Object > list_tmp;
|
||||
|
||||
TootApiResult parseStatuses( TootApiResult result ){
|
||||
if( result != null ){
|
||||
saveRange( result, true, true );
|
||||
who_account = TootAccount.parse( log, access_info, result.object );
|
||||
list_tmp = new ArrayList<>();
|
||||
list_tmp.addAll( TootStatus.parseList( log, access_info, result.array ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TootApiResult parseAccountList( TootApiResult result ){
|
||||
if( result != null ){
|
||||
saveRange( result, true, true );
|
||||
list_tmp = new ArrayList<>();
|
||||
list_tmp.addAll( TootAccount.parseList( log, access_info, result.array ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -426,7 +443,8 @@ class Column {
|
||||
TootApiResult parseReports( TootApiResult result ){
|
||||
if( result != null ){
|
||||
saveRange( result, true, true );
|
||||
tmp_list_report = TootReport.parseList( log, result.array );
|
||||
list_tmp = new ArrayList<>();
|
||||
list_tmp.addAll( TootReport.parseList( log, result.array ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -434,7 +452,8 @@ class Column {
|
||||
TootApiResult parseNotifications( TootApiResult result ){
|
||||
if( result != null ){
|
||||
saveRange( result, true, true );
|
||||
tmp_list_notification = TootNotification.parseList( log, access_info, result.array );
|
||||
list_tmp = new ArrayList<>();
|
||||
list_tmp.addAll( TootNotification.parseList( log, access_info, result.array ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -478,20 +497,31 @@ class Column {
|
||||
|
||||
case TYPE_PROFILE:
|
||||
if( who_account == null ){
|
||||
parseAccount( client.request(
|
||||
String.format( Locale.JAPAN, PATH_PROFILE1_FORMAT, who_id ) ) );
|
||||
parseAccount1( client.request(
|
||||
String.format( Locale.JAPAN, PATH_ACCOUNT, profile_id ) ) );
|
||||
client.callback.publishApiProgress( "" );
|
||||
}
|
||||
|
||||
return parseStatuses( client.request(
|
||||
String.format( Locale.JAPAN, PATH_PROFILE2_FORMAT, who_id ) ) );
|
||||
switch( profile_tab ){
|
||||
default:
|
||||
case TAB_STATUS:
|
||||
return parseStatuses( client.request(
|
||||
String.format( Locale.JAPAN, PATH_ACCOUNT_STATUSES, profile_id ) ) );
|
||||
case TAB_FOLLOWING:
|
||||
|
||||
return parseAccountList( client.request(
|
||||
String.format( Locale.JAPAN, PATH_ACCOUNT_FOLLOWING, profile_id ) ) );
|
||||
case TAB_FOLLOWERS:
|
||||
return parseAccountList( client.request(
|
||||
String.format( Locale.JAPAN, PATH_ACCOUNT_FOLLOWERS, profile_id ) ) );
|
||||
|
||||
}
|
||||
|
||||
case TYPE_FAVOURITES:
|
||||
return parseStatuses( client.request( PATH_FAVOURITES ) );
|
||||
|
||||
case TYPE_HASHTAG:
|
||||
return parseStatuses( client.request(
|
||||
String.format( Locale.JAPAN, PATH_HASHTAG_FORMAT, Uri.encode( hashtag ) ) ) );
|
||||
String.format( Locale.JAPAN, PATH_HASHTAG, Uri.encode( hashtag ) ) ) );
|
||||
|
||||
case TYPE_REPORTS:
|
||||
return parseReports( client.request( PATH_REPORTS ) );
|
||||
@ -503,28 +533,28 @@ class Column {
|
||||
|
||||
// 指定された発言そのもの
|
||||
result = client.request(
|
||||
String.format( Locale.JAPAN, PATH_CONVERSATION1_FORMAT, status_id ) );
|
||||
String.format( Locale.JAPAN, PATH_STATUSES, status_id ) );
|
||||
if( result == null || result.object == null ) return result;
|
||||
TootStatus target_status = TootStatus.parse( log, access_info, result.object );
|
||||
target_status.conversation_main = true;
|
||||
|
||||
// 前後の会話
|
||||
result = client.request(
|
||||
String.format( Locale.JAPAN, PATH_CONVERSATION2_FORMAT, status_id ) );
|
||||
String.format( Locale.JAPAN, PATH_STATUSES_CONTEXT, status_id ) );
|
||||
if( result == null || result.object == null ) return result;
|
||||
|
||||
// 一つのリストにまとめる
|
||||
TootContext context = TootContext.parse( log, access_info, result.object );
|
||||
tmp_list_status = new TootStatus.List();
|
||||
if( context.ancestors != null ) tmp_list_status.addAll( context.ancestors );
|
||||
tmp_list_status.add( target_status );
|
||||
if( context.descendants != null ) tmp_list_status.addAll( context.descendants );
|
||||
list_tmp = new ArrayList<>( 1 + context.ancestors.size() + context.descendants.size() );
|
||||
if( context.ancestors != null ) list_tmp.addAll( context.ancestors );
|
||||
list_tmp.add( target_status );
|
||||
if( context.descendants != null ) list_tmp.addAll( context.descendants );
|
||||
|
||||
//
|
||||
return result;
|
||||
|
||||
case TYPE_SEARCH:
|
||||
String path = String.format( Locale.JAPAN, PATH_SEARCH_FORMAT, Uri.encode( search_query ) );
|
||||
String path = String.format( Locale.JAPAN, PATH_SEARCH, Uri.encode( search_query ) );
|
||||
if( search_resolve ) path = path + "&resolve=1";
|
||||
|
||||
result = client.request( path );
|
||||
@ -532,10 +562,10 @@ class Column {
|
||||
|
||||
TootResults tmp = TootResults.parse( log, access_info, result.object );
|
||||
if( tmp != null ){
|
||||
tmp_list_result = new ArrayList<>();
|
||||
tmp_list_result.addAll( tmp.accounts );
|
||||
tmp_list_result.addAll( tmp.hashtags );
|
||||
tmp_list_result.addAll( tmp.statuses );
|
||||
list_tmp = new ArrayList<>();
|
||||
list_tmp.addAll( tmp.hashtags );
|
||||
list_tmp.addAll( tmp.accounts );
|
||||
list_tmp.addAll( tmp.statuses );
|
||||
}
|
||||
return result;
|
||||
|
||||
@ -560,28 +590,10 @@ class Column {
|
||||
if( result.error != null ){
|
||||
Column.this.mInitialLoadingError = result.error;
|
||||
}else{
|
||||
switch( type ){
|
||||
default:
|
||||
case TYPE_HOME:
|
||||
case TYPE_LOCAL:
|
||||
case TYPE_FEDERATE:
|
||||
case TYPE_PROFILE:
|
||||
case TYPE_FAVOURITES:
|
||||
case TYPE_CONVERSATION:
|
||||
case TYPE_HASHTAG:
|
||||
initList( status_list, tmp_list_status );
|
||||
break;
|
||||
|
||||
case TYPE_REPORTS:
|
||||
initList( report_list, tmp_list_report );
|
||||
break;
|
||||
|
||||
case TYPE_NOTIFICATIONS:
|
||||
initList( notification_list, tmp_list_notification );
|
||||
break;
|
||||
case TYPE_SEARCH:
|
||||
initList( result_list, tmp_list_result );
|
||||
|
||||
if( list_tmp != null ){
|
||||
list_data.clear();
|
||||
list_data.addAll( list_tmp );
|
||||
}
|
||||
|
||||
}
|
||||
@ -592,11 +604,11 @@ class Column {
|
||||
AsyncTaskCompat.executeParallel( task );
|
||||
}
|
||||
|
||||
static final Pattern reMaxId = Pattern.compile( "&max_id=(\\d+)" ); // より古いデータの取得に使う
|
||||
static final Pattern reSinceId = Pattern.compile( "&since_id=(\\d+)" ); // より新しいデータの取得に使う
|
||||
private static final Pattern reMaxId = Pattern.compile( "&max_id=(\\d+)" ); // より古いデータの取得に使う
|
||||
private static final Pattern reSinceId = Pattern.compile( "&since_id=(\\d+)" ); // より新しいデータの取得に使う
|
||||
|
||||
String max_id;
|
||||
String since_id;
|
||||
private String max_id;
|
||||
private String since_id;
|
||||
|
||||
private void saveRange( TootApiResult result, boolean bBottom, boolean bTop ){
|
||||
// Link: <https://mastodon.juggler.jp/api/v1/timelines/home?limit=80&max_id=405228>; rel="next",
|
||||
@ -623,7 +635,7 @@ class Column {
|
||||
}
|
||||
}
|
||||
|
||||
String addRange( boolean bBottom, String path ){
|
||||
private String addRange( boolean bBottom, String path ){
|
||||
char delm = ( - 1 != path.indexOf( '?' ) ? '&' : '?' );
|
||||
if( bBottom ){
|
||||
if( max_id != null ) return path + delm + "max_id=" + max_id;
|
||||
@ -633,34 +645,7 @@ class Column {
|
||||
return path;
|
||||
}
|
||||
|
||||
< T > void initList( ArrayList< T > dst, ArrayList< T > src ){
|
||||
if( src == null ) return;
|
||||
dst.clear();
|
||||
dst.addAll( src );
|
||||
}
|
||||
|
||||
< T extends TootId > void mergeList( ArrayList< T > dst, ArrayList< T > src, boolean bBottom ){
|
||||
// 古いリストにある要素の集合
|
||||
HashSet< Long > id_set = new HashSet();
|
||||
for( T t : dst ){
|
||||
id_set.add( t.id );
|
||||
}
|
||||
ArrayList< T > tmp_list = new ArrayList<>( src.size() );
|
||||
for( T t : src ){
|
||||
if( id_set.contains( t.id ) ) continue;
|
||||
tmp_list.add( t );
|
||||
}
|
||||
|
||||
if( ! bBottom ){
|
||||
tmp_list.addAll( dst );
|
||||
dst.clear();
|
||||
dst.addAll( tmp_list );
|
||||
}else{
|
||||
dst.addAll( tmp_list );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean startRefresh( final boolean bBottom ){
|
||||
boolean startRefresh( final boolean bBottom ){
|
||||
if( last_task != null ){
|
||||
log.d( "busy" );
|
||||
return false;
|
||||
@ -676,22 +661,29 @@ class Column {
|
||||
|
||||
AsyncTask< Void, Void, TootApiResult > task = this.last_task = new AsyncTask< Void, Void, TootApiResult >() {
|
||||
|
||||
TootStatus.List tmp_list_status;
|
||||
TootReport.List tmp_list_report;
|
||||
TootNotification.List tmp_list_notification;
|
||||
|
||||
TootApiResult parseStatuses( TootApiResult result ){
|
||||
TootApiResult parseAccount1( TootApiResult result ){
|
||||
if( result != null ){
|
||||
saveRange( result, bBottom, ! bBottom );
|
||||
tmp_list_status = TootStatus.parseList( log, access_info, result.array );
|
||||
who_account = TootAccount.parse( log, access_info, result.object );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TootApiResult parseAccount( TootApiResult result ){
|
||||
TootApiResult parseAccountList( TootApiResult result ){
|
||||
if( result != null ){
|
||||
saveRange( result, bBottom, ! bBottom );
|
||||
who_account = TootAccount.parse( log, access_info, result.object );
|
||||
list_tmp = new ArrayList<>();
|
||||
list_tmp.addAll( TootAccount.parseList( log, access_info, result.array ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ArrayList< Object > list_tmp;
|
||||
|
||||
TootApiResult parseStatuses( TootApiResult result ){
|
||||
if( result != null ){
|
||||
saveRange( result, bBottom, ! bBottom );
|
||||
list_tmp = new ArrayList<>();
|
||||
list_tmp.addAll( TootStatus.parseList( log, access_info, result.array ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -699,7 +691,8 @@ class Column {
|
||||
TootApiResult parseReports( TootApiResult result ){
|
||||
if( result != null ){
|
||||
saveRange( result, bBottom, ! bBottom );
|
||||
tmp_list_report = TootReport.parseList( log, result.array );
|
||||
list_tmp = new ArrayList<>();
|
||||
list_tmp.addAll( TootReport.parseList( log, result.array ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -707,7 +700,8 @@ class Column {
|
||||
TootApiResult parseNotifications( TootApiResult result ){
|
||||
if( result != null ){
|
||||
saveRange( result, bBottom, ! bBottom );
|
||||
tmp_list_notification = TootNotification.parseList( log, access_info, result.array );
|
||||
list_tmp = new ArrayList<>();
|
||||
list_tmp.addAll( TootNotification.parseList( log, access_info, result.array ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -757,18 +751,30 @@ class Column {
|
||||
|
||||
case TYPE_PROFILE:
|
||||
if( who_account == null ){
|
||||
parseAccount( client.request(
|
||||
String.format( Locale.JAPAN, PATH_PROFILE1_FORMAT, who_id ) ) );
|
||||
parseAccount1( client.request(
|
||||
String.format( Locale.JAPAN, PATH_ACCOUNT, profile_id ) ) );
|
||||
|
||||
client.callback.publishApiProgress( "" );
|
||||
}
|
||||
switch( profile_tab ){
|
||||
default:
|
||||
case TAB_STATUS:
|
||||
return parseStatuses( client.request(addRange( bBottom,
|
||||
String.format( Locale.JAPAN, PATH_ACCOUNT_STATUSES, profile_id ) ) ));
|
||||
case TAB_FOLLOWING:
|
||||
|
||||
return parseAccountList( client.request(addRange( bBottom,
|
||||
String.format( Locale.JAPAN, PATH_ACCOUNT_FOLLOWING, profile_id ) ) ));
|
||||
case TAB_FOLLOWERS:
|
||||
return parseAccountList( client.request(addRange( bBottom,
|
||||
String.format( Locale.JAPAN, PATH_ACCOUNT_FOLLOWERS, profile_id ) ) ));
|
||||
|
||||
}
|
||||
|
||||
return parseStatuses( client.request( addRange( bBottom,
|
||||
String.format( Locale.JAPAN, PATH_PROFILE2_FORMAT, who_id ) ) ) );
|
||||
|
||||
case TYPE_HASHTAG:
|
||||
return parseStatuses( client.request( addRange( bBottom,
|
||||
String.format( Locale.JAPAN, PATH_HASHTAG_FORMAT, Uri.encode( hashtag ) ) ) ) );
|
||||
String.format( Locale.JAPAN, PATH_HASHTAG, Uri.encode( hashtag ) ) ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -789,27 +795,51 @@ class Column {
|
||||
if( result.error != null ){
|
||||
Column.this.mRefreshLoadingError = result.error;
|
||||
}else{
|
||||
switch( type ){
|
||||
default:
|
||||
case TYPE_HOME:
|
||||
case TYPE_LOCAL:
|
||||
case TYPE_FEDERATE:
|
||||
case TYPE_PROFILE:
|
||||
case TYPE_FAVOURITES:
|
||||
case TYPE_HASHTAG:
|
||||
mergeList( status_list, tmp_list_status, bBottom );
|
||||
break;
|
||||
|
||||
case TYPE_REPORTS:
|
||||
mergeList( report_list, tmp_list_report, bBottom );
|
||||
break;
|
||||
|
||||
case TYPE_NOTIFICATIONS:
|
||||
mergeList( notification_list, tmp_list_notification, bBottom );
|
||||
break;
|
||||
if( list_tmp != null ){
|
||||
// 古いリストにある要素のIDの集合集合
|
||||
HashSet< Long > set_status_id = new HashSet<>();
|
||||
HashSet< Long > set_notification_id = new HashSet<>();
|
||||
HashSet< Long > set_report_id = new HashSet<>();
|
||||
HashSet< Long > set_account_id = new HashSet<>();
|
||||
for( Object o : list_data ){
|
||||
if( o instanceof TootStatus ){
|
||||
set_status_id.add( ( (TootStatus) o ).id );
|
||||
}else if( o instanceof TootNotification ){
|
||||
set_notification_id.add( ( (TootNotification) o ).id );
|
||||
}else if( o instanceof TootReport ){
|
||||
set_report_id.add( ( (TootReport) o ).id );
|
||||
}else if( o instanceof TootAccount ){
|
||||
set_account_id.add( ( (TootAccount) o ).id );
|
||||
}
|
||||
}
|
||||
ArrayList< Object > list_new = new ArrayList<>();
|
||||
for( Object o : list_tmp ){
|
||||
if( o instanceof TootStatus ){
|
||||
if( set_status_id.contains( ( (TootStatus) o ).id ) ) continue;
|
||||
}else if( o instanceof TootNotification ){
|
||||
if( set_notification_id.contains( ( (TootNotification) o ).id ) )
|
||||
continue;
|
||||
}else if( o instanceof TootReport ){
|
||||
if( set_report_id.contains( ( (TootReport) o ).id ) ) continue;
|
||||
}else if( o instanceof TootAccount ){
|
||||
if( set_account_id.contains( ( (TootAccount) o ).id ) ) continue;
|
||||
}
|
||||
list_new.add( o );
|
||||
}
|
||||
|
||||
if( ! bBottom ){
|
||||
// 新しいデータの後に今のデータが並ぶ
|
||||
list_new.addAll( list_data );
|
||||
list_data.clear();
|
||||
list_data.addAll( list_new );
|
||||
}else{
|
||||
// 今のデータの後にさらに古いデータが続く
|
||||
list_data.addAll( list_new );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fireVisualCallback();
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
package jp.juggler.subwaytooter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
@ -32,6 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import jp.juggler.subwaytooter.api.entity.TootAccount;
|
||||
import jp.juggler.subwaytooter.api.entity.TootAttachment;
|
||||
import jp.juggler.subwaytooter.api.entity.TootNotification;
|
||||
import jp.juggler.subwaytooter.api.entity.TootRelationShip;
|
||||
import jp.juggler.subwaytooter.api.entity.TootStatus;
|
||||
import jp.juggler.subwaytooter.table.ContentWarning;
|
||||
import jp.juggler.subwaytooter.table.MediaShown;
|
||||
@ -174,8 +177,16 @@ public class ColumnViewHolder implements View.OnClickListener, Column.VisualCall
|
||||
tvLoading.setText( message );
|
||||
}
|
||||
|
||||
|
||||
// final RelationshipMap.UpdateCallback callback_relation = new RelationshipMap.UpdateCallback() {
|
||||
// @Override public void onRelationShipUpdate(){
|
||||
// onVisualColumn();
|
||||
// }
|
||||
// };
|
||||
|
||||
@Override
|
||||
public void onVisualColumn(){
|
||||
// App1.relationship_map.checkUpdate( activity, column.access_info,callback_relation );
|
||||
|
||||
tvColumnContext.setText( column.access_info.getFullAcct( column.access_info ) );
|
||||
tvColumnName.setText( column.getColumnName( false ) );
|
||||
@ -209,51 +220,12 @@ public class ColumnViewHolder implements View.OnClickListener, Column.VisualCall
|
||||
}
|
||||
}
|
||||
|
||||
switch( column.type ){
|
||||
default:
|
||||
case Column.TYPE_HOME:
|
||||
case Column.TYPE_LOCAL:
|
||||
case Column.TYPE_FEDERATE:
|
||||
case Column.TYPE_FAVOURITES:
|
||||
case Column.TYPE_PROFILE:
|
||||
if( column.status_list.isEmpty() && vh_header == null ){
|
||||
showError( activity.getString( R.string.list_empty ) );
|
||||
}else{
|
||||
tvLoading.setVisibility( View.GONE );
|
||||
swipyRefreshLayout.setVisibility( View.VISIBLE );
|
||||
status_adapter.set( column.status_list );
|
||||
}
|
||||
break;
|
||||
|
||||
case Column.TYPE_REPORTS:
|
||||
if( column.report_list.isEmpty() ){
|
||||
showError( activity.getString( R.string.list_empty ) );
|
||||
}else{
|
||||
tvLoading.setVisibility( View.GONE );
|
||||
swipyRefreshLayout.setVisibility( View.VISIBLE );
|
||||
status_adapter.set( column.report_list );
|
||||
}
|
||||
break;
|
||||
|
||||
case Column.TYPE_NOTIFICATIONS:
|
||||
if( column.notification_list.isEmpty() ){
|
||||
showError( activity.getString( R.string.list_empty ) );
|
||||
}else{
|
||||
tvLoading.setVisibility( View.GONE );
|
||||
swipyRefreshLayout.setVisibility( View.VISIBLE );
|
||||
status_adapter.set( column.notification_list );
|
||||
}
|
||||
break;
|
||||
|
||||
case Column.TYPE_SEARCH:
|
||||
if( column.result_list.isEmpty() ){
|
||||
showError( activity.getString( R.string.list_empty ) );
|
||||
}else{
|
||||
tvLoading.setVisibility( View.GONE );
|
||||
swipyRefreshLayout.setVisibility( View.VISIBLE );
|
||||
status_adapter.set( column.result_list );
|
||||
}
|
||||
break;
|
||||
if( column. list_data.isEmpty() && vh_header == null ){
|
||||
showError( activity.getString( R.string.list_empty ) );
|
||||
}else{
|
||||
tvLoading.setVisibility( View.GONE );
|
||||
swipyRefreshLayout.setVisibility( View.VISIBLE );
|
||||
status_adapter.set( column.list_data );
|
||||
}
|
||||
|
||||
proc_restore_scroll.run();
|
||||
@ -376,21 +348,29 @@ public class ColumnViewHolder implements View.OnClickListener, Column.VisualCall
|
||||
@Override
|
||||
public void onClick( View v ){
|
||||
switch( v.getId() ){
|
||||
|
||||
case R.id.ivBackground:
|
||||
if( who != null ){
|
||||
// 強制的にブラウザで開く
|
||||
activity.openChromeTab( access_info, who.url, true );
|
||||
}
|
||||
break;
|
||||
|
||||
case R.id.btnFollowing:
|
||||
Utils.showToast( activity, false, "not implemented" );
|
||||
column.profile_tab = Column.TAB_FOLLOWING;
|
||||
column.reload();
|
||||
break;
|
||||
|
||||
case R.id.btnFollowers:
|
||||
Utils.showToast( activity, false, "not implemented" );
|
||||
column.profile_tab = Column.TAB_FOLLOWERS;
|
||||
column.reload();
|
||||
break;
|
||||
|
||||
case R.id.btnStatusCount:
|
||||
Utils.showToast( activity, false, "not implemented" );
|
||||
column.profile_tab = Column.TAB_STATUS;
|
||||
column.reload();
|
||||
break;
|
||||
|
||||
case R.id.btnMore:
|
||||
activity.openAccountMoreMenu( access_info, who );
|
||||
break;
|
||||
@ -663,6 +643,9 @@ public class ColumnViewHolder implements View.OnClickListener, Column.VisualCall
|
||||
ivFollow.setImageUrl( who.avatar_static, App1.getImageLoader() );
|
||||
tvFollowerName.setText( who.display_name );
|
||||
tvFollowerAcct.setText( access_info.getFullAcct( who ) );
|
||||
|
||||
btnFollow.setImageResource( R.drawable.btn_follow );
|
||||
|
||||
}
|
||||
|
||||
private void showStatus( ActMain activity, View view, TootStatus status, SavedAccount account ){
|
||||
@ -829,9 +812,11 @@ public class ColumnViewHolder implements View.OnClickListener, Column.VisualCall
|
||||
break;
|
||||
case R.id.btnFollow:
|
||||
activity.openAccountMoreMenu( access_info, account_follow );
|
||||
break;
|
||||
|
||||
case R.id.btnSearchTag:
|
||||
activity.openHashTag( access_info,search_tag );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
109
app/src/main/java/jp/juggler/subwaytooter/RelationshipMap.java
Normal file
@ -0,0 +1,109 @@
|
||||
//package jp.juggler.subwaytooter;
|
||||
//
|
||||
//import android.os.AsyncTask;
|
||||
//import android.os.SystemClock;
|
||||
//import android.support.annotation.NonNull;
|
||||
//
|
||||
//import java.util.HashMap;
|
||||
//
|
||||
//import jp.juggler.subwaytooter.api.TootApiClient;
|
||||
//import jp.juggler.subwaytooter.api.TootApiResult;
|
||||
//import jp.juggler.subwaytooter.api.entity.TootRelationShip;
|
||||
//import jp.juggler.subwaytooter.table.SavedAccount;
|
||||
//import jp.juggler.subwaytooter.util.LogCategory;
|
||||
//
|
||||
//class RelationshipMap {
|
||||
//
|
||||
// private static final LogCategory log = new LogCategory( "RelationshipMap" );
|
||||
//
|
||||
//
|
||||
// interface UpdateCallback {
|
||||
// void onRelationShipUpdate();
|
||||
// }
|
||||
//
|
||||
// private static class RelationshipPerAccount extends HashMap< Long, TootRelationShip > {
|
||||
// long last_update;
|
||||
// }
|
||||
//
|
||||
// private final HashMap< String, RelationshipPerAccount > map_account = new HashMap<>();
|
||||
//
|
||||
// @NonNull
|
||||
// private RelationshipPerAccount getRelationshipPerAccount( @NonNull SavedAccount access_info ){
|
||||
// RelationshipPerAccount ra;
|
||||
// ra = map_account.get( access_info.acct );
|
||||
// if( ra == null ){
|
||||
// ra = new RelationshipPerAccount();
|
||||
// map_account.put( access_info.acct, ra );
|
||||
// }
|
||||
// return ra;
|
||||
// }
|
||||
//
|
||||
// public TootRelationShip get( @NonNull SavedAccount access_info, long id ){
|
||||
// return getRelationshipPerAccount( access_info ).get( id );
|
||||
// }
|
||||
//
|
||||
// public void put( @NonNull SavedAccount access_info, @NonNull TootRelationShip relation ){
|
||||
// getRelationshipPerAccount( access_info ).put( relation.id,relation );
|
||||
// }
|
||||
//
|
||||
// public void addFollowing( SavedAccount access_info, long id ){
|
||||
// RelationshipPerAccount ra = getRelationshipPerAccount( access_info );
|
||||
// TootRelationShip rs = ra.get( id);
|
||||
// if(rs == null ){
|
||||
// rs = new TootRelationShip();
|
||||
// ra.put( id, rs );
|
||||
// }
|
||||
// rs.following = true;
|
||||
// }
|
||||
//
|
||||
// void checkUpdate( @NonNull final ActMain activity, @NonNull final SavedAccount access_info, final UpdateCallback callback ){
|
||||
// final RelationshipPerAccount ra = getRelationshipPerAccount( access_info );
|
||||
// long now = SystemClock.elapsedRealtime();
|
||||
// if( now - ra.last_update < 300000L ) return;
|
||||
// ra.last_update = now;
|
||||
//
|
||||
// new AsyncTask< Void, Void, TootApiResult >() {
|
||||
//
|
||||
// TootRelationShip.List list;
|
||||
//
|
||||
// @Override protected TootApiResult doInBackground( Void... params ){
|
||||
//
|
||||
// TootApiClient client = new TootApiClient( activity, new TootApiClient.Callback() {
|
||||
// @Override public boolean isApiCancelled(){
|
||||
// return isCancelled();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void publishApiProgress( final String s ){
|
||||
// }
|
||||
// } );
|
||||
//
|
||||
// client.setAccount( access_info );
|
||||
// TootApiResult result = client.request( "/api/v1/accounts/relationships" );
|
||||
// if( result != null && result.array != null ){
|
||||
// list = TootRelationShip.parseList( log, result.array );
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onCancelled( TootApiResult result ){
|
||||
// onPostExecute( null );
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onPostExecute( TootApiResult result ){
|
||||
//
|
||||
// if( isCancelled() || result == null ){
|
||||
// return;
|
||||
// }
|
||||
// if( list != null ){
|
||||
// for( TootRelationShip item : list ){
|
||||
// ra.put( item.id, item );
|
||||
// }
|
||||
// callback.onRelationShipUpdate();
|
||||
// }
|
||||
// }
|
||||
// }.execute();
|
||||
// }
|
||||
//}
|
@ -1,7 +1,10 @@
|
||||
package jp.juggler.subwaytooter.api.entity;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import jp.juggler.subwaytooter.util.LogCategory;
|
||||
|
||||
public class TootRelationShip {
|
||||
@ -42,4 +45,27 @@ public class TootRelationShip {
|
||||
}
|
||||
}
|
||||
|
||||
public static class List extends ArrayList< TootRelationShip > {
|
||||
public List(){
|
||||
super();
|
||||
}
|
||||
|
||||
public List( int capacity ){
|
||||
super( capacity );
|
||||
}
|
||||
}
|
||||
|
||||
public static List parseList( LogCategory log, JSONArray array ){
|
||||
List result = new List();
|
||||
if( array != null ){
|
||||
for( int i = array.length() - 1 ; i >= 0 ; -- i ){
|
||||
JSONObject src = array.optJSONObject( i );
|
||||
if( src == null ) continue;
|
||||
TootRelationShip item = parse( log, src );
|
||||
if( item != null ) result.add( 0, item );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class AccountPicker {
|
||||
Collections.sort( account_list, new Comparator< SavedAccount >() {
|
||||
@Override
|
||||
public int compare( SavedAccount o1, SavedAccount o2 ){
|
||||
return String.CASE_INSENSITIVE_ORDER.compare( o1.user, o2.user );
|
||||
return String.CASE_INSENSITIVE_ORDER.compare( o1.acct, o2.acct );
|
||||
}
|
||||
} );
|
||||
|
||||
@ -46,7 +46,7 @@ public class AccountPicker {
|
||||
|
||||
for(int i=0,ie=account_list.size();i<ie;++i){
|
||||
SavedAccount ai = account_list.get(i);
|
||||
caption_list[i] = ai.user;
|
||||
caption_list[i] = ai.acct;
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(activity)
|
||||
|
@ -35,7 +35,7 @@ public class SavedAccount extends TootAccount implements LinkClickContext{
|
||||
// login information
|
||||
public long db_id = INVALID_ID;
|
||||
public String host;
|
||||
public String user;
|
||||
public String acct; // user@host
|
||||
public JSONObject token_info;
|
||||
public String visibility;
|
||||
public boolean confirm_boost;
|
||||
@ -73,7 +73,7 @@ public class SavedAccount extends TootAccount implements LinkClickContext{
|
||||
if( dst != null){
|
||||
dst.db_id = cursor.getLong( cursor.getColumnIndex( COL_ID ) );
|
||||
dst.host = cursor.getString( cursor.getColumnIndex( COL_HOST ) );
|
||||
dst.user = cursor.getString( cursor.getColumnIndex( COL_USER ) );
|
||||
dst.acct = cursor.getString( cursor.getColumnIndex( COL_USER ) );
|
||||
|
||||
int colIdx_visibility = cursor.getColumnIndex( COL_VISIBILITY );
|
||||
dst.visibility = cursor.isNull( colIdx_visibility )? null : cursor.getString( colIdx_visibility );
|
||||
@ -87,11 +87,11 @@ public class SavedAccount extends TootAccount implements LinkClickContext{
|
||||
}
|
||||
|
||||
|
||||
public static long insert( String host, String user, JSONObject account,JSONObject token ){
|
||||
public static long insert( String host, String acct, JSONObject account,JSONObject token ){
|
||||
try{
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put( COL_HOST, host );
|
||||
cv.put( COL_USER, user );
|
||||
cv.put( COL_USER, acct );
|
||||
cv.put( COL_ACCOUNT, account.toString() );
|
||||
cv.put( COL_TOKEN, token.toString() );
|
||||
return App1.getDB().insert( table, null, cv );
|
||||
|
BIN
app/src/main/res/drawable-hdpi/ic_action_name.png
Normal file
After Width: | Height: | Size: 971 B |
BIN
app/src/main/res/drawable-hdpi/ic_blocked.png
Normal file
After Width: | Height: | Size: 971 B |
BIN
app/src/main/res/drawable-hdpi/ic_follow_requested.png
Normal file
After Width: | Height: | Size: 357 B |
BIN
app/src/main/res/drawable-hdpi/ic_info.png
Normal file
After Width: | Height: | Size: 708 B |
BIN
app/src/main/res/drawable-hdpi/ic_muted.png
Normal file
After Width: | Height: | Size: 762 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_name.png
Normal file
After Width: | Height: | Size: 604 B |
BIN
app/src/main/res/drawable-mdpi/ic_blocked.png
Normal file
After Width: | Height: | Size: 604 B |
BIN
app/src/main/res/drawable-mdpi/ic_follow_requested.png
Normal file
After Width: | Height: | Size: 264 B |
BIN
app/src/main/res/drawable-mdpi/ic_info.png
Normal file
After Width: | Height: | Size: 463 B |
BIN
app/src/main/res/drawable-mdpi/ic_muted.png
Normal file
After Width: | Height: | Size: 470 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_name.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_blocked.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_follow_requested.png
Normal file
After Width: | Height: | Size: 394 B |
BIN
app/src/main/res/drawable-xhdpi/ic_info.png
Normal file
After Width: | Height: | Size: 868 B |
BIN
app/src/main/res/drawable-xhdpi/ic_muted.png
Normal file
After Width: | Height: | Size: 870 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_name.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_blocked.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_follow_requested.png
Normal file
After Width: | Height: | Size: 647 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_info.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_muted.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
99
app/src/main/res/layout/act_about.xml
Normal file
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:fillViewport="true"
|
||||
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingEnd="@dimen/activity_horizontal_margin"
|
||||
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingStart="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="32sp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvVersion"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="version 0.0.0"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="0.2"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/please_rate"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnRate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/btn_bg_transparent"
|
||||
android:padding="8dp"
|
||||
android:text="@string/rate_on_store"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="0.2"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/please_donate"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnDonate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/btn_bg_transparent"
|
||||
android:padding="8dp"
|
||||
tools:text="enty...."
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
18
app/src/main/res/layout/act_oss_license.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:fillViewport="true"
|
||||
android:padding="12dp"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/tvText"
|
||||
>
|
||||
|
||||
</TextView>
|
||||
</ScrollView>
|
@ -79,6 +79,16 @@
|
||||
android:id="@+id/nav_app_setting"
|
||||
android:icon="@drawable/ic_setting"
|
||||
android:title="@string/app_setting"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_app_about"
|
||||
android:icon="@drawable/ic_info"
|
||||
android:title="@string/app_about"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_oss_license"
|
||||
android:icon="@drawable/ic_info"
|
||||
android:title="@string/oss_license"/>
|
||||
</menu>
|
||||
</item>
|
||||
</group>
|
||||
|
119
app/src/main/res/raw/oss_license.txt
Normal file
@ -0,0 +1,119 @@
|
||||
====================================================
|
||||
Ranks/emojione
|
||||
https://github.com/Ranks/emojione
|
||||
|
||||
EmojiOne Artwork
|
||||
- Applies to all PNG files found in the emojione-assets repo as well as any adaptations made.
|
||||
- Free license: emojione.com/developers/free-license
|
||||
- Premium license: emojione.com/developers/premium-license
|
||||
|
||||
EmojiOne Non-Artwork
|
||||
- Applies to the Javascript, JSON, PHP, CSS, HTML files, and everything else not covered under the artwork license above, found in both the emojione and emojione-assets repos.
|
||||
- License: MIT
|
||||
- Complete Legal Terms: http://opensource.org/licenses/MIT
|
||||
|
||||
====================================================
|
||||
google/volley
|
||||
https://github.com/google/volley
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
====================================================
|
||||
square/okhttp
|
||||
https://github.com/square/okhttp
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
====================================================
|
||||
Commons IO
|
||||
https://commons.apache.org/proper/commons-io/
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
====================================================
|
||||
chrisjenx/Calligraphy
|
||||
https://github.com/chrisjenx/Calligraphy
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
====================================================
|
||||
woxblom/DragListView
|
||||
https://github.com/woxblom/DragListView
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
====================================================
|
||||
omadahealth/SwipyRefreshLayout
|
||||
https://github.com/omadahealth/SwipyRefreshLayout
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 OrangeGangsters
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -138,4 +138,10 @@
|
||||
<string name="follow_from_another_account">別のアカウントでフォロー</string>
|
||||
<string name="favourite_from_another_account">別のアカウントでお気に入り</string>
|
||||
<string name="boost_from_another_account">別のアカウントでブースト</string>
|
||||
<string name="app_about">このアプリについて</string>
|
||||
<string name="please_rate">ストアで評価やレビューをお願いします!</string>
|
||||
<string name="rate_on_store">ストアで評価</string>
|
||||
<string name="please_donate">開発継続のために寄付をお願いします!</string>
|
||||
<string name="version_is">バージョン %1$s</string>
|
||||
<string name="oss_license">OSSライセンス</string>
|
||||
</resources>
|
||||
|
@ -137,4 +137,10 @@
|
||||
<string name="confirm_close_column">close thic colum?</string>
|
||||
<string name="favourite_from_another_account">favourite from another account</string>
|
||||
<string name="boost_from_another_account">boost from another account</string>
|
||||
<string name="app_about">about this app</string>
|
||||
<string name="oss_license">OSS license</string>
|
||||
<string name="please_rate">Please rating and write review!</string>
|
||||
<string name="rate_on_store">rate on store</string>
|
||||
<string name="please_donate">Please support this app!</string>
|
||||
<string name="version_is">version %1$s</string>
|
||||
</resources>
|
||||
|