diff --git a/app/build.gradle b/app/build.gradle index 01c3c2c3..553f1fee 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -40,4 +40,8 @@ dependencies { transitive = true } compile 'com.github.chrisbanes:PhotoView:1.3.1' + compile 'com.mikepenz:google-material-typeface:3.0.1.0.original@aar' + compile 'com.github.arimorty:floatingsearchview:2.0.3' + compile 'com.jakewharton:butterknife:8.4.0' + annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0' } diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java index 6889bc8e..356c0cb0 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java @@ -41,7 +41,6 @@ import android.provider.OpenableColumns; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StringRes; -import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v13.view.inputmethod.EditorInfoCompat; import android.support.v13.view.inputmethod.InputConnectionCompat; @@ -57,14 +56,15 @@ import android.text.Spanned; import android.text.TextWatcher; import android.text.style.ForegroundColorSpan; import android.view.Gravity; -import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.webkit.MimeTypeMap; +import android.widget.Button; import android.widget.EditText; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; @@ -72,6 +72,7 @@ import android.widget.TextView; import com.keylesspalace.tusky.entity.Media; import com.keylesspalace.tusky.entity.Status; +import com.squareup.picasso.Picasso; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; @@ -100,8 +101,6 @@ public class ComposeActivity extends BaseActivity { private static final int MEDIA_SIZE_UNKNOWN = -1; private String inReplyToId; - private String domain; - private String accessToken; private EditText textEditor; private LinearLayout mediaPreviewBar; private ArrayList mediaQueued; @@ -117,6 +116,10 @@ public class ComposeActivity extends BaseActivity { private ProgressDialog finishingUploadDialog; private EditText contentWarningEditor; private boolean mediaPickEnabled; + private ImageButton pickBtn; + private Button nsfwBtn; + private ImageButton visibilityBtn; + private Button floatingBtn; private static class QueuedMedia { enum Type { @@ -325,6 +328,7 @@ public class ComposeActivity extends BaseActivity { actionBar.setTitle(null); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setDisplayShowHomeEnabled(true); + actionBar.setHomeAsUpIndicator(R.drawable.ic_close_24dp); } SharedPreferences preferences = getSharedPreferences( @@ -332,13 +336,35 @@ public class ComposeActivity extends BaseActivity { mediaPickEnabled = true; - FloatingActionButton floatingBtn = (FloatingActionButton) findViewById(R.id.floating_btn); + floatingBtn = (Button) findViewById(R.id.floating_btn); + pickBtn = (ImageButton) findViewById(R.id.compose_photo_pick); + nsfwBtn = (Button) findViewById(R.id.action_toggle_nsfw); + visibilityBtn = (ImageButton) findViewById(R.id.action_toggle_visibility); + floatingBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { sendStatus(); } }); + pickBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onMediaPick(); + } + }); + nsfwBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + toggleNsfw(); + } + }); + visibilityBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showComposeOptions(); + } + }); ArrayList savedMediaQueued = null; if (savedInstanceState != null) { @@ -362,6 +388,12 @@ public class ComposeActivity extends BaseActivity { statusHideText = false; } + if (statusMarkSensitive) { + nsfwBtn.setTextColor(ContextCompat.getColor(this, R.color.color_accent_dark)); + } else { + nsfwBtn.setTextColor(ContextCompat.getColor(this, R.color.image_button_dark)); + } + Intent intent = getIntent(); String[] mentionedUsernames = null; if (intent != null) { @@ -375,9 +407,6 @@ public class ComposeActivity extends BaseActivity { mentionedUsernames = intent.getStringArrayExtra("mentioned_usernames"); } - domain = preferences.getString("domain", null); - accessToken = preferences.getString("accessToken", null); - textEditor = createEditText(null); // new String[] { "image/gif", "image/webp" } if (savedInstanceState != null) { textEditor.onRestoreInstanceState(savedInstanceState.getParcelable("textEditorState")); @@ -435,10 +464,19 @@ public class ComposeActivity extends BaseActivity { } } + private void toggleNsfw() { + statusMarkSensitive = !statusMarkSensitive; + + if (statusMarkSensitive) { + nsfwBtn.setTextColor(ContextCompat.getColor(this, R.color.color_accent_dark)); + } else { + nsfwBtn.setTextColor(ContextCompat.getColor(this, R.color.image_button_dark)); + } + } + private void showComposeOptions() { ComposeOptionsFragment fragment = ComposeOptionsFragment.newInstance( - statusVisibility, statusMarkSensitive, statusHideText, - showMarkSensitive, inReplyToId != null, + statusVisibility, statusHideText, inReplyToId != null, new ComposeOptionsFragment.Listener() { @Override public int describeContents() { @@ -453,11 +491,6 @@ public class ComposeActivity extends BaseActivity { statusVisibility = visibility; } - @Override - public void onMarkSensitiveChanged(boolean markSensitive) { - statusMarkSensitive = markSensitive; - } - @Override public void onContentWarningChanged(boolean hideText) { showContentWarning(hideText); @@ -551,6 +584,7 @@ public class ComposeActivity extends BaseActivity { editText.setLayoutParams(layoutParams); editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE); editText.setEms(10); + editText.setBackgroundColor(0); editText.setGravity(Gravity.START | Gravity.TOP); editText.setHint(R.string.hint_compose); return editText; @@ -758,23 +792,12 @@ public class ComposeActivity extends BaseActivity { private void enableMediaPicking() { mediaPickEnabled = true; - invalidateOptionsMenu(); + pickBtn.setEnabled(true); } private void disableMediaPicking() { mediaPickEnabled = false; - invalidateOptionsMenu(); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - if (mediaPickEnabled) { - menu.findItem(R.id.compose_photo_pick).setEnabled(true); - } else { - menu.findItem(R.id.compose_photo_pick).setEnabled(false); - } - - return super.onPrepareOptionsMenu(menu); + pickBtn.setEnabled(false); } private void addMediaToQueue(QueuedMedia.Type type, Bitmap preview, Uri uri, long mediaSize) { @@ -786,10 +809,15 @@ public class ComposeActivity extends BaseActivity { int marginBottom = resources.getDimensionPixelSize( R.dimen.compose_media_preview_margin_bottom); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(side, side); - layoutParams.setMargins(margin, margin, margin, marginBottom); + layoutParams.setMargins(margin, 0, margin, marginBottom); view.setLayoutParams(layoutParams); - view.setImageBitmap(preview); - view.setScaleType(ImageView.ScaleType.CENTER_CROP); + + Picasso.with(this) + .load(uri) + .resize(side, side) + .centerCrop() + .into(view); + view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -1055,8 +1083,16 @@ public class ComposeActivity extends BaseActivity { void showMarkSensitive(boolean show) { showMarkSensitive = show; + if(!showMarkSensitive) { statusMarkSensitive = false; + nsfwBtn.setTextColor(ContextCompat.getColor(this, R.color.image_button_dark)); + } + + if(show) { + nsfwBtn.setVisibility(View.VISIBLE); + } else { + nsfwBtn.setVisibility(View.GONE); } } @@ -1069,12 +1105,6 @@ public class ComposeActivity extends BaseActivity { } } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.compose_toolbar, menu); - return super.onCreateOptionsMenu(menu); - } - @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { @@ -1082,16 +1112,6 @@ public class ComposeActivity extends BaseActivity { onBackPressed(); return true; } - - case R.id.compose_photo_pick: { - onMediaPick(); - return true; - } - - case R.id.compose_options: { - showComposeOptions(); - return true; - } } return super.onOptionsItemSelected(item); diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeOptionsFragment.java b/app/src/main/java/com/keylesspalace/tusky/ComposeOptionsFragment.java index fe9edfdc..40680bae 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ComposeOptionsFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/ComposeOptionsFragment.java @@ -15,21 +15,18 @@ import android.widget.RadioGroup; public class ComposeOptionsFragment extends BottomSheetDialogFragment { public interface Listener extends Parcelable { void onVisibilityChanged(String visibility); - void onMarkSensitiveChanged(boolean markSensitive); void onContentWarningChanged(boolean hideText); } private Listener listener; - public static ComposeOptionsFragment newInstance(String visibility, boolean markSensitive, - boolean hideText, boolean showMarkSensitive, boolean isReply, Listener listener) { + public static ComposeOptionsFragment newInstance(String visibility, + boolean hideText, boolean isReply, Listener listener) { Bundle arguments = new Bundle(); ComposeOptionsFragment fragment = new ComposeOptionsFragment(); arguments.putParcelable("listener", listener); arguments.putString("visibility", visibility); - arguments.putBoolean("markSensitive", markSensitive); arguments.putBoolean("hideText", hideText); - arguments.putBoolean("showMarkSensitive", showMarkSensitive); arguments.putBoolean("isReply", isReply); fragment.setArguments(arguments); return fragment; @@ -44,9 +41,7 @@ public class ComposeOptionsFragment extends BottomSheetDialogFragment { Bundle arguments = getArguments(); listener = arguments.getParcelable("listener"); String statusVisibility = arguments.getString("visibility"); - boolean statusMarkSensitive = arguments.getBoolean("markSensitive"); boolean statusHideText = arguments.getBoolean("hideText"); - boolean showMarkSensitive = arguments.getBoolean("showMarkSensitive"); boolean isReply = arguments.getBoolean("isReply"); RadioGroup radio = (RadioGroup) rootView.findViewById(R.id.radio_visibility); @@ -91,20 +86,6 @@ public class ComposeOptionsFragment extends BottomSheetDialogFragment { publicButton.setEnabled(false); } - CheckBox markSensitive = (CheckBox) rootView.findViewById(R.id.compose_mark_sensitive); - if (showMarkSensitive) { - markSensitive.setChecked(statusMarkSensitive); - markSensitive.setEnabled(true); - markSensitive.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - listener.onMarkSensitiveChanged(isChecked); - } - }); - } else { - markSensitive.setEnabled(false); - } - CheckBox hideText = (CheckBox) rootView.findViewById(R.id.compose_hide_text); hideText.setChecked(statusHideText); hideText.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java index 3d886cef..94116846 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java @@ -32,13 +32,17 @@ import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.ImageView; +import com.arlib.floatingsearchview.FloatingSearchView; import com.keylesspalace.tusky.entity.Account; +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.SecondaryDrawerItem; import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem; import com.mikepenz.materialdrawer.model.interfaces.IProfile; import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader; @@ -71,8 +75,8 @@ public class MainActivity extends BaseActivity { // Fetch user info while we're doing other things. fetchUserInfo(); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - setSupportActionBar(toolbar); + //Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + //setSupportActionBar(toolbar); FloatingActionButton floatingBtn = (FloatingActionButton) findViewById(R.id.floating_btn); floatingBtn.setOnClickListener(new View.OnClickListener() { @@ -83,25 +87,13 @@ public class MainActivity extends BaseActivity { } }); + final FloatingSearchView searchView = (FloatingSearchView) findViewById(R.id.floating_search_view); + headerResult = new AccountHeaderBuilder() .withActivity(this) .withSelectionListEnabledForSingleProfile(false) - .withTranslucentStatusBar(true) + .withDividerBelowHeader(false) .withCompactStyle(true) - .withOnAccountHeaderProfileImageListener(new AccountHeader.OnAccountHeaderProfileImageListener() { - @Override - public boolean onProfileImageClick(View view, IProfile profile, boolean current) { - Intent intent = new Intent(MainActivity.this, AccountActivity.class); - intent.putExtra("id", loggedInAccountId); - startActivity(intent); - return false; - } - - @Override - public boolean onProfileImageLongClick(View view, IProfile profile, boolean current) { - return false; - } - }) .build(); DrawerImageLoader.init(new AbstractDrawerImageLoader() { @@ -118,16 +110,17 @@ public class MainActivity extends BaseActivity { drawer = new DrawerBuilder() .withActivity(this) - .withToolbar(toolbar) - .withTranslucentStatusBar(true) + //.withToolbar(toolbar) .withAccountHeader(headerResult) .withHasStableIds(true) .withSelectedItem(-1) .addDrawerItems( - new PrimaryDrawerItem().withIdentifier(1).withName(getString(R.string.action_view_favourites)).withSelectable(false), - new PrimaryDrawerItem().withIdentifier(2).withName(getString(R.string.action_view_blocks)).withSelectable(false), - new PrimaryDrawerItem().withIdentifier(3).withName(getString(R.string.action_view_preferences)).withSelectable(false), - new PrimaryDrawerItem().withIdentifier(4).withName(getString(R.string.action_logout)).withSelectable(false) + new PrimaryDrawerItem().withIdentifier(0).withName(R.string.action_view_profile).withSelectable(false).withIcon(GoogleMaterial.Icon.gmd_person), + new PrimaryDrawerItem().withIdentifier(1).withName(getString(R.string.action_view_favourites)).withSelectable(false).withIcon(GoogleMaterial.Icon.gmd_star), + new PrimaryDrawerItem().withIdentifier(2).withName(getString(R.string.action_view_blocks)).withSelectable(false).withIcon(GoogleMaterial.Icon.gmd_block), + new DividerDrawerItem(), + new SecondaryDrawerItem().withIdentifier(3).withName(getString(R.string.action_view_preferences)).withSelectable(false), + new SecondaryDrawerItem().withIdentifier(4).withName(getString(R.string.action_logout)).withSelectable(false) ) .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() { @Override @@ -135,7 +128,11 @@ public class MainActivity extends BaseActivity { if (drawerItem != null) { long drawerItemIdentifier = drawerItem.getIdentifier(); - if (drawerItemIdentifier == 1) { + if (drawerItemIdentifier == 0) { + Intent intent = new Intent(MainActivity.this, AccountActivity.class); + intent.putExtra("id", loggedInAccountId); + startActivity(intent); + } else if (drawerItemIdentifier == 1) { Intent intent = new Intent(MainActivity.this, FavouritesActivity.class); startActivity(intent); } else if (drawerItemIdentifier == 2) { @@ -165,6 +162,8 @@ public class MainActivity extends BaseActivity { }) .build(); + searchView.attachNavigationDrawerToMenuButton(drawer.getDrawerLayout()); + // Setup the tabs and timeline pager. TimelinePagerAdapter adapter = new TimelinePagerAdapter(getSupportFragmentManager()); String[] pageTitles = { @@ -236,39 +235,40 @@ public class MainActivity extends BaseActivity { final String domain = preferences.getString("domain", null); String id = preferences.getString("loggedInAccountId", null); String username = preferences.getString("loggedInAccountUsername", null); - //if (id != null && username != null) { - // loggedInAccountId = id; - // loggedInAccountUsername = username; - //} else { - mastodonAPI.accountVerifyCredentials().enqueue(new Callback() { - @Override - public void onResponse(Call call, retrofit2.Response response) { - Account me = response.body(); - ImageView background = headerResult.getHeaderBackgroundView(); - Picasso.with(MainActivity.this) - .load(me.header) - .placeholder(R.drawable.account_header_missing) - .resize(background.getWidth(), background.getHeight()) - .centerCrop() - .into(background); + if (id != null && username != null) { + loggedInAccountId = id; + loggedInAccountUsername = username; + } - headerResult.addProfiles( - new ProfileDrawerItem() - .withName(me.displayName) - .withEmail(String.format("%s@%s", me.username, domain)) - .withIcon(me.avatar) - ); + mastodonAPI.accountVerifyCredentials().enqueue(new Callback() { + @Override + public void onResponse(Call call, retrofit2.Response response) { + Account me = response.body(); + ImageView background = headerResult.getHeaderBackgroundView(); - //onFetchUserInfoSuccess(response.body().id, response.body().username); - } + Picasso.with(MainActivity.this) + .load(me.header) + .placeholder(R.drawable.account_header_missing) + .resize(background.getWidth(), background.getHeight()) + .centerCrop() + .into(background); - @Override - public void onFailure(Call call, Throwable t) { - onFetchUserInfoFailure((Exception) t); - } - }); - //} + headerResult.addProfiles( + new ProfileDrawerItem() + .withName(me.displayName) + .withEmail(String.format("%s@%s", me.username, domain)) + .withIcon(me.avatar) + ); + + //onFetchUserInfoSuccess(response.body().id, response.body().username); + } + + @Override + public void onFailure(Call call, Throwable t) { + onFetchUserInfoFailure((Exception) t); + } + }); } private void onFetchUserInfoSuccess(String id, String username) { diff --git a/app/src/main/java/com/keylesspalace/tusky/StatusViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/StatusViewHolder.java index ac346b98..c64f669f 100644 --- a/app/src/main/java/com/keylesspalace/tusky/StatusViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/StatusViewHolder.java @@ -233,12 +233,13 @@ class StatusViewHolder extends RecyclerView.ViewHolder { previews[i].setVisibility(View.VISIBLE); Picasso.with(context) - .load(previewUrl) - .placeholder(mediaPreviewUnloadedId) - .into(previews[i]); + .load(previewUrl) + .placeholder(mediaPreviewUnloadedId) + .into(previews[i]); final String url = attachments[i].url; final Status.MediaAttachment.Type type = attachments[i].type; + previews[i].setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/app/src/main/java/com/keylesspalace/tusky/ViewMediaFragment.java b/app/src/main/java/com/keylesspalace/tusky/ViewMediaFragment.java index ffb74241..dd17c131 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ViewMediaFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/ViewMediaFragment.java @@ -28,6 +28,9 @@ import uk.co.senab.photoview.PhotoView; import uk.co.senab.photoview.PhotoViewAttacher; public class ViewMediaFragment extends Fragment { + + private PhotoViewAttacher attacher; + public static ViewMediaFragment newInstance(String url) { Bundle arguments = new Bundle(); ViewMediaFragment fragment = new ViewMediaFragment(); @@ -45,7 +48,7 @@ public class ViewMediaFragment extends Fragment { String url = arguments.getString("url"); PhotoView photoView = (PhotoView) rootView.findViewById(R.id.view_media_image); - final PhotoViewAttacher attacher = new PhotoViewAttacher(photoView); + attacher = new PhotoViewAttacher(photoView); attacher.setOnPhotoTapListener(new PhotoViewAttacher.OnPhotoTapListener() { @Override @@ -76,6 +79,12 @@ public class ViewMediaFragment extends Fragment { return rootView; } + @Override + public void onDestroyView() { + attacher.cleanup(); + super.onDestroyView(); + } + private void dismiss() { getFragmentManager().popBackStack(); } diff --git a/app/src/main/res/drawable/ic_close_24dp.xml b/app/src/main/res/drawable/ic_close_24dp.xml new file mode 100644 index 00000000..72af1301 --- /dev/null +++ b/app/src/main/res/drawable/ic_close_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_public_24dp.xml b/app/src/main/res/drawable/ic_public_24dp.xml new file mode 100644 index 00000000..d976b424 --- /dev/null +++ b/app/src/main/res/drawable/ic_public_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_compose.xml b/app/src/main/res/layout/activity_compose.xml index a1bd33f8..8183cea8 100644 --- a/app/src/main/res/layout/activity_compose.xml +++ b/app/src/main/res/layout/activity_compose.xml @@ -1,6 +1,7 @@ @@ -9,85 +10,129 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> + + app:popupTheme="@style/AppTheme.Account.ToolbarPopupTheme.Dark" /> - - - + android:orientation="vertical" + android:layout_marginBottom="8dp"> + + + + android:paddingRight="16dp"> - + android:layout_height="wrap_content"> + - + - + + + android:paddingRight="16dp" + android:paddingTop="4dp"> + + + + + +