1
0
mirror of https://github.com/tateisu/SubwayTooter synced 2025-01-27 09:11:23 +01:00

カラム設定で添付データありの発言だけ閲覧。取得漏れの可能性がある場所に隙間を表示。ブロックしたユーザ、ミュートしたユーザのリスト

This commit is contained in:
tateisu 2017-04-27 01:36:28 +09:00
parent 6d24d0d7ed
commit 454e93b842
35 changed files with 1142 additions and 259 deletions

View File

@ -7,6 +7,7 @@
<w>enty</w>
<w>favourited</w>
<w>hashtag</w>
<w>hashtags</w>
<w>noto</w>
<w>nsfw</w>
<w>reblog</w>

View File

@ -9,8 +9,8 @@ android {
applicationId "jp.juggler.subwaytooter"
minSdkVersion 21
targetSdkVersion 25
versionCode 14
versionName "0.1.4"
versionCode 15
versionName "0.1.5"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

View File

@ -69,12 +69,17 @@ public class ActMain extends AppCompatActivity
// super.attachBaseContext( CalligraphyContextWrapper.wrap(newBase));
// }
float density;
SharedPreferences pref;
@Override
protected void onCreate( Bundle savedInstanceState ){
super.onCreate( savedInstanceState );
this.density = getResources().getDisplayMetrics().density;
requestWindowFeature( Window.FEATURE_NO_TITLE );
pref = Pref.pref( this );
@ -297,6 +302,13 @@ public class ActMain extends AppCompatActivity
}else if( id == R.id.nav_app_exit ){
finish();
}else if( id == R.id.nav_add_mutes ){
performAddTimeline( Column.TYPE_MUTES );
}else if( id == R.id.nav_add_blocks ){
performAddTimeline( Column.TYPE_BLOCKS );
// Handle the camera action
// }else if( id == R.id.nav_gallery ){
//
@ -1206,7 +1218,7 @@ public class ActMain extends AppCompatActivity
static final String FILE_COLUMN_LIST = "column_list";
private void saveColumnList(){
void saveColumnList(){
JSONArray array = encodeColumnList();
try{
OutputStream os = openFileOutput( FILE_COLUMN_LIST, MODE_PRIVATE );
@ -1495,6 +1507,11 @@ public class ActMain extends AppCompatActivity
for( Column column : pager_adapter.column_list ){
column.removeStatusByAccount( access_info, who.id );
}
}else{
for( Column column : pager_adapter.column_list ){
column.removeFromMuteList( access_info, who.id );
}
}
showColumnMatchAccount( access_info );
}
@ -1569,6 +1586,10 @@ public class ActMain extends AppCompatActivity
for( Column column : pager_adapter.column_list ){
column.removeStatusByAccount( access_info, who.id );
}
}else{
for( Column column : pager_adapter.column_list ){
column.removeFromBlockList( access_info, who.id );
}
}
showColumnMatchAccount( access_info );
}

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
@ -30,6 +31,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.TootGap;
import jp.juggler.subwaytooter.api.entity.TootNotification;
import jp.juggler.subwaytooter.api.entity.TootStatus;
import jp.juggler.subwaytooter.table.ContentWarning;
@ -39,7 +41,7 @@ import jp.juggler.subwaytooter.util.Emojione;
import jp.juggler.subwaytooter.util.LogCategory;
import jp.juggler.subwaytooter.util.Utils;
class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, SwipyRefreshLayout.OnRefreshListener {
class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, SwipyRefreshLayout.OnRefreshListener, CompoundButton.OnCheckedChangeListener {
private static final LogCategory log = new LogCategory( "ColumnViewHolder" );
public final ActMain activity;
@ -72,10 +74,14 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
private View btnSearch;
private EditText etSearch;
private CheckBox cbResolve;
private View llColumnSetting;
void onPageCreate( View root, int page_idx, int page_count ){
log.d( "onPageCreate:%s", column.getColumnName( true ) );
( (TextView) root.findViewById( R.id.tvColumnIndex ) )
.setText( activity.getString( R.string.column_index, page_idx + 1, page_count ) );
@ -86,7 +92,6 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
root.findViewById( R.id.btnColumnReload ).setOnClickListener( this );
root.findViewById( R.id.llColumnHeader ).setOnClickListener( this );
tvLoading = (TextView) root.findViewById( R.id.tvLoading );
listView = (ListView) root.findViewById( R.id.listView );
status_adapter = new StatusListAdapter();
@ -94,14 +99,42 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
this.swipyRefreshLayout = (SwipyRefreshLayout) root.findViewById( R.id.swipyRefreshLayout );
swipyRefreshLayout.setOnRefreshListener( this );
swipyRefreshLayout.setDistanceToTriggerSync( (int) ( 0.5f + 20 * activity.getResources().getDisplayMetrics().density ) );
swipyRefreshLayout.setDistanceToTriggerSync( (int) ( 0.5f + 20f * activity.density ) );
View llSearch = root.findViewById( R.id.llSearch );
btnSearch = root.findViewById( R.id.btnSearch );
etSearch = (EditText) root.findViewById( R.id.etSearch );
cbResolve = (CheckBox) root.findViewById( R.id.cbResolve );
listView.setFastScrollEnabled( !Pref.pref(activity).getBoolean( Pref.KEY_DISABLE_FAST_SCROLLER,false) );
listView.setFastScrollEnabled( ! Pref.pref( activity ).getBoolean( Pref.KEY_DISABLE_FAST_SCROLLER, false ) );
boolean bAllowColumnSetting;
switch( column.type ){
default:
bAllowColumnSetting = true;
break;
case Column.TYPE_SEARCH:
case Column.TYPE_CONVERSATION:
case Column.TYPE_REPORTS:
case Column.TYPE_BLOCKS:
case Column.TYPE_MUTES:
case Column.TYPE_NOTIFICATIONS:
bAllowColumnSetting = false;
break;
}
View btnColumnSetting = root.findViewById( R.id.btnColumnSetting );
llColumnSetting = root.findViewById( R.id.llColumnSetting );
if( ! bAllowColumnSetting ){
btnColumnSetting.setVisibility( View.GONE );
llColumnSetting.setVisibility( View.GONE );
}else{
btnColumnSetting.setVisibility( View.VISIBLE );
btnColumnSetting.setOnClickListener( this );
llColumnSetting.setVisibility( View.GONE );
CheckBox cbWithAttachment = (CheckBox) root.findViewById( R.id.cbWithAttachment );
cbWithAttachment.setChecked( column.with_attachment );
cbWithAttachment.setOnCheckedChangeListener( this );
}
if( column.type != Column.TYPE_SEARCH ){
llSearch.setVisibility( View.GONE );
@ -138,7 +171,16 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
onVisualColumn();
}
@Override public void onCheckedChanged( CompoundButton view, boolean isChecked ){
switch( view.getId() ){
case R.id.cbWithAttachment:
column.with_attachment = isChecked;
activity.saveColumnList();
column.reload();
break;
}
}
@Override
public void onClick( View v ){
switch( v.getId() ){
@ -163,7 +205,11 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
break;
case R.id.llColumnHeader:
if( status_adapter.getCount() > 0 ) listView.setSelectionFromTop( 0,0);
if( status_adapter.getCount() > 0 ) listView.setSelectionFromTop( 0, 0 );
break;
case R.id.btnColumnSetting:
llColumnSetting.setVisibility( llColumnSetting.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE );
break;
}
@ -177,16 +223,15 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
private void showError( String message ){
tvLoading.setVisibility( View.VISIBLE );
tvLoading.setText( message );
swipyRefreshLayout.setVisibility( View.GONE );
// ロード完了後に先頭から表示させる
if( status_adapter.getCount() > 0 ){
listView.setSelectionFromTop( 0,0 );
listView.setSelectionFromTop( 0, 0 );
}
}
// final RelationshipMap.UpdateCallback callback_relation = new RelationshipMap.UpdateCallback() {
// @Override public void onRelationShipUpdate(){
// onVisualColumn();
@ -229,28 +274,32 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
}
}
if( column. list_data.isEmpty() && vh_header == null ){
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 );
if( column.scroll_hack > 0 ){
listView.setSelectionFromTop( column.scroll_hack-1,-(int)(0.5f + 80f * activity.density ));
column.scroll_hack = 0;
}
}
proc_restore_scroll.run();
}
@Override
public void onRefresh( SwipyRefreshLayoutDirection direction ){
if( ! column.startRefresh( direction == SwipyRefreshLayoutDirection.BOTTOM ) ){
@Override public void onRefresh( SwipyRefreshLayoutDirection direction ){
String error = column.startRefresh( direction == SwipyRefreshLayoutDirection.BOTTOM );
if( ! TextUtils.isEmpty( error ) ){
swipyRefreshLayout.setRefreshing( false );
Utils.showToast( activity, true, error );
}
}
private final Runnable proc_restore_scroll = new Runnable() {
@Override
public void run(){
@Override public void run(){
if( column.scroll_pos == 0 && column.scroll_y == 0 ){
return;
}
@ -357,29 +406,29 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
@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:
column.profile_tab = Column.TAB_FOLLOWING;
column.reload();
break;
case R.id.btnFollowers:
column.profile_tab = Column.TAB_FOLLOWERS;
column.reload();
break;
case R.id.btnStatusCount:
column.profile_tab = Column.TAB_STATUS;
column.reload();
break;
case R.id.btnMore:
activity.openAccountMoreMenu( access_info, who );
break;
@ -483,6 +532,8 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
View llSearchTag;
Button btnSearchTag;
TootGap gap;
StatusViewHolder( View view ){
this.llBoosted = view.findViewById( R.id.llBoosted );
@ -490,7 +541,7 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
this.tvBoosted = (TextView) view.findViewById( R.id.tvBoosted );
this.tvBoostedTime = (TextView) view.findViewById( R.id.tvBoostedTime );
this.tvBoostedAcct = (TextView) view.findViewById( R.id.tvBoostedAcct );
this.llFollow = view.findViewById( R.id.llFollow );
this.ivFollow = (NetworkImageView) view.findViewById( R.id.ivFollow );
this.tvFollowerName = (TextView) view.findViewById( R.id.tvFollowerName );
@ -502,8 +553,8 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
this.ivThumbnail = (NetworkImageView) view.findViewById( R.id.ivThumbnail );
this.tvName = (TextView) view.findViewById( R.id.tvName );
this.tvTime = (TextView) view.findViewById( R.id.tvTime );
this.tvAcct =(TextView) view.findViewById( R.id.tvAcct );
this.tvAcct = (TextView) view.findViewById( R.id.tvAcct );
this.llContentWarning = view.findViewById( R.id.llContentWarning );
this.tvContentWarning = (TextView) view.findViewById( R.id.tvContentWarning );
this.btnContentWarning = (Button) view.findViewById( R.id.btnContentWarning );
@ -565,7 +616,7 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
if( item == null ) return;
if( item instanceof String ){
showSearchTag( (String) item);
showSearchTag( (String) item );
}else if( item instanceof TootAccount ){
showFollow( (TootAccount) item );
}else if( item instanceof TootNotification ){
@ -619,13 +670,23 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
}else{
showStatus( activity, status, access_info );
}
}else if( item instanceof TootGap ){
showGap( (TootGap) item );
}
}
private void showSearchTag( String tag ){
this.gap = null;
search_tag = tag;
llSearchTag.setVisibility( View.VISIBLE );
btnSearchTag.setText( "#"+tag);
btnSearchTag.setText( "#" + tag );
}
private void showGap( TootGap gap ){
this.gap = gap;
search_tag = null;
llSearchTag.setVisibility( View.VISIBLE );
btnSearchTag.setText( activity.getString( R.string.read_gap ) );
}
void showBoost( TootAccount who, long time, int icon_id, CharSequence text ){
@ -633,7 +694,7 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
llBoosted.setVisibility( View.VISIBLE );
ivBoosted.setImageResource( icon_id );
tvBoostedTime.setText( TootStatus.formatTime( time ) );
tvBoostedAcct.setText(access_info.getFullAcct( who ) );
tvBoostedAcct.setText( access_info.getFullAcct( who ) );
tvBoosted.setText( text );
}
@ -645,21 +706,21 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
tvFollowerAcct.setText( access_info.getFullAcct( who ) );
btnFollow.setImageResource( R.drawable.btn_follow );
}
private void showStatus( ActMain activity, TootStatus status, SavedAccount account ){
this.status = status;
account_thumbnail = status.account;
llStatus.setVisibility( View.VISIBLE );
tvAcct.setText( account.getFullAcct( status.account ) );
tvTime.setText( TootStatus.formatTime( status.time_created_at ) );
tvAcct.setText( account.getFullAcct( status.account ) );
tvTime.setText( TootStatus.formatTime( status.time_created_at ) );
tvName.setText( status.account.display_name );
ivThumbnail.setImageUrl( status.account.avatar_static, App1.getImageLoader() );
tvContent.setText( status.decoded_content );
// if( status.decoded_tags == null ){
// tvTags.setVisibility( View.GONE );
// }else{
@ -812,9 +873,18 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
case R.id.btnFollow:
activity.openAccountMoreMenu( access_info, account_follow );
break;
case R.id.btnSearchTag:
activity.openHashTag( access_info,search_tag );
if( search_tag != null ){
activity.openHashTag( access_info, search_tag );
}else if( gap != null ){
String error = column.startGap( gap );
if( ! TextUtils.isEmpty( error ) ){
Utils.showToast( activity, true, error );
}else{
swipyRefreshLayout.setRefreshing( true );
}
}
break;
}
}
@ -824,7 +894,7 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
TootAttachment a = status.media_attachments.get( i );
String sv;
if( Pref.pref(activity).getBoolean( Pref.KEY_PRIOR_LOCAL_URL,false )){
if( Pref.pref( activity ).getBoolean( Pref.KEY_PRIOR_LOCAL_URL, false ) ){
sv = a.url;
if( TextUtils.isEmpty( sv ) ){
sv = a.remote_url;
@ -841,7 +911,6 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
}
}
}
}

View File

@ -1,9 +1,9 @@
package jp.juggler.subwaytooter.api.entity;
import android.support.annotation.NonNull;
import android.text.Spannable;
import android.text.TextUtils;
import jp.juggler.subwaytooter.table.SavedAccount;
import jp.juggler.subwaytooter.util.Emojione;
import org.json.JSONArray;
@ -113,14 +113,16 @@ public class TootAccount {
return parse( log, account, src, new TootAccount() );
}
public static List parseList( LogCategory log, LinkClickContext account,JSONArray array ){
@NonNull public static List parseList( LogCategory log, LinkClickContext account, JSONArray array ){
List result = new List();
if( array != null ){
for( int i = array.length() - 1 ; i >= 0 ; -- i ){
int array_size = array.length();
result.ensureCapacity( array_size );
for( int i=0;i<array_size;++i){
JSONObject src = array.optJSONObject( i );
if( src == null ) continue;
TootAccount item = parse( log, account,src );
if( item != null ) result.add( 0, item );
if( item != null ) result.add( item );
}
}
return result;

View File

@ -1,5 +1,7 @@
package jp.juggler.subwaytooter.api.entity;
import android.support.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONObject;
@ -56,13 +58,17 @@ public class TootAttachment {
}
}
public static List parseList( LogCategory log, JSONArray array ){
@NonNull public static List parseList( LogCategory log, JSONArray array ){
List result = new List();
for( int i = array.length() - 1 ; i >= 0 ; -- i ){
JSONObject src = array.optJSONObject( i );
if( src == null ) continue;
TootAttachment item = parse( log, src );
if( item != null ) result.add( 0, item );
if( array != null ){
int array_size = array.length();
result.ensureCapacity( array_size );
for( int i=0;i<array_size;++i){
JSONObject src = array.optJSONObject( i );
if( src == null ) continue;
TootAttachment item = parse( log, src );
if( item != null ) result.add( item );
}
}
return result;
}

View File

@ -0,0 +1,14 @@
package jp.juggler.subwaytooter.api.entity;
public class TootGap {
public String max_id;
public String since_id;
public TootGap( String max_id, String since_id ){
this.max_id = max_id;
this.since_id = since_id;
}
public TootGap( long max_id, String since_id ){
this.max_id = Long.toString(max_id);
this.since_id = since_id;
}
}

View File

@ -1,9 +1,5 @@
package jp.juggler.subwaytooter.api.entity;
/**
* Created by tateisu on 2017/04/23.
*/
public class TootId {
public long id;

View File

@ -1,5 +1,7 @@
package jp.juggler.subwaytooter.api.entity;
import android.support.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONObject;
@ -13,6 +15,7 @@ public class TootMention {
public static class List extends ArrayList< TootMention > {
}
// URL of user's profile (can be remote)
public String url;
@ -41,15 +44,17 @@ public class TootMention {
}
}
@NonNull
public static List parseList( LogCategory log, JSONArray array ){
List result = new List();
if( array != null ){
for( int i = array.length() - 1 ; i >= 0 ; -- i ){
int array_size = array.length();
result.ensureCapacity( array_size );
for( int i = 0 ; i < array_size ; ++ i ){
JSONObject src = array.optJSONObject( i );
if( src == null ) continue;
TootMention item = parse( log, src );
if( item != null ) result.add( 0, item );
if( item != null ) result.add( item );
}
}
return result;

View File

@ -1,5 +1,7 @@
package jp.juggler.subwaytooter.api.entity;
import android.support.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONObject;
@ -43,8 +45,8 @@ public class TootNotification extends TootId {
dst.id = src.optLong( "id" );
dst.type = Utils.optStringX( src, "type" );
dst.created_at = Utils.optStringX( src, "created_at" );
dst.account = TootAccount.parse( log, accopunt, src.optJSONObject( "account" ) );
dst.status = TootStatus.parse( log, accopunt, src.optJSONObject( "status" ) );
dst.account = TootAccount.parse( log, accopunt, src.optJSONObject( "account" ) );
dst.status = TootStatus.parse( log, accopunt, src.optJSONObject( "status" ) );
dst.time_created_at = TootStatus.parseTime( log, dst.created_at );
@ -66,14 +68,17 @@ public class TootNotification extends TootId {
}
}
public static List parseList( LogCategory log, LinkClickContext accopunt,JSONArray array ){
@NonNull
public static List parseList( LogCategory log, LinkClickContext account, JSONArray array ){
List result = new List();
if( array != null ){
for( int i = array.length() - 1 ; i >= 0 ; -- i ){
int array_size = array.length();
result.ensureCapacity( array_size );
for( int i = 0 ; i < array_size ; ++ i ){
JSONObject src = array.optJSONObject( i );
if( src == null ) continue;
TootNotification item = parse( log, accopunt,src );
if( item != null ) result.add( 0, item );
TootNotification item = parse( log, account, src );
if( item != null ) result.add( item );
}
}
return result;

View File

@ -1,5 +1,7 @@
package jp.juggler.subwaytooter.api.entity;
import android.support.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONObject;
@ -40,7 +42,7 @@ public class TootRelationShip {
return dst;
}catch( Throwable ex ){
ex.printStackTrace();
log.e(ex,"TootRelationShip.parse failed.");
log.e( ex, "TootRelationShip.parse failed." );
return null;
}
}
@ -55,17 +57,19 @@ public class TootRelationShip {
}
}
@NonNull
public static List parseList( LogCategory log, JSONArray array ){
List result = new List();
if( array != null ){
for( int i = array.length() - 1 ; i >= 0 ; -- i ){
int array_size = array.length();
result.ensureCapacity( array_size );
for( int i = 0 ; i < array_size ; ++ i ){
JSONObject src = array.optJSONObject( i );
if( src == null ) continue;
TootRelationShip item = parse( log, src );
if( item != null ) result.add( 0, item );
if( item != null ) result.add( item );
}
}
return result;
}
}

View File

@ -1,5 +1,7 @@
package jp.juggler.subwaytooter.api.entity;
import android.support.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONObject;
@ -8,7 +10,7 @@ import java.util.ArrayList;
import jp.juggler.subwaytooter.util.LogCategory;
import jp.juggler.subwaytooter.util.Utils;
public class TootReport extends TootId{
public class TootReport extends TootId {
// The ID of the report
//TootId public long id;
@ -34,14 +36,17 @@ public class TootReport extends TootId{
}
@NonNull
public static List parseList( LogCategory log, JSONArray array ){
List result = new List();
if( array != null ){
for( int i = array.length() - 1 ; i >= 0 ; -- i ){
int array_size = array.length();
result.ensureCapacity( array_size );
for( int i = 0 ; i < array_size ; ++ i ){
JSONObject src = array.optJSONObject( i );
if( src == null ) continue;
TootReport item = parse( log, src );
if( item != null ) result.add( 0, item );
if( item != null ) result.add( item );
}
}
return result;

View File

@ -12,15 +12,15 @@ public class TootResults {
// An array of matched Accounts
public TootAccount.List accounts;
// An array of matchhed Statuses
// An array of matched Statuses
public TootStatus.List statuses;
// An array of matched hashtags, as strings
public ArrayList< String > hashtags;
public static TootResults parse( LogCategory log, LinkClickContext account,JSONObject src ){
if( src == null ) return null;
public static TootResults parse( LogCategory log, LinkClickContext account, JSONObject src ){
try{
if( src == null ) return null;
TootResults dst = new TootResults();
dst.accounts = TootAccount.parseList( log, account, src.optJSONArray( "accounts" ) );
dst.statuses = TootStatus.parseList( log, account, src.optJSONArray( "statuses" ) );

View File

@ -1,5 +1,6 @@
package jp.juggler.subwaytooter.api.entity;
import android.support.annotation.NonNull;
import android.text.Spannable;
import android.text.TextUtils;
@ -117,10 +118,10 @@ public class TootStatus extends TootId {
status.id = src.optLong( "id" );
status.uri = Utils.optStringX( src, "uri" );
status.url = Utils.optStringX( src, "url" );
status.account = TootAccount.parse( log, account,src.optJSONObject( "account" ) );
status.account = TootAccount.parse( log, account, src.optJSONObject( "account" ) );
status.in_reply_to_id = Utils.optStringX( src, "in_reply_to_id" ); // null
status.in_reply_to_account_id = Utils.optStringX( src, "in_reply_to_account_id" ); // null
status.reblog = TootStatus.parse( log, account,src.optJSONObject( "reblog" ) );
status.reblog = TootStatus.parse( log, account, src.optJSONObject( "reblog" ) );
status.content = Utils.optStringX( src, "content" );
status.created_at = Utils.optStringX( src, "created_at" ); // "2017-04-16T09:37:14.000Z"
status.reblogs_count = src.optLong( "reblogs_count" );
@ -136,12 +137,12 @@ public class TootStatus extends TootId {
status.application = Utils.optStringX( src, "application" ); // null
status.time_created_at = parseTime( log, status.created_at );
status.decoded_content = HTMLDecoder.decodeHTML( account,status.content );
status.decoded_content = HTMLDecoder.decodeHTML( account, status.content );
// status.decoded_tags = HTMLDecoder.decodeTags( account,status.tags );
status.decoded_mentions = HTMLDecoder.decodeMentions(account, status.mentions );
if( !TextUtils.isEmpty( status.spoiler_text ) ){
status.decoded_spoiler_text = HTMLDecoder.decodeHTML(account, status.spoiler_text );
status.decoded_mentions = HTMLDecoder.decodeMentions( account, status.mentions );
if( ! TextUtils.isEmpty( status.spoiler_text ) ){
status.decoded_spoiler_text = HTMLDecoder.decodeHTML( account, status.spoiler_text );
}
return status;
}catch( Throwable ex ){
@ -151,14 +152,17 @@ public class TootStatus extends TootId {
}
}
public static List parseList( LogCategory log, LinkClickContext account,JSONArray array ){
@NonNull
public static List parseList( LogCategory log, LinkClickContext account, JSONArray array ){
List result = new List();
if( array != null ){
for( int i = array.length() - 1 ; i >= 0 ; -- i ){
int array_size = array.length();
result.ensureCapacity( array_size );
for( int i = 0 ; i < array_size ; ++ i ){
JSONObject src = array.optJSONObject( i );
if( src == null ) continue;
TootStatus item = parse( log,account, src );
if( item != null ) result.add( 0, item );
TootStatus item = parse( log, account, src );
if( item != null ) result.add( item );
}
}
return result;

View File

@ -1,5 +1,7 @@
package jp.juggler.subwaytooter.api.entity;
import android.support.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONObject;
@ -16,36 +18,37 @@ public class TootTag {
// The URL of the hashtag
public String url;
public static TootTag parse( LogCategory log, JSONObject src ){
if( src == null ) return null;
try{
TootTag dst = new TootTag();
dst.name = Utils.optStringX(src, "name" );
dst.url = Utils.optStringX(src, "url" );
dst.name = Utils.optStringX( src, "name" );
dst.url = Utils.optStringX( src, "url" );
return dst;
}catch( Throwable ex ){
ex.printStackTrace();
log.e(ex,"TootTag.parse failed.");
log.e( ex, "TootTag.parse failed." );
return null;
}
}
public static class List extends ArrayList<TootTag>{
public static class List extends ArrayList< TootTag > {
}
public static TootTag.List parseList( LogCategory log, JSONArray array ){
TootTag.List result = new TootTag.List();
@NonNull
public static List parseList( LogCategory log, JSONArray array ){
List result = new List();
if( array != null ){
for( int i = array.length() - 1 ; i >= 0 ; -- i ){
int array_size = array.length();
result.ensureCapacity( array_size );
for( int i = 0 ; i < array_size ; ++ i ){
JSONObject src = array.optJSONObject( i );
if( src == null ) continue;
TootTag item = parse( log, src );
if( item != null ) result.add( 0, item );
if( item != null ) result.add( item );
}
}
return result;
}
}

View File

@ -24,8 +24,10 @@ public abstract class Emojione
void closeSpan(){
if( last_span_start >= 0 ){
CalligraphyTypefaceSpan typefaceSpan = new CalligraphyTypefaceSpan( App1.typeface_emoji );
sb.setSpan(typefaceSpan, last_span_start,last_span_end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
if( last_span_end > last_span_start ){
CalligraphyTypefaceSpan typefaceSpan = new CalligraphyTypefaceSpan( App1.typeface_emoji );
sb.setSpan( typefaceSpan, last_span_start, last_span_end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE );
}
last_span_start = -1;
}
}

View File

@ -148,12 +148,14 @@ public class HTMLDecoder {
if( DEBUG_HTML_PARSER ) sb.append( "(start " + tag + ")" );
int start = sb.length();
for( Node child : child_nodes ){
child.encodeSpan( account,sb );
}
int end = sb.length();
if( "a".equals( tag ) ){
if( end >start && "a".equals( tag ) ){
Matcher m = reHref.matcher( text );
if( m.find() ){
final String href = decodeEntity( m.group( 1 ) ).toString();
@ -165,7 +167,7 @@ public class HTMLDecoder {
link_callback.onClickLink( account,href );
}
}
}, start, sb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
}, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
}
}
}
@ -216,14 +218,17 @@ public class HTMLDecoder {
int start = sb.length();
sb.append('#');
sb.append(item.name);
final String item_url = item.url;
sb.setSpan( new ClickableSpan() {
@Override public void onClick( View widget ){
if( link_callback != null ){
link_callback.onClickLink( account,item_url );
int end = sb.length();
if( end > start ){
final String item_url = item.url;
sb.setSpan( new ClickableSpan() {
@Override public void onClick( View widget ){
if( link_callback != null ){
link_callback.onClickLink( account,item_url );
}
}
}
}, start, sb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
}, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
}
}
return sb;
}
@ -236,14 +241,17 @@ public class HTMLDecoder {
int start = sb.length();
sb.append('@');
sb.append( item.acct );
final String item_url = item.url;
sb.setSpan( new ClickableSpan() {
@Override public void onClick( View widget ){
if( link_callback != null ){
link_callback.onClickLink( account,item_url );
int end = sb.length();
if( end > start){
final String item_url = item.url;
sb.setSpan( new ClickableSpan() {
@Override public void onClick( View widget ){
if( link_callback != null ){
link_callback.onClickLink( account,item_url );
}
}
}
}, start, sb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
}, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
}
}
return sb;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

View File

@ -138,63 +138,66 @@
</LinearLayout>
<LinearLayout
<RelativeLayout
android:id="@+id/llStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<LinearLayout
android:id="@+id/llTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="@+id/tvAcct"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:layout_weight="1"
android:ellipsize="end"
android:gravity="end"
android:maxLines="1"
android:textColor="#888888"
android:textSize="12sp"
tools:text="who@hoge"
/>
<TextView
android:id="@+id/tvTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:textColor="#888888"
android:textSize="12sp"
tools:text="2017-04-16 09:37:14"
/>
</LinearLayout>
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/ivThumbnail"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_below="@id/llTime"
android:layout_marginEnd="4dp"
android:layout_marginTop="20dp"
android:layout_marginTop="4dp"
android:background="@drawable/btn_bg_transparent"
android:contentDescription="@string/thumbnail"
android:scaleType="centerCrop"
/>
<LinearLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_below="@id/llTime"
android:layout_toEndOf="@id/ivThumbnail"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="@+id/tvAcct"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:layout_weight="1"
android:ellipsize="end"
android:gravity="end"
android:maxLines="1"
android:textColor="#888888"
android:textSize="12sp"
tools:text="who@hoge"
/>
<TextView
android:id="@+id/tvTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:textColor="#888888"
android:textSize="12sp"
tools:text="2017-04-16 09:37:14"
/>
</LinearLayout>
<TextView
android:id="@+id/tvName"
android:layout_width="match_parent"
@ -215,10 +218,10 @@
<Button
android:id="@+id/btnContentWarning"
android:background="@drawable/btn_bg_ddd"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginEnd="8dp"
android:background="@drawable/btn_bg_ddd"
android:minWidth="40dp"
android:padding="4dp"
tools:text="見る"
@ -282,6 +285,7 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/btn_bg_ddd"
android:contentDescription="@string/thumbnail"
android:scaleType="centerCrop"
/>
@ -292,6 +296,7 @@
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:background="@drawable/btn_bg_ddd"
android:contentDescription="@string/thumbnail"
android:scaleType="centerCrop"
/>
@ -302,6 +307,7 @@
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:background="@drawable/btn_bg_ddd"
android:contentDescription="@string/thumbnail"
android:scaleType="centerCrop"
/>
@ -312,6 +318,7 @@
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:background="@drawable/btn_bg_ddd"
android:contentDescription="@string/thumbnail"
android:scaleType="centerCrop"
/>
@ -342,8 +349,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal"
android:layout_marginTop="3dp"
android:orientation="horizontal"
>
<ImageButton
@ -360,6 +367,7 @@
android:id="@+id/btnReply"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="2dp"
android:background="@drawable/btn_bg_transparent"
android:contentDescription="@string/reply"
android:minWidth="40dp"
@ -370,6 +378,7 @@
android:id="@+id/btnBoost"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="2dp"
android:background="@drawable/btn_bg_transparent"
android:drawablePadding="4dp"
android:minWidth="48dp"
@ -381,6 +390,7 @@
android:id="@+id/btnFavourite"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="2dp"
android:background="@drawable/btn_bg_transparent"
android:drawablePadding="4dp"
android:minWidth="48dp"
@ -392,6 +402,7 @@
android:id="@+id/btnMore"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="2dp"
android:background="@drawable/btn_bg_transparent"
android:contentDescription="@string/more"
android:minWidth="40dp"
@ -401,7 +412,7 @@
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/llSearchTag"

View File

@ -64,12 +64,23 @@
tools:text="tvColumnName"
/>
<ImageButton
android:id="@+id/btnColumnSetting"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="2dp"
android:background="@drawable/btn_bg_transparent"
android:contentDescription="@string/setting"
android:src="@drawable/ic_tune"
/>
<ImageButton
android:id="@+id/btnColumnReload"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginStart="2dp"
android:background="@drawable/btn_bg_transparent"
android:contentDescription="@string/reload"
android:src="@drawable/btn_refresh"
@ -80,7 +91,7 @@
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginStart="2dp"
android:background="@drawable/btn_bg_transparent"
android:contentDescription="@string/close_column"
android:src="@drawable/black_close"
@ -91,7 +102,25 @@
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:background="#ccc"
android:id="@+id/llColumnSetting"
>
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/with_attachment"
android:id="@+id/cbWithAttachment"
/>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -56,6 +56,15 @@
android:icon="@drawable/btn_statuses"
android:title="@string/your_statuses"/>
<item
android:id="@+id/nav_add_mutes"
android:icon="@drawable/ic_mute"
android:title="@string/muted_users"/>
<item
android:id="@+id/nav_add_blocks"
android:icon="@drawable/ic_block"
android:title="@string/blocked_users"/>
<!--<item-->
<!--android:id="@+id/nav_add_reports"-->
<!--android:icon="@drawable/btn_report"-->

View File

@ -156,4 +156,11 @@
<string name="prior_local_url_when_open_attachment">添付画像を開く時に自タンスURLを重視</string>
<string name="disable_fast_scroller">FastScrollerを無効にする(アプリ再起動が必要)</string>
<string name="delete_succeeded">削除できました</string>
<string name="developer">開発者</string>
<string name="with_attachment">添付データあり</string>
<string name="read_gap">ギャップを読む</string>
<string name="column_is_busy">別の処理を行っています</string>
<string name="blocked_users">ブロックしたユーザ</string>
<string name="end_of_list">リストの終端</string>
<string name="muted_users">ミュートしたユーザ</string>
</resources>

View File

@ -156,4 +156,10 @@
<string name="disable_fast_scroller">disable fast scroller (app restart required)</string>
<string name="delete_succeeded">delete succeeded</string>
<string name="developer">developer</string>
<string name="with_attachment">with attachment</string>
<string name="column_is_busy">column is busy</string>
<string name="read_gap">read gap</string>
<string name="muted_users">mutes users</string>
<string name="blocked_users">blocked users</string>
<string name="end_of_list">end of list</string>
</resources>