v0.7.3
|
@ -1,6 +1,7 @@
|
|||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="tateisu">
|
||||
<words>
|
||||
<w>adamrocker</w>
|
||||
<w>dont</w>
|
||||
<w>emoji</w>
|
||||
<w>emojione</w>
|
||||
|
@ -18,6 +19,7 @@
|
|||
<w>reblogged</w>
|
||||
<w>reblogs</w>
|
||||
<w>sephiroth</w>
|
||||
<w>simeji</w>
|
||||
<w>styler</w>
|
||||
<w>subwaytooter</w>
|
||||
<w>swipy</w>
|
||||
|
|
|
@ -9,8 +9,8 @@ android {
|
|||
applicationId "jp.juggler.subwaytooter"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 72
|
||||
versionName "0.7.2"
|
||||
versionCode 73
|
||||
versionName "0.7.3"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.apache.commons.io.output.FileWriterWithEncoding;
|
|||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import jp.juggler.subwaytooter.table.SavedAccount;
|
||||
import jp.juggler.subwaytooter.util.LogCategory;
|
||||
|
@ -101,16 +100,17 @@ public class ActAppSetting extends AppCompatActivity
|
|||
int footer_button_fg_color;
|
||||
int footer_tab_bg_color;
|
||||
int footer_tab_divider_color;
|
||||
int footer_tab_indicator_color;
|
||||
|
||||
ImageView ivFooterToot;
|
||||
ImageView ivFooterMenu;
|
||||
View llFooterBG;
|
||||
View vFooterDivider1;
|
||||
View vFooterDivider2;
|
||||
View vIndicator;
|
||||
|
||||
EditText etColumnWidth;
|
||||
EditText etMediaThumbHeight;
|
||||
|
||||
|
||||
TextView tvTimelineFontUrl;
|
||||
String timeline_font;
|
||||
|
@ -228,6 +228,9 @@ public class ActAppSetting extends AppCompatActivity
|
|||
findViewById( R.id.btnTabBackgroundColorReset ).setOnClickListener( this );
|
||||
findViewById( R.id.btnTabDividerColorEdit ).setOnClickListener( this );
|
||||
findViewById( R.id.btnTabDividerColorReset ).setOnClickListener( this );
|
||||
findViewById( R.id.btnTabIndicatorColorEdit ).setOnClickListener( this );
|
||||
findViewById( R.id.btnTabIndicatorColorReset ).setOnClickListener( this );
|
||||
|
||||
findViewById( R.id.btnTimelineFontEdit ).setOnClickListener( this );
|
||||
findViewById( R.id.btnTimelineFontReset ).setOnClickListener( this );
|
||||
findViewById( R.id.btnSettingExport ).setOnClickListener( this );
|
||||
|
@ -241,6 +244,7 @@ public class ActAppSetting extends AppCompatActivity
|
|||
llFooterBG = findViewById( R.id.llFooterBG );
|
||||
vFooterDivider1 = findViewById( R.id.vFooterDivider1 );
|
||||
vFooterDivider2 = findViewById( R.id.vFooterDivider2 );
|
||||
vIndicator = findViewById( R.id.vIndicator );
|
||||
|
||||
etColumnWidth = (EditText) findViewById( R.id.etColumnWidth );
|
||||
etMediaThumbHeight = (EditText) findViewById( R.id.etMediaThumbHeight );
|
||||
|
@ -282,6 +286,7 @@ public class ActAppSetting extends AppCompatActivity
|
|||
footer_button_fg_color = pref.getInt( Pref.KEY_FOOTER_BUTTON_FG_COLOR, 0 );
|
||||
footer_tab_bg_color = pref.getInt( Pref.KEY_FOOTER_TAB_BG_COLOR, 0 );
|
||||
footer_tab_divider_color = pref.getInt( Pref.KEY_FOOTER_TAB_DIVIDER_COLOR, 0 );
|
||||
footer_tab_indicator_color = pref.getInt( Pref.KEY_FOOTER_TAB_INDICATOR_COLOR, 0 );
|
||||
|
||||
etColumnWidth.setText( pref.getString( Pref.KEY_COLUMN_WIDTH, "" ) );
|
||||
etMediaThumbHeight.setText( pref.getString( Pref.KEY_MEDIA_THUMB_HEIGHT, "" ) );
|
||||
|
@ -324,7 +329,8 @@ public class ActAppSetting extends AppCompatActivity
|
|||
.putInt( Pref.KEY_FOOTER_BUTTON_FG_COLOR, footer_button_fg_color )
|
||||
.putInt( Pref.KEY_FOOTER_TAB_BG_COLOR, footer_tab_bg_color )
|
||||
.putInt( Pref.KEY_FOOTER_TAB_DIVIDER_COLOR, footer_tab_divider_color )
|
||||
|
||||
.putInt( Pref.KEY_FOOTER_TAB_INDICATOR_COLOR, footer_tab_indicator_color )
|
||||
|
||||
.putString( Pref.KEY_TIMELINE_FONT, timeline_font )
|
||||
.putString( Pref.KEY_COLUMN_WIDTH, etColumnWidth.getText().toString().trim() )
|
||||
.putString( Pref.KEY_MEDIA_THUMB_HEIGHT, etMediaThumbHeight.getText().toString().trim() )
|
||||
|
@ -350,12 +356,13 @@ public class ActAppSetting extends AppCompatActivity
|
|||
static final int COLOR_DIALOG_ID_FOOTER_BUTTON_FG = 2;
|
||||
static final int COLOR_DIALOG_ID_FOOTER_TAB_BG = 3;
|
||||
static final int COLOR_DIALOG_ID_FOOTER_TAB_DIVIDER = 4;
|
||||
static final int COLOR_DIALOG_ID_FOOTER_TAB_INDICATOR = 5;
|
||||
|
||||
@Override public void onClick( View v ){
|
||||
switch( v.getId() ){
|
||||
|
||||
case R.id.btnFooterBackgroundEdit:
|
||||
openColorPicker( COLOR_DIALOG_ID_FOOTER_BUTTON_BG, footer_button_bg_color );
|
||||
openColorPicker( COLOR_DIALOG_ID_FOOTER_BUTTON_BG, footer_button_bg_color ,false);
|
||||
break;
|
||||
|
||||
case R.id.btnFooterBackgroundReset:
|
||||
|
@ -365,7 +372,7 @@ public class ActAppSetting extends AppCompatActivity
|
|||
break;
|
||||
|
||||
case R.id.btnFooterForegroundColorEdit:
|
||||
openColorPicker( COLOR_DIALOG_ID_FOOTER_BUTTON_FG, footer_button_fg_color );
|
||||
openColorPicker( COLOR_DIALOG_ID_FOOTER_BUTTON_FG, footer_button_fg_color ,false);
|
||||
break;
|
||||
|
||||
case R.id.btnFooterForegroundColorReset:
|
||||
|
@ -375,7 +382,7 @@ public class ActAppSetting extends AppCompatActivity
|
|||
break;
|
||||
|
||||
case R.id.btnTabBackgroundColorEdit:
|
||||
openColorPicker( COLOR_DIALOG_ID_FOOTER_TAB_BG, footer_tab_bg_color );
|
||||
openColorPicker( COLOR_DIALOG_ID_FOOTER_TAB_BG, footer_tab_bg_color ,false);
|
||||
break;
|
||||
|
||||
case R.id.btnTabBackgroundColorReset:
|
||||
|
@ -385,7 +392,7 @@ public class ActAppSetting extends AppCompatActivity
|
|||
break;
|
||||
|
||||
case R.id.btnTabDividerColorEdit:
|
||||
openColorPicker( COLOR_DIALOG_ID_FOOTER_TAB_DIVIDER, footer_tab_divider_color );
|
||||
openColorPicker( COLOR_DIALOG_ID_FOOTER_TAB_DIVIDER, footer_tab_divider_color ,false);
|
||||
break;
|
||||
|
||||
case R.id.btnTabDividerColorReset:
|
||||
|
@ -394,6 +401,16 @@ public class ActAppSetting extends AppCompatActivity
|
|||
showFooterColor();
|
||||
break;
|
||||
|
||||
case R.id.btnTabIndicatorColorEdit:
|
||||
openColorPicker( COLOR_DIALOG_ID_FOOTER_TAB_INDICATOR, footer_tab_indicator_color ,true);
|
||||
break;
|
||||
|
||||
case R.id.btnTabIndicatorColorReset:
|
||||
footer_tab_indicator_color = 0;
|
||||
saveUIToData();
|
||||
showFooterColor();
|
||||
break;
|
||||
|
||||
case R.id.btnTimelineFontReset:
|
||||
timeline_font = "";
|
||||
saveUIToData();
|
||||
|
@ -462,11 +479,11 @@ public class ActAppSetting extends AppCompatActivity
|
|||
super.onActivityResult( requestCode, resultCode, data );
|
||||
}
|
||||
|
||||
void openColorPicker( int id, int color ){
|
||||
void openColorPicker( int id, int color ,boolean bShowAlphaSlider ){
|
||||
ColorPickerDialog.Builder builder = ColorPickerDialog.newBuilder()
|
||||
.setDialogType( ColorPickerDialog.TYPE_CUSTOM )
|
||||
.setAllowPresets( true )
|
||||
.setShowAlphaSlider( false )
|
||||
.setShowAlphaSlider( bShowAlphaSlider )
|
||||
.setDialogId( id );
|
||||
if( color != 0 ) builder.setColor( color );
|
||||
builder.show( this );
|
||||
|
@ -498,7 +515,12 @@ public class ActAppSetting extends AppCompatActivity
|
|||
saveUIToData();
|
||||
showFooterColor();
|
||||
break;
|
||||
|
||||
case COLOR_DIALOG_ID_FOOTER_TAB_INDICATOR:
|
||||
if( color == 0 ) color = 0x01000000;
|
||||
footer_tab_indicator_color = color;
|
||||
saveUIToData();
|
||||
showFooterColor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -543,6 +565,13 @@ public class ActAppSetting extends AppCompatActivity
|
|||
vFooterDivider1.setBackgroundColor( c );
|
||||
vFooterDivider2.setBackgroundColor( c );
|
||||
}
|
||||
|
||||
c = footer_tab_indicator_color;
|
||||
if( c == 0 ){
|
||||
vIndicator.setBackgroundColor( Styler.getAttributeColor( this, R.attr.colorAccent ) );
|
||||
}else{
|
||||
vIndicator.setBackgroundColor( c );
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void beforeTextChanged( CharSequence s, int start, int count, int after ){
|
||||
|
|
|
@ -38,7 +38,6 @@ import android.view.WindowManager;
|
|||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.json.JSONException;
|
||||
|
@ -78,6 +77,7 @@ import jp.juggler.subwaytooter.util.LinkClickContext;
|
|||
import jp.juggler.subwaytooter.util.LogCategory;
|
||||
import jp.juggler.subwaytooter.util.MyClickableSpan;
|
||||
import jp.juggler.subwaytooter.util.Utils;
|
||||
import jp.juggler.subwaytooter.view.ColumnStripLinearLayout;
|
||||
import jp.juggler.subwaytooter.view.GravitySnapHelper;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
|
@ -228,6 +228,8 @@ public class ActMain extends AppCompatActivity
|
|||
for( Column column : app_state.column_list ){
|
||||
column.onResume( this );
|
||||
}
|
||||
|
||||
updateColumnStripSelection(-1,-1f);
|
||||
}
|
||||
|
||||
private void handleSentIntent( final Intent sent_intent ){
|
||||
|
@ -278,7 +280,7 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
@Override
|
||||
public void onPageScrolled( int position, float positionOffset, int positionOffsetPixels ){
|
||||
|
||||
updateColumnStripSelection(position,positionOffset);
|
||||
}
|
||||
|
||||
@Override public void onPageSelected( final int position ){
|
||||
|
@ -293,8 +295,10 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override public void onPageScrollStateChanged( int state ){
|
||||
|
||||
}
|
||||
|
@ -602,7 +606,7 @@ public class ActMain extends AppCompatActivity
|
|||
ColumnPagerAdapter pager_adapter;
|
||||
View llEmpty;
|
||||
DrawerLayout drawer;
|
||||
LinearLayout llColumnStrip;
|
||||
ColumnStripLinearLayout llColumnStrip;
|
||||
HorizontalScrollView svColumnStrip;
|
||||
ImageButton btnMenu;
|
||||
ImageButton btnToot;
|
||||
|
@ -655,7 +659,7 @@ public class ActMain extends AppCompatActivity
|
|||
btnToot = (ImageButton) findViewById( R.id.btnToot );
|
||||
vFooterDivider1 = findViewById( R.id.vFooterDivider1 );
|
||||
vFooterDivider2 = findViewById( R.id.vFooterDivider2 );
|
||||
llColumnStrip = (LinearLayout) findViewById( R.id.llColumnStrip );
|
||||
llColumnStrip = (ColumnStripLinearLayout) findViewById( R.id.llColumnStrip );
|
||||
svColumnStrip = (HorizontalScrollView) findViewById( R.id.svColumnStrip );
|
||||
|
||||
btnToot.setOnClickListener( this );
|
||||
|
@ -733,6 +737,7 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
@Override public void onScrolled( RecyclerView recyclerView, int dx, int dy ){
|
||||
super.onScrolled( recyclerView, dx, dy );
|
||||
updateColumnStripSelection(-1,-1f);
|
||||
}
|
||||
} );
|
||||
///////tablet_pager.setHasFixedSize( true );
|
||||
|
@ -796,8 +801,43 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
}
|
||||
svColumnStrip.requestLayout();
|
||||
updateColumnStripSelection(-1,-1f);
|
||||
|
||||
}
|
||||
|
||||
private void updateColumnStripSelection(final int position,final float positionOffset){
|
||||
handler.post( new Runnable() {
|
||||
@Override public void run(){
|
||||
if( isFinishing() ) return;
|
||||
|
||||
if( app_state.column_list.isEmpty() ){
|
||||
llColumnStrip.setColumnRange(-1,-1,0f);
|
||||
}else if( pager_adapter != null ){
|
||||
if( position >= 0 ){
|
||||
llColumnStrip.setColumnRange( position, position, positionOffset );
|
||||
}else{
|
||||
int c = pager.getCurrentItem();
|
||||
llColumnStrip.setColumnRange( c, c, 0f );
|
||||
}
|
||||
}else{
|
||||
int first = tablet_layout_manager.findFirstVisibleItemPosition();
|
||||
int last = tablet_layout_manager.findLastVisibleItemPosition();
|
||||
|
||||
if( last-first > nScreenColumn-1 ){
|
||||
last = first + nScreenColumn - 1;
|
||||
}
|
||||
float slide_ratio = 0f;
|
||||
if( first != RecyclerView.NO_POSITION && nColumnWidth > 0 ){
|
||||
View child = tablet_layout_manager.findViewByPosition( first );
|
||||
slide_ratio = Math.abs( child.getLeft() / (float)nColumnWidth);
|
||||
log.d("slide_ratio %s",slide_ratio);
|
||||
}
|
||||
|
||||
llColumnStrip.setColumnRange(first,last,slide_ratio);
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
private void scrollColumnStrip( final int select ){
|
||||
int child_count = llColumnStrip.getChildCount();
|
||||
if( select < 0 || select >= child_count ){
|
||||
|
@ -2966,7 +3006,7 @@ public class ActMain extends AppCompatActivity
|
|||
int footer_button_fg_color = pref.getInt( Pref.KEY_FOOTER_BUTTON_FG_COLOR, 0 );
|
||||
int footer_tab_bg_color = pref.getInt( Pref.KEY_FOOTER_TAB_BG_COLOR, 0 );
|
||||
int footer_tab_divider_color = pref.getInt( Pref.KEY_FOOTER_TAB_DIVIDER_COLOR, 0 );
|
||||
|
||||
int footer_tab_indicator_color = pref.getInt( Pref.KEY_FOOTER_TAB_INDICATOR_COLOR, 0 );
|
||||
int c = footer_button_bg_color;
|
||||
if( c == 0 ){
|
||||
btnMenu.setBackgroundResource( R.drawable.btn_bg_ddd );
|
||||
|
@ -3003,6 +3043,9 @@ public class ActMain extends AppCompatActivity
|
|||
vFooterDivider1.setBackgroundColor( c );
|
||||
vFooterDivider2.setBackgroundColor( c );
|
||||
}
|
||||
|
||||
c = footer_tab_indicator_color;
|
||||
llColumnStrip.setColor(c);
|
||||
}
|
||||
|
||||
ArrayList< SavedAccount > makeAccountListNonPseudo( LogCategory log ){
|
||||
|
@ -3196,6 +3239,7 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
|
||||
int nScreenColumn;
|
||||
int nColumnWidth;
|
||||
|
||||
private void resizeColumnWidth(){
|
||||
|
||||
|
@ -3248,6 +3292,7 @@ public class ActMain extends AppCompatActivity
|
|||
column_w = column_w_max;
|
||||
}
|
||||
|
||||
nColumnWidth = column_w;
|
||||
tablet_pager_adapter.setColumnWidth( column_w );
|
||||
tablet_snap_helper.setColumnWidth( column_w );
|
||||
}
|
||||
|
@ -3414,4 +3459,7 @@ public class ActMain extends AppCompatActivity
|
|||
progress.show();
|
||||
task.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import android.support.v4.content.ContextCompat;
|
|||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
|
@ -32,6 +33,7 @@ import android.view.ViewTreeObserver;
|
|||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
@ -64,8 +66,10 @@ import jp.juggler.subwaytooter.table.AcctSet;
|
|||
import jp.juggler.subwaytooter.table.PostDraft;
|
||||
import jp.juggler.subwaytooter.table.SavedAccount;
|
||||
import jp.juggler.subwaytooter.dialog.ActionsDialog;
|
||||
import jp.juggler.subwaytooter.table.TagSet;
|
||||
import jp.juggler.subwaytooter.util.HTMLDecoder;
|
||||
import jp.juggler.subwaytooter.util.LogCategory;
|
||||
import jp.juggler.subwaytooter.util.MyClickableSpan;
|
||||
import jp.juggler.subwaytooter.view.MyEditText;
|
||||
import jp.juggler.subwaytooter.view.MyNetworkImageView;
|
||||
import jp.juggler.subwaytooter.util.PostAttachment;
|
||||
|
@ -75,7 +79,6 @@ import okhttp3.MediaType;
|
|||
import okhttp3.MultipartBody;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import okio.BufferedSink;
|
||||
|
||||
public class ActPost extends AppCompatActivity implements View.OnClickListener, PostAttachment.Callback {
|
||||
|
@ -162,11 +165,15 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
case R.id.btnMore:
|
||||
performMore();
|
||||
break;
|
||||
|
||||
case R.id.btnPlugin:
|
||||
openMushroom();
|
||||
}
|
||||
}
|
||||
|
||||
private static final int REQUEST_CODE_ATTACHMENT = 1;
|
||||
private static final int REQUEST_CODE_CAMERA = 2;
|
||||
private static final int REQUEST_CODE_MUSHROOM = 3;
|
||||
|
||||
@Override
|
||||
protected void onActivityResult( int requestCode, int resultCode, Intent data ){
|
||||
|
@ -210,6 +217,9 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
addAttachment( uri, type );
|
||||
}
|
||||
}
|
||||
}else if( requestCode == REQUEST_CODE_MUSHROOM && resultCode == RESULT_OK ){
|
||||
String text = data.getStringExtra( "replace_key" );
|
||||
applyMushroomResult( text );
|
||||
}
|
||||
super.onActivityResult( requestCode, resultCode, data );
|
||||
}
|
||||
|
@ -240,6 +250,11 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
}
|
||||
|
||||
if( savedInstanceState != null ){
|
||||
|
||||
mushroom_input = savedInstanceState.getInt( STATE_MUSHROOM_INPUT, 0 );
|
||||
mushroom_start = savedInstanceState.getInt( STATE_MUSHROOM_START, 0 );
|
||||
mushroom_end = savedInstanceState.getInt( STATE_MUSHROOM_END, 0 );
|
||||
|
||||
long account_db_id = savedInstanceState.getLong( KEY_ACCOUNT_DB_ID, SavedAccount.INVALID_ID );
|
||||
if( account_db_id != SavedAccount.INVALID_ID ){
|
||||
for( int i = 0, ie = account_list.size() ; i < ie ; ++ i ){
|
||||
|
@ -451,6 +466,10 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
protected void onSaveInstanceState( Bundle outState ){
|
||||
super.onSaveInstanceState( outState );
|
||||
|
||||
outState.putInt( STATE_MUSHROOM_INPUT, mushroom_input );
|
||||
outState.putInt( STATE_MUSHROOM_START, mushroom_start );
|
||||
outState.putInt( STATE_MUSHROOM_END, mushroom_end );
|
||||
|
||||
if( account != null ){
|
||||
outState.putLong( KEY_ACCOUNT_DB_ID, account.db_id );
|
||||
}
|
||||
|
@ -553,6 +572,8 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
btnPost.setOnClickListener( this );
|
||||
btnRemoveReply.setOnClickListener( this );
|
||||
|
||||
findViewById( R.id.btnPlugin ).setOnClickListener( this );
|
||||
|
||||
for( MyNetworkImageView iv : ivMedia ){
|
||||
iv.setOnClickListener( this );
|
||||
iv.setDefaultImageResId( Styler.getAttributeResourceId( this, R.attr.ic_loading ) );
|
||||
|
@ -609,6 +630,8 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
}
|
||||
};
|
||||
|
||||
static final Pattern reCharsNotTag = Pattern.compile( "[\\s\\-+.,:;/]" );
|
||||
|
||||
final Runnable proc_text_changed = new Runnable() {
|
||||
@Override public void run(){
|
||||
int start = etContent.getSelectionStart();
|
||||
|
@ -643,7 +666,8 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
}
|
||||
// 登場した@の数
|
||||
if( count_atMark == 0 ){
|
||||
closeAcctPopup();
|
||||
// 次はAcctじゃなくてHashtagの補完を試みる
|
||||
checkTag();
|
||||
return;
|
||||
}else if( count_atMark == 1 ){
|
||||
start = pos_atMark[ 0 ];
|
||||
|
@ -668,6 +692,37 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
popup.setList( acct_list, start, end );
|
||||
}
|
||||
}
|
||||
|
||||
private void checkTag(){
|
||||
int end = etContent.getSelectionEnd();
|
||||
|
||||
String src = etContent.getText().toString();
|
||||
int last_sharp = src.lastIndexOf( '#' );
|
||||
|
||||
if( last_sharp == - 1 || end - last_sharp < 3 ){
|
||||
closeAcctPopup();
|
||||
return;
|
||||
}
|
||||
|
||||
String part = src.substring( last_sharp + 1, end );
|
||||
if( reCharsNotTag.matcher( part ).find() ){
|
||||
closeAcctPopup();
|
||||
return;
|
||||
}
|
||||
|
||||
int limit = 100;
|
||||
String s = src.substring( last_sharp + 1, end );
|
||||
ArrayList< String > tag_list = TagSet.searchPrefix( s, limit );
|
||||
log.d( "search for %s, result=%d", s, tag_list.size() );
|
||||
if( tag_list.isEmpty() ){
|
||||
closeAcctPopup();
|
||||
}else{
|
||||
if( popup == null || ! popup.isShowing() ){
|
||||
popup = new PopupAutoCompleteAcct( ActPost.this, etContent, formRoot );
|
||||
}
|
||||
popup.setList( tag_list, last_sharp, end );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PopupAutoCompleteAcct popup;
|
||||
|
@ -1017,7 +1072,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void writeTo( BufferedSink sink ) throws IOException{
|
||||
public void writeTo( @NonNull BufferedSink sink ) throws IOException{
|
||||
InputStream is = opener.open();
|
||||
if( is == null )
|
||||
throw new IOException( "openInputStream() failed. uri=" + uri );
|
||||
|
@ -1044,7 +1099,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
|
||||
opener.deleteTempFile();
|
||||
|
||||
if( result.object != null ){
|
||||
if( result != null && result.object != null ){
|
||||
pa.attachment = TootAttachment.parse( log, result.object );
|
||||
if( pa.attachment == null ){
|
||||
result.error = "TootAttachment.parse failed";
|
||||
|
@ -1411,8 +1466,33 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
.header( "Idempotency-Key", digest );
|
||||
|
||||
TootApiResult result = client.request( "/api/v1/statuses", request_builder );
|
||||
if( result.object != null ){
|
||||
if( result != null && result.object != null ){
|
||||
status = TootStatus.parse( log, account, result.object );
|
||||
|
||||
Spannable s = status.decoded_content;
|
||||
MyClickableSpan[] span_list = s.getSpans( 0, s.length(), MyClickableSpan.class );
|
||||
if( span_list != null ){
|
||||
ArrayList< String > tag_list = new ArrayList<>();
|
||||
for( MyClickableSpan span : span_list ){
|
||||
int start = s.getSpanStart( span );
|
||||
int end = s.getSpanEnd( span );
|
||||
String text = s.subSequence( start, end ).toString();
|
||||
if( text.startsWith( "#" ) ){
|
||||
tag_list.add( text.substring( 1 ) );
|
||||
}
|
||||
}
|
||||
int count = tag_list.size();
|
||||
if( count > 0 ){
|
||||
TagSet.saveList(
|
||||
System.currentTimeMillis()
|
||||
, tag_list.toArray( new String[ count ] )
|
||||
, 0
|
||||
, count
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
|
||||
|
@ -1427,7 +1507,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
protected void onPostExecute( TootApiResult result ){
|
||||
try{
|
||||
progress.dismiss();
|
||||
}catch(Throwable ignored){
|
||||
}catch( Throwable ignored ){
|
||||
// java.lang.IllegalArgumentException:
|
||||
// at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:396)
|
||||
// at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:322)
|
||||
|
@ -1478,7 +1558,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
llReply.setVisibility( View.GONE );
|
||||
}else{
|
||||
llReply.setVisibility( View.VISIBLE );
|
||||
tvReplyTo.setText( HTMLDecoder.decodeHTML( account ,in_reply_to_text ,true,null ));
|
||||
tvReplyTo.setText( HTMLDecoder.decodeHTML( account, in_reply_to_text, true, null ) );
|
||||
ivReply.setCornerRadius( pref, 16f );
|
||||
ivReply.setImageUrl( in_reply_to_image );
|
||||
|
||||
|
@ -1545,9 +1625,8 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
@Override public void onDraftSelected( JSONObject draft ){
|
||||
restoreDraft( draft );
|
||||
}
|
||||
});
|
||||
} );
|
||||
|
||||
|
||||
}
|
||||
|
||||
static boolean check_exist( String url ){
|
||||
|
@ -1573,14 +1652,8 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
@Override protected String doInBackground( Void... params ){
|
||||
|
||||
String content = draft.optString( DRAFT_CONTENT );
|
||||
String content_warning = draft.optString( DRAFT_CONTENT_WARNING );
|
||||
boolean content_warning_checked = draft.optBoolean( DRAFT_CONTENT_WARNING_CHECK );
|
||||
boolean nsfw_checked = draft.optBoolean( DRAFT_NSFW_CHECK );
|
||||
long account_db_id = draft.optLong( DRAFT_ACCOUNT_DB_ID );
|
||||
JSONArray tmp_attachment_list = draft.optJSONArray( DRAFT_ATTACHMENT_LIST );
|
||||
long reply_id = draft.optLong( DRAFT_REPLY_ID, in_reply_to_id );
|
||||
String reply_text = draft.optString( DRAFT_REPLY_TEXT, in_reply_to_text );
|
||||
String reply_image = draft.optString( DRAFT_REPLY_IMAGE, in_reply_to_image );
|
||||
|
||||
account = SavedAccount.loadAccount( log, account_db_id );
|
||||
if( account == null ){
|
||||
|
@ -1735,4 +1808,75 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
task.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Mushroom plugin
|
||||
|
||||
private static final String STATE_MUSHROOM_INPUT = "mushroom_input";
|
||||
private static final String STATE_MUSHROOM_START = "mushroom_start";
|
||||
private static final String STATE_MUSHROOM_END = "mushroom_end";
|
||||
int mushroom_input;
|
||||
int mushroom_start;
|
||||
int mushroom_end;
|
||||
|
||||
@NonNull String prepareMushroomText( @NonNull EditText et ){
|
||||
mushroom_start = et.getSelectionStart();
|
||||
mushroom_end = et.getSelectionEnd();
|
||||
if( mushroom_end > mushroom_start ){
|
||||
return et.getText().toString().substring( mushroom_start, mushroom_end );
|
||||
}else{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void applyMushroomText( @NonNull EditText et, @NonNull String text ){
|
||||
String src = et.getText().toString();
|
||||
if( mushroom_start > src.length() ) mushroom_start = src.length();
|
||||
if( mushroom_end > src.length() ) mushroom_end = src.length();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( src.substring( 0, mushroom_start ) );
|
||||
int new_sel_start = sb.length();
|
||||
sb.append( text );
|
||||
int new_sel_end = sb.length();
|
||||
sb.append( src.substring( mushroom_end ) );
|
||||
et.setText( sb );
|
||||
et.setSelection( new_sel_end, new_sel_end );
|
||||
}
|
||||
|
||||
void openMushroom(){
|
||||
try{
|
||||
String text;
|
||||
if( etContentWarning.hasFocus() ){
|
||||
mushroom_input = 1;
|
||||
text = prepareMushroomText( etContentWarning );
|
||||
}else{
|
||||
mushroom_input = 0;
|
||||
text = prepareMushroomText( etContent );
|
||||
}
|
||||
Intent intent = new Intent( "com.adamrocker.android.simeji.ACTION_INTERCEPT" );
|
||||
intent.addCategory( "com.adamrocker.android.simeji.REPLACE" );
|
||||
intent.putExtra( "replace_key", text );
|
||||
|
||||
// Create intent to show chooser
|
||||
Intent chooser = Intent.createChooser( intent, getString( R.string.select_plugin ) );
|
||||
|
||||
// Verify the intent will resolve to at least one activity
|
||||
if( intent.resolveActivity( getPackageManager() ) == null ){
|
||||
Utils.showToast( this, false, R.string.plugin_not_installed );
|
||||
return;
|
||||
}
|
||||
startActivityForResult( chooser, REQUEST_CODE_MUSHROOM );
|
||||
|
||||
}catch( Throwable ex ){
|
||||
Utils.showToast( this, ex, R.string.plugin_not_installed );
|
||||
}
|
||||
}
|
||||
|
||||
private void applyMushroomResult( String text ){
|
||||
if( mushroom_input == 1 ){
|
||||
applyMushroomText( etContentWarning, text );
|
||||
}else{
|
||||
applyMushroomText( etContent, text );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import jp.juggler.subwaytooter.table.MutedWord;
|
|||
import jp.juggler.subwaytooter.table.NotificationTracking;
|
||||
import jp.juggler.subwaytooter.table.PostDraft;
|
||||
import jp.juggler.subwaytooter.table.SavedAccount;
|
||||
import jp.juggler.subwaytooter.table.TagSet;
|
||||
import jp.juggler.subwaytooter.table.UserRelation;
|
||||
import jp.juggler.subwaytooter.util.LogCategory;
|
||||
import okhttp3.CipherSuite;
|
||||
|
@ -50,7 +51,7 @@ public class App1 extends Application {
|
|||
static final LogCategory log = new LogCategory( "App1" );
|
||||
|
||||
static final String DB_NAME = "app_db";
|
||||
static final int DB_VERSION = 14;
|
||||
static final int DB_VERSION = 15;
|
||||
// 2017/4/25 v10 1=>2 SavedAccount に通知設定を追加
|
||||
// 2017/4/25 v10 1=>2 NotificationTracking テーブルを追加
|
||||
// 2017/4/29 v20 2=>5 MediaShown,ContentWarningのインデクスが間違っていたので貼り直す
|
||||
|
@ -63,6 +64,7 @@ public class App1 extends Application {
|
|||
// 2017/5/17 v59 11=>12 PostDraft テーブルの追加
|
||||
// 2017/5/23 v68 12=>13 SavedAccountに項目追加
|
||||
// 2017/5/25 v69 13=>14 SavedAccountに項目追加
|
||||
// 2017/5/27 v73 14=>15 TagSetテーブルの追加
|
||||
|
||||
private static DBOpenHelper db_open_helper;
|
||||
|
||||
|
@ -120,6 +122,7 @@ public class App1 extends Application {
|
|||
AcctColor.onDBCreate( db );
|
||||
MutedWord.onDBCreate( db );
|
||||
PostDraft.onDBCreate( db );
|
||||
TagSet.onDBCreate(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -137,6 +140,7 @@ public class App1 extends Application {
|
|||
AcctColor.onDBUpgrade( db, oldVersion, newVersion );
|
||||
MutedWord.onDBUpgrade( db, oldVersion, newVersion );
|
||||
PostDraft.onDBUpgrade( db, oldVersion, newVersion );
|
||||
TagSet.onDBUpgrade( db, oldVersion, newVersion );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -308,6 +308,7 @@ public class AppDataExporter {
|
|||
case Pref.KEY_FOOTER_BUTTON_FG_COLOR:
|
||||
case Pref.KEY_FOOTER_TAB_BG_COLOR:
|
||||
case Pref.KEY_FOOTER_TAB_DIVIDER_COLOR:
|
||||
case Pref.KEY_FOOTER_TAB_INDICATOR_COLOR:
|
||||
int iv = reader.nextInt();
|
||||
e.putInt( k, iv );
|
||||
break;
|
||||
|
|
|
@ -33,11 +33,13 @@ import jp.juggler.subwaytooter.api.entity.TootRelationShip;
|
|||
import jp.juggler.subwaytooter.api.entity.TootReport;
|
||||
import jp.juggler.subwaytooter.api.entity.TootResults;
|
||||
import jp.juggler.subwaytooter.api.entity.TootStatus;
|
||||
import jp.juggler.subwaytooter.api.entity.TootTag;
|
||||
import jp.juggler.subwaytooter.table.AcctColor;
|
||||
import jp.juggler.subwaytooter.table.AcctSet;
|
||||
import jp.juggler.subwaytooter.table.MutedApp;
|
||||
import jp.juggler.subwaytooter.table.MutedWord;
|
||||
import jp.juggler.subwaytooter.table.SavedAccount;
|
||||
import jp.juggler.subwaytooter.table.TagSet;
|
||||
import jp.juggler.subwaytooter.table.UserRelation;
|
||||
import jp.juggler.subwaytooter.util.BucketList;
|
||||
import jp.juggler.subwaytooter.api.DuplicateMap;
|
||||
|
@ -1267,6 +1269,7 @@ class Column implements StreamReader.Callback {
|
|||
|
||||
HashSet< Long > who_set = new HashSet<>();
|
||||
HashSet< String > acct_set = new HashSet<>();
|
||||
HashSet< String > tag_set = new HashSet<>();
|
||||
{
|
||||
TootAccount a;
|
||||
TootStatus s;
|
||||
|
@ -1278,6 +1281,11 @@ class Column implements StreamReader.Callback {
|
|||
acct_set.add( "@" + access_info.getFullAcct( a ) );
|
||||
}else if( o instanceof TootStatus ){
|
||||
s = (TootStatus) o;
|
||||
if( s.tags != null ){
|
||||
for(TootTag tag : s.tags){
|
||||
tag_set.add( tag.name);
|
||||
}
|
||||
}
|
||||
a = s.account;
|
||||
if( a != null ){
|
||||
who_set.add( a.id );
|
||||
|
@ -1285,6 +1293,13 @@ class Column implements StreamReader.Callback {
|
|||
}
|
||||
s = s.reblog;
|
||||
if( s != null ){
|
||||
|
||||
if( s.tags != null ){
|
||||
for(TootTag tag : s.tags){
|
||||
tag_set.add( tag.name);
|
||||
}
|
||||
}
|
||||
|
||||
a = s.account;
|
||||
if( a != null ){
|
||||
who_set.add( a.id );
|
||||
|
@ -1302,6 +1317,13 @@ class Column implements StreamReader.Callback {
|
|||
//
|
||||
s = n.status;
|
||||
if( s != null ){
|
||||
|
||||
if( s.tags != null ){
|
||||
for(TootTag tag : s.tags){
|
||||
tag_set.add( tag.name);
|
||||
}
|
||||
}
|
||||
|
||||
a = s.account;
|
||||
if( a != null ){
|
||||
who_set.add( a.id );
|
||||
|
@ -1309,6 +1331,13 @@ class Column implements StreamReader.Callback {
|
|||
}
|
||||
s = s.reblog;
|
||||
if( s != null ){
|
||||
|
||||
if( s.tags != null ){
|
||||
for(TootTag tag : s.tags){
|
||||
tag_set.add( tag.name);
|
||||
}
|
||||
}
|
||||
|
||||
a = s.account;
|
||||
if( a != null ){
|
||||
who_set.add( a.id );
|
||||
|
@ -1372,7 +1401,26 @@ class Column implements StreamReader.Callback {
|
|||
log.d( "updateRelation: update %d acct.", n );
|
||||
|
||||
}
|
||||
|
||||
size = tag_set.size();
|
||||
if( size > 0 ){
|
||||
String[] tag_list = new String[ size ];
|
||||
{
|
||||
int n = 0;
|
||||
for( String l : tag_set ){
|
||||
tag_list[ n++ ] = l;
|
||||
}
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
int n = 0;
|
||||
while( n < size ){
|
||||
int length = size - n;
|
||||
if( length > ACCT_DB_STEP ) length = ACCT_DB_STEP;
|
||||
TagSet.saveList( now, tag_list, n, length );
|
||||
n += length;
|
||||
}
|
||||
log.d( "updateRelation: update %d tag.", n );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void startRefreshForPost( long status_id, int refresh_after_toot ){
|
||||
|
|
|
@ -37,6 +37,7 @@ public class Pref {
|
|||
static final String KEY_FOOTER_BUTTON_FG_COLOR = "footer_button_fg_color";
|
||||
static final String KEY_FOOTER_TAB_BG_COLOR = "footer_tab_bg_color";
|
||||
static final String KEY_FOOTER_TAB_DIVIDER_COLOR = "footer_tab_divider_color";
|
||||
static final String KEY_FOOTER_TAB_INDICATOR_COLOR = "footer_tab_indicator_color";
|
||||
|
||||
static final String KEY_DONT_USE_STREAMING = "dont_use_streaming";
|
||||
static final String KEY_DONT_REFRESH_ON_RESUME = "dont_refresh_on_resume";
|
||||
|
|
|
@ -67,7 +67,7 @@ public class LoginForm {
|
|||
if( TextUtils.isEmpty( instance ) ){
|
||||
Utils.showToast( activity, true, R.string.instance_not_specified );
|
||||
return;
|
||||
}else if( instance.contains( "/" )){
|
||||
}else if( instance.contains( "/" ) || instance.contains( "@" ) ){
|
||||
Utils.showToast( activity, true, R.string.instance_not_need_slash );
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
package jp.juggler.subwaytooter.table;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import jp.juggler.subwaytooter.App1;
|
||||
import jp.juggler.subwaytooter.util.LogCategory;
|
||||
|
||||
public class TagSet {
|
||||
|
||||
private static final LogCategory log = new LogCategory( "TagSet" );
|
||||
|
||||
private static final String table = "tag_set";
|
||||
private static final String COL_TIME_SAVE = "time_save";
|
||||
private static final String COL_TAG = "tag"; // タグ。先頭の#を含まない
|
||||
|
||||
public static void onDBCreate( SQLiteDatabase db ){
|
||||
log.d( "onDBCreate!" );
|
||||
db.execSQL(
|
||||
"create table if not exists " + table
|
||||
+ "(_id INTEGER PRIMARY KEY"
|
||||
+ "," + COL_TIME_SAVE + " integer not null"
|
||||
+ "," + COL_TAG + " text not null"
|
||||
+ ")"
|
||||
);
|
||||
db.execSQL(
|
||||
"create unique index if not exists " + table + "_tag on " + table + "(" + COL_TAG + ")"
|
||||
);
|
||||
db.execSQL(
|
||||
"create index if not exists " + table + "_time on " + table + "(" + COL_TIME_SAVE + ")"
|
||||
);
|
||||
}
|
||||
|
||||
public static void onDBUpgrade( SQLiteDatabase db, int oldVersion, int newVersion ){
|
||||
if( oldVersion < 15 && newVersion >= 15 ){
|
||||
onDBCreate( db );
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteOld( long now ){
|
||||
try{
|
||||
// 古いデータを掃除する
|
||||
long expire = now - 86400000L * 365;
|
||||
App1.getDB().delete( table, COL_TIME_SAVE + "<?", new String[]{ Long.toString( expire ) } );
|
||||
|
||||
}catch( Throwable ex ){
|
||||
log.e( ex, "deleteOld failed." );
|
||||
}
|
||||
}
|
||||
|
||||
// public static void save1( long now, String acct ){
|
||||
// try{
|
||||
//
|
||||
// ContentValues cv = new ContentValues();
|
||||
// cv.put( COL_TIME_SAVE, now );
|
||||
// cv.put( COL_ACCT, acct );
|
||||
// App1.getDB().replace( table, null, cv );
|
||||
// }catch( Throwable ex ){
|
||||
// log.e( ex, "save failed." );
|
||||
// }
|
||||
// }
|
||||
|
||||
public static void saveList( long now, String[] src_list, int offset, int length ){
|
||||
|
||||
try{
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put( COL_TIME_SAVE, now );
|
||||
|
||||
boolean bOK = false;
|
||||
SQLiteDatabase db = App1.getDB();
|
||||
db.execSQL( "BEGIN TRANSACTION" );
|
||||
try{
|
||||
for( int i = 0 ; i < length ; ++ i ){
|
||||
String acct = src_list[ i + offset ];
|
||||
cv.put( COL_TAG, acct );
|
||||
db.replace( table, null, cv );
|
||||
}
|
||||
bOK = true;
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
log.e( ex, "saveList failed." );
|
||||
}
|
||||
if( bOK ){
|
||||
db.execSQL( "COMMIT TRANSACTION" );
|
||||
}else{
|
||||
db.execSQL( "ROLLBACK TRANSACTION" );
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
log.e( ex, "saveList failed." );
|
||||
}
|
||||
}
|
||||
|
||||
private static final String prefix_search_where = COL_TAG + " like ? escape '$'";
|
||||
|
||||
private static final ThreadLocal< String[] > prefix_search_where_arg = new ThreadLocal< String[] >() {
|
||||
@Override protected String[] initialValue(){
|
||||
return new String[ 1 ];
|
||||
}
|
||||
};
|
||||
|
||||
private static String makePattern( String src ){
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for( int i = 0, ie = src.length() ; i < ie ; ++ i ){
|
||||
char c = src.charAt( i );
|
||||
if( c == '%' || c == '_' || c == '$' ){
|
||||
sb.append( '$' );
|
||||
}
|
||||
sb.append( c );
|
||||
}
|
||||
// 前方一致検索にするため、末尾に%をつける
|
||||
sb.append( '%' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@NonNull public static ArrayList< String > searchPrefix( @NonNull String prefix ,int limit){
|
||||
try{
|
||||
String[] where_arg = prefix_search_where_arg.get();
|
||||
where_arg[ 0 ] = makePattern( prefix );
|
||||
Cursor cursor = App1.getDB().query( table, null, prefix_search_where, where_arg, null, null, COL_TAG + " asc limit "+limit );
|
||||
if( cursor != null ){
|
||||
try{
|
||||
ArrayList< String > dst = new ArrayList<>( cursor.getCount() );
|
||||
int idx_acct = cursor.getColumnIndex( COL_TAG );
|
||||
while( cursor.moveToNext() ){
|
||||
dst.add( "#"+cursor.getString( idx_acct ) );
|
||||
}
|
||||
return dst;
|
||||
}finally{
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
log.e( ex, "searchPrefix failed." );
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package jp.juggler.subwaytooter.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import jp.juggler.subwaytooter.R;
|
||||
import jp.juggler.subwaytooter.Styler;
|
||||
|
||||
public class ColumnStripLinearLayout extends LinearLayout {
|
||||
public ColumnStripLinearLayout( Context context ){
|
||||
super( context );
|
||||
init();
|
||||
}
|
||||
|
||||
public ColumnStripLinearLayout( Context context, @Nullable AttributeSet attrs ){
|
||||
super( context, attrs );
|
||||
init();
|
||||
}
|
||||
|
||||
public ColumnStripLinearLayout( Context context, @Nullable AttributeSet attrs, int defStyleAttr ){
|
||||
super( context, attrs, defStyleAttr );
|
||||
init();
|
||||
}
|
||||
|
||||
final Paint paint = new Paint();
|
||||
final Rect rect = new Rect();
|
||||
int h ;
|
||||
void init(){
|
||||
h = (int)(0.5f + 2f * getResources().getDisplayMetrics().density );
|
||||
}
|
||||
|
||||
int first;
|
||||
int last;
|
||||
float slide_ratio;
|
||||
|
||||
public void setColumnRange(int first,int last,float slide_ratio){
|
||||
if( this.first == first && this.last == last && this.slide_ratio == slide_ratio ) return;
|
||||
this.first = first;
|
||||
this.last = last;
|
||||
this.slide_ratio = slide_ratio;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
int color;
|
||||
public void setColor( int color ){
|
||||
if( color == 0 ) color = Styler.getAttributeColor(getContext(), R.attr.colorAccent);
|
||||
if( this.color == color ) return;
|
||||
this.color = color;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
@Override protected void dispatchDraw(Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
|
||||
if( first < 0 || last >= getChildCount() ) return;
|
||||
|
||||
View child = getChildAt( first );
|
||||
rect.left = child.getLeft();
|
||||
child = getChildAt( last );
|
||||
rect.right = child.getRight();
|
||||
|
||||
if( slide_ratio != 0f){
|
||||
child = getChildAt( first );
|
||||
int w = child.getWidth();
|
||||
int slide = (int)(0.5f + slide_ratio * w);
|
||||
rect.left += slide;
|
||||
rect.right += slide;
|
||||
}
|
||||
|
||||
rect.top = 0;
|
||||
rect.bottom = h;
|
||||
paint.setColor( color );
|
||||
canvas.drawRect( rect,paint );
|
||||
}
|
||||
|
||||
}
|
After Width: | Height: | Size: 613 B |
After Width: | Height: | Size: 538 B |
After Width: | Height: | Size: 429 B |
After Width: | Height: | Size: 355 B |
After Width: | Height: | Size: 714 B |
After Width: | Height: | Size: 619 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.0 KiB |
|
@ -363,83 +363,93 @@
|
|||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llFooterBG"
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/colorColumnStripBackground"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivFooterMenu"
|
||||
android:layout_width="48dp"
|
||||
<LinearLayout
|
||||
android:id="@+id/llFooterBG"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/btn_bg_ddd"
|
||||
android:importantForAccessibility="no"
|
||||
app:srcCompat="?attr/ic_hamburger"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:id="@+id/vFooterDivider1"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorImageButton"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/svColumnStrip"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
|
||||
android:cacheColorHint="#00000000"
|
||||
android:fadingEdge="horizontal"
|
||||
android:fadingEdgeLength="20dp"
|
||||
android:fillViewport="true"
|
||||
android:scrollbars="none"
|
||||
android:background="?attr/colorColumnStripBackground"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llColumnStrip"
|
||||
android:layout_width="wrap_content"
|
||||
<ImageView
|
||||
android:id="@+id/ivFooterMenu"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/btn_bg_ddd"
|
||||
android:importantForAccessibility="no"
|
||||
app:srcCompat="?attr/ic_hamburger"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:id="@+id/vFooterDivider1"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:background="?attr/colorImageButton"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/svColumnStrip"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
|
||||
android:cacheColorHint="#00000000"
|
||||
android:fadingEdge="horizontal"
|
||||
android:fadingEdgeLength="20dp"
|
||||
android:fillViewport="true"
|
||||
android:scrollbars="none"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llColumnStrip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/vFooterDivider2"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorImageButton"
|
||||
/>
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivFooterToot"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/btn_bg_ddd"
|
||||
android:contentDescription="@string/toot"
|
||||
app:srcCompat="?attr/ic_edit"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<View
|
||||
android:id="@+id/vFooterDivider2"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorImageButton"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivFooterToot"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/btn_bg_ddd"
|
||||
android:contentDescription="@string/toot"
|
||||
app:srcCompat="?attr/ic_edit"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<View android:layout_width="48dp"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
tools:background="#f00"
|
||||
android:id="@+id/vIndicator"/>
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
@ -557,6 +567,33 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/tab_indicator_color"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnTabIndicatorColorEdit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/edit"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnTabIndicatorColorReset"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/reset"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View style="@style/setting_divider"/>
|
||||
|
||||
|
@ -678,11 +715,13 @@
|
|||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<TextView
|
||||
style="@style/setting_horizontal_stretch"
|
||||
android:text="@string/custom_stream_listener_desc"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<View style="@style/setting_divider"/>
|
||||
|
||||
<!--<TextView-->
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
android:id="@+id/svColumnStrip"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
<jp.juggler.subwaytooter.view.ColumnStripLinearLayout
|
||||
android:id="@+id/llColumnStrip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
|
|
|
@ -248,6 +248,16 @@
|
|||
tools:src="?attr/ic_public"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnPlugin"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:background="@drawable/btn_bg_transparent"
|
||||
android:contentDescription="@string/plugin"
|
||||
android:src="?attr/ic_plugin"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnMore"
|
||||
android:layout_width="48dp"
|
||||
|
|
|
@ -165,7 +165,7 @@
|
|||
<string name="image_pick">Choisir une image</string>
|
||||
<string name="instance">Instance</string>
|
||||
<string name="instance_hint">Ex) mastodon.social</string>
|
||||
<string name="instance_not_need_slash">Veuillez entrer seulement le nom de l\'hôte de l\'instance, sans « / ».</string>
|
||||
<string name="instance_not_need_slash">Veuillez entrer seulement le nom de l\'hôte de l\'instance, sans « / », « \@ ».</string>
|
||||
<string name="instance_not_specified">Instance non spécifiée</string>
|
||||
<string name="it_is_you">C\'est vous.</string>
|
||||
<string name="last_selection">Dernière sélection</string>
|
||||
|
@ -338,6 +338,10 @@
|
|||
<string name="custom_stream_listener_desc">This setting is for advanced users. If you are not sure, please don\'t edit.</string>
|
||||
<string name="custom_stream_listener_was_reset">Custom notification listener was reset.</string>
|
||||
<string name="input_url_and_secret_then_test">Input URL and Secret, then tap Test button.</string>
|
||||
<string name="tab_indicator_color">Tab\'s indicator color</string>
|
||||
<string name="plugin">Plugin</string>
|
||||
<string name="select_plugin">Select plugin</string>
|
||||
<string name="plugin_not_installed">Plugin is not installed.</string>
|
||||
|
||||
<!--<string name="abc_action_bar_home_description">Revenir à l\'accueil</string>-->
|
||||
<!--<string name="abc_action_bar_home_description_format">%1$s, %2$s</string>-->
|
||||
|
|
|
@ -204,7 +204,7 @@
|
|||
<!---->
|
||||
<string name="conversation_around">会話の流れ(id:%1$d)</string>
|
||||
<!---->
|
||||
<string name="instance_not_need_slash">インスタンスには\'/\'を含めずに、ホスト名だけを指定してください</string>
|
||||
<string name="instance_not_need_slash">インスタンスには\'/\',\'\@\'を含めずに、ホスト名だけを指定してください</string>
|
||||
<!---->
|
||||
<string name="mail_address_not_contains_at_mark">メールアドレスが不十分です。\'@\'や\'.\'がありません</string>
|
||||
<!---->
|
||||
|
@ -625,5 +625,9 @@
|
|||
<string name="test">テスト</string>
|
||||
<string name="custom_stream_listener_was_reset">カスタム通知リスナを使わないようにしました</string>
|
||||
<string name="input_url_and_secret_then_test">URLとシークレットを入力してテストボタンを押してください</string>
|
||||
<string name="tab_indicator_color">タブのインジケータの色</string>
|
||||
<string name="plugin">プラグイン</string>
|
||||
<string name="select_plugin">プラグインの選択</string>
|
||||
<string name="plugin_not_installed">プラグインがインストールされてません</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -116,5 +116,6 @@
|
|||
|
||||
<attr name="ic_hamburger" format="reference" />
|
||||
<attr name="ic_delete" format="reference" />
|
||||
<attr name="ic_plugin" format="reference" />
|
||||
|
||||
</resources>
|
|
@ -104,8 +104,8 @@
|
|||
<string name="column">Column</string>
|
||||
<string name="conversation_view">Conversation view</string>
|
||||
<string name="conversation_around">Conversation around toot:%1$d</string>
|
||||
<string name="instance_not_need_slash">Hostname of the instance, without \'/\'.</string>
|
||||
<string name="mail_address_not_contains_at_mark">Use emails that contains \'@\' and \'.\'</string>
|
||||
<string name="instance_not_need_slash">Hostname of the instance, without \'/\', \'\@\'.</string>
|
||||
<string name="mail_address_not_contains_at_mark">Use emails that contains \'\@\' and \'.\'</string>
|
||||
<string name="instance_hint">ex) mastodon.social</string>
|
||||
<string name="mail_hint">ex) your@e-mail.address</string>
|
||||
<string name="unfollow">Unfollow</string>
|
||||
|
@ -334,4 +334,8 @@
|
|||
<string name="custom_stream_listener_desc">This setting is for advanced users. If you are not sure, please don\'t edit.</string>
|
||||
<string name="custom_stream_listener_was_reset">Custom notification listener was reset.</string>
|
||||
<string name="input_url_and_secret_then_test">Input URL and Secret, then tap Test button.</string>
|
||||
<string name="tab_indicator_color">Tab\'s indicator color</string>
|
||||
<string name="plugin">Plugin</string>
|
||||
<string name="select_plugin">Select plugin</string>
|
||||
<string name="plugin_not_installed">Plugin is not installed.</string>
|
||||
</resources>
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
|
||||
<item name="ic_hamburger">@drawable/ic_hamburger</item>
|
||||
<item name="ic_delete">@drawable/ic_delete</item>
|
||||
<item name="ic_plugin">@drawable/ic_plugin</item>
|
||||
|
||||
|
||||
</style>
|
||||
|
@ -173,7 +174,7 @@
|
|||
|
||||
<item name="ic_hamburger">@drawable/ic_hamburger_dark</item>
|
||||
<item name="ic_delete">@drawable/ic_delete_dark</item>
|
||||
|
||||
<item name="ic_plugin">@drawable/ic_plugin_dark</item>
|
||||
|
||||
</style>
|
||||
|
||||
|
|