convert MainActivity to Kotlin and upgrade MaterialDrawer to version 8 (#1748)
* convert MainActivity to Kotlin * migrate to MaterialDrawer 8 * fix drawer styles * revert removing BezelImageView and material_drawer_header override * fix tests * add lost comment back to material_drawer_header.xml * add tools:parentTag to material_drawer_header.xml * use when instead of if in MainActivity * fix statusbar color over the drawer * cleanup drawer item creation * tint secondary drawer items as well * remove unnecessary ids * fix header text color in the light theme * improve header text contrast
This commit is contained in:
parent
d44eada140
commit
2cf1e366b8
|
@ -101,6 +101,7 @@ ext.retrofitVersion = '2.8.1'
|
|||
ext.okhttpVersion = '4.4.0'
|
||||
ext.glideVersion = '4.11.0'
|
||||
ext.daggerVersion = '2.27'
|
||||
ext.materialdrawerVersion = '8.0.1'
|
||||
|
||||
// if libraries are changed here, they should also be changed in LicenseActivity
|
||||
dependencies {
|
||||
|
@ -159,10 +160,9 @@ dependencies {
|
|||
|
||||
implementation "com.github.chrisbanes:PhotoView:2.3.0"
|
||||
|
||||
implementation("com.mikepenz:materialdrawer:6.1.2@aar") {
|
||||
transitive = true
|
||||
}
|
||||
implementation "com.mikepenz:google-material-typeface:3.0.1.3.original@aar"
|
||||
implementation "com.mikepenz:materialdrawer:$materialdrawerVersion"
|
||||
implementation "com.mikepenz:materialdrawer-iconics:$materialdrawerVersion"
|
||||
implementation 'com.mikepenz:google-material-typeface:3.0.1.4.original-kotlin@aar'
|
||||
|
||||
implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0"
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
*/
|
||||
private fun loadResources() {
|
||||
toolbarColor = ThemeUtils.getColor(this, R.attr.colorSurface)
|
||||
statusBarColorTransparent = ContextCompat.getColor(this, R.color.header_background_filter)
|
||||
statusBarColorTransparent = ContextCompat.getColor(this, R.color.transparent_statusbar_background)
|
||||
statusBarColorOpaque = ThemeUtils.getColor(this, R.attr.colorPrimaryDark)
|
||||
avatarSize = resources.getDimension(R.dimen.account_activity_avatar_size)
|
||||
titleVisibleHeight = resources.getDimensionPixelSize(R.dimen.account_activity_scroll_title_visible_height)
|
||||
|
|
|
@ -17,26 +17,26 @@ package com.keylesspalace.tusky
|
|||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.resource.bitmap.FitCenter
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.keylesspalace.tusky.adapter.AccountFieldEditAdapter
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
|
@ -44,8 +44,10 @@ import com.keylesspalace.tusky.entity.Account
|
|||
import com.keylesspalace.tusky.entity.Instance
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import com.keylesspalace.tusky.viewmodel.EditProfileViewModel
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
import com.mikepenz.iconics.utils.colorInt
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import com.theartofdev.edmodo.cropper.CropImage
|
||||
import kotlinx.android.synthetic.main.activity_edit_profile.*
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
|
@ -103,7 +105,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
fieldList.layoutManager = LinearLayoutManager(this)
|
||||
fieldList.adapter = accountFieldEditAdapter
|
||||
|
||||
val plusDrawable = IconicsDrawable(this, GoogleMaterial.Icon.gmd_add).sizeDp(12).color(Color.WHITE)
|
||||
val plusDrawable = IconicsDrawable(this, GoogleMaterial.Icon.gmd_add).apply { sizeDp = 12; colorInt = Color.WHITE }
|
||||
|
||||
addFieldButton.setCompoundDrawablesRelativeWithIntrinsicBounds(plusDrawable, null, null, null)
|
||||
|
||||
|
|
|
@ -39,8 +39,12 @@ import com.keylesspalace.tusky.util.*
|
|||
import com.keylesspalace.tusky.viewmodel.ListsViewModel
|
||||
import com.keylesspalace.tusky.viewmodel.ListsViewModel.Event.*
|
||||
import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.*
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
import com.mikepenz.iconics.utils.color
|
||||
import com.mikepenz.iconics.utils.colorInt
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import com.mikepenz.iconics.utils.toIconicsColor
|
||||
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider.from
|
||||
import com.uber.autodispose.autoDispose
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
|
@ -235,7 +239,7 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
|
|||
.apply {
|
||||
val context = nameTextView.context
|
||||
val iconColor = ThemeUtils.getColor(context, android.R.attr.textColorTertiary)
|
||||
val icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_list).sizeDp(20).color(iconColor)
|
||||
val icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_list).apply { sizeDp = 20; colorInt = iconColor }
|
||||
|
||||
nameTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null)
|
||||
}
|
||||
|
|
|
@ -1,663 +0,0 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||
import androidx.emoji.text.EmojiCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.viewpager2.widget.MarginPageTransformer;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
import com.keylesspalace.tusky.appstore.CacheUpdater;
|
||||
import com.keylesspalace.tusky.appstore.EventHub;
|
||||
import com.keylesspalace.tusky.appstore.MainTabsChangedEvent;
|
||||
import com.keylesspalace.tusky.appstore.ProfileEditedEvent;
|
||||
import com.keylesspalace.tusky.components.compose.ComposeActivity;
|
||||
import com.keylesspalace.tusky.components.conversation.ConversationsRepository;
|
||||
import com.keylesspalace.tusky.components.scheduled.ScheduledTootActivity;
|
||||
import com.keylesspalace.tusky.components.search.SearchActivity;
|
||||
import com.keylesspalace.tusky.db.AccountEntity;
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.fragment.SFragment;
|
||||
import com.keylesspalace.tusky.interfaces.ActionButtonActivity;
|
||||
import com.keylesspalace.tusky.interfaces.ReselectableFragment;
|
||||
import com.keylesspalace.tusky.pager.MainPagerAdapter;
|
||||
import com.keylesspalace.tusky.util.CustomEmojiHelper;
|
||||
import com.keylesspalace.tusky.util.NotificationHelper;
|
||||
import com.keylesspalace.tusky.util.ShareShortcutHelper;
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
|
||||
import com.mikepenz.materialdrawer.AccountHeader;
|
||||
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
|
||||
import com.mikepenz.materialdrawer.Drawer;
|
||||
import com.mikepenz.materialdrawer.DrawerBuilder;
|
||||
import com.mikepenz.materialdrawer.model.DividerDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
||||
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader;
|
||||
import com.mikepenz.materialdrawer.util.DrawerImageLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.android.AndroidInjector;
|
||||
import dagger.android.DispatchingAndroidInjector;
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
|
||||
import static com.keylesspalace.tusky.util.MediaUtilsKt.deleteStaleCachedMedia;
|
||||
import static com.uber.autodispose.AutoDispose.autoDisposable;
|
||||
import static com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider.from;
|
||||
|
||||
public final class MainActivity extends BottomSheetActivity implements ActionButtonActivity,
|
||||
HasAndroidInjector {
|
||||
|
||||
private static final String TAG = "MainActivity"; // logging tag
|
||||
private static final long DRAWER_ITEM_ADD_ACCOUNT = -13;
|
||||
private static final long DRAWER_ITEM_EDIT_PROFILE = 0;
|
||||
private static final long DRAWER_ITEM_FAVOURITES = 1;
|
||||
private static final long DRAWER_ITEM_BOOKMARKS = 2;
|
||||
private static final long DRAWER_ITEM_LISTS = 3;
|
||||
private static final long DRAWER_ITEM_SEARCH = 4;
|
||||
private static final long DRAWER_ITEM_SAVED_TOOT = 5;
|
||||
private static final long DRAWER_ITEM_ACCOUNT_SETTINGS = 6;
|
||||
private static final long DRAWER_ITEM_SETTINGS = 7;
|
||||
private static final long DRAWER_ITEM_ABOUT = 8;
|
||||
private static final long DRAWER_ITEM_LOG_OUT = 9;
|
||||
private static final long DRAWER_ITEM_FOLLOW_REQUESTS = 10;
|
||||
private static final long DRAWER_ITEM_SCHEDULED_TOOT = 11;
|
||||
public static final String STATUS_URL = "statusUrl";
|
||||
|
||||
@Inject
|
||||
public DispatchingAndroidInjector<Object> androidInjector;
|
||||
@Inject
|
||||
public EventHub eventHub;
|
||||
@Inject
|
||||
public CacheUpdater cacheUpdater;
|
||||
@Inject
|
||||
ConversationsRepository conversationRepository;
|
||||
|
||||
private FloatingActionButton composeButton;
|
||||
private AccountHeader headerResult;
|
||||
private Drawer drawer;
|
||||
private TabLayout tabLayout;
|
||||
private ViewPager2 viewPager;
|
||||
|
||||
private int notificationTabPosition;
|
||||
private MainPagerAdapter adapter;
|
||||
|
||||
private final EmojiCompat.InitCallback emojiInitCallback = new EmojiCompat.InitCallback() {
|
||||
@Override
|
||||
public void onInitialized() {
|
||||
if(!isDestroyed()) {
|
||||
updateProfiles();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (accountManager.getActiveAccount() == null) {
|
||||
// will be redirected to LoginActivity by BaseActivity
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = getIntent();
|
||||
boolean showNotificationTab = false;
|
||||
|
||||
if (intent != null) {
|
||||
|
||||
/** there are two possibilities the accountId can be passed to MainActivity:
|
||||
- from our code as long 'account_id'
|
||||
- from share shortcuts as String 'android.intent.extra.shortcut.ID'
|
||||
*/
|
||||
long accountId = intent.getLongExtra(NotificationHelper.ACCOUNT_ID, -1);
|
||||
if(accountId == -1) {
|
||||
String accountIdString = intent.getStringExtra(ShortcutManagerCompat.EXTRA_SHORTCUT_ID);
|
||||
if(accountIdString != null) {
|
||||
accountId = Long.parseLong(accountIdString);
|
||||
}
|
||||
}
|
||||
boolean accountRequested = (accountId != -1);
|
||||
|
||||
if (accountRequested) {
|
||||
AccountEntity account = accountManager.getActiveAccount();
|
||||
if (account == null || accountId != account.getId()) {
|
||||
accountManager.setActiveAccount(accountId);
|
||||
}
|
||||
}
|
||||
|
||||
if (ComposeActivity.canHandleMimeType(intent.getType())) {
|
||||
// Sharing to Tusky from an external app
|
||||
if (accountRequested) {
|
||||
// The correct account is already active
|
||||
forwardShare(intent);
|
||||
} else {
|
||||
// No account was provided, show the chooser
|
||||
showAccountChooserDialog(getString(R.string.action_share_as), true, account -> {
|
||||
long requestedId = account.getId();
|
||||
AccountEntity activeAccount = accountManager.getActiveAccount();
|
||||
if (activeAccount != null && requestedId == activeAccount.getId()) {
|
||||
// The correct account is already active
|
||||
forwardShare(intent);
|
||||
} else {
|
||||
// A different account was requested, restart the activity
|
||||
intent.putExtra(NotificationHelper.ACCOUNT_ID, requestedId);
|
||||
changeAccount(requestedId, intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (accountRequested) {
|
||||
// user clicked a notification, show notification tab and switch user if necessary
|
||||
showNotificationTab = true;
|
||||
}
|
||||
}
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
composeButton = findViewById(R.id.floating_btn);
|
||||
tabLayout = findViewById(R.id.tab_layout);
|
||||
viewPager = findViewById(R.id.pager);
|
||||
|
||||
composeButton.setOnClickListener(v -> {
|
||||
Intent composeIntent = new Intent(getApplicationContext(), ComposeActivity.class);
|
||||
startActivity(composeIntent);
|
||||
});
|
||||
|
||||
setupDrawer();
|
||||
|
||||
/* Fetch user info while we're doing other things. This has to be done after setting up the
|
||||
* drawer, though, because its callback touches the header in the drawer. */
|
||||
fetchUserInfo();
|
||||
|
||||
setupTabs(showNotificationTab);
|
||||
|
||||
int pageMargin = getResources().getDimensionPixelSize(R.dimen.tab_page_margin);
|
||||
viewPager.setPageTransformer(new MarginPageTransformer(pageMargin));
|
||||
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
viewPager.setCurrentItem(tab.getPosition());
|
||||
|
||||
if (tab.getPosition() == notificationTabPosition) {
|
||||
NotificationHelper.clearNotificationsForActiveAccount(MainActivity.this, accountManager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
if (adapter != null) {
|
||||
Fragment fragment = adapter.getFragment(tab.getPosition());
|
||||
if (fragment instanceof ReselectableFragment) {
|
||||
((ReselectableFragment) fragment).onReselect();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Setup push notifications
|
||||
if (NotificationHelper.areNotificationsEnabled(this, accountManager)) {
|
||||
NotificationHelper.enablePullNotifications();
|
||||
} else {
|
||||
NotificationHelper.disablePullNotifications();
|
||||
}
|
||||
|
||||
eventHub.getEvents()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.as(autoDisposable(from(this, Lifecycle.Event.ON_DESTROY)))
|
||||
.subscribe(event -> {
|
||||
if (event instanceof ProfileEditedEvent) {
|
||||
onFetchUserInfoSuccess(((ProfileEditedEvent) event).getNewProfileData());
|
||||
}
|
||||
if (event instanceof MainTabsChangedEvent) {
|
||||
setupTabs(false);
|
||||
}
|
||||
});
|
||||
|
||||
// Flush old media that was cached for sharing
|
||||
deleteStaleCachedMedia(getApplicationContext().getExternalFilesDir("Tusky"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
NotificationHelper.clearNotificationsForActiveAccount(this, accountManager);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (drawer != null && drawer.isDrawerOpen()) {
|
||||
drawer.closeDrawer();
|
||||
} else if (viewPager.getCurrentItem() != 0) {
|
||||
viewPager.setCurrentItem(0);
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_MENU: {
|
||||
if (drawer.isDrawerOpen()) {
|
||||
drawer.closeDrawer();
|
||||
} else {
|
||||
drawer.openDrawer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case KeyEvent.KEYCODE_SEARCH: {
|
||||
startActivityWithSlideInAnimation(SearchActivity.getIntent(this));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.isCtrlPressed() || event.isShiftPressed()) {
|
||||
// FIXME: blackberry keyONE raises SHIFT key event even CTRL IS PRESSED
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_N: {
|
||||
// open compose activity by pressing SHIFT + N (or CTRL + N)
|
||||
Intent composeIntent = new Intent(getApplicationContext(), ComposeActivity.class);
|
||||
startActivity(composeIntent);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
String statusUrl = intent.getStringExtra(STATUS_URL);
|
||||
if (statusUrl != null) {
|
||||
viewUrl(statusUrl, PostLookupFallbackBehavior.DISPLAY_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
EmojiCompat.get().unregisterInitCallback(emojiInitCallback);
|
||||
}
|
||||
|
||||
private void forwardShare(Intent intent) {
|
||||
Intent composeIntent = new Intent(this, ComposeActivity.class);
|
||||
composeIntent.setAction(intent.getAction());
|
||||
composeIntent.setType(intent.getType());
|
||||
composeIntent.putExtras(intent);
|
||||
composeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
startActivity(composeIntent);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void setupDrawer() {
|
||||
headerResult = new AccountHeaderBuilder()
|
||||
.withActivity(this)
|
||||
.withDividerBelowHeader(false)
|
||||
.withHeaderBackgroundScaleType(ImageView.ScaleType.CENTER_CROP)
|
||||
.withCurrentProfileHiddenInList(true)
|
||||
.withOnAccountHeaderListener((view, profile, current) -> handleProfileClick(profile, current))
|
||||
.addProfiles(
|
||||
new ProfileSettingDrawerItem()
|
||||
.withIdentifier(DRAWER_ITEM_ADD_ACCOUNT)
|
||||
.withName(R.string.add_account_name)
|
||||
.withDescription(R.string.add_account_description)
|
||||
.withIcon(GoogleMaterial.Icon.gmd_add))
|
||||
.build();
|
||||
|
||||
headerResult.getView()
|
||||
.findViewById(R.id.material_drawer_account_header_current)
|
||||
.setContentDescription(getString(R.string.action_view_profile));
|
||||
|
||||
ImageView background = headerResult.getHeaderBackgroundView();
|
||||
background.setColorFilter(ContextCompat.getColor(this, R.color.header_background_filter));
|
||||
background.setBackgroundColor(ContextCompat.getColor(this, R.color.tusky_grey_10));
|
||||
|
||||
final boolean animateAvatars = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getBoolean("animateGifAvatars", false);
|
||||
|
||||
DrawerImageLoader.init(new AbstractDrawerImageLoader() {
|
||||
@Override
|
||||
public void set(ImageView imageView, Uri uri, Drawable placeholder, String tag) {
|
||||
if(animateAvatars) {
|
||||
Glide.with(MainActivity.this)
|
||||
.load(uri)
|
||||
.placeholder(placeholder)
|
||||
.into(imageView);
|
||||
} else {
|
||||
Glide.with(MainActivity.this)
|
||||
.asBitmap()
|
||||
.load(uri)
|
||||
.placeholder(placeholder)
|
||||
.into(imageView);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(ImageView imageView) {
|
||||
Glide.with(MainActivity.this).clear(imageView);
|
||||
}
|
||||
});
|
||||
|
||||
List<IDrawerItem> listItems = new ArrayList<>(11);
|
||||
listItems.add(new PrimaryDrawerItem().withIdentifier(DRAWER_ITEM_EDIT_PROFILE).withName(R.string.action_edit_profile).withSelectable(false).withIcon(GoogleMaterial.Icon.gmd_person));
|
||||
listItems.add(new PrimaryDrawerItem().withIdentifier(DRAWER_ITEM_FAVOURITES).withName(R.string.action_view_favourites).withSelectable(false).withIcon(GoogleMaterial.Icon.gmd_star));
|
||||
listItems.add(new PrimaryDrawerItem().withIdentifier(DRAWER_ITEM_BOOKMARKS).withName(R.string.action_view_bookmarks).withSelectable(false).withIcon(GoogleMaterial.Icon.gmd_bookmark));
|
||||
listItems.add(new PrimaryDrawerItem().withIdentifier(DRAWER_ITEM_LISTS).withName(R.string.action_lists).withSelectable(false).withIcon(GoogleMaterial.Icon.gmd_list));
|
||||
listItems.add(new PrimaryDrawerItem().withIdentifier(DRAWER_ITEM_SEARCH).withName(R.string.action_search).withSelectable(false).withIcon(GoogleMaterial.Icon.gmd_search));
|
||||
listItems.add(new PrimaryDrawerItem().withIdentifier(DRAWER_ITEM_SAVED_TOOT).withName(R.string.action_access_saved_toot).withSelectable(false).withIcon(R.drawable.ic_notebook).withIconTintingEnabled(true));
|
||||
listItems.add(new PrimaryDrawerItem().withIdentifier(DRAWER_ITEM_SCHEDULED_TOOT).withName(R.string.action_access_scheduled_toot).withSelectable(false).withIcon(R.drawable.ic_access_time).withIconTintingEnabled(true));
|
||||
listItems.add(new DividerDrawerItem());
|
||||
listItems.add(new SecondaryDrawerItem().withIdentifier(DRAWER_ITEM_ACCOUNT_SETTINGS).withName(R.string.action_view_account_preferences).withSelectable(false).withIcon(R.drawable.ic_account_settings).withIconTintingEnabled(true));
|
||||
listItems.add(new SecondaryDrawerItem().withIdentifier(DRAWER_ITEM_SETTINGS).withName(R.string.action_view_preferences).withSelectable(false).withIcon(GoogleMaterial.Icon.gmd_settings));
|
||||
listItems.add(new SecondaryDrawerItem().withIdentifier(DRAWER_ITEM_ABOUT).withName(R.string.about_title_activity).withSelectable(false).withIcon(GoogleMaterial.Icon.gmd_info));
|
||||
listItems.add(new SecondaryDrawerItem().withIdentifier(DRAWER_ITEM_LOG_OUT).withName(R.string.action_logout).withSelectable(false).withIcon(R.drawable.ic_logout).withIconTintingEnabled(true));
|
||||
|
||||
drawer = new DrawerBuilder()
|
||||
.withActivity(this)
|
||||
.withAccountHeader(headerResult)
|
||||
.withHasStableIds(true)
|
||||
.withSelectedItem(-1)
|
||||
.withDrawerItems(listItems)
|
||||
.withToolbar(findViewById(R.id.main_toolbar))
|
||||
.withOnDrawerItemClickListener((view, position, drawerItem) -> {
|
||||
if (drawerItem != null) {
|
||||
long drawerItemIdentifier = drawerItem.getIdentifier();
|
||||
|
||||
if (drawerItemIdentifier == DRAWER_ITEM_EDIT_PROFILE) {
|
||||
Intent intent = new Intent(MainActivity.this, EditProfileActivity.class);
|
||||
startActivityWithSlideInAnimation(intent);
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_FAVOURITES) {
|
||||
Intent intent = StatusListActivity.newFavouritesIntent(MainActivity.this);
|
||||
startActivityWithSlideInAnimation(intent);
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_BOOKMARKS) {
|
||||
Intent intent = StatusListActivity.newBookmarksIntent(MainActivity.this);
|
||||
startActivityWithSlideInAnimation(intent);
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_SEARCH) {
|
||||
startActivityWithSlideInAnimation(SearchActivity.getIntent(this));
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_ACCOUNT_SETTINGS) {
|
||||
Intent intent = PreferencesActivity.newIntent(MainActivity.this, PreferencesActivity.ACCOUNT_PREFERENCES);
|
||||
startActivityWithSlideInAnimation(intent);
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_SETTINGS) {
|
||||
Intent intent = PreferencesActivity.newIntent(MainActivity.this, PreferencesActivity.GENERAL_PREFERENCES);
|
||||
startActivityWithSlideInAnimation(intent);
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_ABOUT) {
|
||||
Intent intent = new Intent(MainActivity.this, AboutActivity.class);
|
||||
startActivityWithSlideInAnimation(intent);
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_LOG_OUT) {
|
||||
logout();
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_FOLLOW_REQUESTS) {
|
||||
Intent intent = new Intent(MainActivity.this, AccountListActivity.class);
|
||||
intent.putExtra("type", AccountListActivity.Type.FOLLOW_REQUESTS);
|
||||
startActivityWithSlideInAnimation(intent);
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_SAVED_TOOT) {
|
||||
Intent intent = new Intent(MainActivity.this, SavedTootActivity.class);
|
||||
startActivityWithSlideInAnimation(intent);
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_SCHEDULED_TOOT) {
|
||||
startActivityWithSlideInAnimation(ScheduledTootActivity.newIntent(this));
|
||||
} else if (drawerItemIdentifier == DRAWER_ITEM_LISTS) {
|
||||
startActivityWithSlideInAnimation(ListsActivity.newIntent(this));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
.build();
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
IDrawerItem debugItem = new SecondaryDrawerItem()
|
||||
.withIdentifier(1337)
|
||||
.withName("debug")
|
||||
.withDisabledTextColor(Color.GREEN)
|
||||
.withSelectable(false)
|
||||
.withEnabled(false);
|
||||
drawer.addItem(debugItem);
|
||||
}
|
||||
|
||||
EmojiCompat.get().registerInitCallback(emojiInitCallback);
|
||||
}
|
||||
|
||||
private void setupTabs(boolean selectNotificationTab) {
|
||||
List<TabData> tabs = accountManager.getActiveAccount().getTabPreferences();
|
||||
|
||||
adapter = new MainPagerAdapter(tabs, this);
|
||||
viewPager.setAdapter(adapter);
|
||||
|
||||
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> { }).attach();
|
||||
|
||||
tabLayout.removeAllTabs();
|
||||
for (int i = 0; i < tabs.size(); i++) {
|
||||
TabLayout.Tab tab = tabLayout.newTab()
|
||||
.setIcon(tabs.get(i).getIcon());
|
||||
if (tabs.get(i).getId().equals(TabDataKt.LIST)) {
|
||||
tab.setContentDescription(tabs.get(i).getArguments().get(1));
|
||||
} else {
|
||||
tab.setContentDescription(tabs.get(i).getText());
|
||||
}
|
||||
tabLayout.addTab(tab);
|
||||
if (tabs.get(i).getId().equals(TabDataKt.NOTIFICATIONS)) {
|
||||
notificationTabPosition = i;
|
||||
if (selectNotificationTab) {
|
||||
tab.select();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean handleProfileClick(IProfile profile, boolean current) {
|
||||
AccountEntity activeAccount = accountManager.getActiveAccount();
|
||||
|
||||
//open profile when active image was clicked
|
||||
if (current && activeAccount != null) {
|
||||
Intent intent = AccountActivity.getIntent(this, activeAccount.getAccountId());
|
||||
startActivityWithSlideInAnimation(intent);
|
||||
new Handler().postDelayed(() -> drawer.closeDrawer(), 100);
|
||||
return true;
|
||||
}
|
||||
//open LoginActivity to add new account
|
||||
if (profile.getIdentifier() == DRAWER_ITEM_ADD_ACCOUNT) {
|
||||
startActivityWithSlideInAnimation(LoginActivity.getIntent(this, true));
|
||||
new Handler().postDelayed(() -> drawer.closeDrawer(), 100);
|
||||
return true;
|
||||
}
|
||||
//change Account
|
||||
changeAccount(profile.getIdentifier(), null);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private void changeAccount(long newSelectedId, @Nullable Intent forward) {
|
||||
cacheUpdater.stop();
|
||||
SFragment.flushFilters();
|
||||
accountManager.setActiveAccount(newSelectedId);
|
||||
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
if (forward != null) {
|
||||
intent.setType(forward.getType());
|
||||
intent.setAction(forward.getAction());
|
||||
intent.putExtras(forward);
|
||||
}
|
||||
startActivity(intent);
|
||||
finishWithoutSlideOutAnimation();
|
||||
|
||||
overridePendingTransition(R.anim.explode, R.anim.explode);
|
||||
}
|
||||
|
||||
private void logout() {
|
||||
|
||||
AccountEntity activeAccount = accountManager.getActiveAccount();
|
||||
|
||||
if (activeAccount != null) {
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.action_logout)
|
||||
.setMessage(getString(R.string.action_logout_confirm, activeAccount.getFullName()))
|
||||
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
|
||||
|
||||
NotificationHelper.deleteNotificationChannelsForAccount(accountManager.getActiveAccount(), MainActivity.this);
|
||||
cacheUpdater.clearForUser(activeAccount.getId());
|
||||
conversationRepository.deleteCacheForAccount(activeAccount.getId());
|
||||
ShareShortcutHelper.removeShortcut(this, activeAccount);
|
||||
|
||||
AccountEntity newAccount = accountManager.logActiveAccountOut();
|
||||
|
||||
if (!NotificationHelper.areNotificationsEnabled(MainActivity.this, accountManager)) {
|
||||
NotificationHelper.disablePullNotifications();
|
||||
}
|
||||
|
||||
Intent intent;
|
||||
if (newAccount == null) {
|
||||
intent = LoginActivity.getIntent(MainActivity.this, false);
|
||||
} else {
|
||||
intent = new Intent(MainActivity.this, MainActivity.class);
|
||||
}
|
||||
startActivity(intent);
|
||||
finishWithoutSlideOutAnimation();
|
||||
})
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchUserInfo() {
|
||||
mastodonApi.accountVerifyCredentials()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.as(autoDisposable(from(this, Lifecycle.Event.ON_DESTROY)))
|
||||
.subscribe(this::onFetchUserInfoSuccess, MainActivity::onFetchUserInfoFailure);
|
||||
}
|
||||
|
||||
private void onFetchUserInfoSuccess(Account me) {
|
||||
|
||||
// Add the header image and avatar from the account, into the navigation drawer header.
|
||||
|
||||
ImageView background = headerResult.getHeaderBackgroundView();
|
||||
|
||||
Glide.with(MainActivity.this)
|
||||
.asBitmap()
|
||||
.load(me.getHeader())
|
||||
.into(background);
|
||||
|
||||
accountManager.updateActiveAccount(me);
|
||||
|
||||
NotificationHelper.createNotificationChannelsForAccount(accountManager.getActiveAccount(), this);
|
||||
|
||||
// Show follow requests in the menu, if this is a locked account.
|
||||
if (me.getLocked() && drawer.getDrawerItem(DRAWER_ITEM_FOLLOW_REQUESTS) == null) {
|
||||
PrimaryDrawerItem followRequestsItem = new PrimaryDrawerItem()
|
||||
.withIdentifier(DRAWER_ITEM_FOLLOW_REQUESTS)
|
||||
.withName(R.string.action_view_follow_requests)
|
||||
.withSelectable(false)
|
||||
.withIcon(GoogleMaterial.Icon.gmd_person_add);
|
||||
drawer.addItemAtPosition(followRequestsItem, 4);
|
||||
} else if (!me.getLocked()) {
|
||||
drawer.removeItem(DRAWER_ITEM_FOLLOW_REQUESTS);
|
||||
}
|
||||
|
||||
updateProfiles();
|
||||
|
||||
ShareShortcutHelper.updateShortcut(this, accountManager.getActiveAccount());
|
||||
|
||||
}
|
||||
|
||||
private void updateProfiles() {
|
||||
|
||||
List<AccountEntity> allAccounts = accountManager.getAllAccountsOrderedByActive();
|
||||
|
||||
List<IProfile> profiles = new ArrayList<>(allAccounts.size() + 1);
|
||||
|
||||
for (AccountEntity acc : allAccounts) {
|
||||
CharSequence emojifiedName = CustomEmojiHelper.emojifyString(acc.getDisplayName(), acc.getEmojis(), headerResult.getView());
|
||||
emojifiedName = EmojiCompat.get().process(emojifiedName);
|
||||
|
||||
profiles.add(
|
||||
new ProfileDrawerItem()
|
||||
.withSetSelected(acc.isActive())
|
||||
.withName(emojifiedName)
|
||||
.withIcon(acc.getProfilePictureUrl())
|
||||
.withNameShown(true)
|
||||
.withIdentifier(acc.getId())
|
||||
.withEmail(acc.getFullName()));
|
||||
|
||||
}
|
||||
|
||||
// reuse the already existing "add account" item
|
||||
for (IProfile profile : headerResult.getProfiles()) {
|
||||
if (profile.getIdentifier() == DRAWER_ITEM_ADD_ACCOUNT) {
|
||||
profiles.add(profile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
headerResult.clear();
|
||||
headerResult.setProfiles(profiles);
|
||||
headerResult.setActiveProfile(accountManager.getActiveAccount().getId());
|
||||
}
|
||||
|
||||
private static void onFetchUserInfoFailure(Throwable throwable) {
|
||||
Log.e(TAG, "Failed to fetch user info. " + throwable.getMessage());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public FloatingActionButton getActionButton() {
|
||||
return composeButton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AndroidInjector<Object> androidInjector() {
|
||||
return androidInjector;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,650 @@
|
|||
/* Copyright 2020 Tusky Contributors
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky
|
||||
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.emoji.text.EmojiCompat
|
||||
import androidx.emoji.text.EmojiCompat.InitCallback
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.viewpager2.widget.MarginPageTransformer
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.google.android.material.tabs.TabLayoutMediator.TabConfigurationStrategy
|
||||
import com.keylesspalace.tusky.appstore.*
|
||||
import com.keylesspalace.tusky.components.compose.ComposeActivity
|
||||
import com.keylesspalace.tusky.components.compose.ComposeActivity.Companion.canHandleMimeType
|
||||
import com.keylesspalace.tusky.components.conversation.ConversationsRepository
|
||||
import com.keylesspalace.tusky.components.scheduled.ScheduledTootActivity
|
||||
import com.keylesspalace.tusky.components.search.SearchActivity
|
||||
import com.keylesspalace.tusky.db.AccountEntity
|
||||
import com.keylesspalace.tusky.entity.Account
|
||||
import com.keylesspalace.tusky.fragment.SFragment
|
||||
import com.keylesspalace.tusky.interfaces.AccountSelectionListener
|
||||
import com.keylesspalace.tusky.interfaces.ActionButtonActivity
|
||||
import com.keylesspalace.tusky.interfaces.ReselectableFragment
|
||||
import com.keylesspalace.tusky.pager.MainPagerAdapter
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
import com.mikepenz.materialdrawer.iconics.iconicsIcon
|
||||
import com.mikepenz.materialdrawer.model.*
|
||||
import com.mikepenz.materialdrawer.model.interfaces.*
|
||||
import com.mikepenz.materialdrawer.util.*
|
||||
import com.mikepenz.materialdrawer.widget.AccountHeaderView
|
||||
import com.uber.autodispose.android.lifecycle.autoDispose
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInjector {
|
||||
@Inject
|
||||
lateinit var androidInjector: DispatchingAndroidInjector<Any>
|
||||
|
||||
@Inject
|
||||
lateinit var eventHub: EventHub
|
||||
|
||||
@Inject
|
||||
lateinit var cacheUpdater: CacheUpdater
|
||||
|
||||
@Inject
|
||||
lateinit var conversationRepository: ConversationsRepository
|
||||
|
||||
private lateinit var header: AccountHeaderView
|
||||
private lateinit var drawerToggle: ActionBarDrawerToggle
|
||||
|
||||
private var notificationTabPosition = 0
|
||||
|
||||
private var adapter: MainPagerAdapter? = null
|
||||
|
||||
private val emojiInitCallback = object : InitCallback() {
|
||||
override fun onInitialized() {
|
||||
if (!isDestroyed) {
|
||||
updateProfiles()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (accountManager.activeAccount == null) {
|
||||
// will be redirected to LoginActivity by BaseActivity
|
||||
return
|
||||
}
|
||||
var showNotificationTab = false
|
||||
if (intent != null) {
|
||||
/** there are two possibilities the accountId can be passed to MainActivity:
|
||||
* - from our code as long 'account_id'
|
||||
* - from share shortcuts as String 'android.intent.extra.shortcut.ID'
|
||||
*/
|
||||
var accountId = intent.getLongExtra(NotificationHelper.ACCOUNT_ID, -1)
|
||||
if (accountId == -1L) {
|
||||
val accountIdString = intent.getStringExtra(ShortcutManagerCompat.EXTRA_SHORTCUT_ID)
|
||||
if (accountIdString != null) {
|
||||
accountId = accountIdString.toLong()
|
||||
}
|
||||
}
|
||||
val accountRequested = accountId != -1L
|
||||
if (accountRequested) {
|
||||
val account = accountManager.activeAccount
|
||||
if (account == null || accountId != account.id) {
|
||||
accountManager.setActiveAccount(accountId)
|
||||
}
|
||||
}
|
||||
if (canHandleMimeType(intent.type)) {
|
||||
// Sharing to Tusky from an external app
|
||||
if (accountRequested) {
|
||||
// The correct account is already active
|
||||
forwardShare(intent)
|
||||
} else {
|
||||
// No account was provided, show the chooser
|
||||
showAccountChooserDialog(getString(R.string.action_share_as), true, object : AccountSelectionListener {
|
||||
override fun onAccountSelected(account: AccountEntity) {
|
||||
val requestedId = account.id
|
||||
val activeAccount = accountManager.activeAccount
|
||||
if (activeAccount != null && requestedId == activeAccount.id) {
|
||||
// The correct account is already active
|
||||
forwardShare(intent)
|
||||
} else {
|
||||
// A different account was requested, restart the activity
|
||||
intent.putExtra(NotificationHelper.ACCOUNT_ID, requestedId)
|
||||
changeAccount(requestedId, intent)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if (accountRequested) {
|
||||
// user clicked a notification, show notification tab and switch user if necessary
|
||||
showNotificationTab = true
|
||||
}
|
||||
}
|
||||
window.statusBarColor = Color.TRANSPARENT // don't draw a status bar, the DrawerLayout and the MaterialDrawerLayout have their own
|
||||
setContentView(R.layout.activity_main)
|
||||
composeButton.setOnClickListener {
|
||||
val composeIntent = Intent(applicationContext, ComposeActivity::class.java)
|
||||
startActivity(composeIntent)
|
||||
}
|
||||
setupDrawer(savedInstanceState)
|
||||
|
||||
/* Fetch user info while we're doing other things. This has to be done after setting up the
|
||||
* drawer, though, because its callback touches the header in the drawer. */
|
||||
fetchUserInfo()
|
||||
|
||||
setupTabs(showNotificationTab)
|
||||
|
||||
val pageMargin = resources.getDimensionPixelSize(R.dimen.tab_page_margin)
|
||||
viewPager.setPageTransformer(MarginPageTransformer(pageMargin))
|
||||
tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||
if (tab.position == notificationTabPosition) {
|
||||
NotificationHelper.clearNotificationsForActiveAccount(this@MainActivity, accountManager)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab) {}
|
||||
|
||||
override fun onTabReselected(tab: TabLayout.Tab) {
|
||||
val fragment = adapter?.getFragment(tab.position)
|
||||
if (fragment is ReselectableFragment) {
|
||||
(fragment as ReselectableFragment).onReselect()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Setup push notifications
|
||||
if (NotificationHelper.areNotificationsEnabled(this, accountManager)) {
|
||||
NotificationHelper.enablePullNotifications()
|
||||
} else {
|
||||
NotificationHelper.disablePullNotifications()
|
||||
}
|
||||
eventHub.events
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.autoDispose(this, Lifecycle.Event.ON_DESTROY)
|
||||
.subscribe { event: Event? ->
|
||||
when (event) {
|
||||
is ProfileEditedEvent -> onFetchUserInfoSuccess(event.newProfileData)
|
||||
is MainTabsChangedEvent -> setupTabs(false)
|
||||
}
|
||||
}
|
||||
|
||||
// Flush old media that was cached for sharing
|
||||
deleteStaleCachedMedia(applicationContext.getExternalFilesDir("Tusky"))
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
NotificationHelper.clearNotificationsForActiveAccount(this, accountManager)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
when {
|
||||
mainDrawerLayout.isOpen -> {
|
||||
mainDrawerLayout.close()
|
||||
}
|
||||
viewPager.currentItem != 0 -> {
|
||||
viewPager.currentItem = 0
|
||||
}
|
||||
else -> {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_MENU -> {
|
||||
if (mainDrawerLayout.isOpen) {
|
||||
mainDrawerLayout.close()
|
||||
} else {
|
||||
mainDrawerLayout.open()
|
||||
}
|
||||
return true
|
||||
}
|
||||
KeyEvent.KEYCODE_SEARCH -> {
|
||||
startActivityWithSlideInAnimation(SearchActivity.getIntent(this))
|
||||
return true
|
||||
}
|
||||
}
|
||||
if (event.isCtrlPressed || event.isShiftPressed) {
|
||||
// FIXME: blackberry keyONE raises SHIFT key event even CTRL IS PRESSED
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_N -> {
|
||||
|
||||
// open compose activity by pressing SHIFT + N (or CTRL + N)
|
||||
val composeIntent = Intent(applicationContext, ComposeActivity::class.java)
|
||||
startActivity(composeIntent)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event)
|
||||
}
|
||||
|
||||
public override fun onPostCreate(savedInstanceState: Bundle?) {
|
||||
super.onPostCreate(savedInstanceState)
|
||||
|
||||
drawerToggle.syncState()
|
||||
|
||||
if (intent != null) {
|
||||
val statusUrl = intent.getStringExtra(STATUS_URL)
|
||||
if (statusUrl != null) {
|
||||
viewUrl(statusUrl, PostLookupFallbackBehavior.DISPLAY_ERROR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
EmojiCompat.get().unregisterInitCallback(emojiInitCallback)
|
||||
}
|
||||
|
||||
private fun forwardShare(intent: Intent) {
|
||||
val composeIntent = Intent(this, ComposeActivity::class.java)
|
||||
composeIntent.action = intent.action
|
||||
composeIntent.type = intent.type
|
||||
composeIntent.putExtras(intent)
|
||||
composeIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(composeIntent)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun setupDrawer(savedInstanceState: Bundle?) {
|
||||
|
||||
drawerToggle = ActionBarDrawerToggle(this, mainDrawerLayout, mainToolbar, com.mikepenz.materialdrawer.R.string.material_drawer_open, com.mikepenz.materialdrawer.R.string.material_drawer_close)
|
||||
|
||||
header = AccountHeaderView(this).apply {
|
||||
headerBackgroundScaleType = ImageView.ScaleType.CENTER_CROP
|
||||
currentHiddenInList = true
|
||||
onAccountHeaderListener = { _: View?, profile: IProfile, current: Boolean -> handleProfileClick(profile, current) }
|
||||
addProfile(ProfileSettingDrawerItem().apply {
|
||||
identifier = DRAWER_ITEM_ADD_ACCOUNT
|
||||
nameRes = R.string.add_account_name
|
||||
descriptionRes = R.string.add_account_description
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_add
|
||||
}, 0)
|
||||
attachToSliderView(mainDrawer)
|
||||
dividerBelowHeader = false
|
||||
closeDrawerOnProfileListClick = true
|
||||
}
|
||||
|
||||
header.accountHeaderBackground.setColorFilter(ContextCompat.getColor(this, R.color.headerBackgroundFilter))
|
||||
header.accountHeaderBackground.setBackgroundColor(ThemeUtils.getColor(this, R.attr.colorBackgroundAccent))
|
||||
val animateAvatars = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getBoolean("animateGifAvatars", false)
|
||||
|
||||
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
|
||||
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
|
||||
if (animateAvatars) {
|
||||
Glide.with(imageView.context)
|
||||
.load(uri)
|
||||
.placeholder(placeholder)
|
||||
.into(imageView)
|
||||
} else {
|
||||
Glide.with(imageView.context)
|
||||
.asBitmap()
|
||||
.load(uri)
|
||||
.placeholder(placeholder)
|
||||
.into(imageView)
|
||||
}
|
||||
}
|
||||
|
||||
override fun cancel(imageView: ImageView) {
|
||||
Glide.with(imageView.context).clear(imageView)
|
||||
}
|
||||
|
||||
override fun placeholder(ctx: Context, tag: String?): Drawable {
|
||||
if (tag == DrawerImageLoader.Tags.PROFILE.name || tag == DrawerImageLoader.Tags.PROFILE_DRAWER_ITEM.name) {
|
||||
return ctx.getDrawable(R.drawable.avatar_default)!!
|
||||
}
|
||||
|
||||
return super.placeholder(ctx, tag)
|
||||
}
|
||||
})
|
||||
|
||||
mainDrawer.apply {
|
||||
tintStatusBar = true
|
||||
addItems(
|
||||
primaryDrawerItem {
|
||||
nameRes = R.string.action_edit_profile
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_person
|
||||
onClick = {
|
||||
val intent = Intent(context, EditProfileActivity::class.java)
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
}
|
||||
},
|
||||
primaryDrawerItem {
|
||||
nameRes = R.string.action_view_favourites
|
||||
isSelectable = false
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_star
|
||||
onClick = {
|
||||
val intent = StatusListActivity.newFavouritesIntent(context)
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
}
|
||||
},
|
||||
primaryDrawerItem {
|
||||
nameRes = R.string.action_view_bookmarks
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_bookmark
|
||||
onClick = {
|
||||
val intent = StatusListActivity.newBookmarksIntent(context)
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
}
|
||||
},
|
||||
primaryDrawerItem {
|
||||
nameRes = R.string.action_lists
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_list
|
||||
onClick = {
|
||||
startActivityWithSlideInAnimation(ListsActivity.newIntent(context))
|
||||
}
|
||||
},
|
||||
primaryDrawerItem {
|
||||
nameRes = R.string.action_search
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_search
|
||||
onClick = {
|
||||
startActivityWithSlideInAnimation(SearchActivity.getIntent(context))
|
||||
}
|
||||
},
|
||||
primaryDrawerItem {
|
||||
nameRes = R.string.action_access_saved_toot
|
||||
iconRes = R.drawable.ic_notebook
|
||||
onClick = {
|
||||
val intent = Intent(context, SavedTootActivity::class.java)
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
}
|
||||
},
|
||||
primaryDrawerItem {
|
||||
nameRes = R.string.action_access_scheduled_toot
|
||||
iconRes = R.drawable.ic_access_time
|
||||
onClick = {
|
||||
startActivityWithSlideInAnimation(ScheduledTootActivity.newIntent(context))
|
||||
}
|
||||
},
|
||||
DividerDrawerItem(),
|
||||
secondaryDrawerItem {
|
||||
nameRes = R.string.action_view_account_preferences
|
||||
iconRes = R.drawable.ic_account_settings
|
||||
onClick = {
|
||||
val intent = PreferencesActivity.newIntent(context, PreferencesActivity.ACCOUNT_PREFERENCES)
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
}
|
||||
},
|
||||
secondaryDrawerItem {
|
||||
nameRes = R.string.action_view_preferences
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_settings
|
||||
onClick = {
|
||||
val intent = PreferencesActivity.newIntent(context, PreferencesActivity.GENERAL_PREFERENCES)
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
}
|
||||
},
|
||||
secondaryDrawerItem {
|
||||
nameRes = R.string.about_title_activity
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_info
|
||||
onClick = {
|
||||
val intent = Intent(context, AboutActivity::class.java)
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
}
|
||||
},
|
||||
secondaryDrawerItem {
|
||||
nameRes = R.string.action_logout
|
||||
iconRes = R.drawable.ic_logout
|
||||
onClick = ::logout
|
||||
}
|
||||
)
|
||||
setSavedInstance(savedInstanceState)
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
mainDrawer.addItems(
|
||||
secondaryDrawerItem {
|
||||
nameText = "debug"
|
||||
isEnabled = false
|
||||
textColor = ColorStateList.valueOf(Color.GREEN)
|
||||
}
|
||||
)
|
||||
}
|
||||
EmojiCompat.get().registerInitCallback(emojiInitCallback)
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
drawerToggle.onConfigurationChanged(newConfig)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (drawerToggle.onOptionsItemSelected(item)) {
|
||||
return true
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(mainDrawer.saveInstanceState(outState))
|
||||
}
|
||||
|
||||
private fun setupTabs(selectNotificationTab: Boolean) {
|
||||
val tabs = accountManager.activeAccount!!.tabPreferences
|
||||
adapter = MainPagerAdapter(tabs, this)
|
||||
viewPager.adapter = adapter
|
||||
TabLayoutMediator(tabLayout, viewPager, TabConfigurationStrategy { _: TabLayout.Tab?, _: Int -> }).attach()
|
||||
tabLayout.removeAllTabs()
|
||||
for (i in tabs.indices) {
|
||||
val tab = tabLayout.newTab()
|
||||
.setIcon(tabs[i].icon)
|
||||
if (tabs[i].id == LIST) {
|
||||
tab.contentDescription = tabs[i].arguments[1]
|
||||
} else {
|
||||
tab.setContentDescription(tabs[i].text)
|
||||
}
|
||||
tabLayout.addTab(tab)
|
||||
if (tabs[i].id == NOTIFICATIONS) {
|
||||
notificationTabPosition = i
|
||||
if (selectNotificationTab) {
|
||||
tab.select()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleProfileClick(profile: IProfile, current: Boolean): Boolean {
|
||||
val activeAccount = accountManager.activeAccount
|
||||
|
||||
//open profile when active image was clicked
|
||||
if (current && activeAccount != null) {
|
||||
val intent = AccountActivity.getIntent(this, activeAccount.accountId)
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
return false
|
||||
}
|
||||
//open LoginActivity to add new account
|
||||
if (profile.identifier == DRAWER_ITEM_ADD_ACCOUNT) {
|
||||
startActivityWithSlideInAnimation(LoginActivity.getIntent(this, true))
|
||||
return false
|
||||
}
|
||||
//change Account
|
||||
changeAccount(profile.identifier, null)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun changeAccount(newSelectedId: Long, forward: Intent?) {
|
||||
cacheUpdater.stop()
|
||||
SFragment.flushFilters()
|
||||
accountManager.setActiveAccount(newSelectedId)
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
if (forward != null) {
|
||||
intent.type = forward.type
|
||||
intent.action = forward.action
|
||||
intent.putExtras(forward)
|
||||
}
|
||||
startActivity(intent)
|
||||
finishWithoutSlideOutAnimation()
|
||||
overridePendingTransition(R.anim.explode, R.anim.explode)
|
||||
}
|
||||
|
||||
private fun logout() {
|
||||
accountManager.activeAccount?.let { activeAccount ->
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.action_logout)
|
||||
.setMessage(getString(R.string.action_logout_confirm, activeAccount.fullName))
|
||||
.setPositiveButton(android.R.string.yes) { _: DialogInterface?, _: Int ->
|
||||
NotificationHelper.deleteNotificationChannelsForAccount(activeAccount, this@MainActivity)
|
||||
cacheUpdater.clearForUser(activeAccount.id)
|
||||
conversationRepository.deleteCacheForAccount(activeAccount.id)
|
||||
removeShortcut(this, activeAccount)
|
||||
val newAccount = accountManager.logActiveAccountOut()
|
||||
if (!NotificationHelper.areNotificationsEnabled(this@MainActivity, accountManager)) {
|
||||
NotificationHelper.disablePullNotifications()
|
||||
}
|
||||
val intent: Intent
|
||||
intent = if (newAccount == null) {
|
||||
LoginActivity.getIntent(this@MainActivity, false)
|
||||
} else {
|
||||
Intent(this@MainActivity, MainActivity::class.java)
|
||||
}
|
||||
startActivity(intent)
|
||||
finishWithoutSlideOutAnimation()
|
||||
}
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchUserInfo() {
|
||||
mastodonApi.accountVerifyCredentials()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.autoDispose(this, Lifecycle.Event.ON_DESTROY)
|
||||
.subscribe(
|
||||
{ userInfo ->
|
||||
onFetchUserInfoSuccess(userInfo)
|
||||
},
|
||||
{ throwable ->
|
||||
Log.e(TAG, "Failed to fetch user info. " + throwable.message)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun onFetchUserInfoSuccess(me: Account) {
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(me.header)
|
||||
.into(header.accountHeaderBackground)
|
||||
|
||||
accountManager.updateActiveAccount(me)
|
||||
NotificationHelper.createNotificationChannelsForAccount(accountManager.activeAccount!!, this)
|
||||
|
||||
// Show follow requests in the menu, if this is a locked account.
|
||||
if (me.locked && mainDrawer.getDrawerItem(DRAWER_ITEM_FOLLOW_REQUESTS) == null) {
|
||||
val followRequestsItem = primaryDrawerItem {
|
||||
identifier = DRAWER_ITEM_FOLLOW_REQUESTS
|
||||
nameRes = R.string.action_view_follow_requests
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_person_add
|
||||
onClick = {
|
||||
val intent = Intent(this@MainActivity, AccountListActivity::class.java)
|
||||
intent.putExtra("type", AccountListActivity.Type.FOLLOW_REQUESTS)
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
}
|
||||
}
|
||||
mainDrawer.addItemAtPosition(4, followRequestsItem)
|
||||
} else if (!me.locked) {
|
||||
mainDrawer.removeItems(DRAWER_ITEM_FOLLOW_REQUESTS)
|
||||
}
|
||||
updateProfiles()
|
||||
updateShortcut(this, accountManager.activeAccount!!)
|
||||
}
|
||||
|
||||
private fun updateProfiles() {
|
||||
val profiles: MutableList<IProfile> = accountManager.getAllAccountsOrderedByActive().map { acc ->
|
||||
val emojifiedName = EmojiCompat.get().process(CustomEmojiHelper.emojifyString(acc.displayName, acc.emojis, header))
|
||||
|
||||
ProfileDrawerItem().apply {
|
||||
isSelected = acc.isActive
|
||||
nameText = emojifiedName
|
||||
iconUrl = acc.profilePictureUrl
|
||||
isNameShown = true
|
||||
identifier = acc.id
|
||||
descriptionText = acc.fullName
|
||||
}
|
||||
}.toMutableList()
|
||||
|
||||
// reuse the already existing "add account" item
|
||||
for (profile in header.profiles.orEmpty()) {
|
||||
if (profile.identifier == DRAWER_ITEM_ADD_ACCOUNT) {
|
||||
profiles.add(profile)
|
||||
break
|
||||
}
|
||||
}
|
||||
header.clear()
|
||||
header.profiles = profiles
|
||||
header.setActiveProfile(accountManager.activeAccount!!.id)
|
||||
}
|
||||
|
||||
override fun getActionButton(): FloatingActionButton? = composeButton
|
||||
|
||||
override fun androidInjector() = androidInjector
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MainActivity" // logging tag
|
||||
private const val DRAWER_ITEM_ADD_ACCOUNT: Long = -13
|
||||
private const val DRAWER_ITEM_FOLLOW_REQUESTS: Long = 10
|
||||
const val STATUS_URL = "statusUrl"
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun primaryDrawerItem(block: PrimaryDrawerItem.() -> Unit): PrimaryDrawerItem {
|
||||
return PrimaryDrawerItem()
|
||||
.apply {
|
||||
isSelectable = false
|
||||
isIconTinted = true
|
||||
}
|
||||
.apply(block)
|
||||
}
|
||||
|
||||
private inline fun secondaryDrawerItem(block: SecondaryDrawerItem.() -> Unit): SecondaryDrawerItem {
|
||||
return SecondaryDrawerItem()
|
||||
.apply {
|
||||
isSelectable = false
|
||||
isIconTinted = true
|
||||
}
|
||||
.apply(block)
|
||||
}
|
||||
|
||||
private var AbstractDrawerItem<*, *>.onClick: () -> Unit
|
||||
get() = throw UnsupportedOperationException()
|
||||
set(value) {
|
||||
onDrawerItemClickListener = { _, _, _ ->
|
||||
value()
|
||||
true
|
||||
}
|
||||
}
|
|
@ -54,13 +54,14 @@ import com.keylesspalace.tusky.util.StatusDisplayOptions;
|
|||
import com.keylesspalace.tusky.util.TimestampUtils;
|
||||
import com.keylesspalace.tusky.viewdata.NotificationViewData;
|
||||
import com.keylesspalace.tusky.viewdata.StatusViewData;
|
||||
import com.mikepenz.iconics.utils.Utils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import at.connyduck.sparkbutton.helpers.Utils;
|
||||
|
||||
public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||
|
||||
public interface AdapterDataSource<T> {
|
||||
|
@ -140,7 +141,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
view.setLayoutParams(
|
||||
new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
Utils.convertDpToPx(parent.getContext(), 24)
|
||||
Utils.dpToPx(parent.getContext(), 24)
|
||||
)
|
||||
);
|
||||
return new RecyclerView.ViewHolder(view) {
|
||||
|
|
|
@ -49,7 +49,6 @@ import com.keylesspalace.tusky.viewdata.PollOptionViewData;
|
|||
import com.keylesspalace.tusky.viewdata.PollViewData;
|
||||
import com.keylesspalace.tusky.viewdata.PollViewDataKt;
|
||||
import com.keylesspalace.tusky.viewdata.StatusViewData;
|
||||
import com.mikepenz.iconics.utils.Utils;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
@ -59,6 +58,7 @@ import java.util.Locale;
|
|||
import java.util.Objects;
|
||||
|
||||
import at.connyduck.sparkbutton.SparkButton;
|
||||
import at.connyduck.sparkbutton.helpers.Utils;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
|
||||
import static com.keylesspalace.tusky.viewdata.PollViewDataKt.buildDescription;
|
||||
|
@ -294,7 +294,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
avatarRadius = avatarRadius48dp;
|
||||
|
||||
} else {
|
||||
int padding = Utils.convertDpToPx(avatar.getContext(), 12);
|
||||
int padding = Utils.dpToPx(avatar.getContext(), 12);
|
||||
avatar.setPaddingRelative(0, 0, padding, padding);
|
||||
|
||||
avatarInset.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -65,7 +65,6 @@ import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener
|
|||
import com.keylesspalace.tusky.components.compose.dialog.makeCaptionDialog
|
||||
import com.keylesspalace.tusky.components.compose.dialog.showAddPollDialog
|
||||
import com.keylesspalace.tusky.components.compose.view.ComposeOptionsListener
|
||||
import com.keylesspalace.tusky.components.compose.view.ComposeScheduleView
|
||||
import com.keylesspalace.tusky.db.AccountEntity
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
|
@ -74,8 +73,10 @@ import com.keylesspalace.tusky.entity.Emoji
|
|||
import com.keylesspalace.tusky.entity.NewPoll
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
import com.mikepenz.iconics.utils.colorInt
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.activity_compose.*
|
||||
import java.io.File
|
||||
|
@ -231,7 +232,7 @@ class ComposeActivity : BaseActivity(),
|
|||
if (replyingStatusAuthor != null) {
|
||||
composeReplyView.show()
|
||||
composeReplyView.text = getString(R.string.replying_to, replyingStatusAuthor)
|
||||
val arrowDownIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_arrow_drop_down).sizeDp(12)
|
||||
val arrowDownIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_arrow_drop_down).apply { sizeDp = 12 }
|
||||
|
||||
ThemeUtils.setDrawableTint(this, arrowDownIcon, android.R.attr.textColorTertiary)
|
||||
composeReplyView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, arrowDownIcon, null)
|
||||
|
@ -244,7 +245,7 @@ class ComposeActivity : BaseActivity(),
|
|||
composeReplyView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, arrowDownIcon, null)
|
||||
} else {
|
||||
composeReplyContentView.show()
|
||||
val arrowUpIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_arrow_drop_up).sizeDp(12)
|
||||
val arrowUpIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_arrow_drop_up).apply { sizeDp = 12 }
|
||||
|
||||
ThemeUtils.setDrawableTint(this, arrowUpIcon, android.R.attr.textColorTertiary)
|
||||
composeReplyView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, arrowUpIcon, null)
|
||||
|
@ -364,13 +365,13 @@ class ComposeActivity : BaseActivity(),
|
|||
|
||||
val textColor = ThemeUtils.getColor(this, android.R.attr.textColorTertiary)
|
||||
|
||||
val cameraIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_camera_alt).color(textColor).sizeDp(18)
|
||||
val cameraIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_camera_alt).apply { colorInt = textColor; sizeDp = 18 }
|
||||
actionPhotoTake.setCompoundDrawablesRelativeWithIntrinsicBounds(cameraIcon, null, null, null)
|
||||
|
||||
val imageIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_image).color(textColor).sizeDp(18)
|
||||
val imageIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_image).apply { colorInt = textColor; sizeDp = 18 }
|
||||
actionPhotoPick.setCompoundDrawablesRelativeWithIntrinsicBounds(imageIcon, null, null, null)
|
||||
|
||||
val pollIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_poll).color(textColor).sizeDp(18)
|
||||
val pollIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_poll).apply { colorInt = textColor; sizeDp = 18 }
|
||||
addPollTextActionTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(pollIcon, null, null, null)
|
||||
|
||||
actionPhotoTake.setOnClickListener { initiateCameraApp() }
|
||||
|
|
|
@ -21,8 +21,10 @@ import android.util.AttributeSet
|
|||
import com.google.android.material.button.MaterialButton
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
import com.mikepenz.iconics.utils.colorInt
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
|
||||
class TootButton
|
||||
@JvmOverloads constructor(
|
||||
|
@ -59,7 +61,7 @@ class TootButton
|
|||
Status.Visibility.PRIVATE,
|
||||
Status.Visibility.DIRECT -> {
|
||||
setText(R.string.action_send)
|
||||
IconicsDrawable(context, GoogleMaterial.Icon.gmd_lock).sizeDp(18).color(Color.WHITE)
|
||||
IconicsDrawable(context, GoogleMaterial.Icon.gmd_lock).apply { sizeDp = 18; colorInt = Color.WHITE }
|
||||
}
|
||||
else -> {
|
||||
null
|
||||
|
|
|
@ -121,7 +121,6 @@ class SearchActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||
override fun androidInjector() = androidInjector
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getIntent(context: Context) = Intent(context, SearchActivity::class.java)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,10 @@ import com.keylesspalace.tusky.entity.Filter
|
|||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.util.ThemeUtils
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
import com.mikepenz.iconics.utils.colorInt
|
||||
import com.mikepenz.iconics.utils.sizeRes
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
@ -72,8 +74,6 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
|
|||
private lateinit var publicFiltersPreference: Preference
|
||||
private lateinit var threadFiltersPreference: Preference
|
||||
|
||||
private val iconSize by lazy { resources.getDimensionPixelSize(R.dimen.preference_icon_size) }
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.account_preferences)
|
||||
|
||||
|
@ -92,9 +92,9 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
|
|||
publicFiltersPreference = requirePreference("publicFilters")
|
||||
threadFiltersPreference = requirePreference("threadFilters")
|
||||
|
||||
notificationPreference.icon = IconicsDrawable(notificationPreference.context, GoogleMaterial.Icon.gmd_notifications).sizePx(iconSize).color(ThemeUtils.getColor(notificationPreference.context, R.attr.iconColor))
|
||||
notificationPreference.icon = IconicsDrawable(notificationPreference.context, GoogleMaterial.Icon.gmd_notifications).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(notificationPreference.context, R.attr.iconColor) }
|
||||
mutedUsersPreference.icon = getTintedIcon(R.drawable.ic_mute_24dp)
|
||||
blockedUsersPreference.icon = IconicsDrawable(blockedUsersPreference.context, GoogleMaterial.Icon.gmd_block).sizePx(iconSize).color(ThemeUtils.getColor(blockedUsersPreference.context, R.attr.iconColor))
|
||||
blockedUsersPreference.icon = IconicsDrawable(blockedUsersPreference.context, GoogleMaterial.Icon.gmd_block).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(blockedUsersPreference.context, R.attr.iconColor) }
|
||||
mutedDomainsPreference.icon = getTintedIcon(R.drawable.ic_mute_24dp)
|
||||
|
||||
notificationPreference.onPreferenceClickListener = this
|
||||
|
|
|
@ -22,8 +22,10 @@ import com.keylesspalace.tusky.PreferencesActivity
|
|||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.util.ThemeUtils
|
||||
import com.keylesspalace.tusky.util.getNonNullString
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
import com.mikepenz.iconics.utils.colorInt
|
||||
import com.mikepenz.iconics.utils.sizeRes
|
||||
|
||||
fun PreferenceFragmentCompat.requirePreference(key: String): Preference {
|
||||
return findPreference(key)!!
|
||||
|
@ -31,20 +33,18 @@ fun PreferenceFragmentCompat.requirePreference(key: String): Preference {
|
|||
|
||||
class PreferencesFragment : PreferenceFragmentCompat() {
|
||||
|
||||
private val iconSize by lazy {resources.getDimensionPixelSize(R.dimen.preference_icon_size)}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences)
|
||||
|
||||
val themePreference: Preference = requirePreference("appTheme")
|
||||
themePreference.icon = IconicsDrawable(themePreference.context, GoogleMaterial.Icon.gmd_palette).sizePx(iconSize).color(ThemeUtils.getColor(themePreference.context, R.attr.iconColor))
|
||||
themePreference.icon = IconicsDrawable(themePreference.context, GoogleMaterial.Icon.gmd_palette).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(themePreference.context, R.attr.iconColor) }
|
||||
|
||||
val emojiPreference: Preference = requirePreference("emojiCompat")
|
||||
emojiPreference.icon = IconicsDrawable(emojiPreference.context, GoogleMaterial.Icon.gmd_sentiment_satisfied).sizePx(iconSize).color(ThemeUtils.getColor(emojiPreference.context, R.attr.iconColor))
|
||||
emojiPreference.icon = IconicsDrawable(emojiPreference.context, GoogleMaterial.Icon.gmd_sentiment_satisfied).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(themePreference.context, R.attr.iconColor) }
|
||||
|
||||
val textSizePreference: Preference = requirePreference("statusTextSize")
|
||||
textSizePreference.icon = IconicsDrawable(textSizePreference.context, GoogleMaterial.Icon.gmd_format_size).sizePx(iconSize).color(ThemeUtils.getColor(textSizePreference.context, R.attr.iconColor))
|
||||
textSizePreference.icon = IconicsDrawable(textSizePreference.context, GoogleMaterial.Icon.gmd_format_size).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(themePreference.context, R.attr.iconColor) }
|
||||
|
||||
val timelineFilterPreferences: Preference = requirePreference("timelineFilterPreferences")
|
||||
timelineFilterPreferences.setOnPreferenceClickListener {
|
||||
|
@ -67,7 +67,7 @@ class PreferencesFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
|
||||
val languagePreference: Preference = requirePreference("language")
|
||||
languagePreference.icon = IconicsDrawable(languagePreference.context, GoogleMaterial.Icon.gmd_translate).sizePx(iconSize).color(ThemeUtils.getColor(languagePreference.context, R.attr.iconColor))
|
||||
languagePreference.icon = IconicsDrawable(languagePreference.context, GoogleMaterial.Icon.gmd_translate).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(themePreference.context, R.attr.iconColor) }
|
||||
|
||||
val botIndicatorPreference = requirePreference("showBotOverlay")
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ public class CustomEmojiHelper {
|
|||
* @param view a reference to the a view the emojis will be shown in (should be the TextView, but parents of the TextView are also acceptable)
|
||||
* @return the text with the shortcodes replaced by EmojiSpans
|
||||
*/
|
||||
@NonNull
|
||||
public static Spanned emojifyText(@NonNull Spanned text, @Nullable List<Emoji> emojis, @NonNull final View view) {
|
||||
|
||||
if (emojis != null && !emojis.isEmpty()) {
|
||||
|
@ -74,6 +75,7 @@ public class CustomEmojiHelper {
|
|||
return text;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Spanned emojifyString(@NonNull String string, @Nullable List<Emoji> emojis, @NonNull final View ciew) {
|
||||
return emojifyText(new SpannedString(string), emojis, ciew);
|
||||
}
|
||||
|
@ -81,7 +83,8 @@ public class CustomEmojiHelper {
|
|||
|
||||
public static class EmojiSpan extends ReplacementSpan {
|
||||
|
||||
private @Nullable Drawable imageDrawable;
|
||||
@Nullable
|
||||
private Drawable imageDrawable;
|
||||
private WeakReference<View> viewWeakReference;
|
||||
|
||||
EmojiSpan(View view) {
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.util.AttributeSet;
|
|||
import android.view.View;
|
||||
import android.view.ViewOutlineProvider;
|
||||
|
||||
|
||||
/**
|
||||
* override BezelImageView from MaterialDrawer library to provide custom outline
|
||||
*/
|
||||
|
@ -39,7 +38,6 @@ public class BezelImageView extends com.mikepenz.materialdrawer.view.BezelImageV
|
|||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int old_w, int old_h) {
|
||||
setOutlineProvider(new CustomOutline(w, h));
|
||||
|
|
|
@ -1,57 +1,71 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.drawerlayout.widget.DrawerLayout 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_main"
|
||||
android:id="@+id/mainDrawerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.MainActivity">
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/main_appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:elevationOverlayEnabled="false"
|
||||
android:elevation="@dimen/actionbar_elevation">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/main_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:contentInsetStartWithNavigation="0dp">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tab_layout"
|
||||
style="@style/TuskyTabAppearance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:tabGravity="fill"
|
||||
app:tabMaxWidth="0dp"
|
||||
app:tabMode="fixed"
|
||||
app:tabUnboundedRipple="false" />
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/pager"
|
||||
android:background="?attr/windowBackgroundColor"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/tab_layout"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
tools:context="com.keylesspalace.tusky.MainActivity">
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/floating_btn"
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="@dimen/actionbar_elevation"
|
||||
app:elevationOverlayEnabled="false">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/mainToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:contentInsetStartWithNavigation="0dp">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabLayout"
|
||||
style="@style/TuskyTabAppearance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:tabGravity="fill"
|
||||
app:tabMaxWidth="0dp"
|
||||
app:tabMode="fixed"
|
||||
app:tabUnboundedRipple="false" />
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/tabLayout"
|
||||
android:background="?attr/windowBackgroundColor"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/composeButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:contentDescription="@string/action_compose"
|
||||
app:layout_anchor="@id/viewPager"
|
||||
app:layout_anchorGravity="bottom|end"
|
||||
app:srcCompat="@drawable/ic_create_24dp" />
|
||||
|
||||
<include layout="@layout/item_status_bottom_sheet" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<com.mikepenz.materialdrawer.widget.MaterialDrawerSliderView
|
||||
android:id="@+id/mainDrawer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:contentDescription="@string/action_compose"
|
||||
app:layout_anchor="@id/pager"
|
||||
app:layout_anchorGravity="bottom|end"
|
||||
app:srcCompat="@drawable/ic_create_24dp" />
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:fitsSystemWindows="true" />
|
||||
|
||||
<include layout="@layout/item_status_bottom_sheet" />
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<!-- this replaces the default material_drawer_header.xml from the MaterialDrawer library -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<!-- this replaces the default material_drawer_header.xml from the MaterialDrawer library to enable rounded avatars -->
|
||||
<merge 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/material_drawer_account_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/material_drawer_account_header_height"
|
||||
android:clickable="true">
|
||||
android:clickable="true"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/material_drawer_account_header_background"
|
||||
|
@ -25,64 +27,132 @@
|
|||
|
||||
<com.keylesspalace.tusky.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_current"
|
||||
style="@style/BezelImageView"
|
||||
android:layout_width="@dimen/material_drawer_account_header_selected"
|
||||
android:layout_height="@dimen/material_drawer_account_header_selected"
|
||||
android:layout_marginStart="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginLeft="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginTop="@dimen/material_drawer_account_header_horizontal_top"
|
||||
android:clickable="true"
|
||||
android:elevation="8dp"
|
||||
android:elevation="2dp"
|
||||
android:focusable="true"
|
||||
android:src="@drawable/avatar_default"
|
||||
app:biv_maskDrawable="@drawable/materialdrawer_shape_large"
|
||||
android:scaleType="fitCenter"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline"
|
||||
app:materialDrawerMaskDrawable="@drawable/materialdrawer_shape_large" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/material_drawer_account_header_current_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="4dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:lines="1"
|
||||
android:minWidth="20dp"
|
||||
android:paddingLeft="1dp"
|
||||
android:paddingRight="1dp"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/material_drawer_item_badge_text"
|
||||
app:layout_constraintBottom_toBottomOf="@id/material_drawer_account_header_current"
|
||||
app:layout_constraintStart_toStartOf="@id/material_drawer_account_header_current"
|
||||
tools:text="99" />
|
||||
|
||||
<com.keylesspalace.tusky.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_small_first"
|
||||
style="@style/BezelImageView"
|
||||
android:layout_width="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_height="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_marginTop="@dimen/material_drawer_account_header_horizontal_top"
|
||||
android:layout_marginEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginRight="@dimen/material_drawer_vertical_padding"
|
||||
android:clickable="true"
|
||||
android:elevation="8dp"
|
||||
android:elevation="2dp"
|
||||
android:focusable="true"
|
||||
android:src="@drawable/avatar_default"
|
||||
app:biv_maskDrawable="@drawable/materialdrawer_shape_small"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintEnd_toStartOf="@id/material_drawer_account_header_small_second"
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/material_drawer_account_header_small_first_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="4dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:lines="1"
|
||||
android:minWidth="20dp"
|
||||
android:paddingLeft="1dp"
|
||||
android:paddingRight="1dp"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/material_drawer_item_badge_small_text"
|
||||
app:layout_constraintBottom_toBottomOf="@id/material_drawer_account_header_small_first"
|
||||
app:layout_constraintStart_toStartOf="@id/material_drawer_account_header_small_first"
|
||||
tools:text="99" />
|
||||
|
||||
<com.keylesspalace.tusky.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_small_second"
|
||||
style="@style/BezelImageView"
|
||||
android:layout_width="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_height="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_marginTop="@dimen/material_drawer_account_header_horizontal_top"
|
||||
android:layout_marginEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginRight="@dimen/material_drawer_vertical_padding"
|
||||
android:clickable="true"
|
||||
android:elevation="8dp"
|
||||
android:elevation="2dp"
|
||||
android:focusable="true"
|
||||
android:src="@drawable/avatar_default"
|
||||
app:biv_maskDrawable="@drawable/materialdrawer_shape_small"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintEnd_toStartOf="@id/material_drawer_account_header_small_third"
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/material_drawer_account_header_small_second_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="4dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:lines="1"
|
||||
android:minWidth="20dp"
|
||||
android:paddingLeft="1dp"
|
||||
android:paddingRight="1dp"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/material_drawer_item_badge_small_text"
|
||||
app:layout_constraintBottom_toBottomOf="@id/material_drawer_account_header_small_second"
|
||||
app:layout_constraintStart_toStartOf="@id/material_drawer_account_header_small_second"
|
||||
tools:text="99" />
|
||||
|
||||
<com.keylesspalace.tusky.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_small_third"
|
||||
style="@style/BezelImageView"
|
||||
android:layout_width="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_height="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_marginTop="@dimen/material_drawer_account_header_horizontal_top"
|
||||
android:layout_marginEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginRight="@dimen/material_drawer_vertical_padding"
|
||||
android:clickable="true"
|
||||
android:elevation="8dp"
|
||||
android:elevation="2dp"
|
||||
android:focusable="true"
|
||||
android:src="@drawable/avatar_default"
|
||||
app:biv_maskDrawable="@drawable/materialdrawer_shape_small"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/material_drawer_account_header_small_third_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="4dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:lines="1"
|
||||
android:minWidth="20dp"
|
||||
android:paddingLeft="1dp"
|
||||
android:paddingRight="1dp"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/material_drawer_item_badge_small_text"
|
||||
app:layout_constraintBottom_toBottomOf="@id/material_drawer_account_header_small_third"
|
||||
app:layout_constraintStart_toStartOf="@id/material_drawer_account_header_small_third"
|
||||
tools:text="99" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/material_drawer_text_guideline"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -95,7 +165,6 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginLeft="@dimen/material_drawer_vertical_padding"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
|
@ -111,7 +180,6 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginLeft="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginBottom="@dimen/material_drawer_padding"
|
||||
android:fontFamily="sans-serif"
|
||||
android:lines="1"
|
||||
|
@ -127,8 +195,7 @@
|
|||
android:layout_width="@dimen/material_drawer_account_header_dropdown"
|
||||
android:layout_height="@dimen/material_drawer_account_header_dropdown"
|
||||
android:layout_marginEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginRight="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginBottom="@dimen/material_drawer_account_header_dropdown_margin_bottom"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</merge>
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
<color name="favoriteButtonActiveColor">@color/tusky_orange</color>
|
||||
|
||||
<color name="headerBackgroundFilter">@color/header_background_filter_dark</color>
|
||||
|
||||
<bool name="lightNavigationBar">false</bool>
|
||||
|
||||
</resources>
|
|
@ -26,7 +26,9 @@
|
|||
|
||||
<color name="transparent_tusky_blue">#8c2b90d9</color>
|
||||
<color name="transparent_black">#8f000000</color>
|
||||
<color name="header_background_filter">#44000000</color>
|
||||
<color name="header_background_filter_dark">#44000000</color>
|
||||
<color name="header_background_filter_light">#66FFFFFF</color>
|
||||
<color name="transparent_statusbar_background">#44000000</color>
|
||||
|
||||
<!-- colors used in the elephant friend drawables -->
|
||||
<color name="elephant_friend_border_color">#121419</color>
|
||||
|
|
|
@ -67,14 +67,8 @@
|
|||
|
||||
<item name="textColorDisabled">@color/textColorDisabled</item>
|
||||
|
||||
<item name="material_drawer_background">@color/colorBackground</item>
|
||||
<item name="material_drawer_primary_text">@color/textColorSecondary</item>
|
||||
<item name="material_drawer_primary_icon">@color/iconColor</item>
|
||||
<item name="material_drawer_secondary_text">@color/textColorTertiary</item>
|
||||
<item name="material_drawer_hint_text">@color/textColorTertiary</item>
|
||||
<item name="material_drawer_divider">?attr/dividerColor</item>
|
||||
<item name="material_drawer_header_selection_text">@color/white</item>
|
||||
<item name="material_drawer_header_selection_subtext">@color/white</item>
|
||||
<item name="materialDrawerStyle">@style/TuskyDrawerStyle</item>
|
||||
<item name="materialDrawerHeaderStyle">@style/TuskyDrawerHeaderStyle</item>
|
||||
|
||||
<item name="alertDialogTheme">@style/TuskyDialog</item>
|
||||
<item name="snackbarButtonStyle">@style/TuskyButton.TextButton</item>
|
||||
|
@ -142,17 +136,26 @@
|
|||
<item name="colorBackgroundAccent">@color/tusky_grey_20</item>
|
||||
|
||||
<item name="dividerColor">@color/tusky_grey_10</item>
|
||||
|
||||
<item name="material_drawer_background">@color/black</item>
|
||||
<item name="material_drawer_primary_icon">@color/tusky_grey_40</item>
|
||||
</style>
|
||||
|
||||
<style name="TuskyBlackTheme" parent="TuskyBlackThemeBase" />
|
||||
|
||||
<style name="TuskyDrawerStyle" parent ="Widget.MaterialDrawerStyle">
|
||||
<item name="materialDrawerBackground">?android:colorBackground</item>
|
||||
<item name="materialDrawerPrimaryIcon">?iconColor</item>
|
||||
<item name="materialDrawerSecondaryIcon">?iconColor</item>
|
||||
<item name="materialDrawerDividerColor">?dividerColor</item>
|
||||
</style>
|
||||
|
||||
<style name="TuskyDrawerHeaderStyle" parent ="Widget.MaterialDrawerHeaderStyle">
|
||||
<item name="materialDrawerHeaderSelectionText">?android:textColorPrimary</item>
|
||||
<item name="materialDrawerHeaderSelectionSubtext">?android:textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<!-- customize the shape of the avatars in account selection list -->
|
||||
<style name="BezelImageView">
|
||||
<item name="biv_maskDrawable">@drawable/materialdrawer_shape_small</item>
|
||||
<item name="biv_drawCircularShadow">false</item>
|
||||
<item name="materialDrawerMaskDrawable">@drawable/materialdrawer_shape_small</item>
|
||||
<item name="materialDrawerDrawCircularShadow">false</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
<color name="favoriteButtonActiveColor">@color/tusky_orange_light</color>
|
||||
|
||||
<color name="headerBackgroundFilter">@color/header_background_filter_light</color>
|
||||
|
||||
<bool name="lightNavigationBar">true</bool>
|
||||
|
||||
</resources>
|
|
@ -115,7 +115,7 @@ class FilterTest {
|
|||
|
||||
|
||||
activity.supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.activity_main, fragment, "fragment")
|
||||
.replace(R.id.mainDrawerLayout, fragment, "fragment")
|
||||
.commit()
|
||||
|
||||
fragment.reloadFilters(false)
|
||||
|
|
Loading…
Reference in New Issue