SubwayTooter-Android-App/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgListMember.java

420 lines
12 KiB
Java

package jp.juggler.subwaytooter.dialog;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Spannable;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import jp.juggler.subwaytooter.ActMain;
import jp.juggler.subwaytooter.App1;
import jp.juggler.subwaytooter.R;
import jp.juggler.subwaytooter.Styler;
import jp.juggler.subwaytooter.action.ActionUtils;
import jp.juggler.subwaytooter.action.Action_List;
import jp.juggler.subwaytooter.action.Action_ListMember;
import jp.juggler.subwaytooter.api.TootApiClient;
import jp.juggler.subwaytooter.api.TootApiResult;
import jp.juggler.subwaytooter.api.TootTask;
import jp.juggler.subwaytooter.api.TootTaskRunner;
import jp.juggler.subwaytooter.api.entity.TootAccount;
import jp.juggler.subwaytooter.api.entity.TootList;
import jp.juggler.subwaytooter.api.entity.TootResults;
import jp.juggler.subwaytooter.api.TootParser;
import jp.juggler.subwaytooter.table.AcctColor;
import jp.juggler.subwaytooter.table.SavedAccount;
import jp.juggler.subwaytooter.util.NetworkEmojiInvalidator;
import jp.juggler.subwaytooter.util.Utils;
import jp.juggler.subwaytooter.view.MyListView;
import jp.juggler.subwaytooter.view.MyNetworkImageView;
public class DlgListMember implements View.OnClickListener {
@NonNull private final ActMain activity;
@NonNull private final Dialog dialog;
@NonNull private final Button btnListOwner;
@NonNull private final Button btnCreateList;
@NonNull private final ArrayList< SavedAccount > account_list;
@NonNull private final String target_user_full_acct;
@Nullable private SavedAccount list_owner;
@Nullable private TootAccount local_who;
public DlgListMember( @NonNull ActMain _activity, @NonNull TootAccount who, @NonNull SavedAccount _list_owner ){
this.activity = _activity;
this.account_list = ActionUtils.makeAccountListNonPseudo( _activity, null );
this.target_user_full_acct = _list_owner.getFullAcct( who );
if( _list_owner.isPseudo() ){
this.list_owner = null;
}else{
this.list_owner = _list_owner;
}
@SuppressLint("InflateParams") final View view = activity.getLayoutInflater().inflate( R.layout.dlg_list_member, null, false );
MyNetworkImageView ivUser = view.findViewById( R.id.ivUser );
TextView tvUserName = view.findViewById( R.id.tvUserName );
TextView tvUserAcct = view.findViewById( R.id.tvUserAcct );
btnListOwner = view.findViewById( R.id.btnListOwner );
btnCreateList = view.findViewById( R.id.btnCreateList );
MyListView listView = view.findViewById( R.id.listView );
this.adapter = new MyListAdapter();
listView.setAdapter( adapter );
btnCreateList.setOnClickListener( this );
btnListOwner.setOnClickListener( this );
view.findViewById( R.id.btnClose ).setOnClickListener( this );
ivUser.setImageUrl( App1.pref, 16f, who.avatar_static, who.avatar );
NetworkEmojiInvalidator user_name_invalidator = new NetworkEmojiInvalidator( activity.handler, tvUserName );
Spannable name = who.decodeDisplayName( activity );
tvUserName.setText( name );
user_name_invalidator.register( name );
tvUserAcct.setText( target_user_full_acct );
setListOwner( list_owner );
this.dialog = new Dialog( activity );
Window w = dialog.getWindow();
if( w != null ){
w.setFlags( 0, Window.FEATURE_NO_TITLE );
w.setLayout(
WindowManager.LayoutParams.MATCH_PARENT
, WindowManager.LayoutParams.MATCH_PARENT
);
}
dialog.setTitle( R.string.your_lists );
dialog.setContentView( view );
}
public void show(){
Window w = dialog.getWindow();
if( w != null ){
w.setLayout(
WindowManager.LayoutParams.MATCH_PARENT
, WindowManager.LayoutParams.MATCH_PARENT
);
}
dialog.show();
}
@Override public void onClick( View v ){
switch( v.getId() ){
case R.id.btnClose:
try{
dialog.dismiss();
}catch( Throwable ignored ){
}
break;
case R.id.btnListOwner:
AccountPicker.pick( activity, false, false, null, account_list, new AccountPicker.AccountPickerCallback() {
@Override public void onAccountPicked( @NonNull SavedAccount ai ){
setListOwner( ai );
}
} );
break;
case R.id.btnCreateList:
openListCreator();
break;
}
}
// リストオーナボタンの文字列を更新する
// リスト一覧を取得する
private void setListOwner( @Nullable SavedAccount a ){
this.list_owner = a;
if( a == null ){
btnListOwner.setText( R.string.not_selected );
btnListOwner.setTextColor( Styler.getAttributeColor( activity, android.R.attr.textColorPrimary ) );
btnListOwner.setBackgroundResource( R.drawable.btn_bg_transparent );
//
}else{
String acct = a.getFullAcct( a );
AcctColor ac = AcctColor.load( acct );
String nickname = AcctColor.hasNickname( ac ) ? ac.nickname : acct;
btnListOwner.setText( nickname );
if( AcctColor.hasColorBackground( ac ) ){
btnListOwner.setBackgroundColor( ac.color_bg );
}else{
btnListOwner.setBackgroundResource( R.drawable.btn_bg_transparent );
}
if( AcctColor.hasColorForeground( ac ) ){
btnListOwner.setTextColor( ac.color_fg );
}else{
btnListOwner.setTextColor( Styler.getAttributeColor( activity, android.R.attr.textColorPrimary ) );
}
}
loadLists();
}
// リストの一覧とターゲットユーザの登録状況を取得する
private void loadLists(){
if( list_owner == null ){
showList( null );
return;
}
new TootTaskRunner( activity, true ).run( list_owner, new TootTask() {
@Override public TootApiResult background( @NonNull TootApiClient client ){
// リストに追加したいアカウントの自タンスでのアカウントIDを取得する
local_who = null;
TootApiResult result = client.request( "/api/v1/search?resolve=true&q=" + Uri.encode( target_user_full_acct ) );
if( result == null || result.object == null ){
return result;
}
TootResults search_result = new TootParser(activity, list_owner).results( result.object );
if( search_result != null ){
for( TootAccount a : search_result.accounts ){
if( target_user_full_acct.equalsIgnoreCase( list_owner.getFullAcct( a ) ) ){
local_who = a;
break;
}
}
}
if( local_who == null ){
return new TootApiResult( activity.getString( R.string.account_sync_failed ) );
}
// リスト登録状況を取得
result = client.request( "/api/v1/accounts/" + local_who.id + "/lists" );
if( result == null || result.array == null ){
return result;
}
// 結果を解釈する
HashSet< Long > set_registered = new HashSet<>();
for( TootList a : TootList.parseList( result.array ) ){
set_registered.add( a.id );
}
// リスト一覧を取得
result = client.request( "/api/v1/lists" );
if( result == null || result.array == null ){
return result;
}
new_list = TootList.parseList( result.array );
Collections.sort( new_list );
// isRegistered を設定する
for( TootList a : new_list ){
if( set_registered.contains( a.id ) ) a.isRegistered = true;
}
return result;
}
TootList.List new_list;
@Override public void handleResult( @Nullable TootApiResult result ){
showList( new_list );
//noinspection StatementWithEmptyBody
if( result != null
&& ! TextUtils.isEmpty( result.error )
&& ! ( result.response != null && result.response.code() == 404 )
){
Utils.showToast( activity, true, result.error );
}
}
} );
}
private void showList( @Nullable TootList.List _list ){
btnCreateList.setEnabled( _list != null );
adapter.item_list.clear();
if( _list == null ){
adapter.item_list.add( new ErrorItem( activity.getString( R.string.cant_access_list ) ) );
}else if( _list.isEmpty() ){
adapter.item_list.add( new ErrorItem( activity.getString( R.string.list_not_created ) ) );
}else{
adapter.item_list.addAll( _list );
}
adapter.notifyDataSetChanged();
}
private void openListCreator(){
DlgTextInput.show( activity, activity.getString( R.string.list_create ), null, new DlgTextInput.Callback() {
@Override public void onEmptyError(){
Utils.showToast( activity, false, R.string.list_name_empty );
}
@Override public void onOK( final Dialog dialog, final String title ){
if( list_owner == null ){
Utils.showToast( activity, false, "list owner is not selected." );
return;
}
Action_List.create( activity, list_owner, title, new Action_List.CreateCallback() {
@Override public void onCreated( @NonNull TootList list ){
try{
dialog.dismiss();
}catch( Throwable ignored ){
}
loadLists();
}
} );
}
} );
}
static class ErrorItem {
final String message;
ErrorItem( String message ){
this.message = message;
}
}
private final MyListAdapter adapter;
private class MyListAdapter extends BaseAdapter {
final ArrayList< Object > item_list = new ArrayList<>();
@Override public int getCount(){
return item_list.size();
}
@Override public Object getItem( int position ){
if( position >= 0 && position < item_list.size() ) return item_list.get( position );
return null;
}
@Override public long getItemId( int position ){
return 0;
}
@Override public int getViewTypeCount(){
return 2;
}
@Override public int getItemViewType( int position ){
Object o = getItem( position );
if( o instanceof TootList ) return 0;
return 1;
}
@Override public View getView( int position, View view, ViewGroup parent ){
Object o = getItem( position );
if( o instanceof TootList ){
VH_List holder;
if( view != null ){
holder = (VH_List) view.getTag();
}else{
view = activity.getLayoutInflater().inflate( R.layout.lv_list_member_list, parent, false );
holder = new VH_List( view );
view.setTag( holder );
}
holder.bind( (TootList) o );
}else if( o instanceof ErrorItem ){
VH_Error holder;
if( view != null ){
holder = (VH_Error) view.getTag();
}else{
view = activity.getLayoutInflater().inflate( R.layout.lv_list_member_error, parent, false );
holder = new VH_Error( view );
view.setTag( holder );
}
holder.bind( (ErrorItem) o );
}
return view;
}
}
class VH_List implements CompoundButton.OnCheckedChangeListener, Action_ListMember.Callback {
final CheckBox cbItem;
boolean bBusy;
TootList item;
VH_List( View view ){
this.cbItem = view.findViewById( R.id.cbItem );
cbItem.setOnCheckedChangeListener( this );
}
public void bind( TootList item ){
this.item = item;
cbItem.setText( item.title );
bBusy = true;
cbItem.setChecked( item.isRegistered );
bBusy = false;
}
@Override public void onCheckedChanged( CompoundButton view, boolean isChecked ){
if( bBusy ){
// ユーザ操作以外で変更されたなら何もしない
return;
}
if( list_owner == null ){
Utils.showToast( activity, false, "list owner is not selected" );
return;
}
if( local_who == null ){
Utils.showToast( activity, false, "target user is not synchronized" );
return;
}
// 状態をサーバに伝える
if( isChecked ){
Action_ListMember.add( activity, list_owner, item.id, local_who, false, this );
}else{
Action_ListMember.delete( activity, list_owner, item.id, local_who, this );
}
}
@Override public void onListMemberUpdated( boolean willRegistered, boolean bSuccess ){
if( ! bSuccess ){
item.isRegistered = ! willRegistered;
adapter.notifyDataSetChanged();
}
}
}
class VH_Error {
final TextView tvError;
VH_Error( View view ){
this.tvError = view.findViewById( R.id.tvError );
}
public void bind( ErrorItem o ){
this.tvError.setText( o.message );
}
}
}