カラム設定にブースト非表示、返信非表示、正規表現フィルタ、通知の削除を追加。発言の公開範囲が非公開以下だった場合にブーストボタンの表示を変更
This commit is contained in:
parent
6689da0bb3
commit
943498928b
|
@ -9,8 +9,8 @@ android {
|
|||
applicationId "jp.juggler.subwaytooter"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 16
|
||||
versionName "0.1.6"
|
||||
versionCode 17
|
||||
versionName "0.1.7"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
|
||||
android:windowSoftInputMode="adjustPan|stateAlwaysHidden"
|
||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
|
||||
>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
|
|
@ -8,10 +8,10 @@ import android.content.SharedPreferences;
|
|||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.os.AsyncTaskCompat;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
@ -72,6 +72,7 @@ public class ActMain extends AppCompatActivity
|
|||
float density;
|
||||
|
||||
SharedPreferences pref;
|
||||
Handler handler;
|
||||
|
||||
@Override
|
||||
protected void onCreate( Bundle savedInstanceState ){
|
||||
|
@ -82,6 +83,7 @@ public class ActMain extends AppCompatActivity
|
|||
requestWindowFeature( Window.FEATURE_NO_TITLE );
|
||||
|
||||
pref = Pref.pref( this );
|
||||
handler = new Handler( );
|
||||
|
||||
initUI();
|
||||
|
||||
|
@ -470,7 +472,7 @@ public class ActMain extends AppCompatActivity
|
|||
if( account != null ){
|
||||
Column column = addColumn( account, Column.TYPE_NOTIFICATIONS );
|
||||
if( ! column.bInitialLoading ){
|
||||
column.reload();
|
||||
column.startLoading();
|
||||
}
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
|
@ -552,7 +554,7 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
this.host = client.instance;
|
||||
|
||||
TootApiResult result = client.authorize2( uri.toString(), code );
|
||||
TootApiResult result = client.authorize2( code );
|
||||
if( result != null && result.object != null ){
|
||||
// taは使い捨てなので、生成に使うLinkClickContextはダミーで問題ない
|
||||
LinkClickContext lcc = new LinkClickContext() {
|
||||
|
@ -592,7 +594,7 @@ public class ActMain extends AppCompatActivity
|
|||
// 自動でリロードする
|
||||
for( Column c : pager_adapter.column_list ){
|
||||
if( c.access_info.acct.equals( sa.acct ) ){
|
||||
c.reload();
|
||||
c.startLoading();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -714,6 +716,7 @@ public class ActMain extends AppCompatActivity
|
|||
addColumn( access_info, Column.TYPE_HASHTAG, tag );
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
interface GetAccountCallback {
|
||||
|
@ -1944,4 +1947,73 @@ public class ActMain extends AppCompatActivity
|
|||
startActivityForResult( new Intent( this, ActAbout.class ), REQUEST_APP_ABOUT );
|
||||
}
|
||||
|
||||
|
||||
public void deleteNotification( boolean bConfirmed, final SavedAccount target_account ){
|
||||
if( ! bConfirmed ){
|
||||
new AlertDialog.Builder( this )
|
||||
.setMessage( R.string.confirm_delete_notification )
|
||||
.setNegativeButton( R.string.cancel, null )
|
||||
.setPositiveButton( R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( DialogInterface dialog, int which ){
|
||||
deleteNotification( true, target_account );
|
||||
}
|
||||
} )
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
new AsyncTask< Void, Void, TootApiResult >() {
|
||||
|
||||
@Override
|
||||
protected TootApiResult doInBackground( Void... params ){
|
||||
TootApiClient client = new TootApiClient( ActMain.this, new TootApiClient.Callback() {
|
||||
@Override
|
||||
public boolean isApiCancelled(){
|
||||
return isCancelled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishApiProgress( String s ){
|
||||
|
||||
}
|
||||
} );
|
||||
client.setAccount( target_account );
|
||||
|
||||
Request.Builder request_builder = new Request.Builder().post(
|
||||
RequestBody.create(
|
||||
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED
|
||||
, "" // 空データ
|
||||
) );
|
||||
TootApiResult result = client.request( "/api/v1/notifications/clear" , request_builder );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled( TootApiResult result ){
|
||||
onPostExecute( null );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute( TootApiResult result ){
|
||||
if( result == null ){
|
||||
//cancelled.
|
||||
}else if( result.object != null ){
|
||||
// ok. empty object will be returned.
|
||||
for( Column column : pager_adapter.column_list ){
|
||||
if( column.type == Column.TYPE_NOTIFICATIONS
|
||||
&& column.access_info.acct.equals( target_account.acct )
|
||||
){
|
||||
column.removeNotifications();
|
||||
}
|
||||
}
|
||||
Utils.showToast( ActMain.this, false, R.string.delete_succeeded );
|
||||
}else{
|
||||
Utils.showToast( ActMain.this, false, result.error );
|
||||
}
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public class AlarmService extends IntentService {
|
|||
static final String KEY_TIME = "<>time";
|
||||
private static final String ACTION_DATA_INJECTED = "data_injected";
|
||||
private static final String EXTRA_DB_ID = "db_id";
|
||||
private static final String ACTION_DATA_DELETED = "data_deleted";
|
||||
|
||||
public AlarmService(){
|
||||
// name: Used to name the worker thread, important only for debugging.
|
||||
|
@ -94,7 +95,9 @@ public class AlarmService extends IntentService {
|
|||
String action = intent.getAction();
|
||||
log.d("onHandleIntent action=%s",action);
|
||||
|
||||
if( ACTION_DATA_INJECTED.equals( action ) ){
|
||||
if( ACTION_DATA_DELETED.equals( action ) ){
|
||||
deleteCacheData(intent.getLongExtra( EXTRA_DB_ID ,-1L));
|
||||
}else if( ACTION_DATA_INJECTED.equals( action ) ){
|
||||
processInjectedData();
|
||||
}else if( AlarmReceiver.ACTION_FROM_RECEIVER.equals( action ) ){
|
||||
WakefulBroadcastReceiver.completeWakefulIntent( intent );
|
||||
|
@ -181,7 +184,6 @@ public class AlarmService extends IntentService {
|
|||
}
|
||||
|
||||
|
||||
|
||||
private static class Data {
|
||||
SavedAccount access_info;
|
||||
TootNotification notification;
|
||||
|
@ -502,4 +504,23 @@ public class AlarmService extends IntentService {
|
|||
nr.save();
|
||||
}
|
||||
}
|
||||
|
||||
public static void dataRemoved( Context context, long db_id ){
|
||||
Intent intent = new Intent( context, AlarmService.class );
|
||||
intent.putExtra( EXTRA_DB_ID,db_id );
|
||||
intent.setAction( ACTION_DATA_DELETED );
|
||||
context.startService( intent );
|
||||
}
|
||||
private void deleteCacheData( long db_id ){
|
||||
|
||||
SavedAccount account = SavedAccount.loadAccount( log,db_id );
|
||||
if( account == null ) return;
|
||||
|
||||
NotificationTracking nr = NotificationTracking.load( db_id );
|
||||
|
||||
nr.last_data = new JSONArray().toString();
|
||||
|
||||
nr.save();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -72,8 +72,12 @@ class Column {
|
|||
|
||||
private static final String KEY_ACCOUNT_ROW_ID = "account_id";
|
||||
private static final String KEY_TYPE = "type";
|
||||
private static final String KEY_WITH_ATTACHMENT = "with_attachment";
|
||||
static final String KEY_DONT_CLOSE = "dont_close";
|
||||
private static final String KEY_WITH_ATTACHMENT = "with_attachment";
|
||||
private static final String KEY_DONT_SHOW_BOOST = "dont_show_boost";
|
||||
private static final String KEY_DONT_SHOW_REPLY = "dont_show_reply";
|
||||
private static final String KEY_REGEX_TEXT = "regex_text";
|
||||
|
||||
|
||||
|
||||
private static final String KEY_PROFILE_ID = "profile_id";
|
||||
|
@ -105,9 +109,14 @@ class Column {
|
|||
|
||||
final int type;
|
||||
|
||||
boolean with_attachment;
|
||||
boolean dont_close;
|
||||
|
||||
boolean with_attachment;
|
||||
boolean dont_show_boost;
|
||||
boolean dont_show_reply;
|
||||
String regex_text;
|
||||
|
||||
|
||||
private long profile_id;
|
||||
volatile TootAccount who_account;
|
||||
int profile_tab = TAB_STATUS;
|
||||
|
@ -156,8 +165,11 @@ class Column {
|
|||
void encodeJSON( JSONObject item, int old_index ) throws JSONException{
|
||||
item.put( KEY_ACCOUNT_ROW_ID, access_info.db_id );
|
||||
item.put( KEY_TYPE, type );
|
||||
item.put( KEY_WITH_ATTACHMENT, with_attachment );
|
||||
item.put( KEY_DONT_CLOSE, dont_close );
|
||||
item.put( KEY_WITH_ATTACHMENT, with_attachment );
|
||||
item.put( KEY_DONT_SHOW_BOOST, dont_show_boost );
|
||||
item.put( KEY_DONT_SHOW_REPLY, dont_show_reply );
|
||||
item.put( KEY_REGEX_TEXT, regex_text );
|
||||
|
||||
switch( type ){
|
||||
case TYPE_CONVERSATION:
|
||||
|
@ -189,8 +201,11 @@ class Column {
|
|||
if( ac == null ) throw new RuntimeException( "missing account" );
|
||||
this.access_info = ac;
|
||||
this.type = src.optInt( KEY_TYPE );
|
||||
this.with_attachment = src.optBoolean( KEY_WITH_ATTACHMENT );
|
||||
this.dont_close = src.optBoolean( KEY_DONT_CLOSE );
|
||||
this.with_attachment = src.optBoolean( KEY_WITH_ATTACHMENT );
|
||||
this.dont_show_boost = src.optBoolean( KEY_DONT_SHOW_BOOST );
|
||||
this.dont_show_reply = src.optBoolean( KEY_DONT_SHOW_REPLY );
|
||||
this.regex_text = Utils.optStringX(src, KEY_REGEX_TEXT);
|
||||
|
||||
switch( type ){
|
||||
|
||||
|
@ -315,6 +330,7 @@ class Column {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
interface StatusEntryCallback {
|
||||
void onIterate( TootStatus status );
|
||||
}
|
||||
|
@ -502,20 +518,62 @@ class Column {
|
|||
|
||||
final ArrayList< Object > list_data = new ArrayList<>();
|
||||
|
||||
void reload(){
|
||||
list_data.clear();
|
||||
startLoading();
|
||||
}
|
||||
|
||||
private static boolean hasMedia( TootStatus status ){
|
||||
if( status == null ) return false;
|
||||
TootAttachment.List list = status.media_attachments;
|
||||
return ! ( list == null || list.isEmpty() );
|
||||
}
|
||||
|
||||
private void startLoading(){
|
||||
private boolean isFiltered(){
|
||||
return ( with_attachment
|
||||
|| dont_show_boost
|
||||
|| dont_show_reply
|
||||
|| !TextUtils.isEmpty( regex_text )
|
||||
);
|
||||
}
|
||||
|
||||
private void addWithFilter( ArrayList< Object > dst, TootStatus.List src ){
|
||||
if( ! isFiltered() ){
|
||||
dst.addAll( src );
|
||||
return;
|
||||
}
|
||||
Pattern pattern = null;
|
||||
if( ! TextUtils.isEmpty( regex_text ) ){
|
||||
try{
|
||||
pattern = Pattern.compile( regex_text );
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
for( TootStatus status : src ){
|
||||
if( with_attachment ){
|
||||
if( ! hasMedia( status ) && ! hasMedia( status.reblog ) ) continue;
|
||||
}
|
||||
if( dont_show_boost ){
|
||||
if( status.reblog != null ) continue;
|
||||
}
|
||||
if( dont_show_reply ){
|
||||
if( status.in_reply_to_id != null
|
||||
|| ( status.reblog != null && status.reblog.in_reply_to_id != null )
|
||||
) continue;
|
||||
}
|
||||
if( pattern != null ){
|
||||
if( status.reblog != null ){
|
||||
if( pattern.matcher( status.reblog.decoded_content.toString() ).find() )
|
||||
continue;
|
||||
}else{
|
||||
if( pattern.matcher( status.decoded_content.toString() ).find() ) continue;
|
||||
|
||||
}
|
||||
}
|
||||
dst.add( status );
|
||||
}
|
||||
}
|
||||
|
||||
void startLoading(){
|
||||
cancelLastTask();
|
||||
|
||||
list_data.clear();
|
||||
mRefreshLoadingError = null;
|
||||
bRefreshLoading = false;
|
||||
mInitialLoadingError = null;
|
||||
|
@ -543,18 +601,11 @@ class Column {
|
|||
//
|
||||
TootStatus.List src = TootStatus.parseList( log, access_info, result.array );
|
||||
list_tmp = new ArrayList<>( src.size() );
|
||||
if( ! with_attachment ){
|
||||
list_tmp.addAll( src );
|
||||
}else{
|
||||
for( TootStatus status : src ){
|
||||
if( hasMedia( status ) || hasMedia( status.reblog ) )
|
||||
list_tmp.add( status );
|
||||
}
|
||||
}
|
||||
addWithFilter(list_tmp,src);
|
||||
//
|
||||
if( max_id != null && with_attachment ){
|
||||
char delimiter = ( - 1 != path_base.indexOf( '?' ) ? '&' : '?' );
|
||||
for( ; ; ){
|
||||
while( isFiltered() && max_id != null && list_tmp.size() < 50 ){
|
||||
if( client.isCancelled() ) break;
|
||||
if( src.isEmpty() ){
|
||||
// 直前のリクエストが空のリストを返したら諦める
|
||||
break;
|
||||
|
@ -570,15 +621,7 @@ class Column {
|
|||
|
||||
src = TootStatus.parseList( log, access_info, result2.array );
|
||||
|
||||
if( ! with_attachment ){
|
||||
list_tmp.addAll( src );
|
||||
}else{
|
||||
for( TootStatus status : src ){
|
||||
if( hasMedia( status ) || hasMedia( status.reblog ) )
|
||||
list_tmp.add( status );
|
||||
}
|
||||
}
|
||||
}
|
||||
addWithFilter(list_tmp,src);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -1022,18 +1065,12 @@ class Column {
|
|||
TootStatus.List src = TootStatus.parseList( log, access_info, result.array );
|
||||
list_tmp = new ArrayList<>();
|
||||
|
||||
if( ! with_attachment ){
|
||||
list_tmp.addAll( src );
|
||||
}else{
|
||||
for( TootStatus status : src ){
|
||||
if( hasMedia( status ) || hasMedia( status.reblog ) )
|
||||
list_tmp.add( status );
|
||||
}
|
||||
}
|
||||
addWithFilter(list_tmp,src);
|
||||
|
||||
if( bBottom ){
|
||||
if( with_attachment ){
|
||||
for( ; ; ){
|
||||
while( list_tmp.size() < 50 ){
|
||||
if( client.isCancelled() ) break;
|
||||
|
||||
// max_id だけを指定した場合、必ずlimit個のデータが帰ってくるとは限らない
|
||||
// 直前のデータが0個なら終了とみなすしかなさそう
|
||||
if( src.isEmpty() ){
|
||||
|
@ -1056,23 +1093,18 @@ class Column {
|
|||
|
||||
src = TootStatus.parseList( log, access_info, result2.array );
|
||||
|
||||
if( ! with_attachment ){
|
||||
list_tmp.addAll( src );
|
||||
}else{
|
||||
for( TootStatus status : src ){
|
||||
if( hasMedia( status ) || hasMedia( status.reblog ) )
|
||||
list_tmp.add( status );
|
||||
}
|
||||
}
|
||||
addWithFilter(list_tmp,src);
|
||||
|
||||
if( ! saveRangeEnd( result2 ) ){
|
||||
log.d( "refresh-status-bottom: saveRangeEnd failed." );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
for( ; ; ){
|
||||
// 頭の方を読む時は隙間を減らすため、フィルタの有無に関係なく繰り返しを行う
|
||||
while( list_tmp.size() < 50 ){
|
||||
if( client.isCancelled() ) break;
|
||||
|
||||
// max_id だけを指定した場合、必ずlimit個のデータが帰ってくるとは限らない
|
||||
// 直前のデータが0個なら終了とみなすしかなさそう
|
||||
if( src.isEmpty() ){
|
||||
|
@ -1102,14 +1134,7 @@ class Column {
|
|||
}
|
||||
|
||||
src = TootStatus.parseList( log, access_info, result2.array );
|
||||
if( ! with_attachment ){
|
||||
list_tmp.addAll( src );
|
||||
}else{
|
||||
for( TootStatus status : src ){
|
||||
if( hasMedia( status ) || hasMedia( status.reblog ) )
|
||||
list_tmp.add( status );
|
||||
}
|
||||
}
|
||||
addWithFilter( list_tmp,src );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1409,6 +1434,8 @@ class Column {
|
|||
|
||||
TootApiResult result = null;
|
||||
for( ; ; ){
|
||||
if( client.isCancelled() ) break;
|
||||
|
||||
if( result != null && SystemClock.elapsedRealtime() - time_start > LOOP_TIMEOUT ){
|
||||
// タイムアウト
|
||||
// 隙間が残る
|
||||
|
@ -1444,14 +1471,7 @@ class Column {
|
|||
// 隙間の最新のステータスIDは取得データ末尾のステータスIDである
|
||||
max_id = Long.toString( src.get( src.size() - 1 ).id );
|
||||
|
||||
if( ! with_attachment ){
|
||||
list_tmp.addAll( src );
|
||||
}else{
|
||||
for( TootStatus status : src ){
|
||||
if( hasMedia( status ) || hasMedia( status.reblog ) )
|
||||
list_tmp.add( status );
|
||||
}
|
||||
}
|
||||
addWithFilter( list_tmp,src );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1594,4 +1614,21 @@ class Column {
|
|||
AsyncTaskCompat.executeParallel( task );
|
||||
return null;
|
||||
}
|
||||
|
||||
void removeNotifications(){
|
||||
cancelLastTask();
|
||||
|
||||
list_data.clear();
|
||||
mRefreshLoadingError = null;
|
||||
bRefreshLoading = false;
|
||||
mInitialLoadingError = null;
|
||||
bInitialLoading = false;
|
||||
max_id = null;
|
||||
since_id = null;
|
||||
|
||||
fireVisualCallback();
|
||||
|
||||
AlarmService.dataRemoved(activity,access_info.db_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package jp.juggler.subwaytooter;
|
|||
import android.content.Context;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
|
@ -27,6 +29,8 @@ import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayoutDirec
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import jp.juggler.subwaytooter.api.entity.TootAccount;
|
||||
import jp.juggler.subwaytooter.api.entity.TootAttachment;
|
||||
|
@ -53,7 +57,7 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
this.column = column;
|
||||
}
|
||||
|
||||
public boolean isPageDestroyed(){
|
||||
private boolean isPageDestroyed(){
|
||||
return is_destroyed.get() || activity.isFinishing();
|
||||
}
|
||||
|
||||
|
@ -74,6 +78,8 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
private EditText etSearch;
|
||||
private CheckBox cbResolve;
|
||||
private View llColumnSetting;
|
||||
private EditText etRegexFilter;
|
||||
private TextView tvRegexFilterError;
|
||||
|
||||
void onPageCreate( View root, int page_idx, int page_count ){
|
||||
log.d( "onPageCreate:%s", column.getColumnName( true ) );
|
||||
|
@ -104,10 +110,10 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
|
||||
listView.setFastScrollEnabled( ! Pref.pref( activity ).getBoolean( Pref.KEY_DISABLE_FAST_SCROLLER, false ) );
|
||||
|
||||
boolean bAllowMediaOnly;
|
||||
boolean bAllowFilter;
|
||||
switch( column.type ){
|
||||
default:
|
||||
bAllowMediaOnly = true;
|
||||
bAllowFilter = true;
|
||||
break;
|
||||
case Column.TYPE_SEARCH:
|
||||
case Column.TYPE_CONVERSATION:
|
||||
|
@ -115,23 +121,85 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
case Column.TYPE_BLOCKS:
|
||||
case Column.TYPE_MUTES:
|
||||
case Column.TYPE_NOTIFICATIONS:
|
||||
bAllowMediaOnly = false;
|
||||
bAllowFilter = false;
|
||||
break;
|
||||
}
|
||||
|
||||
boolean bAllowFilterBoost;
|
||||
switch( column.type ){
|
||||
default:
|
||||
bAllowFilterBoost = false;
|
||||
break;
|
||||
case Column.TYPE_HOME:
|
||||
case Column.TYPE_PROFILE:
|
||||
bAllowFilterBoost = true;
|
||||
break;
|
||||
}
|
||||
|
||||
View btnColumnSetting = root.findViewById( R.id.btnColumnSetting );
|
||||
llColumnSetting = root.findViewById( R.id.llColumnSetting );
|
||||
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 );
|
||||
cbWithAttachment.setEnabled( bAllowMediaOnly );
|
||||
CheckBox cb;
|
||||
cb = (CheckBox) root.findViewById( R.id.cbDontCloseColumn );
|
||||
cb.setChecked( column.dont_close );
|
||||
cb.setOnCheckedChangeListener( this );
|
||||
|
||||
CheckBox cbDontCloseColumn = (CheckBox) root.findViewById( R.id.cbDontCloseColumn );
|
||||
cbDontCloseColumn.setChecked( column.dont_close );
|
||||
cbDontCloseColumn.setOnCheckedChangeListener( this );
|
||||
cb = (CheckBox) root.findViewById( R.id.cbWithAttachment );
|
||||
cb.setChecked( column.with_attachment );
|
||||
cb.setOnCheckedChangeListener( this );
|
||||
cb.setEnabled( bAllowFilter );
|
||||
cb.setVisibility( bAllowFilter ? View.VISIBLE : View.GONE );
|
||||
|
||||
cb = (CheckBox) root.findViewById( R.id.cbDontShowBoost );
|
||||
cb.setChecked( column.dont_show_boost );
|
||||
cb.setOnCheckedChangeListener( this );
|
||||
cb.setEnabled( bAllowFilter );
|
||||
cb.setVisibility( bAllowFilterBoost ? View.VISIBLE : View.GONE );
|
||||
|
||||
cb = (CheckBox) root.findViewById( R.id.cbDontShowReply );
|
||||
cb.setChecked( column.dont_show_reply );
|
||||
cb.setOnCheckedChangeListener( this );
|
||||
cb.setEnabled( bAllowFilter );
|
||||
cb.setVisibility( bAllowFilterBoost ? View.VISIBLE : View.GONE );
|
||||
|
||||
etRegexFilter = (EditText) root.findViewById( R.id.etRegexFilter );
|
||||
if( ! bAllowFilter ){
|
||||
etRegexFilter.setVisibility( View.GONE );
|
||||
root.findViewById( R.id.llRegexFilter ).setVisibility( View.GONE );
|
||||
}else{
|
||||
etRegexFilter.setText( column.regex_text );
|
||||
// tvRegexFilterErrorの表示を更新
|
||||
tvRegexFilterError = (TextView) root.findViewById( R.id.tvRegexFilterError );
|
||||
isRegexValid();
|
||||
// 入力の追跡
|
||||
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 ){
|
||||
activity.handler.removeCallbacks( proc_start_filter );
|
||||
if( isRegexValid() ){
|
||||
activity.handler.postDelayed( proc_start_filter, 1500L );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
Button button = (Button) root.findViewById( R.id.btnDeleteNotification );
|
||||
if( column.type != Column.TYPE_NOTIFICATIONS ){
|
||||
button.setVisibility( View.GONE );
|
||||
}else{
|
||||
button.setVisibility( View.VISIBLE );
|
||||
button.setOnClickListener( this );
|
||||
|
||||
}
|
||||
|
||||
if( column.type != Column.TYPE_SEARCH ){
|
||||
llSearch.setVisibility( View.GONE );
|
||||
|
@ -168,20 +236,62 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
onVisualColumn();
|
||||
}
|
||||
|
||||
private final Runnable proc_start_filter = new Runnable() {
|
||||
@Override public void run(){
|
||||
if( isPageDestroyed() ) return;
|
||||
if( isRegexValid() ){
|
||||
column.regex_text = etRegexFilter.getText().toString();
|
||||
activity.saveColumnList();
|
||||
column.startLoading();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isRegexValid(){
|
||||
String s = etRegexFilter.getText().toString();
|
||||
if( s.length() == 0 ){
|
||||
tvRegexFilterError.setText( "" );
|
||||
return true;
|
||||
}
|
||||
try{
|
||||
@SuppressWarnings("unused") Matcher m = 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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onCheckedChanged( CompoundButton view, boolean isChecked ){
|
||||
switch( view.getId() ){
|
||||
|
||||
case R.id.cbWithAttachment:
|
||||
column.with_attachment = isChecked;
|
||||
activity.saveColumnList();
|
||||
column.reload();
|
||||
break;
|
||||
|
||||
case R.id.cbDontCloseColumn:
|
||||
column.dont_close = isChecked;
|
||||
activity.saveColumnList();
|
||||
break;
|
||||
|
||||
case R.id.cbWithAttachment:
|
||||
column.with_attachment = isChecked;
|
||||
activity.saveColumnList();
|
||||
column.startLoading();
|
||||
break;
|
||||
|
||||
case R.id.cbDontShowBoost:
|
||||
column.dont_show_boost = isChecked;
|
||||
activity.saveColumnList();
|
||||
column.startLoading();
|
||||
break;
|
||||
|
||||
case R.id.cbDontShowReply:
|
||||
column.dont_show_reply = isChecked;
|
||||
activity.saveColumnList();
|
||||
column.startLoading();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,14 +308,14 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
etSearch.setText( column.search_query );
|
||||
cbResolve.setChecked( column.search_resolve );
|
||||
}
|
||||
column.reload();
|
||||
column.startLoading();
|
||||
break;
|
||||
|
||||
case R.id.btnSearch:
|
||||
hideKeyboard( etSearch );
|
||||
column.search_query = etSearch.getText().toString().trim();
|
||||
column.search_resolve = cbResolve.isChecked();
|
||||
column.reload();
|
||||
column.startLoading();
|
||||
break;
|
||||
|
||||
case R.id.llColumnHeader:
|
||||
|
@ -215,6 +325,10 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -350,6 +464,7 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
final Button btnStatusCount;
|
||||
final View btnMore;
|
||||
final TextView tvNote;
|
||||
|
||||
TootAccount who;
|
||||
SavedAccount access_info;
|
||||
|
||||
|
@ -420,17 +535,17 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
|
||||
case R.id.btnFollowing:
|
||||
column.profile_tab = Column.TAB_FOLLOWING;
|
||||
column.reload();
|
||||
column.startLoading();
|
||||
break;
|
||||
|
||||
case R.id.btnFollowers:
|
||||
column.profile_tab = Column.TAB_FOLLOWERS;
|
||||
column.reload();
|
||||
column.startLoading();
|
||||
break;
|
||||
|
||||
case R.id.btnStatusCount:
|
||||
column.profile_tab = Column.TAB_STATUS;
|
||||
column.reload();
|
||||
column.startLoading();
|
||||
break;
|
||||
|
||||
case R.id.btnMore:
|
||||
|
@ -696,7 +811,7 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
void showBoost( TootAccount who, long time, int icon_attr_id, CharSequence text ){
|
||||
account_boost = who;
|
||||
llBoosted.setVisibility( View.VISIBLE );
|
||||
ivBoosted.setImageResource( Styler.getAttributeResourceId(activity,icon_attr_id) );
|
||||
ivBoosted.setImageResource( Styler.getAttributeResourceId( activity, icon_attr_id ) );
|
||||
tvBoostedTime.setText( TootStatus.formatTime( time ) );
|
||||
tvBoostedAcct.setText( access_info.getFullAcct( who ) );
|
||||
tvBoosted.setText( text );
|
||||
|
@ -709,7 +824,7 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
tvFollowerName.setText( who.display_name );
|
||||
tvFollowerAcct.setText( access_info.getFullAcct( who ) );
|
||||
|
||||
btnFollow.setImageResource( Styler.getAttributeResourceId( activity,R.attr.ic_account_add ));
|
||||
btnFollow.setImageResource( Styler.getAttributeResourceId( activity, R.attr.ic_account_add ) );
|
||||
}
|
||||
|
||||
private void showStatus( ActMain activity, TootStatus status, SavedAccount account ){
|
||||
|
@ -763,44 +878,38 @@ class ColumnViewHolder implements View.OnClickListener, Column.VisualCallback, S
|
|||
btnShowMedia.setVisibility( ! is_shown ? View.VISIBLE : View.GONE );
|
||||
}
|
||||
|
||||
Drawable d;
|
||||
int color_normal = Styler.getAttributeColor( activity,R.attr.colorImageButton );
|
||||
int color_accent = Styler.getAttributeColor( activity,R.attr.colorImageButtonAccent );
|
||||
|
||||
if( activity.isBusyBoost( account, status ) ){
|
||||
d = Styler.getAttributeDrawable( activity,R.attr.btn_refresh ).mutate();
|
||||
d.setColorFilter( color_normal, PorterDuff.Mode.SRC_ATOP );
|
||||
btnBoost.setCompoundDrawablesRelativeWithIntrinsicBounds( d, null, null, null );
|
||||
btnBoost.setText( "?" );
|
||||
btnBoost.setTextColor( color_normal );
|
||||
int color_normal = Styler.getAttributeColor( activity, R.attr.colorImageButton );
|
||||
int color_accent = Styler.getAttributeColor( activity, R.attr.colorImageButtonAccent );
|
||||
|
||||
if( TootStatus.VISIBILITY_DIRECT.equals( status.visibility ) ){
|
||||
setButton( btnBoost, false, color_accent, R.attr.ic_mail, "" );
|
||||
}else if( TootStatus.VISIBILITY_PRIVATE.equals( status.visibility ) ){
|
||||
setButton( btnBoost, false, color_accent, R.attr.ic_lock, "" );
|
||||
}else if( activity.isBusyBoost( account, status ) ){
|
||||
setButton( btnBoost, false, color_normal, R.attr.btn_refresh, "?" );
|
||||
}else{
|
||||
int color = ( status.reblogged ? color_accent : color_normal );
|
||||
d = Styler.getAttributeDrawable( activity,R.attr.btn_boost ).mutate();
|
||||
d.setColorFilter( color, PorterDuff.Mode.SRC_ATOP );
|
||||
btnBoost.setCompoundDrawablesRelativeWithIntrinsicBounds( d, null, null, null );
|
||||
btnBoost.setText( Long.toString( status.reblogs_count ) );
|
||||
btnBoost.setTextColor( color );
|
||||
|
||||
setButton( btnBoost, true, color, R.attr.btn_boost, Long.toString( status.reblogs_count ) );
|
||||
}
|
||||
|
||||
if( activity.isBusyFav( account, status ) ){
|
||||
d = Styler.getAttributeDrawable( activity,R.attr.btn_refresh ).mutate();
|
||||
d.setColorFilter( color_normal, PorterDuff.Mode.SRC_ATOP );
|
||||
btnFavourite.setCompoundDrawablesRelativeWithIntrinsicBounds( d, null, null, null );
|
||||
btnFavourite.setText( "?" );
|
||||
btnFavourite.setTextColor( color_normal );
|
||||
setButton( btnFavourite, false, color_normal, R.attr.btn_refresh, "?" );
|
||||
}else{
|
||||
int color = ( status.favourited ? color_accent : color_normal );
|
||||
d = Styler.getAttributeDrawable( activity,R.attr.btn_favourite ).mutate();
|
||||
d.setColorFilter( color, PorterDuff.Mode.SRC_ATOP );
|
||||
btnFavourite.setCompoundDrawablesRelativeWithIntrinsicBounds( d, null, null, null );
|
||||
btnFavourite.setText( Long.toString( status.favourites_count ) );
|
||||
btnFavourite.setTextColor( color );
|
||||
setButton( btnFavourite, true, color, R.attr.btn_favourite, Long.toString( status.favourites_count ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setButton( Button b, boolean enabled, int color, int icon_attr, String text ){
|
||||
Drawable d = Styler.getAttributeDrawable( activity, icon_attr ).mutate();
|
||||
d.setColorFilter( color, PorterDuff.Mode.SRC_ATOP );
|
||||
b.setCompoundDrawablesRelativeWithIntrinsicBounds( d, null, null, null );
|
||||
b.setText( text );
|
||||
b.setTextColor( color );
|
||||
b.setEnabled( enabled );
|
||||
}
|
||||
|
||||
private void showContent( boolean shown ){
|
||||
btnContentWarning.setText( shown ? R.string.hide : R.string.show );
|
||||
llContents.setVisibility( shown ? View.VISIBLE : View.GONE );
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package jp.juggler.subwaytooter.api;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
@ -25,7 +24,7 @@ import okhttp3.Response;
|
|||
public class TootApiClient {
|
||||
private static final LogCategory log = new LogCategory( "TootApiClient" );
|
||||
|
||||
static final OkHttpClient ok_http_client = App1.ok_http_client;
|
||||
private static final OkHttpClient ok_http_client = App1.ok_http_client;
|
||||
|
||||
public interface Callback {
|
||||
boolean isApiCancelled();
|
||||
|
@ -57,6 +56,10 @@ public class TootApiClient {
|
|||
this.account = account;
|
||||
}
|
||||
|
||||
public boolean isCancelled(){
|
||||
return callback.isApiCancelled();
|
||||
}
|
||||
|
||||
public static final MediaType MEDIA_TYPE_FORM_URL_ENCODED = MediaType.parse( "application/x-www-form-urlencoded" );
|
||||
|
||||
public TootApiResult request( String path ){
|
||||
|
@ -66,17 +69,17 @@ public class TootApiClient {
|
|||
public TootApiResult request( String path, Request.Builder request_builder ){
|
||||
log.d( "request: %s", path );
|
||||
TootApiResult result = request_sub( path, request_builder );
|
||||
if( result.error != null ){
|
||||
if( result != null && result.error != null ){
|
||||
log.d( "error: %s", result.error );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static final String KEY_AUTH_VERSION = "SubwayTooterAuthVersion";
|
||||
static final int AUTH_VERSION = 1;
|
||||
static final String REDIRECT_URL = "subwaytooter://oauth";
|
||||
private static final String KEY_AUTH_VERSION = "SubwayTooterAuthVersion";
|
||||
private static final int AUTH_VERSION = 1;
|
||||
private static final String REDIRECT_URL = "subwaytooter://oauth";
|
||||
|
||||
public TootApiResult request_sub( String path, Request.Builder request_builder ){
|
||||
private TootApiResult request_sub( String path, Request.Builder request_builder ){
|
||||
|
||||
if( account == null ){
|
||||
return new TootApiResult( "account is null" );
|
||||
|
@ -217,7 +220,7 @@ public class TootApiClient {
|
|||
+ "&grant_type=authorization_code"
|
||||
// + "&username=" + Uri.encode( user_mail )
|
||||
// + "&password=" + Uri.encode( password )
|
||||
+"&approval_prompt=force"
|
||||
+ "&approval_prompt=force"
|
||||
// +"&access_type=offline"
|
||||
;
|
||||
// APIリクエストは失敗?する
|
||||
|
@ -227,7 +230,7 @@ public class TootApiClient {
|
|||
|
||||
}
|
||||
|
||||
public TootApiResult authorize2( String url, String code ){
|
||||
public TootApiResult authorize2( String code ){
|
||||
|
||||
JSONObject client_info = ClientInfo.load( instance );
|
||||
if( client_info != null && client_info.optInt( KEY_AUTH_VERSION, 0 ) < AUTH_VERSION ){
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llColumnHeader"
|
||||
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:id="@+id/llColumnHeader"
|
||||
android:background="@drawable/btn_bg_ddd"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="3dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="3dp"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
|
@ -52,8 +52,8 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="0dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<TextView
|
||||
|
@ -102,64 +102,127 @@
|
|||
|
||||
|
||||
</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="?attr/colorColumnSettingBackground"
|
||||
android:id="@+id/llColumnSetting"
|
||||
>
|
||||
<CheckBox
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/with_attachment"
|
||||
android:id="@+id/cbWithAttachment"
|
||||
/>
|
||||
android:background="?attr/colorColumnSettingBackground"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="3dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="3dp"
|
||||
>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbDontCloseColumn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dont_close_column"
|
||||
android:id="@+id/cbDontCloseColumn"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<RelativeLayout
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbWithAttachment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingTop="3dp"
|
||||
android:paddingBottom="3dp"
|
||||
android:background="?attr/colorSearchFormBackground"
|
||||
android:id="@+id/llSearch"
|
||||
android:text="@string/with_attachment"
|
||||
/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbDontShowBoost"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dont_show_boost"
|
||||
/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbDontShowReply"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dont_show_reply"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/llRegexFilter"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:labelFor="@+id/etRegexFilter"
|
||||
android:text="@string/regex_filter"
|
||||
android:textColor="?attr/colorColumnHeaderPageNumber"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvRegexFilterError"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_weight="1"
|
||||
android:textColor="?attr/colorRegexFilterError"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etRegexFilter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:scrollHorizontally="true"
|
||||
android:inputType="text"
|
||||
/>
|
||||
<Button
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/notification_delete"
|
||||
android:id="@+id/btnDeleteNotification"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/llSearch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSearchFormBackground"
|
||||
android:paddingBottom="3dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="3dp"
|
||||
>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnSearch"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/btn_bg_transparent"
|
||||
android:src="?attr/ic_search"
|
||||
android:contentDescription="@string/search"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:id="@+id/btnSearch"
|
||||
android:background="@drawable/btn_bg_transparent"
|
||||
android:contentDescription="@string/search"
|
||||
android:src="?attr/ic_search"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etSearch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toStartOf="@id/btnSearch"
|
||||
android:inputType="text"
|
||||
android:id="@+id/etSearch"
|
||||
android:imeOptions="actionSearch"
|
||||
android:inputType="text"
|
||||
tools:ignore="LabelFor"/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbResolve"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/etSearch"
|
||||
android:text="@string/resolve_non_local_account"
|
||||
android:id="@+id/cbResolve"
|
||||
/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
@ -186,11 +249,11 @@
|
|||
|
||||
android:clipToPadding="false"
|
||||
android:fadeScrollbars="false"
|
||||
android:fastScrollEnabled="true"
|
||||
android:paddingBottom="64dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
android:fastScrollEnabled="true"
|
||||
/>
|
||||
|
||||
</com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout>
|
||||
|
|
|
@ -170,8 +170,14 @@
|
|||
<string name="send_header_content_warning">Content-Warning</string>
|
||||
<string name="send_header_url">Status-URL</string>
|
||||
<string name="column_has_dont_close_option">保護されたカラムは閉じられません</string>
|
||||
<string name="dont_close_column">保護(閉じることができない)</string>
|
||||
<string name="dont_close_column">保護(カラムを閉じない)</string>
|
||||
<string name="theme_dark">暗い</string>
|
||||
<string name="theme_light">明るい</string>
|
||||
<string name="ui_theme">UIテーマ(アプリ再起動が必要)</string>
|
||||
<string name="dont_show_boost">ブーストを表示しない</string>
|
||||
<string name="dont_show_reply">返信を表示しない</string>
|
||||
<string name="regex_error">正規表現エラー</string>
|
||||
<string name="regex_filter">正規表現フィルタ(上級者向け)</string>
|
||||
<string name="confirm_delete_notification">ユーザへの通知データがタンスのサーバから削除されます。よろしいですか?</string>
|
||||
<string name="notification_delete">通知の削除</string>
|
||||
</resources>
|
||||
|
|
|
@ -64,6 +64,9 @@
|
|||
<!-- 設定画面のdividerの色 #ddd -->
|
||||
<attr name="colorSettingDivider" format="color"/>
|
||||
|
||||
<!-- カラム設定の正規表現フィルタのエラー表示 #f00 -->
|
||||
<attr name="colorRegexFilterError" format="color"/>
|
||||
|
||||
|
||||
<attr name="btn_attachment" format="reference" />
|
||||
<attr name="btn_boost" format="reference" />
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
<color name="Light_colorShowMediaText">#fff</color>
|
||||
<color name="Light_colorColumnListDeleteBackground">#FF0000</color>
|
||||
<color name="Light_colorColumnListDeleteText">#fff</color>
|
||||
<color name="Light_colorRegexFilterError">#f00</color>
|
||||
|
||||
|
||||
<!-- Dark theme -->
|
||||
|
@ -75,5 +76,6 @@
|
|||
<color name="Dark_colorShowMediaText">#ccFFFFFF</color>
|
||||
<color name="Dark_colorColumnListDeleteBackground">#FF0000</color>
|
||||
<color name="Dark_colorColumnListDeleteText">#fff</color>
|
||||
<color name="Dark_colorRegexFilterError">#f00</color>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -173,4 +173,10 @@
|
|||
<string name="ui_theme">UI theme (app restart required)</string>
|
||||
<string name="theme_light">light</string>
|
||||
<string name="theme_dark">dark</string>
|
||||
<string name="dont_show_boost">dont show boost</string>
|
||||
<string name="dont_show_reply">dont show reply</string>
|
||||
<string name="regex_filter">regex filter</string>
|
||||
<string name="regex_error">regex error</string>
|
||||
<string name="notification_delete">delete notification</string>
|
||||
<string name="confirm_delete_notification">your notification data on instance sarver will be deleted. Are you sure?</string>
|
||||
</resources>
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
<item name="colorSearchFormBackground">@color/Light_colorSearchFormBackground</item>
|
||||
<item name="colorSettingDivider">@color/Light_colorSettingDivider</item>
|
||||
|
||||
<item name="colorRegexFilterError">@color/Light_colorRegexFilterError</item>
|
||||
|
||||
|
||||
<item name="btn_attachment">@drawable/btn_attachment</item>
|
||||
<item name="btn_boost">@drawable/btn_boost</item>
|
||||
<item name="btn_close">@drawable/btn_close</item>
|
||||
|
@ -105,6 +108,7 @@
|
|||
<item name="colorColumnSettingBackground">@color/Dark_colorColumnSettingBackground</item>
|
||||
<item name="colorSearchFormBackground">@color/Dark_colorSearchFormBackground</item>
|
||||
<item name="colorSettingDivider">@color/Dark_colorSettingDivider</item>
|
||||
<item name="colorRegexFilterError">@color/Dark_colorRegexFilterError</item>
|
||||
|
||||
<item name="btn_attachment">@drawable/btn_attachment_dark</item>
|
||||
<item name="btn_boost">@drawable/btn_boost_dark</item>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
#!perl --
|
||||
use strict;
|
||||
use warnings;
|
||||
use Font::FreeType;
|
||||
|
||||
my $face = Font::FreeType->new->face('emojione_android.ttf');
|
||||
|
||||
my $f =0;
|
||||
my $l =0;
|
||||
my $n =0;
|
||||
$face->foreach_char(sub{
|
||||
my $codepoint = $_->char_code;
|
||||
|
||||
if( $codepoint < 80 ){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if($n ==0 ){
|
||||
if( $l == 0 ){
|
||||
print "\tprivate static void initForFont",(++$f),"(){\n";
|
||||
}
|
||||
print "\t\taddFontCode(new int[]{";
|
||||
}
|
||||
|
||||
printf "0x%x,",$codepoint;
|
||||
|
||||
if( ++$n >= 5 ){
|
||||
$n =0;
|
||||
print "});\n";
|
||||
|
||||
if( ++$l >= 100 ){
|
||||
$l = 0;
|
||||
print "\t}\n";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if( $n > 0 ){
|
||||
print "});\n";
|
||||
print "\t}\n";
|
||||
}
|
||||
print "\tstatic{\n";
|
||||
for(my $i=1;$i<=$f;++$i){
|
||||
print"\t\tinitForFont$i();\n";
|
||||
}
|
||||
print "\t}\n";
|
Loading…
Reference in New Issue