ComposeActivity improvements (#548)
* do not add media urls to status text * add scrolling to content * add arrow icon and animation to replying-to toggle * remove unnecessary compose_button_colors.xml * improve toot button * improve bottom bar, add bottom sheet for compose options, dedicated cw button * fix crash on Android < API 21 * move media picking from dialog to bottom sheet * add small style tootbutton * fix colors/button background for light theme * add icons to media chose bottom sheet * improve hide media button, delete unused styles * fix crash on dev build when taking photo * consolidate drawables * consolidate strings and ids, add tooltips to buttons * allow media only toots * change error message to show max size of upload correctly * fix button color * add emoji * code cleanup * Merge branch 'master' into compose_activity_refactoring # Conflicts: # app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java * fix hidden snackbar * improve hint text color * add SendTootService * fix timeline refreshing * toot saving and error handling for sendtootservice * restructure some code * convert EditTextTyped to Kotlin * fixed pick media button disabled color * force sensitive media when content warning is shown * add db cache for emojis & fix tests * reorder buttons to match mastodon web * add possibility to cancel sending of toot * correctly delete sent toots * refresh SavedTootActivity after toot was sent * remove unused resources * correct params for toot saving in SendTootService * consolidate strings * bugfix * remove unused resources * fix notifications on old android for SendTootService * fix crash
This commit is contained in:
parent
8a23f034f0
commit
27eefbf65a
79 changed files with 1815 additions and 1234 deletions
|
|
@ -31,7 +31,6 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
|
||||
import com.keylesspalace.tusky.AccountActivity;
|
||||
import com.keylesspalace.tusky.BaseActivity;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.adapter.AccountAdapter;
|
||||
import com.keylesspalace.tusky.adapter.BlocksAdapter;
|
||||
|
|
|
|||
|
|
@ -1,161 +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.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.BottomSheetDialogFragment;
|
||||
import android.support.graphics.drawable.VectorDrawableCompat;
|
||||
import android.support.v4.graphics.drawable.DrawableCompat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
||||
public class ComposeOptionsFragment extends BottomSheetDialogFragment {
|
||||
public interface Listener {
|
||||
void onVisibilityChanged(Status.Visibility visibility);
|
||||
void onContentWarningChanged(boolean hideText);
|
||||
}
|
||||
|
||||
private RadioGroup radio;
|
||||
private CheckBox hideText;
|
||||
private Listener listener;
|
||||
|
||||
public static ComposeOptionsFragment newInstance(Status.Visibility visibility, boolean hideText) {
|
||||
Bundle arguments = new Bundle();
|
||||
ComposeOptionsFragment fragment = new ComposeOptionsFragment();
|
||||
arguments.putInt("visibilityNum", visibility.getNum());
|
||||
arguments.putBoolean("hideText", hideText);
|
||||
fragment.setArguments(arguments);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
listener = (Listener) context;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_compose_options, container, false);
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
Status.Visibility visibility = Status.Visibility.byNum(
|
||||
arguments.getInt("visibilityNum", 0)
|
||||
);
|
||||
boolean statusHideText = arguments.getBoolean("hideText");
|
||||
|
||||
radio = rootView.findViewById(R.id.radio_visibility);
|
||||
int radioCheckedId = R.id.radio_public;
|
||||
switch (visibility) {
|
||||
case PUBLIC: radioCheckedId = R.id.radio_public; break;
|
||||
case PRIVATE: radioCheckedId = R.id.radio_private; break;
|
||||
case UNLISTED: radioCheckedId = R.id.radio_unlisted; break;
|
||||
case DIRECT: radioCheckedId = R.id.radio_direct; break;
|
||||
}
|
||||
radio.check(radioCheckedId);
|
||||
|
||||
RadioButton publicButton = rootView.findViewById(R.id.radio_public);
|
||||
RadioButton unlistedButton = rootView.findViewById(R.id.radio_unlisted);
|
||||
RadioButton privateButton = rootView.findViewById(R.id.radio_private);
|
||||
RadioButton directButton = rootView.findViewById(R.id.radio_direct);
|
||||
setRadioButtonDrawable(getContext(), publicButton, R.drawable.ic_public_24dp);
|
||||
setRadioButtonDrawable(getContext(), unlistedButton, R.drawable.ic_lock_open_24dp);
|
||||
setRadioButtonDrawable(getContext(), privateButton, R.drawable.ic_lock_outline_24dp);
|
||||
setRadioButtonDrawable(getContext(), directButton, R.drawable.ic_email_24dp);
|
||||
|
||||
hideText = rootView.findViewById(R.id.compose_hide_text);
|
||||
hideText.setChecked(statusHideText);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
radio.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||
Status.Visibility visibility;
|
||||
switch (checkedId) {
|
||||
default:
|
||||
case R.id.radio_public: {
|
||||
visibility = Status.Visibility.PUBLIC;
|
||||
break;
|
||||
}
|
||||
case R.id.radio_unlisted: {
|
||||
visibility = Status.Visibility.UNLISTED;
|
||||
break;
|
||||
}
|
||||
case R.id.radio_private: {
|
||||
visibility = Status.Visibility.PRIVATE;
|
||||
break;
|
||||
}
|
||||
case R.id.radio_direct: {
|
||||
visibility = Status.Visibility.DIRECT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
listener.onVisibilityChanged(visibility);
|
||||
}
|
||||
});
|
||||
hideText.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
listener.onContentWarningChanged(isChecked);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void setRadioButtonDrawable(Context context, RadioButton button,
|
||||
@DrawableRes int id) {
|
||||
ColorStateList list = new ColorStateList(new int[][] {
|
||||
new int[] { -android.R.attr.state_checked },
|
||||
new int[] { android.R.attr.state_checked }
|
||||
}, new int[] {
|
||||
ThemeUtils.getColor(context, R.attr.compose_image_button_tint),
|
||||
ThemeUtils.getColor(context, R.attr.colorAccent)
|
||||
});
|
||||
Drawable drawable = VectorDrawableCompat.create(context.getResources(), id,
|
||||
context.getTheme());
|
||||
if (drawable == null) {
|
||||
return;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
button.setButtonTintList(list);
|
||||
} else {
|
||||
drawable = DrawableCompat.wrap(drawable);
|
||||
DrawableCompat.setTintList(drawable, list);
|
||||
}
|
||||
button.setButtonDrawable(drawable);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,18 +20,14 @@ import android.content.ClipboardManager;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.ActivityOptionsCompat;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.text.Spanned;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import com.keylesspalace.tusky.AccountActivity;
|
||||
import com.keylesspalace.tusky.BaseActivity;
|
||||
import com.keylesspalace.tusky.ComposeActivity;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.ReportActivity;
|
||||
|
|
@ -41,27 +37,16 @@ import com.keylesspalace.tusky.ViewTagActivity;
|
|||
import com.keylesspalace.tusky.ViewThreadActivity;
|
||||
import com.keylesspalace.tusky.ViewVideoActivity;
|
||||
import com.keylesspalace.tusky.db.AccountEntity;
|
||||
import com.keylesspalace.tusky.di.Injectable;
|
||||
import com.keylesspalace.tusky.db.AccountManager;
|
||||
import com.keylesspalace.tusky.entity.Attachment;
|
||||
import com.keylesspalace.tusky.entity.Relationship;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.AdapterItemRemover;
|
||||
import com.keylesspalace.tusky.network.MastodonApi;
|
||||
import com.keylesspalace.tusky.network.TimelineCases;
|
||||
import com.keylesspalace.tusky.receiver.TimelineReceiver;
|
||||
import com.keylesspalace.tusky.util.HtmlUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/* Note from Andrew on Jan. 22, 2017: This class is a design problem for me, so I left it with an
|
||||
* awkward name. TimelineFragment and NotificationFragment have significant overlap but the nature
|
||||
* of that is complicated by how they're coupled with Status and Notification and the corresponding
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue