Account activity redesign (#662)

* Refactor-all-the-things version of the fix for issue #573

* Migrate SpanUtils to kotlin because why not

* Minimal fix for issue #573

* Add tests for compose spanning

* Clean up code suggestions

* Make FakeSpannable.getSpans implementation less awkward

* Add secondary validation pass for urls

* Address code review feedback

* Fixup type filtering in FakeSpannable again

* Make all mentions in compose activity use the default link color

* new layout for AccountActivity

* fix the light theme

* convert AccountActivity to Kotlin

* introduce AccountViewModel

* Merge branch 'master' into account-activity-redesign

# Conflicts:
#	app/src/main/java/com/keylesspalace/tusky/AccountActivity.java

* add Bot badge to profile

* parse custom emojis in usernames

* add possibility to cancel follow request

* add third tab on profiles

* add account fields to profile

* add support for moved accounts

* set click listener on account moved view

* fix tests

* use 24dp as statusbar size

* add ability to hide reblogs from followed accounts

* add button to edit own account to AccountActivity

* set toolbar top margin programmatically

* fix crash

* add shadow behind statusbar

* introduce ViewExtensions to clean up code

* move code out of offsetChangedListener for perf reasons

* clean up stuff

* add error handling

* improve type safety

* fix ConstraintLayout warning

* remove unneeded ressources

* fix event dispatching

* fix crash in event handling

* set correct emoji on title

* improve some things

* wrap follower/foillowing/status views
This commit is contained in:
Konrad Pozniak 2018-06-18 13:26:18 +02:00 committed by GitHub
commit 63f9d99390
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 1422 additions and 978 deletions

View file

@ -2,229 +2,295 @@
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_account"
android:id="@+id/accountCoordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
android:fillViewport="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/account_app_bar_layout"
android:id="@+id/accountAppBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.Account.AppBarLayout">
android:layout_height="wrap_content">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:id="@+id/collapsingToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_height="wrap_content"
app:contentScrim="?attr/toolbar_background_color"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:statusBarScrim="?android:attr/colorBackground"
app:titleEnabled="false">
<RelativeLayout
<ImageView
android:id="@+id/accountHeaderImageView"
android:layout_width="match_parent"
android:layout_height="180dp"
android:layout_alignTop="@+id/account_header_info"
android:background="?attr/account_header_background_color"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:background="#000" />
<android.support.constraint.ConstraintLayout
android:id="@+id/accountHeaderInfoContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/account_header_background_color">
android:layout_marginTop="180dp"
android:paddingEnd="16dp"
android:paddingStart="16dp">
<Button
android:id="@+id/accountFollowButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:textColor="@android:color/white"
android:textSize="?attr/status_text_medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Follow" />
<android.support.text.emoji.widget.EmojiTextView
android:id="@+id/accountDisplayNameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="62dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorPrimary"
android:textSize="?attr/status_text_large"
android:textStyle="normal|bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Tusky Mastodon Client " />
<TextView
android:id="@+id/accountUsernameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorSecondary"
android:textSize="?attr/status_text_medium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/accountDisplayNameTextView"
tools:text="\@Tusky" />
<ImageView
android:id="@+id/account_header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignBottom="@+id/account_header_info"
android:layout_alignTop="@+id/account_header_info"
android:background="@drawable/account_header_default"
android:contentDescription="@null"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
app:layout_collapseMode="pin" />
android:id="@+id/accountLockedImageView"
android:layout_width="16sp"
android:layout_height="16sp"
android:layout_marginStart="4dp"
android:contentDescription="@string/description_account_locked"
android:tint="?android:textColorSecondary"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/accountUsernameTextView"
app:layout_constraintStart_toEndOf="@+id/accountUsernameTextView"
app:layout_constraintTop_toTopOf="@+id/accountUsernameTextView"
app:srcCompat="@drawable/reblog_private_light"
tools:visibility="visible" />
<android.support.constraint.ConstraintLayout
android:id="@+id/account_header_info"
<TextView
android:id="@+id/accountFollowsYouTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:background="@drawable/profile_badge_background"
android:text="@string/follows_you"
android:textSize="?attr/status_text_small"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/accountUsernameTextView"
tools:visibility="visible" />
<TextView
android:id="@+id/accountBadgeTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="6dp"
android:background="@drawable/profile_badge_background"
android:text="@string/profile_badge_bot_text"
android:textSize="?attr/status_text_small"
android:visibility="gone"
app:layout_constraintStart_toEndOf="@id/accountFollowsYouTextView"
app:layout_constraintTop_toBottomOf="@id/accountUsernameTextView"
app:layout_goneMarginStart="0dp"
tools:visibility="visible" />
<android.support.constraint.Barrier
android:id="@+id/labelBarrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="accountFollowsYouTextView,accountBadgeTextView" />
<android.support.text.emoji.widget.EmojiTextView
android:id="@+id/accountNoteTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/labelBarrier"
android:lineSpacingMultiplier="1.1"
android:paddingTop="10dp"
android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium"
app:layout_constraintTop_toBottomOf="@id/labelBarrier"
tools:text="This is a test description. Descriptions can be quite looooong." />
<android.support.v7.widget.RecyclerView
android:id="@+id/accountFieldList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/account_header_gradient"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="?attr/actionBarSize"
app:layout_collapseMode="parallax">
app:layout_constraintTop_toBottomOf="@id/accountNoteTextView"
tools:itemCount="2"
tools:listitem="@layout/item_account_field" />
<com.pkmmte.view.CircularImageView
android:id="@+id/account_avatar"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginEnd="10dp"
android:src="@drawable/avatar_default"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shadow="true" />
<ViewStub
android:id="@+id/accountMovedView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inflatedId="@+id/accountMovedView"
android:layout="@layout/view_account_moved"
app:layout_constraintTop_toBottomOf="@id/accountFieldList" />
<Button
android:id="@+id/follow_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:textSize="?attr/status_text_medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/accountFollowers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/accountFollowing"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/accountMovedView">
<TextView
android:id="@+id/account_follows_you"
android:id="@+id/accountFollowersTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="@string/follows_you"
android:textColor="?android:textColorPrimary"
android:textSize="?attr/status_text_medium"
app:layout_constraintEnd_toEndOf="@id/follow_btn"
app:layout_constraintTop_toBottomOf="@id/follow_btn" />
<android.support.text.emoji.widget.EmojiTextView
android:id="@+id/account_display_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorPrimary"
android:textSize="?attr/status_text_large"
android:textStyle="normal|bold"
app:layout_constraintTop_toBottomOf="@id/account_avatar"
tools:text="Tusky Mastodon Client" />
<TextView
android:id="@+id/account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorSecondary"
android:textSize="?attr/status_text_medium"
app:layout_constraintTop_toBottomOf="@id/account_display_name"
tools:text="\@Tusky" />
<ImageView
android:id="@+id/account_locked"
android:layout_width="16sp"
android:layout_height="16sp"
android:layout_marginStart="4dp"
android:contentDescription="@string/description_account_locked"
android:tint="?android:textColorSecondary"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/account_username"
app:layout_constraintLeft_toRightOf="@id/account_username"
app:srcCompat="@drawable/reblog_private_light"
tools:visibility="visible" />
<android.support.text.emoji.widget.EmojiTextView
android:id="@+id/account_note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/account_username"
android:paddingBottom="16dp"
android:paddingTop="10dp"
android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium"
app:layout_constraintTop_toBottomOf="@id/account_username"
tools:text="This is a test description" />
<TextView
android:id="@+id/followers_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:background="@android:color/transparent"
android:fontFamily="sans-serif-medium"
android:textColor="@color/account_tab_font_color"
android:textSize="?attr/status_text_medium"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/account_note"
tools:text="3000 Followers" />
tools:text="1234" />
<TextView
android:id="@+id/following_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="6dp"
android:text="@string/title_followers"
android:textColor="@color/account_tab_font_color"
android:textSize="?attr/status_text_medium"
app:layout_constraintBottom_toBottomOf="@id/followers_tv"
app:layout_constraintEnd_toStartOf="@id/statuses_btn"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/followers_tv"
app:layout_constraintTop_toTopOf="@id/followers_tv"
tools:text="500 Following" />
android:textSize="?attr/status_text_medium" />
</LinearLayout>
<LinearLayout
android:id="@+id/accountFollowing"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/accountStatuses"
app:layout_constraintStart_toEndOf="@id/accountFollowers"
app:layout_constraintTop_toBottomOf="@id/accountMovedView">
<TextView
android:id="@+id/statuses_btn"
android:id="@+id/accountFollowingTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:fontFamily="sans-serif-medium"
android:textColor="@color/account_tab_font_color"
android:textSize="?attr/status_text_medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/following_tv"
app:layout_constraintTop_toTopOf="@id/followers_tv"
tools:text="3000 Posts" />
tools:text="500" />
</android.support.constraint.ConstraintLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="6dp"
android:text="@string/title_follows"
android:textColor="@color/account_tab_font_color"
android:textSize="?attr/status_text_medium" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/accountStatuses"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/accountFollowing"
app:layout_constraintTop_toBottomOf="@id/accountMovedView">
<TextView
android:id="@+id/accountStatusesTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:fontFamily="sans-serif-medium"
android:textColor="@color/account_tab_font_color"
android:textSize="?attr/status_text_medium"
tools:text="3000" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="6dp"
android:text="@string/title_statuses"
android:textColor="@color/account_tab_font_color"
android:textSize="?attr/status_text_medium" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
<!-- top margin equal to statusbar size will be set programmatically -->
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:id="@+id/accountToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentTop="true"
android:layout_gravity="top"
android:background="@android:color/transparent"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="?attr/toolbar_popup_theme" />
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout
android:id="@+id/accountTabLayout"
style="@style/TuskyTabAppearance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="?android:colorBackground"
app:tabGravity="fill"
app:tabIndicatorHeight="3dp"
app:tabSelectedTextColor="?attr/colorAccent"
app:tabTextAppearance="@style/TuskyTabAppearance" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:id="@+id/accountFragmentViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:colorBackground"
app:tabGravity="fill"
app:tabIndicatorHeight="3dp"
app:tabMaxWidth="0dp"
app:tabSelectedTextColor="?attr/colorAccent"
app:tabTextAppearance="@style/TuskyTabAppearance">
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.design.widget.TabLayout>
</android.support.v4.view.ViewPager>
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<View
android:id="@+id/tab_bottom_shadow"
android:id="@+id/accountTabBottomShadow"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/material_drawer_shadow_bottom"
android:visibility="visible"
app:layout_anchor="@id/tab_layout"
app:layout_anchor="@id/accountTabLayout"
app:layout_anchorGravity="bottom" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/floating_btn"
android:id="@+id/accountFloatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
@ -232,6 +298,18 @@
android:contentDescription="@string/action_mention"
app:srcCompat="@drawable/ic_create_24dp" />
<include layout="@layout/item_status_bottom_sheet"/>
<include layout="@layout/item_status_bottom_sheet" />
<ImageView
android:id="@+id/accountAvatarImageView"
android:layout_width="@dimen/account_activity_avatar_size"
android:layout_height="@dimen/account_activity_avatar_size"
android:layout_marginStart="16dp"
android:background="@drawable/avatar_background"
android:padding="3dp"
app:layout_anchor="@+id/accountHeaderInfoContainer"
app:layout_anchorGravity="top"
app:layout_scrollFlags="scroll"
app:srcCompat="@drawable/avatar_default" />
</android.support.design.widget.CoordinatorLayout>

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="4dp">
<android.support.text.emoji.widget.EmojiTextView
android:id="@+id/accountFieldName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="sans-serif-medium"
android:lineSpacingMultiplier="1.1"
android:textColor="?android:textColorPrimary"
android:textSize="?attr/status_text_medium"
app:layout_constraintEnd_toStartOf="@+id/accountFieldValue"
app:layout_constraintStart_toStartOf="parent"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_max="160dp"
tools:text="Field title " />
<android.support.text.emoji.widget.EmojiTextView
android:id="@+id/accountFieldValue"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:lineSpacingMultiplier="1.1"
android:textSize="?attr/status_text_medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/accountFieldName"
tools:text="Field content. This can contain links and custom emojis" />
</android.support.constraint.ConstraintLayout>

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="12dp"
android:paddingTop="12dp">
<android.support.text.emoji.widget.EmojiTextView
android:id="@+id/accountMovedText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="6dp"
android:textSize="?attr/status_text_medium"
tools:text="Account has moved" />
<ImageView
android:id="@+id/accountMovedAvatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerVertical="true"
android:layout_marginEnd="24dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@id/accountMovedText"
tools:src="@drawable/avatar_default" />
<android.support.text.emoji.widget.EmojiTextView
android:id="@+id/accountMovedDisplayName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorPrimary"
android:textSize="?attr/status_text_large"
android:textStyle="normal|bold"
app:layout_constraintBottom_toTopOf="@id/accountMovedUsername"
app:layout_constraintStart_toEndOf="@id/accountMovedAvatar"
app:layout_constraintTop_toTopOf="@id/accountMovedAvatar"
tools:text="Display name" />
<TextView
android:id="@+id/accountMovedUsername"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorSecondary"
android:textSize="?attr/status_text_medium"
app:layout_constraintBottom_toBottomOf="@id/accountMovedAvatar"
app:layout_constraintStart_toEndOf="@id/accountMovedAvatar"
app:layout_constraintTop_toBottomOf="@id/accountMovedDisplayName"
tools:text="\@username" />
</android.support.constraint.ConstraintLayout>