v1.3.7
- 通信タイムアウトの時間長を調整 - 他人のプロフで固定トゥートのPINアイコンが表示されなかった不具合の修正 - プロフィール編集で文字数を超過した場合に警告を表示する。警告を無視することもできる - トゥート投稿時の残り文字数表示で、アンケート項目の文字数も数える - トゥート投稿時の残り文字数表示で、アンケートが有効なら最大文字数を350に変更する - アプリ設定に「アバターアイコンサイズ」を追加 - アプリ設定に「ローカルユーザのAcctのインスタンス部分を表示しない」を追加
This commit is contained in:
parent
0aa599dc09
commit
58bf2f4ac4
|
@ -9,8 +9,8 @@ android {
|
|||
applicationId "jp.juggler.subwaytooter"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 26
|
||||
versionCode 135
|
||||
versionName "1.3.5"
|
||||
versionCode 137
|
||||
versionName "1.3.7"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
|
|
@ -424,11 +424,11 @@ public class ActAccountSetting extends AppCompatActivity
|
|||
break;
|
||||
|
||||
case R.id.btnDisplayName:
|
||||
sendDisplayName();
|
||||
sendDisplayName(false);
|
||||
break;
|
||||
|
||||
case R.id.btnNote:
|
||||
sendNote();
|
||||
sendNote(false);
|
||||
break;
|
||||
|
||||
case R.id.btnNotificationStyleEdit:
|
||||
|
@ -576,6 +576,7 @@ public class ActAccountSetting extends AppCompatActivity
|
|||
///////////////////////////////////////////////////
|
||||
private void performAccessToken(){
|
||||
|
||||
//noinspection deprecation
|
||||
final ProgressDialog progress = new ProgressDialog( ActAccountSetting.this );
|
||||
|
||||
final AsyncTask< Void, String, TootApiResult > task = new AsyncTask< Void, String, TootApiResult >() {
|
||||
|
@ -692,6 +693,7 @@ public class ActAccountSetting extends AppCompatActivity
|
|||
void loadProfile(){
|
||||
// サーバから情報をロードする
|
||||
|
||||
//noinspection deprecation
|
||||
final ProgressDialog progress = new ProgressDialog( this );
|
||||
|
||||
final AsyncTask< Void, Void, TootApiResult > task = new AsyncTask< Void, Void, TootApiResult >() {
|
||||
|
@ -772,6 +774,8 @@ public class ActAccountSetting extends AppCompatActivity
|
|||
}
|
||||
|
||||
void updateCredential( final String form_data ){
|
||||
|
||||
//noinspection deprecation
|
||||
final ProgressDialog progress = new ProgressDialog( this );
|
||||
|
||||
final AsyncTask< Void, Void, TootApiResult > task = new AsyncTask< Void, Void, TootApiResult >() {
|
||||
|
@ -814,7 +818,7 @@ public class ActAccountSetting extends AppCompatActivity
|
|||
progress.dismiss();
|
||||
}catch( Throwable ignored ){
|
||||
}
|
||||
loadProfile();
|
||||
|
||||
if( result == null ){
|
||||
// cancelled.
|
||||
}else if( data != null ){
|
||||
|
@ -835,12 +839,55 @@ public class ActAccountSetting extends AppCompatActivity
|
|||
progress.show();
|
||||
}
|
||||
|
||||
private void sendDisplayName(){
|
||||
updateCredential( "display_name=" + Uri.encode( etDisplayName.getText().toString() ) );
|
||||
static final int max_length_display_name = 30;
|
||||
static final int max_length_note = 160;
|
||||
|
||||
private void sendDisplayName(boolean bConfirmed){
|
||||
String sv = etDisplayName.getText().toString();
|
||||
if( !bConfirmed ){
|
||||
int length = sv.codePointCount( 0,sv.length() );
|
||||
if( length > max_length_display_name ){
|
||||
new AlertDialog.Builder( this )
|
||||
.setMessage( getString(R.string.length_warning
|
||||
,getString(R.string.display_name)
|
||||
,length,max_length_display_name
|
||||
))
|
||||
.setNegativeButton( R.string.cancel ,null)
|
||||
.setPositiveButton( R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override public void onClick( DialogInterface dialogInterface, int i ){
|
||||
sendDisplayName(true);
|
||||
}
|
||||
} )
|
||||
.setCancelable( true )
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
updateCredential( "display_name=" + Uri.encode(sv ) );
|
||||
}
|
||||
|
||||
private void sendNote(){
|
||||
updateCredential( "note=" + Uri.encode( etNote.getText().toString() ) );
|
||||
private void sendNote(boolean bConfirmed){
|
||||
String sv = etNote.getText().toString();
|
||||
if( !bConfirmed ){
|
||||
int length = sv.codePointCount( 0,sv.length() );
|
||||
if( length > max_length_note ){
|
||||
new AlertDialog.Builder( this )
|
||||
.setMessage( getString(R.string.length_warning
|
||||
,getString(R.string.note)
|
||||
,length,max_length_note
|
||||
))
|
||||
.setNegativeButton( R.string.cancel ,null)
|
||||
.setPositiveButton( R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override public void onClick( DialogInterface dialogInterface, int i ){
|
||||
sendNote(true);
|
||||
}
|
||||
} )
|
||||
.setCancelable( true )
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
updateCredential( "note=" + Uri.encode(sv ) );
|
||||
}
|
||||
|
||||
private static final int PERMISSION_REQUEST_AVATAR = 1;
|
||||
|
|
|
@ -104,6 +104,7 @@ public class ActAppSetting extends AppCompatActivity
|
|||
Switch swMentionFullAcct;
|
||||
Switch swRelativeTimestamp;
|
||||
Switch swDontUseActionButtonWithQuickTootBar;
|
||||
Switch swShortAcctLocalUser;
|
||||
|
||||
Spinner spBackButtonAction;
|
||||
Spinner spUITheme;
|
||||
|
@ -148,6 +149,7 @@ public class ActAppSetting extends AppCompatActivity
|
|||
EditText etAcctFontSize;
|
||||
TextView tvTimelineFontSize;
|
||||
TextView tvAcctFontSize;
|
||||
EditText etAvatarIconSize;
|
||||
|
||||
static final float default_timeline_font_size = 14f;
|
||||
static final float default_acct_font_size = 12f;
|
||||
|
@ -217,6 +219,9 @@ public class ActAppSetting extends AppCompatActivity
|
|||
swDontUseActionButtonWithQuickTootBar = findViewById( R.id.swDontUseActionButtonWithQuickTootBar );
|
||||
swDontUseActionButtonWithQuickTootBar.setOnCheckedChangeListener( this );
|
||||
|
||||
swShortAcctLocalUser = findViewById( R.id.swShortAcctLocalUser );
|
||||
swShortAcctLocalUser.setOnCheckedChangeListener( this );
|
||||
|
||||
cbNotificationSound = findViewById( R.id.cbNotificationSound );
|
||||
cbNotificationVibration = findViewById( R.id.cbNotificationVibration );
|
||||
cbNotificationLED = findViewById( R.id.cbNotificationLED );
|
||||
|
@ -344,6 +349,8 @@ public class ActAppSetting extends AppCompatActivity
|
|||
etAcctFontSize = findViewById( R.id.etAcctFontSize );
|
||||
etAcctFontSize.addTextChangedListener( new SizeCheckTextWatcher( tvAcctFontSize, etAcctFontSize, default_acct_font_size ) );
|
||||
|
||||
etAvatarIconSize = findViewById( R.id.etAvatarIconSize );
|
||||
|
||||
tvTimelineFontUrl = findViewById( R.id.tvTimelineFontUrl );
|
||||
tvTimelineFontBoldUrl = findViewById( R.id.tvTimelineFontBoldUrl );
|
||||
|
||||
|
@ -372,6 +379,7 @@ public class ActAppSetting extends AppCompatActivity
|
|||
swMentionFullAcct.setChecked( pref.getBoolean( Pref.KEY_MENTION_FULL_ACCT, false ) );
|
||||
swRelativeTimestamp.setChecked( pref.getBoolean( Pref.KEY_RELATIVE_TIMESTAMP, false ) );
|
||||
swDontUseActionButtonWithQuickTootBar.setChecked( pref.getBoolean( Pref.KEY_DONT_USE_ACTION_BUTTON, false ) );
|
||||
swShortAcctLocalUser.setChecked( pref.getBoolean( Pref.KEY_SHORT_ACCT_LOCAL_USER, false ) );
|
||||
|
||||
// Switch with default true
|
||||
swDisableFastScroller.setChecked( pref.getBoolean( Pref.KEY_DISABLE_FAST_SCROLLER, true ) );
|
||||
|
@ -401,6 +409,7 @@ public class ActAppSetting extends AppCompatActivity
|
|||
etClientName.setText( pref.getString( Pref.KEY_CLIENT_NAME, "" ) );
|
||||
etQuoteNameFormat.setText( pref.getString( Pref.KEY_QUOTE_NAME_FORMAT, "" ) );
|
||||
etAutoCWLines.setText( pref.getString( Pref.KEY_AUTO_CW_LINES, "0" ) );
|
||||
etAvatarIconSize.setText( pref.getString( Pref.KEY_AVATAR_ICON_SIZE, "48" ) );
|
||||
|
||||
etTimelineFontSize.setText( formatFontSize( pref.getFloat( Pref.KEY_TIMELINE_FONT_SIZE, Float.NaN ) ) );
|
||||
etAcctFontSize.setText( formatFontSize( pref.getFloat( Pref.KEY_ACCT_FONT_SIZE, Float.NaN ) ) );
|
||||
|
@ -441,6 +450,9 @@ public class ActAppSetting extends AppCompatActivity
|
|||
.putBoolean( Pref.KEY_MENTION_FULL_ACCT, swMentionFullAcct.isChecked() )
|
||||
.putBoolean( Pref.KEY_RELATIVE_TIMESTAMP, swRelativeTimestamp.isChecked() )
|
||||
.putBoolean( Pref.KEY_DONT_USE_ACTION_BUTTON, swDontUseActionButtonWithQuickTootBar.isChecked() )
|
||||
.putBoolean( Pref.KEY_SHORT_ACCT_LOCAL_USER, swShortAcctLocalUser.isChecked() )
|
||||
|
||||
|
||||
|
||||
.putBoolean( Pref.KEY_NOTIFICATION_SOUND, cbNotificationSound.isChecked() )
|
||||
.putBoolean( Pref.KEY_NOTIFICATION_VIBRATION, cbNotificationVibration.isChecked() )
|
||||
|
@ -467,6 +479,8 @@ public class ActAppSetting extends AppCompatActivity
|
|||
.putString( Pref.KEY_CLIENT_NAME, etClientName.getText().toString().trim() )
|
||||
.putString( Pref.KEY_QUOTE_NAME_FORMAT, etQuoteNameFormat.getText().toString() ) // not trimmed
|
||||
.putString( Pref.KEY_AUTO_CW_LINES, etAutoCWLines.getText().toString() ) // not trimmed
|
||||
.putString( Pref.KEY_AVATAR_ICON_SIZE, etAvatarIconSize.getText().toString().trim() )
|
||||
|
||||
.putFloat( Pref.KEY_TIMELINE_FONT_SIZE, parseFontSize( etTimelineFontSize.getText().toString().trim() ) )
|
||||
.putFloat( Pref.KEY_ACCT_FONT_SIZE, parseFontSize( etAcctFontSize.getText().toString().trim() ) )
|
||||
|
||||
|
|
|
@ -770,6 +770,8 @@ public class ActMain extends AppCompatActivity
|
|||
Typeface timeline_font_bold;
|
||||
|
||||
boolean dont_crop_media_thumbnail;
|
||||
boolean mShortAcctLocalUser;
|
||||
int mAvatarIconSize;
|
||||
|
||||
View llQuickTootBar;
|
||||
MyEditText etQuickToot;
|
||||
|
@ -805,6 +807,23 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
|
||||
mShortAcctLocalUser = pref.getBoolean( Pref.KEY_SHORT_ACCT_LOCAL_USER ,false);
|
||||
|
||||
{
|
||||
float icon_size_dp = 48f;
|
||||
try{
|
||||
sv = pref.getString( Pref.KEY_AVATAR_ICON_SIZE, "48" );
|
||||
float fv = Float.parseFloat( sv );
|
||||
if( Float.isNaN( fv ) || Float.isInfinite( fv ) || fv < 1f ){
|
||||
// error or bad range
|
||||
}else{
|
||||
icon_size_dp = fv;
|
||||
}
|
||||
}catch(Throwable ex){
|
||||
log.trace( ex );
|
||||
}
|
||||
mAvatarIconSize = (int)(0.5f + icon_size_dp * density );
|
||||
}
|
||||
|
||||
llEmpty = findViewById( R.id.llEmpty );
|
||||
|
||||
|
@ -2669,6 +2688,7 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
|
||||
static final Pattern reUriOStatusToot = Pattern.compile( "tag:([^,]*),[^:]*:objectId=(\\d+):objectType=Status", Pattern.CASE_INSENSITIVE );
|
||||
// static final Pattern reUriActivityPubToot = Pattern.compile( "tag:([^,]*),[^:]*:objectId=(\\d+):objectType=Status", Pattern.CASE_INSENSITIVE );
|
||||
|
||||
public void openStatusOtherInstance( int pos, @NonNull SavedAccount access_info, @NonNull TootStatusLike status ){
|
||||
if( status.account == null ){
|
||||
|
@ -2699,6 +2719,13 @@ public class ActMain extends AppCompatActivity
|
|||
if( m.find() ){
|
||||
status_id_original = Long.parseLong( m.group( 2 ), 10 );
|
||||
// host_original = m.group( 1 );
|
||||
}else{
|
||||
// TODO ActivityPub対応
|
||||
// m = reUriOStatusToot.matcher( ts.uri );
|
||||
// if( m.find() ){
|
||||
// status_id_original = Long.parseLong( m.group( 2 ), 10 );
|
||||
// // host_original = m.group( 1 );
|
||||
// }
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
log.e( ex, "openStatusOtherInstance: cant parse tag: %s", ts.uri );
|
||||
|
|
|
@ -651,6 +651,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
@Override
|
||||
public void onCheckedChanged( CompoundButton buttonView, boolean isChecked ){
|
||||
showEnquete();
|
||||
updateTextCount();
|
||||
}
|
||||
} );
|
||||
|
||||
|
@ -665,27 +666,31 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
}
|
||||
} );
|
||||
|
||||
etContentWarning.addTextChangedListener( new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged( CharSequence s, int start, int count, int after ){
|
||||
|
||||
etContentWarning.addTextChangedListener( text_watcher);
|
||||
for(MyEditText et : list_etChoice ){
|
||||
et.addTextChangedListener( text_watcher);
|
||||
}
|
||||
|
||||
@Override public void onTextChanged( CharSequence s, int start, int before, int count ){
|
||||
|
||||
}
|
||||
|
||||
@Override public void afterTextChanged( Editable s ){
|
||||
updateTextCount();
|
||||
}
|
||||
} );
|
||||
|
||||
scrollView.getViewTreeObserver().addOnScrollChangedListener( scroll_listener );
|
||||
|
||||
View v = findViewById( R.id.btnMore );
|
||||
v.setOnClickListener( this );
|
||||
}
|
||||
|
||||
final TextWatcher text_watcher = new TextWatcher() {
|
||||
@Override public void beforeTextChanged( CharSequence charSequence, int i, int i1, int i2 ){
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTextChanged( CharSequence charSequence, int i, int i1, int i2 ){
|
||||
|
||||
}
|
||||
|
||||
@Override public void afterTextChanged( Editable editable ){
|
||||
updateTextCount();
|
||||
}
|
||||
};
|
||||
|
||||
final ViewTreeObserver.OnScrollChangedListener scroll_listener = new ViewTreeObserver.OnScrollChangedListener() {
|
||||
@Override public void onScrollChanged(){
|
||||
post_helper.onScrollChanged();
|
||||
|
@ -694,12 +699,26 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
};
|
||||
|
||||
private void updateTextCount(){
|
||||
String s = etContent.getText().toString();
|
||||
int count_content = s.codePointCount( 0, s.length() );
|
||||
s = cbContentWarning.isChecked() ? etContentWarning.getText().toString() : "";
|
||||
int count_spoiler = s.codePointCount( 0, s.length() );
|
||||
int length = 0;
|
||||
|
||||
int remain = 500 - count_content - count_spoiler;
|
||||
String s = etContent.getText().toString();
|
||||
length += s.codePointCount( 0, s.length() );
|
||||
|
||||
s = cbContentWarning.isChecked() ? etContentWarning.getText().toString() : "";
|
||||
length += s.codePointCount( 0, s.length() );
|
||||
|
||||
int max;
|
||||
if( !cbEnquete.isChecked() ){
|
||||
max = 500;
|
||||
}else{
|
||||
max = 350;
|
||||
for( MyEditText et : list_etChoice){
|
||||
s = et.getText().toString();
|
||||
length += s.codePointCount( 0, s.length() );
|
||||
}
|
||||
}
|
||||
|
||||
int remain = max - length;
|
||||
tvCharCount.setText( Integer.toString( remain ) );
|
||||
int color = Styler.getAttributeColor( this, remain < 0 ? R.attr.colorRegexFilterError : android.R.attr.textColorPrimary );
|
||||
tvCharCount.setTextColor( color );
|
||||
|
|
|
@ -285,8 +285,8 @@ public class App1 extends Application {
|
|||
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder()
|
||||
.connectTimeout( 30, TimeUnit.SECONDS )
|
||||
.readTimeout( 30, TimeUnit.SECONDS )
|
||||
.writeTimeout( 30, TimeUnit.SECONDS )
|
||||
.readTimeout( 60, TimeUnit.SECONDS )
|
||||
.writeTimeout( 60, TimeUnit.SECONDS )
|
||||
.pingInterval( 10, TimeUnit.SECONDS )
|
||||
.connectionSpecs( spec_list );
|
||||
|
||||
|
|
|
@ -317,6 +317,7 @@ public class AppDataExporter {
|
|||
case Pref.KEY_MENTION_FULL_ACCT:
|
||||
case Pref.KEY_RELATIVE_TIMESTAMP:
|
||||
case Pref.KEY_DONT_USE_ACTION_BUTTON:
|
||||
case Pref.KEY_SHORT_ACCT_LOCAL_USER:
|
||||
boolean bv = reader.nextBoolean();
|
||||
e.putBoolean( k, bv );
|
||||
break;
|
||||
|
@ -352,6 +353,7 @@ public class AppDataExporter {
|
|||
case Pref.KEY_MASTODON_SEARCH_PORTAL_USER_TOKEN:
|
||||
case Pref.KEY_QUOTE_NAME_FORMAT:
|
||||
case Pref.KEY_AUTO_CW_LINES:
|
||||
case Pref.KEY_AVATAR_ICON_SIZE:
|
||||
String sv = reader.nextString();
|
||||
e.putString( k, sv );
|
||||
break;
|
||||
|
|
|
@ -219,6 +219,10 @@ class Column implements StreamReader.Callback {
|
|||
|
||||
String instance_uri;
|
||||
|
||||
// 「インスタンス情報」カラムに表示するインスタンス情報
|
||||
// (SavedAccount中のインスタンス情報とは異なるので注意)
|
||||
TootInstance instance_information;
|
||||
|
||||
ScrollPosition scroll_save;
|
||||
|
||||
Column( @NonNull AppState app_state, @NonNull SavedAccount access_info, @NonNull Callback callback, int type, Object... params ){
|
||||
|
@ -1185,14 +1189,15 @@ class Column implements StreamReader.Callback {
|
|||
return result;
|
||||
}
|
||||
|
||||
TootInstance instance_tmp;
|
||||
|
||||
TootApiResult getInstanceInformation( @NonNull TootApiClient client ,@Nullable String instance_name){
|
||||
instance_tmp = null;
|
||||
if( instance_name != null ) client.setInstance( instance_name );
|
||||
TootApiResult result = client.request( "/api/v1/instance" );
|
||||
if( result != null && result.object != null ){
|
||||
TootInstance instance = TootInstance.parse( result.object );
|
||||
if( instance != null ){
|
||||
access_info.refInstance.set( instance );
|
||||
}
|
||||
instance_tmp = TootInstance.parse( result.object );
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1202,7 +1207,7 @@ class Column implements StreamReader.Callback {
|
|||
TootApiResult result = client.request( path_base );
|
||||
if( result != null && result.array != null ){
|
||||
//
|
||||
TootStatus.List src = TootStatus.parseList( context, access_info, result.array );
|
||||
TootStatus.List src = TootStatus.parseList( context, access_info, result.array ,true);
|
||||
|
||||
for(TootStatus status : src ){
|
||||
log.d("pinned: %s %s",status.id, status.decoded_content);
|
||||
|
@ -1248,7 +1253,7 @@ class Column implements StreamReader.Callback {
|
|||
// break;
|
||||
// }
|
||||
//
|
||||
// src = TootStatus.parseList( context, access_info, result2.array );
|
||||
// src = TootStatus.parseList( context, access_info, result2.array ,true);
|
||||
// for(TootStatus status : src ){
|
||||
// log.d("pinned: %s %s",status.id, status.decoded_content);
|
||||
// }
|
||||
|
@ -1459,12 +1464,16 @@ class Column implements StreamReader.Callback {
|
|||
|
||||
default:
|
||||
case TAB_STATUS:
|
||||
TootInstance instance = access_info.refInstance.get();
|
||||
TootInstance instance = access_info.getInstance();
|
||||
if( access_info.isPseudo() || instance == null ){
|
||||
TootApiResult r2 = getInstanceInformation( client ,null );
|
||||
instance = access_info.refInstance.get();
|
||||
if( instance_tmp != null ){
|
||||
instance = instance_tmp;
|
||||
access_info.setInstance( instance_tmp );
|
||||
}
|
||||
if( access_info.isPseudo() ) return r2;
|
||||
}
|
||||
|
||||
{
|
||||
String s = String.format( Locale.JAPAN, PATH_ACCOUNT_STATUSES, profile_id );
|
||||
if( with_attachment ) s = s + "&only_media=1";
|
||||
|
@ -1612,8 +1621,13 @@ class Column implements StreamReader.Callback {
|
|||
}
|
||||
return result;
|
||||
|
||||
case TYPE_INSTANCE_INFORMATION:
|
||||
return getInstanceInformation( client ,instance_uri);
|
||||
case TYPE_INSTANCE_INFORMATION:{
|
||||
result = getInstanceInformation( client, instance_uri );
|
||||
if( instance_tmp != null ){
|
||||
instance_information = instance_tmp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}finally{
|
||||
try{
|
||||
|
|
|
@ -75,7 +75,7 @@ class HeaderViewHolderInstance extends HeaderViewHolderBase implements View.OnCl
|
|||
|
||||
@Override void bindData( Column column ){
|
||||
this.column = column;
|
||||
this.instance = column.access_info.refInstance.get();
|
||||
this.instance = column.instance_information;
|
||||
|
||||
if( instance == null ){
|
||||
btnInstance.setText( "?" );
|
||||
|
|
|
@ -18,21 +18,24 @@ class HeaderViewHolderSearchDesc extends HeaderViewHolderBase {
|
|||
, arg_activity.getLayoutInflater().inflate( R.layout.lv_header_search_desc, parent, false )
|
||||
);
|
||||
|
||||
if( activity.timeline_font != null ){
|
||||
Utils.scanView( viewRoot, new Utils.ScanViewCallback() {
|
||||
@Override public void onScanView( View v ){
|
||||
try{
|
||||
if( v instanceof Button ){
|
||||
// ボタンは太字なので触らない
|
||||
}else if( v instanceof TextView ){
|
||||
if( activity.timeline_font != null ){
|
||||
( (TextView) v ).setTypeface( activity.timeline_font );
|
||||
}
|
||||
if( ! Float.isNaN( activity.timeline_font_size_sp ) ){
|
||||
( (TextView) v ).setTextSize( activity.timeline_font_size_sp );
|
||||
}
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
log.trace( ex );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
CharSequence sv = HTMLDecoder.decodeHTML( activity, access_info, html, false, true, null );
|
||||
|
||||
|
|
|
@ -243,6 +243,12 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|||
tvAcct.setTextSize( activity.acct_font_size_sp );
|
||||
tvTime.setTextSize( activity.acct_font_size_sp );
|
||||
}
|
||||
|
||||
ivBoosted.getLayoutParams().width =
|
||||
ivFollow.getLayoutParams().width =
|
||||
ivThumbnail.getLayoutParams().width =
|
||||
ivThumbnail.getLayoutParams().height = activity.mAvatarIconSize;
|
||||
|
||||
}
|
||||
|
||||
void bind( Object item ){
|
||||
|
@ -379,7 +385,7 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|||
ivBoosted.setImageResource( Styler.getAttributeResourceId( activity, icon_attr_id ) );
|
||||
tvBoostedTime.setText( TootStatus.formatTime( tvBoostedTime.getContext(), time, true ) );
|
||||
tvBoosted.setText( text );
|
||||
setAcct( tvBoostedAcct, access_info.getFullAcct( who ) );
|
||||
setAcct( tvBoostedAcct, access_info.getFullAcct( who ) ,who.acct);
|
||||
}
|
||||
|
||||
private void showFollow( @NonNull TootAccount who ){
|
||||
|
@ -387,7 +393,7 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|||
llFollow.setVisibility( View.VISIBLE );
|
||||
ivFollow.setImageUrl( activity.pref, 16f, access_info.supplyBaseUrl( who.avatar_static ) );
|
||||
tvFollowerName.setText( who.decoded_display_name );
|
||||
setAcct( tvFollowerAcct, access_info.getFullAcct( who ) );
|
||||
setAcct( tvFollowerAcct, access_info.getFullAcct( who ) ,who.acct );
|
||||
|
||||
UserRelation relation = UserRelation.load( access_info.db_id, who.id );
|
||||
Styler.setFollowIcon( activity, btnFollow, ivFollowedBy, relation );
|
||||
|
@ -399,8 +405,9 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|||
|
||||
showStatusTime( activity, status );
|
||||
|
||||
account_thumbnail = status.account;
|
||||
setAcct( tvAcct, access_info.getFullAcct( status.account ) );
|
||||
TootAccount who = account_thumbnail = status.account;
|
||||
|
||||
setAcct( tvAcct, access_info.getFullAcct( who ) ,who == null ? "?" : who.acct );
|
||||
|
||||
if( status.account == null ){
|
||||
tvName.setText( "?" );
|
||||
|
@ -570,9 +577,9 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|||
tvTime.setText( sb );
|
||||
}
|
||||
|
||||
private void setAcct( TextView tv, String acct ){
|
||||
AcctColor ac = AcctColor.load( acct );
|
||||
tv.setText( AcctColor.hasNickname( ac ) ? ac.nickname : acct );
|
||||
private void setAcct( @NonNull TextView tv, @NonNull String acctLong,@NonNull String acctShort ){
|
||||
AcctColor ac = AcctColor.load( acctLong );
|
||||
tv.setText( AcctColor.hasNickname( ac ) ? ac.nickname : activity.mShortAcctLocalUser ? "@"+acctShort : acctLong );
|
||||
tv.setTextColor( AcctColor.hasColorForeground( ac ) ? ac.color_fg : this.acct_color );
|
||||
|
||||
if( AcctColor.hasColorBackground( ac ) ){
|
||||
|
|
|
@ -84,6 +84,9 @@ public class Pref {
|
|||
|
||||
public static final String KEY_AUTO_CW_LINES = "auto_cw_lines";
|
||||
|
||||
public static final String KEY_SHORT_ACCT_LOCAL_USER = "short_acct_local_user";
|
||||
|
||||
public static final String KEY_AVATAR_ICON_SIZE = "avatar_icon_size";
|
||||
|
||||
// 項目を追加したらAppDataExporter#importPref のswitch文も更新すること
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package jp.juggler.subwaytooter.api.entity;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import jp.juggler.subwaytooter.util.LogCategory;
|
||||
import jp.juggler.subwaytooter.util.Utils;
|
||||
import jp.juggler.subwaytooter.util.VersionString;
|
||||
import jp.juggler.subwaytooter.util.LogCategory;
|
||||
import jp.juggler.subwaytooter.util.Utils;
|
||||
import jp.juggler.subwaytooter.util.VersionString;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class TootInstance {
|
||||
|
@ -27,8 +27,12 @@ public class TootInstance {
|
|||
|
||||
public String version;
|
||||
|
||||
// バージョンの内部表現
|
||||
public VersionString decoded_version;
|
||||
|
||||
// いつ取得したか
|
||||
public long time_parse;
|
||||
|
||||
@Nullable
|
||||
public static TootInstance parse( JSONObject src ){
|
||||
if( src == null ) return null;
|
||||
|
@ -40,6 +44,7 @@ public class TootInstance {
|
|||
dst.email = Utils.optStringX( src, "email" );
|
||||
dst.version = Utils.optStringX( src, "version" );
|
||||
dst.decoded_version = new VersionString( dst.version );
|
||||
dst.time_parse = System.currentTimeMillis();
|
||||
return dst;
|
||||
}catch( Throwable ex ){
|
||||
log.trace( ex );
|
||||
|
@ -48,11 +53,9 @@ public class TootInstance {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isEnoughVersion( @NonNull VersionString check ){
|
||||
if( decoded_version.isEmpty() || check.isEmpty() ) return false;
|
||||
int i = VersionString.compare( decoded_version ,check );
|
||||
int i = VersionString.compare( decoded_version, check );
|
||||
return i >= 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,6 +87,14 @@ public class TootStatus extends TootStatusLike {
|
|||
|
||||
@Nullable
|
||||
public static TootStatus parse( @NonNull Context context, @NonNull SavedAccount access_info, JSONObject src ){
|
||||
return parse( context,access_info,src,false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TootStatus parse( @NonNull Context context, @NonNull SavedAccount access_info, JSONObject src ,boolean bPinned){
|
||||
/*
|
||||
bPinned 引数がtrueになるのはプロフィールカラムからpinned TL を読んだ時だけである
|
||||
*/
|
||||
|
||||
if( src == null ) return null;
|
||||
// log.d( "parse: %s", src.toString() );
|
||||
|
@ -111,7 +119,8 @@ public class TootStatus extends TootStatusLike {
|
|||
|
||||
status.in_reply_to_id = Utils.optStringX( src, "in_reply_to_id" ); // null
|
||||
status.in_reply_to_account_id = Utils.optStringX( src, "in_reply_to_account_id" ); // null
|
||||
status.reblog = TootStatus.parse( context, access_info, src.optJSONObject( "reblog" ) );
|
||||
status.reblog = TootStatus.parse( context, access_info, src.optJSONObject( "reblog" ) ,false );
|
||||
/* Pinned TL を取得した時にreblogが登場することはないので、reblogをパースするときのbPinnedはfalseでよい */
|
||||
status.content = Utils.optStringX( src, "content" );
|
||||
status.created_at = Utils.optStringX( src, "created_at" ); // "2017-04-16T09:37:14.000Z"
|
||||
status.reblogs_count = src.optLong( "reblogs_count" );
|
||||
|
@ -125,7 +134,7 @@ public class TootStatus extends TootStatusLike {
|
|||
status.tags = TootTag.parseList( src.optJSONArray( "tags" ) );
|
||||
status.application = TootApplication.parse( src.optJSONObject( "application" ) ); // null
|
||||
|
||||
status.pinned = src.optBoolean( "pinned" );
|
||||
status.pinned = bPinned || src.optBoolean( "pinned" );
|
||||
|
||||
status.setSpoilerText( context, Utils.optStringX( src, "spoiler_text" ) );
|
||||
|
||||
|
@ -137,7 +146,6 @@ public class TootStatus extends TootStatusLike {
|
|||
// status.decoded_tags = HTMLDecoder.decodeTags( account,status.tags );
|
||||
status.decoded_mentions = HTMLDecoder.decodeMentions( access_info, status.mentions );
|
||||
|
||||
|
||||
status.enquete = NicoEnquete.parse( context,access_info , status.media_attachments , Utils.optStringX( src, "enquete"),status.id,status.time_created_at );
|
||||
|
||||
return status;
|
||||
|
@ -150,6 +158,11 @@ public class TootStatus extends TootStatusLike {
|
|||
|
||||
@NonNull
|
||||
public static List parseList( @NonNull Context context, @NonNull SavedAccount access_info, JSONArray array ){
|
||||
return parseList( context,access_info,array,false );
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static List parseList( @NonNull Context context, @NonNull SavedAccount access_info, JSONArray array ,boolean bPinned){
|
||||
List result = new List();
|
||||
if( array != null ){
|
||||
int array_size = array.length();
|
||||
|
@ -157,7 +170,7 @@ public class TootStatus extends TootStatusLike {
|
|||
for( int i = 0 ; i < array_size ; ++ i ){
|
||||
JSONObject src = array.optJSONObject( i );
|
||||
if( src == null ) continue;
|
||||
TootStatus item = parse( context, access_info, src );
|
||||
TootStatus item = parse( context, access_info, src ,bPinned );
|
||||
if( item != null ) result.add( item );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,8 +84,20 @@ public class SavedAccount extends TootAccount implements LinkClickContext {
|
|||
public long register_time;
|
||||
|
||||
|
||||
private final AtomicReference<TootInstance> refInstance = new AtomicReference<>( null );
|
||||
private static final long INSTANCE_INFORMATION_EXPIRE = 60000L * 5;
|
||||
|
||||
// DBには保存しない
|
||||
public final AtomicReference<TootInstance> refInstance = new AtomicReference<>( null );
|
||||
public @Nullable TootInstance getInstance(){
|
||||
TootInstance instance = refInstance.get();
|
||||
if( instance != null && System.currentTimeMillis() - instance.time_parse > INSTANCE_INFORMATION_EXPIRE ){
|
||||
return null;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
public void setInstance(@NonNull TootInstance instance){
|
||||
if( instance != null ) refInstance.set(instance);
|
||||
}
|
||||
|
||||
|
||||
// アプリデータのインポート時に呼ばれる
|
||||
|
|
|
@ -2,6 +2,7 @@ package jp.juggler.subwaytooter.util;
|
|||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
|
@ -9,17 +10,25 @@ import java.util.ArrayList;
|
|||
public class VersionString {
|
||||
// static final LogCategory log = new LogCategory( "VersionString" );
|
||||
|
||||
private final String src;
|
||||
@NonNull private final String src;
|
||||
|
||||
private final ArrayList<Object> node_list = new ArrayList<>( );
|
||||
@Override public String toString(){
|
||||
return src;
|
||||
}
|
||||
|
||||
private final ArrayList< Object > node_list = new ArrayList<>();
|
||||
|
||||
public boolean isEmpty(){
|
||||
return node_list.isEmpty();
|
||||
}
|
||||
|
||||
private static boolean isDelimiter( char c ){
|
||||
return c == '.' || c == ' ';
|
||||
}
|
||||
|
||||
public VersionString( @Nullable String src ){
|
||||
this.src = src;
|
||||
if( src == null ) return;
|
||||
this.src = src == null ? "" : src;
|
||||
if( TextUtils.isEmpty( src ) ) return;
|
||||
int end = src.length();
|
||||
int next = 0;
|
||||
while( next < end ){
|
||||
|
@ -49,14 +58,10 @@ public class VersionString {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty(){
|
||||
return node_list.isEmpty();
|
||||
}
|
||||
|
||||
// return -1 if a<b , return 1 if a>b , return 0 if a==b
|
||||
public static int compare( @NonNull VersionString a, @NonNull VersionString b ){
|
||||
|
||||
for( int idx =0 ;; ++idx){
|
||||
for( int idx = 0 ; ; ++ idx ){
|
||||
Object ao = ( idx >= a.node_list.size() ? null : a.node_list.get( idx ) );
|
||||
Object bo = ( idx >= b.node_list.size() ? null : b.node_list.get( idx ) );
|
||||
if( ao == null ){
|
||||
|
|
|
@ -591,6 +591,23 @@
|
|||
|
||||
<View style="@style/setting_divider"/>
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/short_acct_local_user"
|
||||
/>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/swShortAcctLocalUser"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
android:gravity="center"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View style="@style/setting_divider"/>
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/relative_timestamp"
|
||||
|
@ -1016,6 +1033,25 @@
|
|||
|
||||
<View style="@style/setting_divider"/>
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:labelFor="@+id/etAvatarIconSize"
|
||||
android:text="@string/avatar_icon_size"
|
||||
/>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etAvatarIconSize"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
android:gravity="center"
|
||||
android:inputType="numberDecimal"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View style="@style/setting_divider"/>
|
||||
|
||||
<!-- =============================================== -->
|
||||
<TextView
|
||||
style="@style/setting_group_header"
|
||||
|
|
|
@ -465,6 +465,9 @@
|
|||
<string name="profile_pin">Pin on profile</string>
|
||||
<string name="profile_unpin">Unpin from profile</string>
|
||||
<string name="profile_pin_progress">Changing pinned status…</string>
|
||||
<string name="length_warning">\"%1$s\" is too long (%2$d/%3$d characters).\nIt is not acceptable in the standard instance, but it may be acceptable in some instances.\nAre you sure?</string>
|
||||
<string name="avatar_icon_size">Avatar icon size (unit:dp. default:48. app restart required)</string>
|
||||
<string name="short_acct_local_user">Short acct for local user (app restart required)</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>-->
|
||||
|
|
|
@ -752,4 +752,8 @@
|
|||
<string name="profile_pin">プロフィールに固定表示</string>
|
||||
<string name="profile_unpin">プロフィールの固定表示を解除</string>
|
||||
<string name="profile_pin_progress">固定表示の変更中…</string>
|
||||
<string name="length_warning">\"%1$s\"が長すぎます(%2$d/%3$d文字).\n標準的なインスタンスではエラーとなりますが、いくつかのインスタンスでは許容されるかも。\nよろしいですか?</string>
|
||||
<string name="avatar_icon_size">アバターアイコンサイズ(単位:dp. デフォルト:48. アプリ再起動が必要)</string>
|
||||
<string name="short_acct_local_user">ローカルユーザのAcct表記を短くする(アプリ再起動が必要)</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -459,5 +459,8 @@
|
|||
<string name="profile_pin">Pin on profile</string>
|
||||
<string name="profile_unpin">Unpin from profile</string>
|
||||
<string name="profile_pin_progress">Changing pinned status…</string>
|
||||
<string name="length_warning">\"%1$s\" is too long (%2$d/%3$d characters).\nIt is not acceptable in the standard instance, but it may be acceptable in some instances.\nAre you sure?</string>
|
||||
<string name="avatar_icon_size">Avatar icon size (unit:dp. default:48. app restart required)</string>
|
||||
<string name="short_acct_local_user">Short acct for local user (app restart required)</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue