Merge remote-tracking branch 'upstream'

This commit is contained in:
sk
2023-02-13 17:26:26 +01:00
14 changed files with 134 additions and 108 deletions

View File

@@ -248,6 +248,6 @@ public class AccountActivationFragment extends ToolbarFragment{
Bundle args=new Bundle(); Bundle args=new Bundle();
args.putString("account", accountID); args.putString("account", accountID);
// Nav.goClearingStack(getActivity(), HomeFragment.class, args); // Nav.goClearingStack(getActivity(), HomeFragment.class, args);
Nav.goClearingStack(getActivity(), OnboardingProfileSetupFragment.class, args); Nav.goClearingStack(getActivity(), OnboardingFollowSuggestionsFragment.class, args);
} }
} }

View File

@@ -5,15 +5,12 @@ import android.app.ProgressDialog;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.LocaleList;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets; import android.view.WindowInsets;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView; import android.widget.TextView;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
@@ -23,7 +20,6 @@ import org.joinmastodon.android.api.requests.instance.GetInstance;
import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.catalog.CatalogInstance; import org.joinmastodon.android.model.catalog.CatalogInstance;
import org.joinmastodon.android.ui.M3AlertDialogBuilder; import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
@@ -31,6 +27,8 @@ import org.xml.sax.InputSource;
import java.io.IOException; import java.io.IOException;
import java.net.IDN; import java.net.IDN;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@@ -50,7 +48,6 @@ import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.utils.BindableViewHolder; import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.MergeRecyclerAdapter; import me.grishka.appkit.utils.MergeRecyclerAdapter;
import me.grishka.appkit.utils.V; import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.UsableRecyclerView;
import okhttp3.Call; import okhttp3.Call;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@@ -112,46 +109,10 @@ abstract class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInsta
} }
protected List<CatalogInstance> sortInstances(List<CatalogInstance> result){ protected List<CatalogInstance> sortInstances(List<CatalogInstance> result){
Map<String, List<CatalogInstance>> byLang=result.stream().collect(Collectors.groupingBy(ci->ci.language)); Map<Boolean, List<CatalogInstance>> byLang=result.stream().sorted(Comparator.comparingInt((CatalogInstance ci)->ci.lastWeekUsers).reversed()).collect(Collectors.groupingBy(ci->ci.approvalRequired));
for(List<CatalogInstance> group:byLang.values()){
Collections.sort(group, (a, b)->{
double aa=Math.abs(DUNBAR-Math.log(a.lastWeekUsers));
double bb=Math.abs(DUNBAR-Math.log(b.lastWeekUsers));
return Double.compare(aa, bb);
});
}
// get the list of user-configured system languages
List<String> userLangs;
if(Build.VERSION.SDK_INT<24){
userLangs=Collections.singletonList(getResources().getConfiguration().locale.getLanguage());
}else{
LocaleList ll=getResources().getConfiguration().getLocales();
userLangs=new ArrayList<>(ll.size());
for(int i=0;i<ll.size();i++){
userLangs.add(ll.get(i).getLanguage());
}
}
// add instances in preferred languages to the top of the list, in the order of preference
ArrayList<CatalogInstance> sortedList=new ArrayList<>(); ArrayList<CatalogInstance> sortedList=new ArrayList<>();
for(String lang:userLangs){ sortedList.addAll(byLang.getOrDefault(false, Collections.emptyList()));
List<CatalogInstance> langInstances=byLang.remove(lang); sortedList.addAll(byLang.getOrDefault(true, Collections.emptyList()));
if(langInstances!=null){
sortedList.addAll(langInstances);
}
}
// sort the remaining language groups by aggregate lastWeekUsers
class InstanceGroup{
public int activeUsers;
public List<CatalogInstance> instances;
}
byLang.values().stream().map(il->{
InstanceGroup group=new InstanceGroup();
group.instances=il;
for(CatalogInstance instance:il){
group.activeUsers+=instance.lastWeekUsers;
}
return group;
}).sorted(Comparator.comparingInt((InstanceGroup g)->g.activeUsers).reversed()).forEachOrdered(ig->sortedList.addAll(ig.instances));
return sortedList; return sortedList;
} }
@@ -208,6 +169,20 @@ abstract class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInsta
cancelLoadingInstanceInfo(); cancelLoadingInstanceInfo();
} }
} }
try{
new URI("https://"+domain+"/api/v1/instance"); // Validate the host by trying to parse the URI
}catch(URISyntaxException x){
showInstanceInfoLoadError(domain, x);
if(fakeInstance!=null){
fakeInstance.description=getString(R.string.error);
if(filteredData.size()>0 && filteredData.get(0)==fakeInstance){
if(list.findViewHolderForAdapterPosition(1) instanceof BindableViewHolder<?> ivh){
ivh.rebind();
}
}
}
return;
}
loadingInstanceDomain=domain; loadingInstanceDomain=domain;
loadingInstanceRequest=new GetInstance(); loadingInstanceRequest=new GetInstance();
loadingInstanceRequest.setCallback(new Callback<>(){ loadingInstanceRequest.setCallback(new Callback<>(){

View File

@@ -64,7 +64,7 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
private List<String> languages=Collections.emptyList(); private List<String> languages=Collections.emptyList();
private PopupMenu langFilterMenu, speedFilterMenu; private PopupMenu langFilterMenu, speedFilterMenu;
private SignupSpeedFilter currentSignupSpeedFilter=SignupSpeedFilter.INSTANT; private SignupSpeedFilter currentSignupSpeedFilter=SignupSpeedFilter.ANY;
private String currentLanguage=null; private String currentLanguage=null;
private boolean searchQueryMode; private boolean searchQueryMode;
private LinearLayout filtersWrap; private LinearLayout filtersWrap;
@@ -75,7 +75,7 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
private FilterChipView categoryGeneral, categorySpecialInterests; private FilterChipView categoryGeneral, categorySpecialInterests;
private List<FilterChipView> regionalFilters; private List<FilterChipView> regionalFilters;
private CatalogInstance.Region chosenRegion; private CatalogInstance.Region chosenRegion;
private CategoryChoice categoryChoice; private CategoryChoice categoryChoice=CategoryChoice.GENERAL;
public InstanceCatalogSignupFragment(){ public InstanceCatalogSignupFragment(){
super(R.layout.fragment_onboarding_common, 10); super(R.layout.fragment_onboarding_common, 10);
@@ -371,6 +371,9 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
if(instances.isEmpty()){ if(instances.isEmpty()){
instances=data.stream().filter(ci->!ci.approvalRequired && ("general".equals(ci.category) || (ci.categories!=null && ci.categories.contains("general")))).collect(Collectors.toList()); instances=data.stream().filter(ci->!ci.approvalRequired && ("general".equals(ci.category) || (ci.categories!=null && ci.categories.contains("general")))).collect(Collectors.toList());
} }
if(instances.isEmpty()){
instances=data.stream().filter(ci->("general".equals(ci.category) || (ci.categories!=null && ci.categories.contains("general")))).collect(Collectors.toList());
}
if(instances.isEmpty()){ if(instances.isEmpty()){
return; return;
} }

View File

@@ -2,8 +2,14 @@ package org.joinmastodon.android.fragments.onboarding;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.graphics.Typeface;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -64,7 +70,7 @@ public class InstanceRulesFragment extends ToolbarFragment{
list.setLayoutManager(new LinearLayoutManager(getActivity())); list.setLayoutManager(new LinearLayoutManager(getActivity()));
View headerView=inflater.inflate(R.layout.item_list_header_simple, list, false); View headerView=inflater.inflate(R.layout.item_list_header_simple, list, false);
TextView text=headerView.findViewById(R.id.text); TextView text=headerView.findViewById(R.id.text);
text.setText(getString(R.string.instance_rules_subtitle, instance.uri)); text.setText(Html.fromHtml(getString(R.string.instance_rules_subtitle, "<b>"+Html.escapeHtml(instance.uri)+"</b>")));
adapter=new MergeRecyclerAdapter(); adapter=new MergeRecyclerAdapter();
adapter.addAdapter(new SingleViewRecyclerAdapter(headerView)); adapter.addAdapter(new SingleViewRecyclerAdapter(headerView));

View File

@@ -191,6 +191,13 @@ public class OnboardingFollowSuggestionsFragment extends BaseRecyclerFragment<Pa
.setCallback(new Callback<>(){ .setCallback(new Callback<>(){
@Override @Override
public void onSuccess(Relationship result){ public void onSuccess(Relationship result){
relationships.put(id, result);
for(int i=0;i<list.getChildCount();i++){
if(list.getChildViewHolder(list.getChildAt(i)) instanceof SuggestionViewHolder svh && svh.getItem().account.id.equals(id)){
svh.rebind();
break;
}
}
numRunningFollowRequests--; numRunningFollowRequests--;
progress.setProgress(progress.getMax()-accountIdsToFollow.size()-numRunningFollowRequests); progress.setProgress(progress.getMax()-accountIdsToFollow.size()-numRunningFollowRequests);
followNextAccount(accountIdsToFollow, progress); followNextAccount(accountIdsToFollow, progress);
@@ -209,20 +216,7 @@ public class OnboardingFollowSuggestionsFragment extends BaseRecyclerFragment<Pa
private void proceed(){ private void proceed(){
Bundle args=new Bundle(); Bundle args=new Bundle();
args.putString("account", accountID); args.putString("account", accountID);
Nav.go(getActivity(), HomeFragment.class, args); Nav.go(getActivity(), OnboardingProfileSetupFragment.class, args);
getActivity().getWindow().getDecorView().postDelayed(()->Nav.finish(this), 500);
}
@Override
protected boolean canGoBack(){
return true;
}
@Override
public void onToolbarNavigationClick(){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.goClearingStack(getActivity(), HomeFragment.class, args);
} }
private class SuggestionsAdapter extends UsableRecyclerView.Adapter<SuggestionViewHolder> implements ImageLoaderRecyclerAdapter{ private class SuggestionsAdapter extends UsableRecyclerView.Adapter<SuggestionViewHolder> implements ImageLoaderRecyclerAdapter{

View File

@@ -151,8 +151,7 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
AccountSessionManager.getInstance().updateAccountInfo(accountID, result); AccountSessionManager.getInstance().updateAccountInfo(accountID, result);
Bundle args=new Bundle(); Bundle args=new Bundle();
args.putString("account", accountID); args.putString("account", accountID);
Nav.go(getActivity(), OnboardingFollowSuggestionsFragment.class, args); Nav.goClearingStack(getActivity(), HomeFragment.class, args);
getActivity().getWindow().getDecorView().postDelayed(()->Nav.finish(OnboardingProfileSetupFragment.this), 500);
} }
@Override @Override
@@ -182,6 +181,11 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
profileFieldsLayout.startDragging(view); profileFieldsLayout.startDragging(view);
return true; return true;
}); });
view.findViewById(R.id.delete).setOnClickListener(v->{
profileFieldsLayout.removeView(view);
if(addRow.getVisibility()==View.GONE)
addRow.setVisibility(View.VISIBLE);
});
return view; return view;
} }
@@ -222,16 +226,4 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
img.setForeground(null); img.setForeground(null);
ViewImageLoader.load(img, null, new UrlImageLoaderRequest(uri, size, size)); ViewImageLoader.load(img, null, new UrlImageLoaderRequest(uri, size, size));
} }
@Override
protected boolean canGoBack(){
return true;
}
@Override
public void onToolbarNavigationClick(){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.goClearingStack(getActivity(), HomeFragment.class, args);
}
} }

View File

@@ -691,12 +691,6 @@ public class UiUtils {
TypedArray ta=button.getContext().obtainStyledAttributes(styleRes, new int[]{android.R.attr.background}); TypedArray ta=button.getContext().obtainStyledAttributes(styleRes, new int[]{android.R.attr.background});
button.setBackground(ta.getDrawable(0)); button.setBackground(ta.getDrawable(0));
ta.recycle(); ta.recycle();
ta=button.getContext().obtainStyledAttributes(styleRes, new int[]{android.R.attr.textColor});
if(relationship.blocking)
button.setTextColor(button.getResources().getColorStateList(R.color.error_600));
else
button.setTextColor(ta.getColorStateList(0));
ta.recycle();
} }
public static void performAccountAction(Activity activity, Account account, String accountID, Relationship relationship, Button button, Consumer<Boolean> progressCallback, Consumer<Relationship> resultCallback) { public static void performAccountAction(Activity activity, Account account, String accountID, Relationship relationship, Button button, Consumer<Boolean> progressCallback, Consumer<Relationship> resultCallback) {

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<selector>
<item android:state_focused="true">
<shape>
<stroke android:color="?colorM3Primary" android:width="2dp"/>
<corners android:radius="4dp"/>
</shape>
</item>
<item>
<shape>
<stroke android:color="?colorM3Outline" android:width="1dp"/>
<corners android:radius="4dp"/>
</shape>
</item>
</selector>
</item>
</layer-list>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M7,21Q6.175,21 5.588,20.413Q5,19.825 5,19V6H4V4H9V3H15V4H20V6H19V19Q19,19.825 18.413,20.413Q17.825,21 17,21ZM17,6H7V19Q7,19 7,19Q7,19 7,19H17Q17,19 17,19Q17,19 17,19ZM9,17H11V8H9ZM13,17H15V8H13ZM7,6V19Q7,19 7,19Q7,19 7,19Q7,19 7,19Q7,19 7,19Z"/>
</vector>

View File

@@ -9,7 +9,8 @@
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1"> android:layout_weight="1"
android:fillViewport="true">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -28,6 +29,11 @@
android:textColor="?colorM3OnSurface" android:textColor="?colorM3OnSurface"
android:text="@string/confirm_email_subtitle"/> android:text="@string/confirm_email_subtitle"/>
<Space
android:layout_width="1dp"
android:layout_height="0px"
android:layout_weight="1"/>
<ImageView <ImageView
android:layout_width="230dp" android:layout_width="230dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -37,6 +43,11 @@
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:src="@drawable/confirm_email_art"/> android:src="@drawable/confirm_email_art"/>
<Space
android:layout_width="1dp"
android:layout_height="0px"
android:layout_weight="1"/>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@@ -40,17 +40,17 @@
android:background="@drawable/bg_onboarding_panel"> android:background="@drawable/bg_onboarding_panel">
<Button <Button
android:id="@+id/btn_skip" android:id="@+id/btn_next"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
style="@style/Widget.Mastodon.M3.Button.Tonal" style="@style/Widget.Mastodon.M3.Button.Tonal"
android:text="@string/skip"/> android:text="@string/follow_all"/>
<Button <Button
android:id="@+id/btn_next" android:id="@+id/btn_skip"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
@@ -58,7 +58,7 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
style="@style/Widget.Mastodon.M3.Button.Filled" style="@style/Widget.Mastodon.M3.Button.Filled"
android:text="@string/follow_all"/> android:text="@string/skip"/>
</LinearLayout> </LinearLayout>

View File

@@ -64,6 +64,7 @@
android:contentDescription="@string/clear" android:contentDescription="@string/clear"
android:stateListAnimator="@null" android:stateListAnimator="@null"
android:elevation="0dp" android:elevation="0dp"
android:tint="?colorM3OnSurfaceVariant"
android:src="@drawable/ic_m3_cancel"/> android:src="@drawable/ic_m3_cancel"/>
</org.joinmastodon.android.ui.views.FloatingHintEditTextLayout> </org.joinmastodon.android.ui.views.FloatingHintEditTextLayout>

View File

@@ -2,32 +2,43 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="56dp" android:layout_height="wrap_content"
android:paddingStart="16dp" android:paddingStart="8dp"
android:paddingEnd="8dp" android:paddingEnd="16dp"
android:clipToPadding="false" android:clipToPadding="false"
android:background="?colorM3Background"> android:background="?colorM3Background">
<ImageView <ImageView
android:id="@+id/dragger_thingy" android:id="@+id/dragger_thingy"
android:layout_width="56dp" android:layout_width="40dp"
android:layout_height="56dp" android:layout_height="40dp"
android:layout_alignParentEnd="true" android:layout_alignParentStart="true"
android:layout_marginEnd="8dp"
android:scaleType="center" android:scaleType="center"
android:tint="?colorM3OnSurface" android:tint="?colorM3OnSurface"
android:contentDescription="@string/reorder"
android:src="@drawable/ic_drag_handle_24px"/> android:src="@drawable/ic_drag_handle_24px"/>
<ImageButton
android:id="@+id/delete"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentEnd="true"
android:layout_marginStart="8dp"
android:scaleType="center"
android:tint="?colorM3OnSurface"
android:background="?android:actionBarItemBackground"
android:contentDescription="@string/delete"
android:src="@drawable/ic_delete_24px"/>
<EditText <EditText
android:id="@+id/content" android:id="@+id/content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="24dp" android:layout_height="wrap_content"
android:layout_marginTop="6dp" android:layout_marginTop="8dp"
android:layout_toStartOf="@id/dragger_thingy" android:layout_toEndOf="@id/dragger_thingy"
android:background="@null" android:layout_toStartOf="@id/delete"
android:padding="0dp" style="@style/Widget.Mastodon.M3.EditText"
android:textAppearance="@style/m3_body_large"
android:textColor="?colorM3OnSurfaceVariant"
android:textColorHint="?colorM3OnSurfaceVariant"
android:inputType="textCapSentences" android:inputType="textCapSentences"
android:hint="@string/field_content" android:hint="@string/field_content"
android:saveEnabled="false" android:saveEnabled="false"
@@ -36,14 +47,13 @@
<EditText <EditText
android:id="@+id/title" android:id="@+id/title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="20dp" android:layout_height="wrap_content"
android:layout_toStartOf="@id/dragger_thingy" android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_toEndOf="@id/dragger_thingy"
android:layout_toStartOf="@id/delete"
android:layout_below="@id/content" android:layout_below="@id/content"
android:background="@null" style="@style/Widget.Mastodon.M3.EditText"
android:padding="0dp"
android:textAppearance="@style/m3_body_medium"
android:textColor="?colorM3OnSurfaceVariant"
android:textColorHint="?colorM3OnSurfaceVariant"
android:inputType="textCapSentences" android:inputType="textCapSentences"
android:hint="@string/field_label" android:hint="@string/field_label"
android:saveEnabled="false" android:saveEnabled="false"

View File

@@ -413,6 +413,18 @@
<item name="android:paddingRight">24dp</item> <item name="android:paddingRight">24dp</item>
</style> </style>
<style name="Widget.Mastodon.M3.EditText" parent="android:Widget.Material.EditText">
<item name="android:background">@drawable/bg_m3_outlined_text_field_nopad</item>
<item name="android:textAppearance">@style/m3_body_large</item>
<item name="android:paddingLeft">16dp</item>
<item name="android:paddingRight">16dp</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingBottom">8dp</item>
<item name="android:minHeight">40dp</item>
<item name="android:textColorHint">?colorM3OnSurfaceVariant</item>
<item name="android:textColor">?colorM3OnSurface</item>
</style>
<style name="alert_title"> <style name="alert_title">
<item name="android:textColor">?android:textColorPrimary</item> <item name="android:textColor">?android:textColorPrimary</item>
<item name="android:textSize">24sp</item> <item name="android:textSize">24sp</item>