v1.0.1
- 投稿画面で返信表示を2回HTMLデコードしていたバグを修正。過去に作成した下書きの表示が少し乱れるかもしれない - トゥート検索カラムでも添付データや正規表現フィルタを使える - 疑似アカウントだと「~のタイムラインを開く」を利用できなかったバグを修正 - トゥート検索の時刻表記UTCから端末タイムゾーンに変換 - アカウントのdisplay_nameに改行が含まれる場合に改行しないようにした
This commit is contained in:
parent
db6db7c47c
commit
aac510aca5
|
@ -9,8 +9,8 @@ android {
|
||||||
applicationId "jp.juggler.subwaytooter"
|
applicationId "jp.juggler.subwaytooter"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
versionCode 100
|
versionCode 101
|
||||||
versionName "1.0.0"
|
versionName "1.0.1"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3779,7 +3779,7 @@ public class ActMain extends AppCompatActivity
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
AccountPicker.pick( this, false, false
|
AccountPicker.pick( this, true, false
|
||||||
, getString( R.string.account_picker_add_timeline_of, host )
|
, getString( R.string.account_picker_add_timeline_of, host )
|
||||||
, account_list, new AccountPicker.AccountPickerCallback() {
|
, account_list, new AccountPicker.AccountPickerCallback() {
|
||||||
@Override public void onAccountPicked( @NonNull SavedAccount ai ){
|
@Override public void onAccountPicked( @NonNull SavedAccount ai ){
|
||||||
|
|
|
@ -443,7 +443,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
||||||
|
|
||||||
// リプライ表示をつける
|
// リプライ表示をつける
|
||||||
in_reply_to_id = reply_status.id;
|
in_reply_to_id = reply_status.id;
|
||||||
in_reply_to_text = reply_status.decoded_content.toString();
|
in_reply_to_text = reply_status.content;
|
||||||
in_reply_to_image = reply_status.account == null ? null : reply_status.account.avatar_static;
|
in_reply_to_image = reply_status.account == null ? null : reply_status.account.avatar_static;
|
||||||
in_reply_to_url = reply_status.url;
|
in_reply_to_url = reply_status.url;
|
||||||
|
|
||||||
|
|
|
@ -55,13 +55,7 @@ public class ActText extends AppCompatActivity implements View.OnClickListener {
|
||||||
|
|
||||||
addHeader( context,sb, R.string.send_header_url, status.url );
|
addHeader( context,sb, R.string.send_header_url, status.url );
|
||||||
|
|
||||||
if( status instanceof TootStatus ){
|
addHeader( context,sb, R.string.send_header_date,TootStatus.formatTime( status.time_created_at ) );
|
||||||
TootStatus ts = (TootStatus)status;
|
|
||||||
addHeader( context,sb, R.string.send_header_date,TootStatus.formatTime( ts.time_created_at ) );
|
|
||||||
}else if( status instanceof MSPToot ){
|
|
||||||
MSPToot ts = (MSPToot)status;
|
|
||||||
addHeader( context,sb, R.string.send_header_date, ts.created_at );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( status.account != null ){
|
if( status.account != null ){
|
||||||
addHeader( context,sb, R.string.send_header_from_acct, access_info.getFullAcct( status.account ) );
|
addHeader( context,sb, R.string.send_header_from_acct, access_info.getFullAcct( status.account ) );
|
||||||
|
|
|
@ -25,7 +25,6 @@ import java.util.regex.Pattern;
|
||||||
import jp.juggler.subwaytooter.api.TootApiClient;
|
import jp.juggler.subwaytooter.api.TootApiClient;
|
||||||
import jp.juggler.subwaytooter.api.TootApiResult;
|
import jp.juggler.subwaytooter.api.TootApiResult;
|
||||||
import jp.juggler.subwaytooter.api.entity.TootAccount;
|
import jp.juggler.subwaytooter.api.entity.TootAccount;
|
||||||
import jp.juggler.subwaytooter.api.entity.TootAttachment;
|
|
||||||
import jp.juggler.subwaytooter.api.entity.TootContext;
|
import jp.juggler.subwaytooter.api.entity.TootContext;
|
||||||
import jp.juggler.subwaytooter.api.entity.TootDomainBlock;
|
import jp.juggler.subwaytooter.api.entity.TootDomainBlock;
|
||||||
import jp.juggler.subwaytooter.api.entity.TootGap;
|
import jp.juggler.subwaytooter.api.entity.TootGap;
|
||||||
|
@ -35,7 +34,6 @@ import jp.juggler.subwaytooter.api.entity.TootReport;
|
||||||
import jp.juggler.subwaytooter.api.entity.TootResults;
|
import jp.juggler.subwaytooter.api.entity.TootResults;
|
||||||
import jp.juggler.subwaytooter.api.entity.TootStatus;
|
import jp.juggler.subwaytooter.api.entity.TootStatus;
|
||||||
import jp.juggler.subwaytooter.api.entity.TootTag;
|
import jp.juggler.subwaytooter.api.entity.TootTag;
|
||||||
import jp.juggler.subwaytooter.api_msp.MSPApiResult;
|
|
||||||
import jp.juggler.subwaytooter.api_msp.MSPClient;
|
import jp.juggler.subwaytooter.api_msp.MSPClient;
|
||||||
import jp.juggler.subwaytooter.api_msp.entity.MSPToot;
|
import jp.juggler.subwaytooter.api_msp.entity.MSPToot;
|
||||||
import jp.juggler.subwaytooter.table.AcctColor;
|
import jp.juggler.subwaytooter.table.AcctColor;
|
||||||
|
@ -757,6 +755,39 @@ class Column implements StreamReader.Callback {
|
||||||
AlarmService.dataRemoved( context, access_info.db_id );
|
AlarmService.dataRemoved( context, access_info.db_id );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void removeMuteApp(){
|
||||||
|
ArrayList< Object > tmp_list = new ArrayList<>( list_data.size() );
|
||||||
|
|
||||||
|
HashSet< String > muted_app = MutedApp.getNameSet();
|
||||||
|
WordTrieTree muted_word = MutedWord.getNameSet();
|
||||||
|
|
||||||
|
for( Object o : list_data ){
|
||||||
|
if( o instanceof TootStatus ){
|
||||||
|
TootStatus item = (TootStatus) o;
|
||||||
|
if( item.checkMuted( muted_app, muted_word ) ){
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( o instanceof TootNotification ){
|
||||||
|
TootNotification item = (TootNotification) o;
|
||||||
|
TootStatus status = item.status;
|
||||||
|
|
||||||
|
if( status != null ){
|
||||||
|
if( status.checkMuted( muted_app, muted_word ) ){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp_list.add( o );
|
||||||
|
}
|
||||||
|
if( tmp_list.size() != list_data.size() ){
|
||||||
|
list_data.clear();
|
||||||
|
list_data.addAll( tmp_list );
|
||||||
|
fireShowContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onDomainBlockChanged( SavedAccount target_account, String domain, boolean bBlocked ){
|
void onDomainBlockChanged( SavedAccount target_account, String domain, boolean bBlocked ){
|
||||||
if( ! target_account.host.equals( access_info.host ) ) return;
|
if( ! target_account.host.equals( access_info.host ) ) return;
|
||||||
if( access_info.isPseudo() ) return;
|
if( access_info.isPseudo() ) return;
|
||||||
|
@ -898,13 +929,7 @@ class Column implements StreamReader.Callback {
|
||||||
final BucketList< Object > list_data = new BucketList<>();
|
final BucketList< Object > list_data = new BucketList<>();
|
||||||
private final DuplicateMap duplicate_map = new DuplicateMap();
|
private final DuplicateMap duplicate_map = new DuplicateMap();
|
||||||
|
|
||||||
private static boolean hasMedia( TootStatus status ){
|
private boolean isFilterEnabled(){
|
||||||
if( status == null ) return false;
|
|
||||||
TootAttachment.List list = status.media_attachments;
|
|
||||||
return ! ( list == null || list.isEmpty() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isFiltered(){
|
|
||||||
return ( with_attachment
|
return ( with_attachment
|
||||||
|| dont_show_boost
|
|| dont_show_boost
|
||||||
|| dont_show_reply
|
|| dont_show_reply
|
||||||
|
@ -912,39 +937,6 @@ class Column implements StreamReader.Callback {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeMuteApp(){
|
|
||||||
ArrayList< Object > tmp_list = new ArrayList<>( list_data.size() );
|
|
||||||
|
|
||||||
HashSet< String > muted_app = MutedApp.getNameSet();
|
|
||||||
WordTrieTree muted_word = MutedWord.getNameSet();
|
|
||||||
|
|
||||||
for( Object o : list_data ){
|
|
||||||
if( o instanceof TootStatus ){
|
|
||||||
TootStatus item = (TootStatus) o;
|
|
||||||
if( item.checkMuted( muted_app, muted_word ) ){
|
|
||||||
continue;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( o instanceof TootNotification ){
|
|
||||||
TootNotification item = (TootNotification) o;
|
|
||||||
TootStatus status = item.status;
|
|
||||||
|
|
||||||
if( status != null ){
|
|
||||||
if( status.checkMuted( muted_app, muted_word ) ){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmp_list.add( o );
|
|
||||||
}
|
|
||||||
if( tmp_list.size() != list_data.size() ){
|
|
||||||
list_data.clear();
|
|
||||||
list_data.addAll( tmp_list );
|
|
||||||
fireShowContent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Pattern column_regex_filter;
|
private Pattern column_regex_filter;
|
||||||
private HashSet< String > muted_app;
|
private HashSet< String > muted_app;
|
||||||
private WordTrieTree muted_word;
|
private WordTrieTree muted_word;
|
||||||
|
@ -963,9 +955,10 @@ class Column implements StreamReader.Callback {
|
||||||
muted_word = MutedWord.getNameSet();
|
muted_word = MutedWord.getNameSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFiltered( TootStatus status ){
|
private boolean isFiltered( @NonNull TootStatus status ){
|
||||||
if( with_attachment ){
|
if( with_attachment ){
|
||||||
if( ! hasMedia( status ) && ! hasMedia( status.reblog ) ) return true;
|
boolean hasMedia = status.reblog != null ? status.reblog.hasMedia() : status.hasMedia();
|
||||||
|
if( ! hasMedia ) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( dont_show_boost ){
|
if( dont_show_boost ){
|
||||||
|
@ -996,6 +989,33 @@ class Column implements StreamReader.Callback {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isFiltered( MSPToot status ){
|
||||||
|
if( with_attachment ){
|
||||||
|
boolean hasMedia = status.hasMedia();
|
||||||
|
if( ! hasMedia ) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( dont_show_boost ){
|
||||||
|
// MSPToot には関連パラメータはない
|
||||||
|
}
|
||||||
|
|
||||||
|
if( dont_show_reply ){
|
||||||
|
// MSPToot には関連パラメータはない
|
||||||
|
}
|
||||||
|
|
||||||
|
if( column_regex_filter != null ){
|
||||||
|
if( column_regex_filter.matcher( status.decoded_content.toString() ).find() )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection RedundantIfStatement
|
||||||
|
if( status.checkMuted( muted_app, muted_word ) ){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
private void addWithFilter( ArrayList< Object > dst, TootStatus.List src ){
|
private void addWithFilter( ArrayList< Object > dst, TootStatus.List src ){
|
||||||
for( TootStatus status : src ){
|
for( TootStatus status : src ){
|
||||||
|
@ -1005,6 +1025,15 @@ class Column implements StreamReader.Callback {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
private void addWithFilter( ArrayList< Object > dst, MSPToot.List src ){
|
||||||
|
for( MSPToot status : src ){
|
||||||
|
if( ! isFiltered( status ) ){
|
||||||
|
dst.add( status );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isFiltered( TootNotification item ){
|
private boolean isFiltered( TootNotification item ){
|
||||||
|
|
||||||
TootStatus status = item.status;
|
TootStatus status = item.status;
|
||||||
|
@ -1074,7 +1103,7 @@ class Column implements StreamReader.Callback {
|
||||||
log.d( "loading-statuses: cancelled." );
|
log.d( "loading-statuses: cancelled." );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( ! isFiltered() ){
|
if( ! isFilterEnabled() ){
|
||||||
log.d( "loading-statuses: isFiltered is false." );
|
log.d( "loading-statuses: isFiltered is false." );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1334,7 +1363,7 @@ class Column implements StreamReader.Callback {
|
||||||
MSPToot.List search_result = MSPToot.parseList( log, access_info, result.array );
|
MSPToot.List search_result = MSPToot.parseList( log, access_info, result.array );
|
||||||
if( search_result != null ){
|
if( search_result != null ){
|
||||||
list_tmp = new ArrayList<>();
|
list_tmp = new ArrayList<>();
|
||||||
list_tmp.addAll( search_result );
|
addWithFilter( list_tmp, search_result );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1908,7 +1937,7 @@ class Column implements StreamReader.Callback {
|
||||||
}
|
}
|
||||||
|
|
||||||
// bottomの場合、フィルタなしなら繰り返さない
|
// bottomの場合、フィルタなしなら繰り返さない
|
||||||
if( ! isFiltered() ){
|
if( ! isFilterEnabled() ){
|
||||||
log.d( "refresh-status-bottom: isFiltered is false." );
|
log.d( "refresh-status-bottom: isFiltered is false." );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2134,7 +2163,7 @@ class Column implements StreamReader.Callback {
|
||||||
MSPToot.List search_result = MSPToot.parseList( log, access_info, result.array );
|
MSPToot.List search_result = MSPToot.parseList( log, access_info, result.array );
|
||||||
if( search_result != null ){
|
if( search_result != null ){
|
||||||
list_tmp = new ArrayList<>();
|
list_tmp = new ArrayList<>();
|
||||||
list_tmp.addAll( search_result );
|
addWithFilter( list_tmp, search_result );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,6 @@ class ColumnViewHolder
|
||||||
bAllowFilter = true;
|
bAllowFilter = true;
|
||||||
break;
|
break;
|
||||||
case Column.TYPE_SEARCH:
|
case Column.TYPE_SEARCH:
|
||||||
case Column.TYPE_SEARCH_PORTAL:
|
|
||||||
case Column.TYPE_CONVERSATION:
|
case Column.TYPE_CONVERSATION:
|
||||||
case Column.TYPE_REPORTS:
|
case Column.TYPE_REPORTS:
|
||||||
case Column.TYPE_BLOCKS:
|
case Column.TYPE_BLOCKS:
|
||||||
|
@ -295,15 +294,17 @@ class ColumnViewHolder
|
||||||
cbResolve.setChecked( column.search_resolve );
|
cbResolve.setChecked( column.search_resolve );
|
||||||
|
|
||||||
vg( cbWithAttachment, bAllowFilter );
|
vg( cbWithAttachment, bAllowFilter );
|
||||||
|
vg( etRegexFilter, bAllowFilter );
|
||||||
|
vg( llRegexFilter, bAllowFilter );
|
||||||
|
|
||||||
vg( cbDontShowBoost, bAllowFilterBoost );
|
vg( cbDontShowBoost, bAllowFilterBoost );
|
||||||
vg( cbDontShowReply, bAllowFilterBoost );
|
vg( cbDontShowReply, bAllowFilterBoost );
|
||||||
|
|
||||||
vg( cbDontStreaming, column.canStreaming() );
|
vg( cbDontStreaming, column.canStreaming() );
|
||||||
vg( cbDontAutoRefresh, column.canAutoRefresh() );
|
vg( cbDontAutoRefresh, column.canAutoRefresh() );
|
||||||
vg( cbHideMediaDefault, column.canShowMedia() );
|
vg( cbHideMediaDefault, column.canShowMedia() );
|
||||||
vg( cbEnableSpeech, column.canSpeech() );
|
vg( cbEnableSpeech, column.canSpeech() );
|
||||||
|
|
||||||
vg( etRegexFilter, bAllowFilter );
|
|
||||||
vg( llRegexFilter, bAllowFilter );
|
|
||||||
|
|
||||||
vg( btnDeleteNotification, column.column_type == Column.TYPE_NOTIFICATIONS );
|
vg( btnDeleteNotification, column.column_type == Column.TYPE_NOTIFICATIONS );
|
||||||
vg( llSearch, (column.column_type == Column.TYPE_SEARCH || column.column_type == Column.TYPE_SEARCH_PORTAL ) );
|
vg( llSearch, (column.column_type == Column.TYPE_SEARCH || column.column_type == Column.TYPE_SEARCH_PORTAL ) );
|
||||||
|
|
|
@ -3,6 +3,7 @@ package jp.juggler.subwaytooter;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.view.ViewCompat;
|
import android.support.v4.view.ViewCompat;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -79,7 +80,7 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
||||||
private final View llSearchTag;
|
private final View llSearchTag;
|
||||||
private final Button btnSearchTag;
|
private final Button btnSearchTag;
|
||||||
|
|
||||||
private final TextView tvApplication;
|
private @Nullable final TextView tvApplication;
|
||||||
|
|
||||||
private TootStatusLike status;
|
private TootStatusLike status;
|
||||||
private TootAccount account_thumbnail;
|
private TootAccount account_thumbnail;
|
||||||
|
@ -343,13 +344,8 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
llStatus.setVisibility( View.VISIBLE );
|
llStatus.setVisibility( View.VISIBLE );
|
||||||
|
|
||||||
if( status instanceof TootStatus ){
|
tvTime.setText( TootStatus.formatTime( status .time_created_at ) );
|
||||||
tvTime.setText( TootStatus.formatTime( ( (TootStatus) status ).time_created_at ) );
|
|
||||||
|
|
||||||
}else if( status instanceof MSPToot ){
|
|
||||||
tvTime.setText( ( (MSPToot) status ).created_at );
|
|
||||||
|
|
||||||
}
|
|
||||||
ivThumbnail.setCornerRadius( activity.pref, 16f );
|
ivThumbnail.setCornerRadius( activity.pref, 16f );
|
||||||
|
|
||||||
account_thumbnail = status.account;
|
account_thumbnail = status.account;
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import jp.juggler.subwaytooter.util.HTMLDecoder;
|
import jp.juggler.subwaytooter.util.HTMLDecoder;
|
||||||
import jp.juggler.subwaytooter.util.LinkClickContext;
|
import jp.juggler.subwaytooter.util.LinkClickContext;
|
||||||
|
@ -146,14 +147,18 @@ public class TootAccount {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final Pattern reLineFeed = Pattern.compile( "[\\s\\t\\x0d\\x0a]+" );
|
||||||
|
|
||||||
public static CharSequence filterDisplayName( String sv ){
|
public static CharSequence filterDisplayName( String sv ){
|
||||||
|
|
||||||
// decode HTML entity
|
// decode HTML entity
|
||||||
sv = HTMLDecoder.decodeEntity( sv );
|
sv = HTMLDecoder.decodeEntity( sv );
|
||||||
|
|
||||||
// sanitize LRO,RLO
|
// sanitize LRO,RLO
|
||||||
sv = Utils.sanitizeBDI( sv );
|
sv = Utils.sanitizeBDI( sv );
|
||||||
|
|
||||||
|
// remove white spaces
|
||||||
|
sv = reLineFeed.matcher( sv ).replaceAll( " " );
|
||||||
|
|
||||||
// decode emoji code
|
// decode emoji code
|
||||||
return Emojione.decodeEmoji( sv );
|
return Emojione.decodeEmoji( sv );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package jp.juggler.subwaytooter.api.entity;
|
package jp.juggler.subwaytooter.api.entity;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.design.widget.NavigationView;
|
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
@ -20,7 +18,6 @@ import java.util.TimeZone;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import jp.juggler.subwaytooter.table.SavedAccount;
|
|
||||||
import jp.juggler.subwaytooter.util.HTMLDecoder;
|
import jp.juggler.subwaytooter.util.HTMLDecoder;
|
||||||
import jp.juggler.subwaytooter.util.LinkClickContext;
|
import jp.juggler.subwaytooter.util.LinkClickContext;
|
||||||
import jp.juggler.subwaytooter.util.LogCategory;
|
import jp.juggler.subwaytooter.util.LogCategory;
|
||||||
|
@ -46,9 +43,6 @@ public class TootStatus extends TootStatusLike {
|
||||||
// A Fediverse-unique resource ID
|
// A Fediverse-unique resource ID
|
||||||
public String uri;
|
public String uri;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// null or the ID of the status it replies to
|
// null or the ID of the status it replies to
|
||||||
public String in_reply_to_id;
|
public String in_reply_to_id;
|
||||||
|
|
||||||
|
@ -57,12 +51,10 @@ public class TootStatus extends TootStatusLike {
|
||||||
|
|
||||||
// null or the reblogged Status
|
// null or the reblogged Status
|
||||||
public TootStatus reblog;
|
public TootStatus reblog;
|
||||||
|
|
||||||
// The time the status was created
|
|
||||||
public String created_at;
|
|
||||||
|
|
||||||
|
// The time the status was created
|
||||||
|
private String created_at;
|
||||||
|
|
||||||
//One of: public, unlisted, private, direct
|
//One of: public, unlisted, private, direct
|
||||||
public String visibility;
|
public String visibility;
|
||||||
public static final String VISIBILITY_PUBLIC = "public";
|
public static final String VISIBILITY_PUBLIC = "public";
|
||||||
|
@ -79,9 +71,6 @@ public class TootStatus extends TootStatusLike {
|
||||||
//An array of Tags
|
//An array of Tags
|
||||||
public TootTag.List tags;
|
public TootTag.List tags;
|
||||||
|
|
||||||
|
|
||||||
public long time_created_at;
|
|
||||||
|
|
||||||
// public Spannable decoded_tags;
|
// public Spannable decoded_tags;
|
||||||
public Spannable decoded_mentions;
|
public Spannable decoded_mentions;
|
||||||
|
|
||||||
|
@ -104,7 +93,7 @@ public class TootStatus extends TootStatusLike {
|
||||||
status.account = TootAccount.parse( log, lcc, src.optJSONObject( "account" ) );
|
status.account = TootAccount.parse( log, lcc, src.optJSONObject( "account" ) );
|
||||||
status.in_reply_to_id = Utils.optStringX( src, "in_reply_to_id" ); // null
|
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.in_reply_to_account_id = Utils.optStringX( src, "in_reply_to_account_id" ); // null
|
||||||
status.reblog = TootStatus.parse( log, lcc,status_host, src.optJSONObject( "reblog" ) );
|
status.reblog = TootStatus.parse( log, lcc, status_host, src.optJSONObject( "reblog" ) );
|
||||||
status.content = Utils.optStringX( src, "content" );
|
status.content = Utils.optStringX( src, "content" );
|
||||||
status.created_at = Utils.optStringX( src, "created_at" ); // "2017-04-16T09:37:14.000Z"
|
status.created_at = Utils.optStringX( src, "created_at" ); // "2017-04-16T09:37:14.000Z"
|
||||||
status.reblogs_count = src.optLong( "reblogs_count" );
|
status.reblogs_count = src.optLong( "reblogs_count" );
|
||||||
|
@ -120,12 +109,12 @@ public class TootStatus extends TootStatusLike {
|
||||||
status.application = TootApplication.parse( log, src.optJSONObject( "application" ) ); // null
|
status.application = TootApplication.parse( log, src.optJSONObject( "application" ) ); // null
|
||||||
|
|
||||||
status.time_created_at = parseTime( log, status.created_at );
|
status.time_created_at = parseTime( log, status.created_at );
|
||||||
status.decoded_content = HTMLDecoder.decodeHTML( lcc, status.content ,true,status.media_attachments );
|
status.decoded_content = HTMLDecoder.decodeHTML( lcc, status.content, true, status.media_attachments );
|
||||||
// status.decoded_tags = HTMLDecoder.decodeTags( account,status.tags );
|
// status.decoded_tags = HTMLDecoder.decodeTags( account,status.tags );
|
||||||
status.decoded_mentions = HTMLDecoder.decodeMentions( lcc, status.mentions );
|
status.decoded_mentions = HTMLDecoder.decodeMentions( lcc, status.mentions );
|
||||||
|
|
||||||
if( ! TextUtils.isEmpty( status.spoiler_text ) ){
|
if( ! TextUtils.isEmpty( status.spoiler_text ) ){
|
||||||
status.decoded_spoiler_text = HTMLDecoder.decodeHTML( lcc, status.spoiler_text ,true,status.media_attachments);
|
status.decoded_spoiler_text = HTMLDecoder.decodeHTML( lcc, status.spoiler_text, true, status.media_attachments );
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}catch( Throwable ex ){
|
}catch( Throwable ex ){
|
||||||
|
@ -144,7 +133,7 @@ public class TootStatus extends TootStatusLike {
|
||||||
for( int i = 0 ; i < array_size ; ++ i ){
|
for( int i = 0 ; i < array_size ; ++ i ){
|
||||||
JSONObject src = array.optJSONObject( i );
|
JSONObject src = array.optJSONObject( i );
|
||||||
if( src == null ) continue;
|
if( src == null ) continue;
|
||||||
TootStatus item = parse( log, lcc,status_host, src );
|
TootStatus item = parse( log, lcc, status_host, src );
|
||||||
if( item != null ) result.add( item );
|
if( item != null ) result.add( item );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,14 +199,14 @@ public class TootStatus extends TootStatusLike {
|
||||||
throw new IndexOutOfBoundsException( "visibility not in range" );
|
throw new IndexOutOfBoundsException( "visibility not in range" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void updateNickname( SavedAccount access_info ){
|
// public void updateNickname( SavedAccount access_info ){
|
||||||
// decoded_content = HTMLDecoder.decodeHTML( access_info, content );
|
// decoded_content = HTMLDecoder.decodeHTML( access_info, content );
|
||||||
// decoded_mentions = HTMLDecoder.decodeMentions( access_info, mentions );
|
// decoded_mentions = HTMLDecoder.decodeMentions( access_info, mentions );
|
||||||
//
|
//
|
||||||
// if( ! TextUtils.isEmpty( spoiler_text ) ){
|
// if( ! TextUtils.isEmpty( spoiler_text ) ){
|
||||||
// decoded_spoiler_text = HTMLDecoder.decodeHTML( access_info, spoiler_text );
|
// decoded_spoiler_text = HTMLDecoder.decodeHTML( access_info, spoiler_text );
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public boolean checkMuted( @NonNull HashSet< String > muted_app, @NonNull WordTrieTree muted_word ){
|
public boolean checkMuted( @NonNull HashSet< String > muted_app, @NonNull WordTrieTree muted_word ){
|
||||||
|
|
||||||
|
@ -245,4 +234,7 @@ public class TootStatus extends TootStatusLike {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasMedia(){
|
||||||
|
return media_attachments != null && media_attachments.size() > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,5 +41,7 @@ public abstract class TootStatusLike extends TootId{
|
||||||
//Application from which the status was posted
|
//Application from which the status was posted
|
||||||
public TootApplication application;
|
public TootApplication application;
|
||||||
|
|
||||||
|
public long time_created_at;
|
||||||
|
|
||||||
|
public abstract boolean hasMedia();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,37 @@
|
||||||
package jp.juggler.subwaytooter.api_msp.entity;
|
package jp.juggler.subwaytooter.api_msp.entity;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.TimeZone;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import jp.juggler.subwaytooter.api.entity.TootAccount;
|
import jp.juggler.subwaytooter.api.entity.TootAccount;
|
||||||
|
import jp.juggler.subwaytooter.api.entity.TootAttachment;
|
||||||
|
import jp.juggler.subwaytooter.api.entity.TootStatus;
|
||||||
import jp.juggler.subwaytooter.api.entity.TootStatusLike;
|
import jp.juggler.subwaytooter.api.entity.TootStatusLike;
|
||||||
import jp.juggler.subwaytooter.table.SavedAccount;
|
import jp.juggler.subwaytooter.table.SavedAccount;
|
||||||
import jp.juggler.subwaytooter.util.HTMLDecoder;
|
import jp.juggler.subwaytooter.util.HTMLDecoder;
|
||||||
import jp.juggler.subwaytooter.util.LogCategory;
|
import jp.juggler.subwaytooter.util.LogCategory;
|
||||||
import jp.juggler.subwaytooter.util.Utils;
|
import jp.juggler.subwaytooter.util.Utils;
|
||||||
|
import jp.juggler.subwaytooter.util.WordTrieTree;
|
||||||
|
|
||||||
public class MSPToot extends TootStatusLike {
|
public class MSPToot extends TootStatusLike {
|
||||||
|
|
||||||
public static class List extends ArrayList<MSPToot> {
|
public static class List extends ArrayList< MSPToot > {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern reAccountUrl = Pattern.compile("\\Ahttps://([^/#?]+)/@([^/#?]+)\\z");
|
private static final Pattern reAccountUrl = Pattern.compile( "\\Ahttps://([^/#?]+)/@([^/#?]+)\\z" );
|
||||||
|
|
||||||
|
|
||||||
private static TootAccount parseAccount( LogCategory log, SavedAccount access_info, JSONObject src ){
|
private static TootAccount parseAccount( LogCategory log, SavedAccount access_info, JSONObject src ){
|
||||||
|
|
||||||
|
@ -40,12 +48,11 @@ public class MSPToot extends TootStatusLike {
|
||||||
}else{
|
}else{
|
||||||
dst.display_name = TootAccount.filterDisplayName( sv );
|
dst.display_name = TootAccount.filterDisplayName( sv );
|
||||||
}
|
}
|
||||||
|
|
||||||
dst.id = src.optLong( "id" );
|
dst.id = src.optLong( "id" );
|
||||||
|
|
||||||
dst.note = Utils.optStringX( src, "note" );
|
dst.note = Utils.optStringX( src, "note" );
|
||||||
dst.decoded_note = HTMLDecoder.decodeHTML( access_info,(dst.note!=null? dst.note :null) ,true,null);
|
dst.decoded_note = HTMLDecoder.decodeHTML( access_info, ( dst.note != null ? dst.note : null ), true, null );
|
||||||
|
|
||||||
|
|
||||||
if( TextUtils.isEmpty( dst.url ) ){
|
if( TextUtils.isEmpty( dst.url ) ){
|
||||||
log.e( "parseAccount: missing url" );
|
log.e( "parseAccount: missing url" );
|
||||||
|
@ -62,101 +69,161 @@ public class MSPToot extends TootStatusLike {
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
// private static final Pattern reTime = Pattern.compile( "\\A(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)" );
|
// private static final Pattern reTime = Pattern.compile( "\\A(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)" );
|
||||||
//
|
//
|
||||||
// private static final TimeZone tz_tokyo = TimeZone.getTimeZone( "Asia/Tokyo" );
|
// private static final TimeZone tz_tokyo = TimeZone.getTimeZone( "Asia/Tokyo" );
|
||||||
//
|
//
|
||||||
// private static long parseMSPTime( LogCategory log, String strTime ){
|
// private static long parseMSPTime( LogCategory log, String strTime ){
|
||||||
// if( ! TextUtils.isEmpty( strTime ) ){
|
// if( ! TextUtils.isEmpty( strTime ) ){
|
||||||
// try{
|
// try{
|
||||||
// Matcher m = reTime.matcher( strTime );
|
// Matcher m = reTime.matcher( strTime );
|
||||||
// if( ! m.find() ){
|
// if( ! m.find() ){
|
||||||
// log.d( "!!invalid time format: %s", strTime );
|
// log.d( "!!invalid time format: %s", strTime );
|
||||||
// }else{
|
// }else{
|
||||||
// GregorianCalendar g = new GregorianCalendar( tz_tokyo );
|
// GregorianCalendar g = new GregorianCalendar( tz_tokyo );
|
||||||
// g.set(
|
// g.set(
|
||||||
// Utils.parse_int( m.group( 1 ), 1 ),
|
// Utils.parse_int( m.group( 1 ), 1 ),
|
||||||
// Utils.parse_int( m.group( 2 ), 1 ) - 1,
|
// Utils.parse_int( m.group( 2 ), 1 ) - 1,
|
||||||
// Utils.parse_int( m.group( 3 ), 1 ),
|
// Utils.parse_int( m.group( 3 ), 1 ),
|
||||||
// Utils.parse_int( m.group( 4 ), 0 ),
|
// Utils.parse_int( m.group( 4 ), 0 ),
|
||||||
// Utils.parse_int( m.group( 5 ), 0 ),
|
// Utils.parse_int( m.group( 5 ), 0 ),
|
||||||
// Utils.parse_int( m.group( 6 ), 0 )
|
// Utils.parse_int( m.group( 6 ), 0 )
|
||||||
// );
|
// );
|
||||||
// g.set( Calendar.MILLISECOND, 0 );
|
// g.set( Calendar.MILLISECOND, 0 );
|
||||||
// return g.getTimeInMillis();
|
// return g.getTimeInMillis();
|
||||||
// }
|
// }
|
||||||
// }catch( Throwable ex ){// ParseException, ArrayIndexOutOfBoundsException
|
// }catch( Throwable ex ){// ParseException, ArrayIndexOutOfBoundsException
|
||||||
// ex.printStackTrace();
|
// ex.printStackTrace();
|
||||||
// log.e( ex, "parseMSPTime failed. src=%s", strTime );
|
// log.e( ex, "parseMSPTime failed. src=%s", strTime );
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// return 0L;
|
// return 0L;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public String created_at;
|
private String created_at;
|
||||||
public ArrayList<String> media_attachments;
|
|
||||||
|
public ArrayList< String > media_attachments;
|
||||||
public long msp_id;
|
public long msp_id;
|
||||||
|
|
||||||
private static MSPToot parse( LogCategory log, SavedAccount access_info,JSONObject src ){
|
private static MSPToot parse( LogCategory log, SavedAccount access_info, JSONObject src ){
|
||||||
if( src == null ) return null;
|
if( src == null ) return null;
|
||||||
MSPToot dst = new MSPToot();
|
MSPToot dst = new MSPToot();
|
||||||
|
|
||||||
dst.account =parseAccount( log, access_info, src.optJSONObject( "account" ));
|
dst.account = parseAccount( log, access_info, src.optJSONObject( "account" ) );
|
||||||
if( dst.account == null ){
|
if( dst.account == null ){
|
||||||
log.e("missing status account");
|
log.e( "missing status account" );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
dst.url = Utils.optStringX( src, "url" );
|
dst.url = Utils.optStringX( src, "url" );
|
||||||
dst.status_host = dst.account.getAcctHost();
|
dst.status_host = dst.account.getAcctHost();
|
||||||
dst.id = src.optLong( "id" ,-1L );
|
dst.id = src.optLong( "id", - 1L );
|
||||||
|
|
||||||
if( TextUtils.isEmpty( dst.url ) || TextUtils.isEmpty( dst.status_host ) || dst.id == -1L ){
|
if( TextUtils.isEmpty( dst.url ) || TextUtils.isEmpty( dst.status_host ) || dst.id == - 1L ){
|
||||||
log.e("missing status url or host or id");
|
log.e( "missing status url or host or id" );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
dst.created_at = Utils.optStringX( src, "created_at" );
|
dst.created_at = Utils.optStringX( src, "created_at" );
|
||||||
|
dst.time_created_at = parseTime( log, dst.created_at );
|
||||||
|
|
||||||
JSONArray a = src.optJSONArray( "media_attachments" );
|
JSONArray a = src.optJSONArray( "media_attachments" );
|
||||||
if( a != null && a.length() > 0 ){
|
if( a != null && a.length() > 0 ){
|
||||||
dst.media_attachments = new ArrayList<>();
|
dst.media_attachments = new ArrayList<>();
|
||||||
for(int i=0,ie=a.length();i<ie;++i){
|
for( int i = 0, ie = a.length() ; i < ie ; ++ i ){
|
||||||
String sv = Utils.optStringX( a,i );
|
String sv = Utils.optStringX( a, i );
|
||||||
if(!TextUtils.isEmpty( sv )){
|
if( ! TextUtils.isEmpty( sv ) ){
|
||||||
dst.media_attachments.add( sv );
|
dst.media_attachments.add( sv );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dst.msp_id = src.optLong("msp_id");
|
dst.msp_id = src.optLong( "msp_id" );
|
||||||
dst.sensitive = (src.optInt( "sensitive" ,0) != 0);
|
dst.sensitive = ( src.optInt( "sensitive", 0 ) != 0 );
|
||||||
|
|
||||||
dst.spoiler_text = Utils.optStringX( src, "spoiler_text" );
|
dst.spoiler_text = Utils.optStringX( src, "spoiler_text" );
|
||||||
if( ! TextUtils.isEmpty( dst.spoiler_text ) ){
|
if( ! TextUtils.isEmpty( dst.spoiler_text ) ){
|
||||||
dst.decoded_spoiler_text = HTMLDecoder.decodeHTML( access_info, dst.spoiler_text ,true,null);
|
dst.decoded_spoiler_text = HTMLDecoder.decodeHTML( access_info, dst.spoiler_text, true, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
dst.content = Utils.optStringX( src, "content" );
|
dst.content = Utils.optStringX( src, "content" );
|
||||||
dst.decoded_content = HTMLDecoder.decodeHTML( access_info, dst.content ,true,null );
|
dst.decoded_content = HTMLDecoder.decodeHTML( access_info, dst.content, true, null );
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List parseList( LogCategory log, SavedAccount access_info, JSONArray array ){
|
||||||
public static List parseList( LogCategory log, SavedAccount access_info,JSONArray array ){
|
|
||||||
List list = new List();
|
List list = new List();
|
||||||
for(int i=0,ie=array.length();i<ie;++i){
|
for( int i = 0, ie = array.length() ; i < ie ; ++ i ){
|
||||||
JSONObject src = array.optJSONObject( i );
|
JSONObject src = array.optJSONObject( i );
|
||||||
if( src == null ) continue;
|
if( src == null ) continue;
|
||||||
MSPToot item = parse( log, access_info,src );
|
MSPToot item = parse( log, access_info, src );
|
||||||
if( item == null ) continue;
|
if( item == null ) continue;
|
||||||
list.add( item );
|
list.add( item );
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Pattern reTime = Pattern.compile( "\\A(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)" );
|
||||||
|
|
||||||
|
|
||||||
|
private static final TimeZone tz_utc = TimeZone.getTimeZone( "UTC" );
|
||||||
|
|
||||||
|
static long parseTime( LogCategory log, String strTime ){
|
||||||
|
if( ! TextUtils.isEmpty( strTime ) ){
|
||||||
|
try{
|
||||||
|
Matcher m = reTime.matcher( strTime );
|
||||||
|
if( ! m.find() ){
|
||||||
|
log.d( "!!invalid time format: %s", strTime );
|
||||||
|
}else{
|
||||||
|
GregorianCalendar g = new GregorianCalendar( tz_utc );
|
||||||
|
g.set(
|
||||||
|
Utils.parse_int( m.group( 1 ), 1 ),
|
||||||
|
Utils.parse_int( m.group( 2 ), 1 ) - 1,
|
||||||
|
Utils.parse_int( m.group( 3 ), 1 ),
|
||||||
|
Utils.parse_int( m.group( 4 ), 0 ),
|
||||||
|
Utils.parse_int( m.group( 5 ), 0 ),
|
||||||
|
Utils.parse_int( m.group( 6 ), 0 )
|
||||||
|
);
|
||||||
|
g.set( Calendar.MILLISECOND, 500 );
|
||||||
|
return g.getTimeInMillis();
|
||||||
|
}
|
||||||
|
}catch( Throwable ex ){// ParseException, ArrayIndexOutOfBoundsException
|
||||||
|
ex.printStackTrace();
|
||||||
|
log.e( ex, "TootStatus.parseTime failed. src=%s", strTime );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkMuted( @NonNull HashSet< String > muted_app, @NonNull WordTrieTree muted_word ){
|
||||||
|
|
||||||
|
// // app mute
|
||||||
|
// if( application != null ){
|
||||||
|
// String name = application.name;
|
||||||
|
// if( name != null ){
|
||||||
|
// if( muted_app.contains( name ) ){
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// word mute
|
||||||
|
if( decoded_content != null && muted_word.containsWord( decoded_content.toString() ) ){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( decoded_spoiler_text != null && muted_word.containsWord( decoded_spoiler_text.toString() ) ){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // reblog
|
||||||
|
// return reblog != null && reblog.checkMuted( muted_app, muted_word );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasMedia(){
|
||||||
|
return media_attachments != null && media_attachments.size() > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,8 +88,6 @@ public class HTMLDecoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static final boolean DEBUG_HTML_PARSER = false;
|
private static final boolean DEBUG_HTML_PARSER = false;
|
||||||
|
|
||||||
private static class Node {
|
private static class Node {
|
||||||
|
@ -135,7 +133,7 @@ public class HTMLDecoder {
|
||||||
LinkClickContext account
|
LinkClickContext account
|
||||||
, SpannableStringBuilder sb
|
, SpannableStringBuilder sb
|
||||||
, boolean bShort
|
, boolean bShort
|
||||||
, @Nullable TootAttachment.List list_attachment
|
, @Nullable TootAttachment.List list_attachment
|
||||||
){
|
){
|
||||||
if( TAG_TEXT.equals( tag ) ){
|
if( TAG_TEXT.equals( tag ) ){
|
||||||
sb.append( Emojione.decodeEmoji( decodeEntity( text ) ) );
|
sb.append( Emojione.decodeEmoji( decodeEntity( text ) ) );
|
||||||
|
@ -145,7 +143,7 @@ public class HTMLDecoder {
|
||||||
|
|
||||||
SpannableStringBuilder sb_tmp;
|
SpannableStringBuilder sb_tmp;
|
||||||
if( bShort && "a".equals( tag ) ){
|
if( bShort && "a".equals( tag ) ){
|
||||||
sb_tmp = new SpannableStringBuilder( );
|
sb_tmp = new SpannableStringBuilder();
|
||||||
}else{
|
}else{
|
||||||
sb_tmp = sb;
|
sb_tmp = sb;
|
||||||
}
|
}
|
||||||
|
@ -153,29 +151,29 @@ public class HTMLDecoder {
|
||||||
int start = sb_tmp.length();
|
int start = sb_tmp.length();
|
||||||
|
|
||||||
for( Node child : child_nodes ){
|
for( Node child : child_nodes ){
|
||||||
child.encodeSpan( account, sb_tmp ,bShort,list_attachment );
|
child.encodeSpan( account, sb_tmp, bShort, list_attachment );
|
||||||
}
|
}
|
||||||
|
|
||||||
int end = sb_tmp.length();
|
int end = sb_tmp.length();
|
||||||
|
|
||||||
if( bShort && "a".equals( tag ) ){
|
if( bShort && "a".equals( tag ) ){
|
||||||
start = sb.length();
|
start = sb.length();
|
||||||
sb.append( encodeShortUrl( sb_tmp.toString(), getHref(), list_attachment ) );
|
sb.append( encodeShortUrl( sb_tmp.toString(), getHref(), list_attachment ) );
|
||||||
end = sb.length();
|
end = sb.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( end > start && "a".equals( tag ) ){
|
if( end > start && "a".equals( tag ) ){
|
||||||
String href = getHref();
|
String href = getHref();
|
||||||
if( href != null){
|
if( href != null ){
|
||||||
MyClickableSpan span = new MyClickableSpan(account,href,account.findAcctColor( href ) ) ;
|
MyClickableSpan span = new MyClickableSpan( account, href, account.findAcctColor( href ) );
|
||||||
sb.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
|
sb.setSpan( span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( DEBUG_HTML_PARSER ) sb.append( "(end " ).append( tag ).append( ")" );
|
if( DEBUG_HTML_PARSER ) sb.append( "(end " ).append( tag ).append( ")" );
|
||||||
|
|
||||||
if( "br".equals( tag ) ) sb.append( '\n' );
|
if( "br".equals( tag ) ) sb.append( '\n' );
|
||||||
|
|
||||||
if( "p".equals( tag ) || "li".equals( tag ) ){
|
if( "p".equals( tag ) || "li".equals( tag ) ){
|
||||||
if( sb.length() > 0 ){
|
if( sb.length() > 0 ){
|
||||||
if( sb.charAt( sb.length() - 1 ) != '\n' ) sb.append( '\n' );
|
if( sb.charAt( sb.length() - 1 ) != '\n' ) sb.append( '\n' );
|
||||||
|
@ -195,7 +193,7 @@ public class HTMLDecoder {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean is_media_attachment( @Nullable TootAttachment.List list_attachment,@Nullable String href){
|
boolean is_media_attachment( @Nullable TootAttachment.List list_attachment, @Nullable String href ){
|
||||||
if( href == null || list_attachment == null ) return false;
|
if( href == null || list_attachment == null ) return false;
|
||||||
for( TootAttachment a : list_attachment ){
|
for( TootAttachment a : list_attachment ){
|
||||||
if( href.equals( a.remote_url )
|
if( href.equals( a.remote_url )
|
||||||
|
@ -205,7 +203,7 @@ public class HTMLDecoder {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CharSequence encodeShortUrl(
|
private CharSequence encodeShortUrl(
|
||||||
String display_url
|
String display_url
|
||||||
, @Nullable String href
|
, @Nullable String href
|
||||||
|
@ -215,8 +213,8 @@ public class HTMLDecoder {
|
||||||
// ハッシュタグやメンションはいじらない
|
// ハッシュタグやメンションはいじらない
|
||||||
return display_url;
|
return display_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( is_media_attachment( list_attachment,href )){
|
if( is_media_attachment( list_attachment, href ) ){
|
||||||
return Emojione.decodeEmoji( ":frame_photo:" );
|
return Emojione.decodeEmoji( ":frame_photo:" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +233,7 @@ public class HTMLDecoder {
|
||||||
sb.append( remain );
|
sb.append( remain );
|
||||||
}
|
}
|
||||||
return sb;
|
return sb;
|
||||||
}catch(Throwable ex){
|
}catch( Throwable ex ){
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
return display_url;
|
return display_url;
|
||||||
}
|
}
|
||||||
|
@ -250,7 +248,7 @@ public class HTMLDecoder {
|
||||||
LinkClickContext account
|
LinkClickContext account
|
||||||
, String src
|
, String src
|
||||||
, boolean bShort
|
, boolean bShort
|
||||||
, @Nullable TootAttachment.List list_attachment
|
, @Nullable TootAttachment.List list_attachment
|
||||||
){
|
){
|
||||||
SpannableStringBuilder sb = new SpannableStringBuilder();
|
SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||||
try{
|
try{
|
||||||
|
@ -259,15 +257,15 @@ public class HTMLDecoder {
|
||||||
Node rootNode = new Node();
|
Node rootNode = new Node();
|
||||||
rootNode.parseChild( tracker, "" );
|
rootNode.parseChild( tracker, "" );
|
||||||
|
|
||||||
rootNode.encodeSpan( account, sb ,bShort,list_attachment);
|
rootNode.encodeSpan( account, sb, bShort, list_attachment );
|
||||||
int end = sb.length();
|
int end = sb.length();
|
||||||
while( end > 0 && isWhitespace( sb.charAt( end - 1 ) ) ) -- end;
|
while( end > 0 && isWhitespace( sb.charAt( end - 1 ) ) ) -- end;
|
||||||
if( end < sb.length() ){
|
if( end < sb.length() ){
|
||||||
sb.delete( end, sb.length() );
|
sb.delete( end, sb.length() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// sb.append( "\n" );
|
// sb.append( "\n" );
|
||||||
// sb.append(src);
|
// sb.append(src);
|
||||||
}
|
}
|
||||||
}catch( Throwable ex ){
|
}catch( Throwable ex ){
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
|
@ -275,29 +273,29 @@ public class HTMLDecoder {
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static Spannable decodeTags( final LinkClickContext account, TootTag.List src_list ){
|
// public static Spannable decodeTags( final LinkClickContext account, TootTag.List src_list ){
|
||||||
// if( src_list == null || src_list.isEmpty() ) return null;
|
// if( src_list == null || src_list.isEmpty() ) return null;
|
||||||
// SpannableStringBuilder sb = new SpannableStringBuilder();
|
// SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||||
// for( TootTag item : src_list ){
|
// for( TootTag item : src_list ){
|
||||||
// if( sb.length() > 0 ) sb.append( " " );
|
// if( sb.length() > 0 ) sb.append( " " );
|
||||||
// int start = sb.length();
|
// int start = sb.length();
|
||||||
// sb.append( '#' );
|
// sb.append( '#' );
|
||||||
// sb.append( item.name );
|
// sb.append( item.name );
|
||||||
// int end = sb.length();
|
// int end = sb.length();
|
||||||
// if( end > start ){
|
// if( end > start ){
|
||||||
// final String item_url = item.url;
|
// final String item_url = item.url;
|
||||||
// sb.setSpan( new ClickableSpan() {
|
// sb.setSpan( new ClickableSpan() {
|
||||||
// @Override public void onClick( View widget ){
|
// @Override public void onClick( View widget ){
|
||||||
// if( link_callback != null ){
|
// if( link_callback != null ){
|
||||||
// link_callback.onClickLink( account, item_url );
|
// link_callback.onClickLink( account, item_url );
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
|
// }, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// return sb;
|
// return sb;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public static Spannable decodeMentions( final LinkClickContext account, TootMention.List src_list ){
|
public static Spannable decodeMentions( final LinkClickContext account, TootMention.List src_list ){
|
||||||
if( src_list == null || src_list.isEmpty() ) return null;
|
if( src_list == null || src_list.isEmpty() ) return null;
|
||||||
|
@ -309,10 +307,9 @@ public class HTMLDecoder {
|
||||||
sb.append( item.acct );
|
sb.append( item.acct );
|
||||||
int end = sb.length();
|
int end = sb.length();
|
||||||
if( end > start ){
|
if( end > start ){
|
||||||
MyClickableSpan span = new MyClickableSpan(account,item.url,account.findAcctColor( item.url ) ) ;
|
MyClickableSpan span = new MyClickableSpan( account, item.url, account.findAcctColor( item.url ) );
|
||||||
|
|
||||||
|
sb.setSpan( span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
|
||||||
sb.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sb;
|
return sb;
|
||||||
|
|
Loading…
Reference in New Issue