903 lines
28 KiB
Java
903 lines
28 KiB
Java
package jp.juggler.subwaytooter;
|
|
|
|
import android.graphics.Bitmap;
|
|
import android.net.Uri;
|
|
import android.os.AsyncTask;
|
|
import android.support.annotation.NonNull;
|
|
import android.support.annotation.Nullable;
|
|
import android.support.v4.view.ViewCompat;
|
|
import android.text.Editable;
|
|
import android.text.TextUtils;
|
|
import android.text.TextWatcher;
|
|
import android.text.method.LinkMovementMethod;
|
|
import android.text.method.MovementMethod;
|
|
import android.view.KeyEvent;
|
|
import android.view.View;
|
|
import android.view.inputmethod.EditorInfo;
|
|
import android.widget.Button;
|
|
import android.widget.CheckBox;
|
|
import android.widget.CompoundButton;
|
|
import android.widget.EditText;
|
|
import android.widget.ImageButton;
|
|
import android.widget.ImageView;
|
|
import android.widget.ListAdapter;
|
|
import android.widget.TextView;
|
|
|
|
import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout;
|
|
import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayoutDirection;
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
import jp.juggler.subwaytooter.table.AcctColor;
|
|
import jp.juggler.subwaytooter.util.HTMLDecoder;
|
|
import jp.juggler.subwaytooter.util.LogCategory;
|
|
import jp.juggler.subwaytooter.view.MyLinkMovementMethod;
|
|
import jp.juggler.subwaytooter.view.MyListView;
|
|
import jp.juggler.subwaytooter.util.ScrollPosition;
|
|
import jp.juggler.subwaytooter.util.Utils;
|
|
|
|
class ColumnViewHolder
|
|
implements View.OnClickListener
|
|
, SwipyRefreshLayout.OnRefreshListener
|
|
, CompoundButton.OnCheckedChangeListener
|
|
{
|
|
private static final LogCategory log = new LogCategory( "ColumnViewHolder" );
|
|
|
|
final ActMain activity;
|
|
|
|
@Nullable Column column;
|
|
@Nullable private ItemListAdapter status_adapter;
|
|
private int page_idx;
|
|
|
|
private final TextView tvLoading;
|
|
private final MyListView listView;
|
|
private final SwipyRefreshLayout swipyRefreshLayout;
|
|
|
|
private final View llColumnHeader;
|
|
private final TextView tvColumnIndex;
|
|
private final TextView tvColumnContext;
|
|
private final ImageView ivColumnIcon;
|
|
private final TextView tvColumnName;
|
|
|
|
private final View llColumnSetting;
|
|
|
|
private final View btnSearch;
|
|
private final EditText etSearch;
|
|
private final CheckBox cbResolve;
|
|
private final EditText etRegexFilter;
|
|
private final TextView tvRegexFilterError;
|
|
|
|
private final ImageButton btnColumnSetting;
|
|
private final ImageButton btnColumnReload;
|
|
private final ImageButton btnColumnClose;
|
|
|
|
private final View flColumnBackground;
|
|
private final ImageView ivColumnBackgroundImage;
|
|
private final View llSearch;
|
|
private final CheckBox cbDontCloseColumn;
|
|
private final CheckBox cbWithAttachment;
|
|
private final CheckBox cbDontShowBoost;
|
|
private final CheckBox cbDontShowReply;
|
|
private final CheckBox cbDontStreaming;
|
|
private final CheckBox cbDontAutoRefresh;
|
|
private final CheckBox cbHideMediaDefault;
|
|
private final CheckBox cbEnableSpeech;
|
|
private final View llRegexFilter;
|
|
private final Button btnDeleteNotification;
|
|
|
|
private final TextView tvSearchDesc;
|
|
|
|
ColumnViewHolder( ActMain arg_activity, View root ){
|
|
this.activity = arg_activity;
|
|
|
|
if( activity.timeline_font != null ){
|
|
Utils.scanView( root, new Utils.ScanViewCallback() {
|
|
@Override public void onScanView( View v ){
|
|
try{
|
|
if( v instanceof Button ){
|
|
// ボタンは太字なので触らない
|
|
}else if( v instanceof TextView ){
|
|
( (TextView) v ).setTypeface( activity.timeline_font );
|
|
}
|
|
}catch(Throwable ex){
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
|
|
|
|
flColumnBackground = root.findViewById( R.id.flColumnBackground );
|
|
ivColumnBackgroundImage = (ImageView) root.findViewById( R.id.ivColumnBackgroundImage );
|
|
llColumnHeader = root.findViewById( R.id.llColumnHeader );
|
|
|
|
tvColumnIndex = (TextView) root.findViewById( R.id.tvColumnIndex );
|
|
|
|
tvColumnName = (TextView) root.findViewById( R.id.tvColumnName );
|
|
tvColumnContext = (TextView) root.findViewById( R.id.tvColumnContext );
|
|
ivColumnIcon = (ImageView) root.findViewById( R.id.ivColumnIcon );
|
|
|
|
btnColumnSetting = (ImageButton) root.findViewById( R.id.btnColumnSetting );
|
|
btnColumnReload = (ImageButton) root.findViewById( R.id.btnColumnReload );
|
|
btnColumnClose = (ImageButton) root.findViewById( R.id.btnColumnClose );
|
|
|
|
tvLoading = (TextView) root.findViewById( R.id.tvLoading );
|
|
listView = (MyListView) root.findViewById( R.id.listView );
|
|
|
|
btnSearch = root.findViewById( R.id.btnSearch );
|
|
etSearch = (EditText) root.findViewById( R.id.etSearch );
|
|
cbResolve = (CheckBox) root.findViewById( R.id.cbResolve );
|
|
|
|
llSearch = root.findViewById( R.id.llSearch );
|
|
|
|
llColumnSetting = root.findViewById( R.id.llColumnSetting );
|
|
|
|
cbDontCloseColumn = (CheckBox) root.findViewById( R.id.cbDontCloseColumn );
|
|
cbWithAttachment = (CheckBox) root.findViewById( R.id.cbWithAttachment );
|
|
cbDontShowBoost = (CheckBox) root.findViewById( R.id.cbDontShowBoost );
|
|
cbDontShowReply = (CheckBox) root.findViewById( R.id.cbDontShowReply );
|
|
cbDontStreaming = (CheckBox) root.findViewById( R.id.cbDontStreaming );
|
|
cbDontAutoRefresh = (CheckBox) root.findViewById( R.id.cbDontAutoRefresh );
|
|
cbHideMediaDefault = (CheckBox) root.findViewById( R.id.cbHideMediaDefault );
|
|
cbEnableSpeech = (CheckBox) root.findViewById( R.id.cbEnableSpeech );
|
|
etRegexFilter = (EditText) root.findViewById( R.id.etRegexFilter );
|
|
llRegexFilter = root.findViewById( R.id.llRegexFilter );
|
|
tvRegexFilterError = (TextView) root.findViewById( R.id.tvRegexFilterError );
|
|
|
|
tvSearchDesc = (TextView) root.findViewById( R.id.tvSearchDesc );
|
|
|
|
btnDeleteNotification = (Button) root.findViewById( R.id.btnDeleteNotification );
|
|
|
|
llColumnHeader.setOnClickListener( this );
|
|
btnColumnSetting.setOnClickListener( this );
|
|
btnColumnReload.setOnClickListener( this );
|
|
btnColumnClose.setOnClickListener( this );
|
|
btnDeleteNotification.setOnClickListener( this );
|
|
|
|
root.findViewById( R.id.btnColor ).setOnClickListener( this );
|
|
|
|
this.swipyRefreshLayout = (SwipyRefreshLayout) root.findViewById( R.id.swipyRefreshLayout );
|
|
swipyRefreshLayout.setOnRefreshListener( this );
|
|
swipyRefreshLayout.setDistanceToTriggerSync( (int) ( 0.5f + 20f * activity.density ) );
|
|
|
|
cbDontCloseColumn.setOnCheckedChangeListener( this );
|
|
cbWithAttachment.setOnCheckedChangeListener( this );
|
|
cbDontShowBoost.setOnCheckedChangeListener( this );
|
|
cbDontShowReply.setOnCheckedChangeListener( this );
|
|
cbDontStreaming.setOnCheckedChangeListener( this );
|
|
cbDontAutoRefresh.setOnCheckedChangeListener( this );
|
|
cbHideMediaDefault.setOnCheckedChangeListener( this );
|
|
cbEnableSpeech.setOnCheckedChangeListener( this );
|
|
|
|
// 入力の追跡
|
|
etRegexFilter.addTextChangedListener( new TextWatcher() {
|
|
@Override
|
|
public void beforeTextChanged( CharSequence s, int start, int count, int after ){
|
|
}
|
|
|
|
@Override
|
|
public void onTextChanged( CharSequence s, int start, int before, int count ){
|
|
}
|
|
|
|
@Override public void afterTextChanged( Editable s ){
|
|
if( loading_busy ) return;
|
|
activity.handler.removeCallbacks( proc_start_filter );
|
|
if( isRegexValid() ){
|
|
activity.handler.postDelayed( proc_start_filter, 1500L );
|
|
}
|
|
}
|
|
} );
|
|
|
|
btnSearch.setOnClickListener( this );
|
|
etSearch.setOnEditorActionListener( new TextView.OnEditorActionListener() {
|
|
@Override public boolean onEditorAction( TextView v, int actionId, KeyEvent event ){
|
|
if( !loading_busy ){
|
|
if( actionId == EditorInfo.IME_ACTION_SEARCH ){
|
|
btnSearch.performClick();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
} );
|
|
|
|
}
|
|
|
|
private boolean isPageDestroyed(){
|
|
return column ==null || activity.isFinishing();
|
|
}
|
|
|
|
void onPageDestroy(int page_idx){
|
|
// タブレットモードの場合、onPageCreateより前に呼ばれる
|
|
|
|
if( column != null ){
|
|
log.d( "onPageDestroy [%d] %s",page_idx, tvColumnName.getText() );
|
|
saveScrollPosition();
|
|
listView.setAdapter( null );
|
|
column.removeColumnViewHolder( this );
|
|
column = null;
|
|
}
|
|
|
|
closeBitmaps();
|
|
|
|
activity.closeListItemPopup();
|
|
}
|
|
|
|
private static void vg( View v, boolean visible ){
|
|
v.setVisibility( visible ? View.VISIBLE : View.GONE );
|
|
}
|
|
|
|
private boolean loading_busy;
|
|
|
|
void onPageCreate( @NonNull Column column, int page_idx, int page_count ){
|
|
loading_busy = true;
|
|
try{
|
|
this.column = column;
|
|
this.page_idx = page_idx;
|
|
|
|
log.d( "onPageCreate [%d] %s",page_idx, column.getColumnName( true ) );
|
|
|
|
boolean bSimpleList = ( column.column_type != Column.TYPE_CONVERSATION && activity.pref.getBoolean( Pref.KEY_SIMPLE_LIST, false ) );
|
|
|
|
tvColumnIndex.setText( activity.getString( R.string.column_index, page_idx + 1, page_count ) );
|
|
|
|
listView.setAdapter( null );
|
|
|
|
this.status_adapter = new ItemListAdapter( activity, column , bSimpleList );
|
|
if( column.column_type == Column.TYPE_PROFILE ){
|
|
status_adapter.header =new HeaderViewHolder( activity, column, listView );
|
|
}else{
|
|
status_adapter.header = null;
|
|
}
|
|
|
|
boolean bAllowFilter;
|
|
switch( column.column_type ){
|
|
default:
|
|
bAllowFilter = true;
|
|
break;
|
|
case Column.TYPE_SEARCH:
|
|
case Column.TYPE_SEARCH_PORTAL:
|
|
case Column.TYPE_CONVERSATION:
|
|
case Column.TYPE_REPORTS:
|
|
case Column.TYPE_BLOCKS:
|
|
case Column.TYPE_DOMAIN_BLOCKS:
|
|
case Column.TYPE_MUTES:
|
|
case Column.TYPE_FOLLOW_REQUESTS:
|
|
case Column.TYPE_NOTIFICATIONS:
|
|
bAllowFilter = false;
|
|
break;
|
|
}
|
|
|
|
boolean bAllowFilterBoost;
|
|
switch( column.column_type ){
|
|
default:
|
|
bAllowFilterBoost = false;
|
|
break;
|
|
case Column.TYPE_HOME:
|
|
case Column.TYPE_PROFILE:
|
|
bAllowFilterBoost = true;
|
|
break;
|
|
}
|
|
|
|
llColumnSetting.setVisibility( View.GONE );
|
|
|
|
cbDontCloseColumn.setChecked( column.dont_close );
|
|
cbWithAttachment.setChecked( column.with_attachment );
|
|
cbDontShowBoost.setChecked( column.dont_show_boost );
|
|
cbDontShowReply.setChecked( column.dont_show_reply );
|
|
cbDontStreaming.setChecked( column.dont_streaming );
|
|
cbDontAutoRefresh.setChecked( column.dont_auto_refresh );
|
|
cbHideMediaDefault.setChecked( column.hide_media_default );
|
|
cbEnableSpeech.setChecked( column.enable_speech );
|
|
|
|
etRegexFilter.setText( column.regex_text );
|
|
etSearch.setText( column.search_query );
|
|
cbResolve.setChecked( column.search_resolve );
|
|
|
|
vg( cbWithAttachment, bAllowFilter );
|
|
vg( cbDontShowBoost, bAllowFilterBoost );
|
|
vg( cbDontShowReply, bAllowFilterBoost );
|
|
vg( cbDontStreaming, column.canStreaming() );
|
|
vg( cbDontAutoRefresh, column.canAutoRefresh() );
|
|
vg( cbHideMediaDefault, column.canShowMedia() );
|
|
vg( cbEnableSpeech, column.canSpeech() );
|
|
|
|
vg( etRegexFilter, bAllowFilter );
|
|
vg( llRegexFilter, bAllowFilter );
|
|
|
|
vg( btnDeleteNotification, column.column_type == Column.TYPE_NOTIFICATIONS );
|
|
vg( llSearch, (column.column_type == Column.TYPE_SEARCH || column.column_type == Column.TYPE_SEARCH_PORTAL ) );
|
|
vg( cbResolve, (column.column_type == Column.TYPE_SEARCH ) );
|
|
|
|
// tvRegexFilterErrorの表示を更新
|
|
if( bAllowFilter ){
|
|
isRegexValid();
|
|
}
|
|
|
|
switch( column.column_type ){
|
|
default:
|
|
swipyRefreshLayout.setEnabled( true );
|
|
swipyRefreshLayout.setDirection( SwipyRefreshLayoutDirection.BOTH );
|
|
break;
|
|
|
|
case Column.TYPE_CONVERSATION:
|
|
case Column.TYPE_SEARCH:
|
|
swipyRefreshLayout.setEnabled( false );
|
|
break;
|
|
|
|
case Column.TYPE_SEARCH_PORTAL:
|
|
swipyRefreshLayout.setEnabled( true );
|
|
swipyRefreshLayout.setDirection( SwipyRefreshLayoutDirection.BOTTOM );
|
|
break;
|
|
|
|
}
|
|
|
|
switch( column.column_type ){
|
|
default:
|
|
tvSearchDesc.setVisibility( View.GONE );
|
|
break;
|
|
case Column.TYPE_SEARCH:
|
|
showSearchDesc( activity.getString( R.string.search_desc_mastodon_api ) );
|
|
break;
|
|
case Column.TYPE_SEARCH_PORTAL:
|
|
showSearchDesc( getSearchDescPortal() );
|
|
break;
|
|
}
|
|
|
|
//
|
|
listView.setAdapter( status_adapter );
|
|
listView.setFastScrollEnabled( ! Pref.pref( activity ).getBoolean( Pref.KEY_DISABLE_FAST_SCROLLER, true ) );
|
|
listView.setOnItemClickListener( status_adapter );
|
|
|
|
column.addColumnViewHolder( this );
|
|
|
|
showColumnColor();
|
|
|
|
showContent();
|
|
}finally{
|
|
loading_busy = false;
|
|
}
|
|
}
|
|
|
|
private String getSearchDescPortal(){
|
|
String language_code = activity.getString( R.string.language_code );
|
|
int res_id;
|
|
if( "ja".equals( language_code ) ){
|
|
res_id = R.raw.search_desc_portal_ja;
|
|
}else{
|
|
res_id = R.raw.search_desc_portal_en;
|
|
}
|
|
byte[] data = Utils.loadRawResource(activity,res_id);
|
|
return data == null ? null : Utils.decodeUTF8( data );
|
|
}
|
|
|
|
private void showSearchDesc( String html ){
|
|
if( column==null) return;
|
|
log.d("showSearchDesc: html=%s",html);
|
|
tvSearchDesc.setVisibility( View.VISIBLE );
|
|
tvSearchDesc.setMovementMethod( MyLinkMovementMethod.getInstance() );
|
|
CharSequence sv = HTMLDecoder.decodeHTML( column.access_info, html, false, null );
|
|
tvSearchDesc.setText( sv );
|
|
}
|
|
|
|
void showColumnColor(){
|
|
if( column == null ) return;
|
|
|
|
int c = column.header_bg_color;
|
|
if( c == 0 ){
|
|
llColumnHeader.setBackgroundResource( R.drawable.btn_bg_ddd );
|
|
}else{
|
|
ViewCompat.setBackground( llColumnHeader, Styler.getAdaptiveRippleDrawable(
|
|
c,
|
|
( column.header_fg_color != 0 ? column.header_fg_color :
|
|
Styler.getAttributeColor( activity, R.attr.colorRippleEffect ) )
|
|
) );
|
|
}
|
|
|
|
c = column.header_fg_color;
|
|
if( c == 0 ){
|
|
tvColumnIndex.setTextColor( Styler.getAttributeColor( activity, R.attr.colorColumnHeaderPageNumber ) );
|
|
tvColumnName.setTextColor( Styler.getAttributeColor( activity, android.R.attr.textColorPrimary ) );
|
|
Styler.setIconDefaultColor( activity, ivColumnIcon, Column.getIconAttrId( column.column_type ) );
|
|
Styler.setIconDefaultColor( activity, btnColumnSetting, R.attr.ic_tune );
|
|
Styler.setIconDefaultColor( activity, btnColumnReload, R.attr.btn_refresh );
|
|
Styler.setIconDefaultColor( activity, btnColumnClose, R.attr.btn_close );
|
|
}else{
|
|
tvColumnIndex.setTextColor( c );
|
|
tvColumnName.setTextColor( c );
|
|
Styler.setIconCustomColor( activity, ivColumnIcon, c, Column.getIconAttrId( column.column_type ) );
|
|
Styler.setIconCustomColor( activity, btnColumnSetting, c, R.attr.ic_tune );
|
|
Styler.setIconCustomColor( activity, btnColumnReload, c, R.attr.btn_refresh );
|
|
Styler.setIconCustomColor( activity, btnColumnClose, c, R.attr.btn_close );
|
|
}
|
|
|
|
c = column.column_bg_color;
|
|
if( c == 0 ){
|
|
ViewCompat.setBackground( flColumnBackground, null );
|
|
}else{
|
|
flColumnBackground.setBackgroundColor( c );
|
|
}
|
|
|
|
ivColumnBackgroundImage.setAlpha( column.column_bg_image_alpha );
|
|
|
|
loadBackgroundImage( ivColumnBackgroundImage, column.column_bg_image );
|
|
|
|
|
|
if( status_adapter != null && status_adapter.header != null ){
|
|
status_adapter.header.showColor();
|
|
}
|
|
}
|
|
|
|
|
|
private String last_image_uri;
|
|
private Bitmap last_image_bitmap;
|
|
private AsyncTask<Void,Void,Bitmap> last_image_task;
|
|
|
|
private void closeBitmaps(){
|
|
try{
|
|
ivColumnBackgroundImage.setVisibility( View.GONE );
|
|
ivColumnBackgroundImage.setImageDrawable( null );
|
|
|
|
if( last_image_bitmap != null ){
|
|
last_image_bitmap.recycle();
|
|
last_image_bitmap = null;
|
|
}
|
|
|
|
if( last_image_task != null ){
|
|
last_image_task.cancel( true );
|
|
last_image_task = null;
|
|
}
|
|
|
|
last_image_uri = null;
|
|
|
|
}catch( Throwable ex ){
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private void loadBackgroundImage( final ImageView iv, final String url ){
|
|
try{
|
|
if( TextUtils.isEmpty( url ) ){
|
|
// 指定がないなら閉じる
|
|
closeBitmaps();
|
|
return;
|
|
}
|
|
|
|
if( url.equals( last_image_uri ) ){
|
|
// 今表示してるのと同じ
|
|
return;
|
|
}
|
|
|
|
// 直前の処理をキャンセルする。Bitmapも破棄する
|
|
closeBitmaps();
|
|
|
|
if( TextUtils.isEmpty( url ) ){
|
|
// この状態でOK
|
|
return;
|
|
}
|
|
last_image_uri = url;
|
|
|
|
final int screen_w = iv.getResources().getDisplayMetrics().widthPixels;
|
|
final int screen_h = iv.getResources().getDisplayMetrics().heightPixels;
|
|
|
|
// 非同期処理を開始
|
|
last_image_task = new AsyncTask< Void, Void, Bitmap >() {
|
|
@Override protected Bitmap doInBackground( Void... params ){
|
|
try{
|
|
int resize_max = ( screen_w > screen_h ? screen_w : screen_h );
|
|
Uri uri = Uri.parse( url );
|
|
return Utils.createResizedBitmap( log, activity, uri, false, resize_max );
|
|
|
|
|
|
}catch(Throwable ex){
|
|
ex.printStackTrace();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override protected void onCancelled( Bitmap bitmap ){
|
|
onPostExecute( bitmap );
|
|
}
|
|
@Override protected void onPostExecute( Bitmap bitmap ){
|
|
if( bitmap !=null ){
|
|
if( isCancelled() || ! url.equals( last_image_uri ) ){
|
|
bitmap.recycle();
|
|
}else{
|
|
last_image_bitmap = bitmap;
|
|
iv.setImageBitmap( last_image_bitmap );
|
|
iv.setVisibility( View.VISIBLE );
|
|
}
|
|
}
|
|
}
|
|
};
|
|
last_image_task.executeOnExecutor( App1.task_executor );
|
|
|
|
}catch( Throwable ex ){
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private final Runnable proc_start_filter = new Runnable() {
|
|
@Override public void run(){
|
|
if( isPageDestroyed() ) return;
|
|
if( column == null ) return;
|
|
|
|
if( isRegexValid() ){
|
|
column.regex_text = etRegexFilter.getText().toString();
|
|
activity.app_state.saveColumnList();
|
|
column.startLoading();
|
|
}
|
|
}
|
|
};
|
|
|
|
private boolean isRegexValid(){
|
|
String s = etRegexFilter.getText().toString();
|
|
if( s.length() == 0 ){
|
|
tvRegexFilterError.setText( "" );
|
|
return true;
|
|
}
|
|
try{
|
|
//noinspection ResultOfMethodCallIgnored
|
|
Pattern.compile( s ).matcher( "" );
|
|
tvRegexFilterError.setText( "" );
|
|
return true;
|
|
}catch( Throwable ex ){
|
|
String message = ex.getMessage();
|
|
if( TextUtils.isEmpty( message ) )
|
|
message = Utils.formatError( ex, activity.getResources(), R.string.regex_error );
|
|
tvRegexFilterError.setText( message );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
boolean isColumnSettingShown(){
|
|
return llColumnSetting.getVisibility() == View.VISIBLE;
|
|
}
|
|
|
|
void closeColumnSetting(){
|
|
llColumnSetting.setVisibility( View.GONE );
|
|
}
|
|
|
|
@Override public void onRefresh( SwipyRefreshLayoutDirection direction ){
|
|
if( column == null ) return;
|
|
|
|
// カラムを追加/削除したときに ColumnからColumnViewHolderへの参照が外れることがある
|
|
// リロードやリフレッシュ操作で直るようにする
|
|
column.addColumnViewHolder( this );
|
|
|
|
column.startRefresh( false, direction == SwipyRefreshLayoutDirection.BOTTOM, - 1L, - 1 );
|
|
}
|
|
|
|
@Override public void onCheckedChanged( CompoundButton view, boolean isChecked ){
|
|
if( loading_busy || column ==null || status_adapter ==null ) return;
|
|
|
|
// カラムを追加/削除したときに ColumnからColumnViewHolderへの参照が外れることがある
|
|
// リロードやリフレッシュ操作で直るようにする
|
|
column.addColumnViewHolder( this );
|
|
|
|
switch( view.getId() ){
|
|
|
|
case R.id.cbDontCloseColumn:
|
|
column.dont_close = isChecked;
|
|
showColumnCloseButton();
|
|
activity.app_state.saveColumnList();
|
|
break;
|
|
|
|
case R.id.cbWithAttachment:
|
|
column.with_attachment = isChecked;
|
|
activity.app_state.saveColumnList();
|
|
column.startLoading();
|
|
break;
|
|
|
|
case R.id.cbDontShowBoost:
|
|
column.dont_show_boost = isChecked;
|
|
activity.app_state.saveColumnList();
|
|
column.startLoading();
|
|
break;
|
|
|
|
case R.id.cbDontShowReply:
|
|
column.dont_show_reply = isChecked;
|
|
activity.app_state.saveColumnList();
|
|
column.startLoading();
|
|
break;
|
|
|
|
case R.id.cbDontStreaming:
|
|
column.dont_streaming = isChecked;
|
|
activity.app_state.saveColumnList();
|
|
if( isChecked ){
|
|
column.stopStreaming();
|
|
}else{
|
|
column.onResume( activity );
|
|
}
|
|
break;
|
|
|
|
case R.id.cbDontAutoRefresh:
|
|
column.dont_auto_refresh = isChecked;
|
|
activity.app_state.saveColumnList();
|
|
break;
|
|
|
|
case R.id.cbHideMediaDefault:
|
|
column.hide_media_default = isChecked;
|
|
activity.app_state.saveColumnList();
|
|
column.fireShowContent();
|
|
break;
|
|
|
|
case R.id.cbEnableSpeech:
|
|
column.enable_speech = isChecked;
|
|
activity.app_state.saveColumnList();
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onClick( View v ){
|
|
if( loading_busy || column ==null || status_adapter ==null ) return;
|
|
|
|
// カラムを追加/削除したときに ColumnからColumnViewHolderへの参照が外れることがある
|
|
// リロードやリフレッシュ操作で直るようにする
|
|
column.addColumnViewHolder( this );
|
|
|
|
switch( v.getId() ){
|
|
case R.id.btnColumnClose:
|
|
activity.closeColumn( false, column );
|
|
break;
|
|
|
|
case R.id.btnColumnReload:
|
|
if( column.column_type == Column.TYPE_SEARCH || column.column_type == Column.TYPE_SEARCH_PORTAL ){
|
|
Utils.hideKeyboard( activity, etSearch );
|
|
etSearch.setText( column.search_query );
|
|
cbResolve.setChecked( column.search_resolve );
|
|
}
|
|
swipyRefreshLayout.setRefreshing( false );
|
|
column.startLoading();
|
|
break;
|
|
|
|
case R.id.btnSearch:
|
|
Utils.hideKeyboard( activity, etSearch );
|
|
column.search_query = etSearch.getText().toString().trim();
|
|
column.search_resolve = cbResolve.isChecked();
|
|
activity.app_state.saveColumnList();
|
|
column.startLoading();
|
|
break;
|
|
|
|
case R.id.llColumnHeader:
|
|
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;
|
|
|
|
case R.id.btnDeleteNotification:
|
|
activity.deleteNotification( false, column.access_info );
|
|
break;
|
|
|
|
case R.id.btnColor:
|
|
int idx = activity.app_state.column_list.indexOf( column );
|
|
ActColumnCustomize.open( activity, idx, ActMain.REQUEST_COLUMN_COLOR );
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
private void showError( String message ){
|
|
tvLoading.setVisibility( View.VISIBLE );
|
|
tvLoading.setText( message );
|
|
|
|
swipyRefreshLayout.setRefreshing( false );
|
|
swipyRefreshLayout.setVisibility( View.GONE );
|
|
|
|
}
|
|
|
|
private void showColumnCloseButton(){
|
|
if( column == null ) return;
|
|
// カラム保護の状態
|
|
btnColumnClose.setEnabled( ! column.dont_close );
|
|
btnColumnClose.setAlpha( column.dont_close ? 0.3f : 1f );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// Column から呼ばれる
|
|
|
|
boolean hasHeaderView(){
|
|
return status_adapter != null && status_adapter.header != null;
|
|
}
|
|
|
|
SwipyRefreshLayout getRefreshLayout(){
|
|
return swipyRefreshLayout;
|
|
}
|
|
|
|
MyListView getListView(){
|
|
return listView;
|
|
}
|
|
|
|
// カラムヘッダなど、負荷が低い部分の表示更新
|
|
void showColumnHeader(){
|
|
if( column == null ) return;
|
|
|
|
String acct = column.access_info.acct;
|
|
AcctColor ac = AcctColor.load( acct );
|
|
int c;
|
|
|
|
tvColumnContext.setText( ac != null && ! TextUtils.isEmpty( ac.nickname ) ? ac.nickname : acct );
|
|
|
|
c = ( ac != null ? ac.color_fg : 0 );
|
|
tvColumnContext.setTextColor( c != 0 ? c : Styler.getAttributeColor( activity, R.attr.colorAcctSmall ) );
|
|
|
|
c = ( ac != null ? ac.color_bg : 0 );
|
|
if( c == 0 ){
|
|
ViewCompat.setBackground( tvColumnContext, null );
|
|
}else{
|
|
tvColumnContext.setBackgroundColor( c );
|
|
}
|
|
tvColumnContext.setPaddingRelative( activity.acct_pad_lr, 0, activity.acct_pad_lr, 0 );
|
|
|
|
tvColumnName.setText( column.getColumnName( false ) );
|
|
|
|
showColumnCloseButton();
|
|
|
|
}
|
|
|
|
void showContent(){
|
|
// クラッシュレポートにadapterとリストデータの状態不整合が多かったので、
|
|
// とりあえずリストデータ変更の通知だけは最優先で行っておく
|
|
try{
|
|
if( status_adapter != null ) status_adapter.notifyDataSetChanged();
|
|
}catch( Throwable ex ){
|
|
ex.printStackTrace();
|
|
}
|
|
|
|
showColumnHeader();
|
|
|
|
if( column == null || column.is_dispose.get() ){
|
|
showError( "column was disposed." );
|
|
return;
|
|
}
|
|
|
|
if( ! column.bFirstInitialized ){
|
|
showError( "initializing" );
|
|
return;
|
|
}
|
|
|
|
if( column.bInitialLoading ){
|
|
String message = column.task_progress;
|
|
if( message == null ) message = "loading?";
|
|
showError( message );
|
|
return;
|
|
}
|
|
|
|
if( ! TextUtils.isEmpty( column.mInitialLoadingError ) ){
|
|
showError( column.mInitialLoadingError );
|
|
return;
|
|
}
|
|
|
|
|
|
if( status_adapter.getCount() == 0 ){
|
|
showError( activity.getString( R.string.list_empty ) );
|
|
return;
|
|
}
|
|
|
|
tvLoading.setVisibility( View.GONE );
|
|
|
|
swipyRefreshLayout.setVisibility( View.VISIBLE );
|
|
|
|
if( status_adapter.header != null ){
|
|
status_adapter.header.bind( column.who_account );
|
|
}
|
|
|
|
if( ! column.bRefreshLoading ){
|
|
swipyRefreshLayout.setRefreshing( false );
|
|
if( column.mRefreshLoadingError != null ){
|
|
Utils.showToast( activity, true, column.mRefreshLoadingError );
|
|
column.mRefreshLoadingError = null;
|
|
}
|
|
}
|
|
|
|
// 表示状態が変わった後にもう一度呼び出す必要があるらしい。。。
|
|
status_adapter.notifyDataSetChanged();
|
|
|
|
proc_restoreScrollPosition.run();
|
|
}
|
|
|
|
private final Runnable proc_restoreScrollPosition = new Runnable() {
|
|
@Override public void run(){
|
|
activity.handler.removeCallbacks( proc_restoreScrollPosition );
|
|
|
|
if( isPageDestroyed() ){
|
|
log.d( "restoreScrollPosition [%d], page is destroyed.");
|
|
return;
|
|
}
|
|
|
|
if( column == null ){
|
|
log.d( "restoreScrollPosition [%d], column==null",page_idx);
|
|
return;
|
|
}
|
|
|
|
if( column .is_dispose.get() ){
|
|
log.d( "restoreScrollPosition [%d], column is disposed",page_idx);
|
|
return;
|
|
}
|
|
|
|
if( column.hasMultipleViewHolder() ){
|
|
log.d( "restoreScrollPosition [%d] %s , column has multiple view holder. retry later.", page_idx, column.getColumnName( true ));
|
|
|
|
// タブレットモードでカラムを追加/削除した際に発生する。
|
|
// このタイミングでスクロール位置を復元してもうまくいかないので延期する
|
|
activity.handler.post( proc_restoreScrollPosition );
|
|
return;
|
|
}
|
|
|
|
ScrollPosition sp = column.scroll_save;
|
|
if( sp == null ){
|
|
log.d( "restoreScrollPosition [%d] %s , column has no saved scroll position.", page_idx, column.getColumnName( true ));
|
|
return;
|
|
}
|
|
|
|
column.scroll_save = null;
|
|
|
|
if( listView.getVisibility() != View.VISIBLE ){
|
|
log.d( "restoreScrollPosition [%d] %s , listView is not visible. saved position %s,%s is dropped."
|
|
, page_idx, column.getColumnName( true )
|
|
,sp.pos
|
|
,sp.top
|
|
);
|
|
}else{
|
|
log.d( "restoreScrollPosition [%d] %s , listView is visible. resume %s,%s"
|
|
, page_idx, column.getColumnName( true )
|
|
,sp.pos
|
|
,sp.top
|
|
);
|
|
sp.restore( listView );
|
|
}
|
|
|
|
}
|
|
};
|
|
|
|
|
|
private void saveScrollPosition(){
|
|
|
|
if( column == null ){
|
|
log.d( "saveScrollPosition [%d] , column==null",page_idx );
|
|
|
|
}else if( column.is_dispose.get() ){
|
|
log.d( "saveScrollPosition [%d] , column is disposed",page_idx );
|
|
|
|
}else if( listView.getVisibility() != View.VISIBLE ){
|
|
|
|
column.scroll_save = new ScrollPosition( 0, 0 );
|
|
log.d( "saveScrollPosition [%d] %s , listView is not visible, save %s,%s"
|
|
, page_idx, column.getColumnName( true )
|
|
,column.scroll_save.pos
|
|
,column.scroll_save.top
|
|
);
|
|
}else{
|
|
|
|
column.scroll_save = new ScrollPosition( listView );
|
|
log.d( "saveScrollPosition [%d] %s , listView is visible, save %s,%s"
|
|
, page_idx, column.getColumnName( true )
|
|
,column.scroll_save.pos
|
|
,column.scroll_save.top
|
|
);
|
|
}
|
|
}
|
|
|
|
@NonNull ScrollPosition getScrollPosition(){
|
|
return new ScrollPosition( listView );
|
|
}
|
|
|
|
void setScrollPosition( @NonNull ScrollPosition sp, final float delta ){
|
|
final ListAdapter last_adapter = listView.getAdapter();
|
|
if( column == null || last_adapter == null ) return;
|
|
|
|
sp.restore( listView );
|
|
|
|
listView.postDelayed( new Runnable() {
|
|
@Override public void run(){
|
|
if( column == null || listView.getAdapter() != last_adapter ) return;
|
|
listView.scrollListBy( (int) ( delta * activity.density ) );
|
|
}
|
|
}, 20L );
|
|
}
|
|
}
|