mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 16:49:40 +01:00
Update chat colors.
This commit is contained in:
committed by
Greyson Parrelli
parent
36fe150678
commit
bcc5d485ab
@@ -5,6 +5,9 @@ import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColorsPalette;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.Wallpaper;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -14,31 +17,44 @@ public interface ChatWallpaper extends Parcelable {
|
||||
|
||||
float FIXED_DIM_LEVEL_FOR_DARK_THEME = 0.2f;
|
||||
|
||||
List<ChatWallpaper> BUILTINS = Arrays.asList(SingleColorChatWallpaper.SOLID_1,
|
||||
SingleColorChatWallpaper.SOLID_2,
|
||||
SingleColorChatWallpaper.SOLID_3,
|
||||
SingleColorChatWallpaper.SOLID_4,
|
||||
SingleColorChatWallpaper.SOLID_5,
|
||||
SingleColorChatWallpaper.SOLID_6,
|
||||
SingleColorChatWallpaper.SOLID_7,
|
||||
SingleColorChatWallpaper.SOLID_8,
|
||||
SingleColorChatWallpaper.SOLID_9,
|
||||
SingleColorChatWallpaper.SOLID_10,
|
||||
SingleColorChatWallpaper.SOLID_11,
|
||||
SingleColorChatWallpaper.SOLID_12,
|
||||
GradientChatWallpaper.GRADIENT_1,
|
||||
GradientChatWallpaper.GRADIENT_2,
|
||||
GradientChatWallpaper.GRADIENT_3,
|
||||
GradientChatWallpaper.GRADIENT_4,
|
||||
GradientChatWallpaper.GRADIENT_5,
|
||||
GradientChatWallpaper.GRADIENT_6,
|
||||
GradientChatWallpaper.GRADIENT_7,
|
||||
GradientChatWallpaper.GRADIENT_8,
|
||||
GradientChatWallpaper.GRADIENT_9);
|
||||
|
||||
float getDimLevelForDarkTheme();
|
||||
|
||||
default @NonNull ChatColors getAutoChatColors() {
|
||||
return ChatColorsMapper.getChatColors(this).withId(ChatColors.Id.Auto.INSTANCE);
|
||||
}
|
||||
|
||||
boolean isSameSource(@NonNull ChatWallpaper chatWallpaper);
|
||||
|
||||
void loadInto(@NonNull ImageView imageView);
|
||||
|
||||
@NonNull Wallpaper serialize();
|
||||
|
||||
enum BuiltIns {
|
||||
INSTANCE;
|
||||
|
||||
@NonNull List<ChatWallpaper> getAllBuiltIns() {
|
||||
return Arrays.asList(
|
||||
SingleColorChatWallpaper.BLUSH,
|
||||
SingleColorChatWallpaper.COPPER,
|
||||
SingleColorChatWallpaper.DUST,
|
||||
SingleColorChatWallpaper.CELADON,
|
||||
SingleColorChatWallpaper.RAINFOREST,
|
||||
SingleColorChatWallpaper.PACIFIC,
|
||||
SingleColorChatWallpaper.FROST,
|
||||
SingleColorChatWallpaper.NAVY,
|
||||
SingleColorChatWallpaper.LILAC,
|
||||
SingleColorChatWallpaper.PINK,
|
||||
SingleColorChatWallpaper.EGGPLANT,
|
||||
SingleColorChatWallpaper.SILVER,
|
||||
GradientChatWallpaper.SUNSET,
|
||||
GradientChatWallpaper.NOIR,
|
||||
GradientChatWallpaper.HEATMAP,
|
||||
GradientChatWallpaper.AQUA,
|
||||
GradientChatWallpaper.IRIDESCENT,
|
||||
GradientChatWallpaper.MONSTERA,
|
||||
GradientChatWallpaper.BLISS,
|
||||
GradientChatWallpaper.SKY,
|
||||
GradientChatWallpaper.PEACH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,14 +41,6 @@ public final class ChatWallpaperActivity extends PassphraseRequiredActivity {
|
||||
dynamicTheme.onCreate(this);
|
||||
setContentView(R.layout.chat_wallpaper_activity);
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
|
||||
toolbar.setNavigationOnClickListener(unused -> {
|
||||
if (!Navigation.findNavController(this, R.id.nav_host_fragment).popBackStack()) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
Bundle extras = getIntent().getExtras();
|
||||
NavGraph graph = Navigation.findNavController(this, R.id.nav_host_fragment).getGraph();
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package org.thoughtcrime.securesms.wallpaper;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -11,23 +15,32 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.widget.ImageViewCompat;
|
||||
import androidx.core.widget.TextViewCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerView;
|
||||
import org.thoughtcrime.securesms.util.DisplayMetricsUtil;
|
||||
import org.thoughtcrime.securesms.util.Projection;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class ChatWallpaperFragment extends Fragment {
|
||||
|
||||
private boolean isSettingDimFromViewModel;
|
||||
private TextView clearWallpaper;
|
||||
private View resetAllWallpaper;
|
||||
private View divider;
|
||||
|
||||
private ChatWallpaperViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public @NonNull View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
@@ -36,24 +49,37 @@ public class ChatWallpaperFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
ChatWallpaperViewModel viewModel = ViewModelProviders.of(requireActivity()).get(ChatWallpaperViewModel.class);
|
||||
viewModel = ViewModelProviders.of(requireActivity()).get(ChatWallpaperViewModel.class);
|
||||
|
||||
ImageView portrait = view.findViewById(R.id.chat_wallpaper_preview_top_bar_portrait);
|
||||
Toolbar toolbar = view.findViewById(R.id.toolbar);
|
||||
ImageView chatWallpaperPreview = view.findViewById(R.id.chat_wallpaper_preview_background);
|
||||
View setWallpaper = view.findViewById(R.id.chat_wallpaper_set_wallpaper);
|
||||
SwitchCompat dimInNightMode = view.findViewById(R.id.chat_wallpaper_dark_theme_dims_wallpaper);
|
||||
View chatWallpaperDim = view.findViewById(R.id.chat_wallpaper_dim);
|
||||
TextView setChatColor = view.findViewById(R.id.chat_wallpaper_set_chat_color);
|
||||
TextView resetChatColors = view.findViewById(R.id.chat_wallpaper_reset_chat_colors);
|
||||
ImageView sentBubble = view.findViewById(R.id.chat_wallpaper_preview_bubble_2);
|
||||
ColorizerView colorizerView = view.findViewById(R.id.colorizer);
|
||||
TextView resetAllWallpaper = view.findViewById(R.id.chat_wallpaper_reset_all_wallpapers);
|
||||
AppCompatImageView recvBubble = view.findViewById(R.id.chat_wallpaper_preview_bubble_1);
|
||||
|
||||
clearWallpaper = view.findViewById(R.id.chat_wallpaper_clear_wallpaper);
|
||||
resetAllWallpaper = view.findViewById(R.id.chat_wallpaper_reset_all_wallpapers);
|
||||
divider = view.findViewById(R.id.chat_wallpaper_divider);
|
||||
toolbar.setTitle(R.string.preferences__chat_color_and_wallpaper);
|
||||
toolbar.setNavigationOnClickListener(nav -> {
|
||||
if (!Navigation.findNavController(nav).popBackStack()) {
|
||||
requireActivity().finish();
|
||||
}
|
||||
});
|
||||
|
||||
forceAspectRatioToScreenByAdjustingHeight(chatWallpaperPreview);
|
||||
|
||||
viewModel.getCurrentWallpaper().observe(getViewLifecycleOwner(), wallpaper -> {
|
||||
if (wallpaper.isPresent()) {
|
||||
wallpaper.get().loadInto(chatWallpaperPreview);
|
||||
ImageViewCompat.setImageTintList(recvBubble, ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.conversation_item_wallpaper_bubble_color)));
|
||||
} else {
|
||||
chatWallpaperPreview.setImageDrawable(null);
|
||||
chatWallpaperPreview.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.signal_background_primary));
|
||||
ImageViewCompat.setImageTintList(recvBubble, ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.signal_background_secondary)));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -71,56 +97,106 @@ public class ChatWallpaperFragment extends Fragment {
|
||||
viewModel.getEnableWallpaperControls().observe(getViewLifecycleOwner(), enableWallpaperControls -> {
|
||||
dimInNightMode.setEnabled(enableWallpaperControls);
|
||||
dimInNightMode.setAlpha(enableWallpaperControls ? 1 : 0.5f);
|
||||
clearWallpaper.setEnabled(enableWallpaperControls);
|
||||
clearWallpaper.setAlpha(enableWallpaperControls ? 1 : 0.5f);
|
||||
});
|
||||
|
||||
chatWallpaperPreview.setOnClickListener(unused -> setWallpaper.performClick());
|
||||
setWallpaper.setOnClickListener(unused -> Navigation.findNavController(view)
|
||||
.navigate(R.id.action_chatWallpaperFragment_to_chatWallpaperSelectionFragment));
|
||||
setChatColor.setOnClickListener(unused -> Navigation.findNavController(view)
|
||||
.navigate(ChatWallpaperFragmentDirections.actionChatWallpaperFragmentToChatColorSelectionFragment(viewModel.getRecipientId())));
|
||||
|
||||
resetAllWallpaper.setVisibility(viewModel.isGlobal() ? View.VISIBLE : View.GONE);
|
||||
if (viewModel.isGlobal()) {
|
||||
resetAllWallpaper.setOnClickListener(unused -> {
|
||||
new MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.ChatWallpaperFragment__reset_wallpaper)
|
||||
.setMessage(R.string.ChatWallpaperFragment__would_you_like_to_override_all_wallpapers)
|
||||
.setPositiveButton(R.string.ChatWallpaperFragment__reset_default_wallpaper, (dialog, which) -> {
|
||||
viewModel.setWallpaper(null);
|
||||
viewModel.setDimInDarkTheme(true);
|
||||
viewModel.saveWallpaperSelection();
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNeutralButton(R.string.ChatWallpaperFragment__reset_all_wallpapers, (dialog, which) -> {
|
||||
viewModel.setWallpaper(null);
|
||||
viewModel.setDimInDarkTheme(true);
|
||||
viewModel.resetAllWallpaper();
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
})
|
||||
.show();
|
||||
});
|
||||
|
||||
clearWallpaper.setOnClickListener(unused -> {
|
||||
confirmAction(viewModel.isGlobal() ? R.string.ChatWallpaperFragment__clear_wallpaper_this_will_not
|
||||
: R.string.ChatWallpaperFragment__clear_wallpaper_for_this_chat,
|
||||
R.string.ChatWallpaperFragment__clear,
|
||||
() -> {
|
||||
viewModel.setWallpaper(null);
|
||||
viewModel.setDimInDarkTheme(true);
|
||||
viewModel.saveWallpaperSelection();
|
||||
});
|
||||
});
|
||||
resetChatColors.setOnClickListener(unused -> {
|
||||
new MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.ChatWallpaperFragment__reset_chat_colors)
|
||||
.setMessage(R.string.ChatWallpaperFragment__would_you_like_to_override_all_chat_colors)
|
||||
.setPositiveButton(R.string.ChatWallpaperFragment__reset_default_colors, (dialog, which) -> {
|
||||
viewModel.clearChatColor();
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNeutralButton(R.string.ChatWallpaperFragment__reset_all_colors, (dialog, which) -> {
|
||||
viewModel.resetAllChatColors();
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
})
|
||||
.show();
|
||||
});
|
||||
} else {
|
||||
resetAllWallpaper.setText(R.string.ChatWallpaperFragment__reset_wallpaper);
|
||||
resetChatColors.setText(R.string.ChatWallpaperFragment__reset_chat_color);
|
||||
|
||||
resetAllWallpaper.setOnClickListener(unused -> {
|
||||
confirmAction(R.string.ChatWallpaperFragment__reset_all_wallpapers_including_custom,
|
||||
R.string.ChatWallpaperFragment__reset,
|
||||
() -> {
|
||||
viewModel.setWallpaper(null);
|
||||
viewModel.setDimInDarkTheme(true);
|
||||
viewModel.resetAllWallpaper();
|
||||
});
|
||||
});
|
||||
resetAllWallpaper.setOnClickListener(unused -> {
|
||||
new MaterialAlertDialogBuilder(requireContext())
|
||||
.setMessage(R.string.ChatWallpaperFragment__reset_wallpaper_question)
|
||||
.setPositiveButton(R.string.ChatWallpaperFragment__reset, (dialog, which) -> {
|
||||
viewModel.setWallpaper(null);
|
||||
viewModel.setDimInDarkTheme(true);
|
||||
viewModel.saveWallpaperSelection();
|
||||
viewModel.refreshChatColors();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss())
|
||||
.show();
|
||||
});
|
||||
|
||||
resetChatColors.setOnClickListener(unused -> {
|
||||
new MaterialAlertDialogBuilder(requireContext())
|
||||
.setMessage(R.string.ChatWallpaperFragment__reset_chat_color_question)
|
||||
.setPositiveButton(R.string.ChatWallpaperFragment__reset, (dialog, which) -> viewModel.clearChatColor())
|
||||
.setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss())
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
dimInNightMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
if (!isSettingDimFromViewModel) {
|
||||
viewModel.setDimInDarkTheme(isChecked);
|
||||
}
|
||||
});
|
||||
|
||||
viewModel.getCurrentChatColors().observe(getViewLifecycleOwner(), chatColors -> {
|
||||
sentBubble.getDrawable().setColorFilter(chatColors.getChatBubbleColorFilter());
|
||||
colorizerView.setBackground(chatColors.getChatBubbleMask());
|
||||
Projection projection = Projection.relativeToViewWithCommonRoot(sentBubble, colorizerView, new Projection.Corners(ViewUtil.dpToPx(10)));
|
||||
colorizerView.setProjections(Collections.singletonList(projection));
|
||||
|
||||
Drawable colorCircle = chatColors.asCircle();
|
||||
colorCircle.setBounds(0, 0, ViewUtil.dpToPx(16), ViewUtil.dpToPx(16));
|
||||
TextViewCompat.setCompoundDrawablesRelative(setChatColor, null, null, colorCircle, null);
|
||||
|
||||
portrait.setImageDrawable(chatColors.asCircle());
|
||||
});
|
||||
|
||||
sentBubble.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> viewModel.refreshChatColors());
|
||||
}
|
||||
|
||||
private void confirmAction(@StringRes int title, @StringRes int positiveActionLabel, @NonNull Runnable onPositiveAction) {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setMessage(title)
|
||||
.setPositiveButton(positiveActionLabel, (dialog, which) -> {
|
||||
onPositiveAction.run();
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setCancelable(true)
|
||||
.show();
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
viewModel.refreshChatColors();
|
||||
}
|
||||
|
||||
private void forceAspectRatioToScreenByAdjustingHeight(@NonNull View view) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.wallpaper;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
@@ -15,15 +16,21 @@ import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerView;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.FullscreenHelper;
|
||||
import org.thoughtcrime.securesms.util.MappingModel;
|
||||
import org.thoughtcrime.securesms.util.Projection;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.WindowUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ChatWallpaperPreviewActivity extends PassphraseRequiredActivity {
|
||||
|
||||
@@ -33,6 +40,12 @@ public class ChatWallpaperPreviewActivity extends PassphraseRequiredActivity {
|
||||
|
||||
private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme();
|
||||
|
||||
private ChatWallpaperPreviewAdapter adapter;
|
||||
private ColorizerView colorizerView;
|
||||
private View bubble2;
|
||||
private OnPageChanged onPageChanged;
|
||||
private ViewPager2 viewPager;
|
||||
|
||||
public static @NonNull Intent create(@NonNull Context context, @NonNull ChatWallpaper selection, @NonNull RecipientId recipientId, boolean dimInDarkMode) {
|
||||
Intent intent = new Intent(context, ChatWallpaperPreviewActivity.class);
|
||||
|
||||
@@ -49,15 +62,17 @@ public class ChatWallpaperPreviewActivity extends PassphraseRequiredActivity {
|
||||
|
||||
setContentView(R.layout.chat_wallpaper_preview_activity);
|
||||
|
||||
ViewPager2 viewPager = findViewById(R.id.preview_pager);
|
||||
ChatWallpaperPreviewAdapter adapter = new ChatWallpaperPreviewAdapter();
|
||||
View submit = findViewById(R.id.preview_set_wallpaper);
|
||||
ChatWallpaperRepository repository = new ChatWallpaperRepository();
|
||||
ChatWallpaper selected = getIntent().getParcelableExtra(EXTRA_CHAT_WALLPAPER);
|
||||
boolean dim = getIntent().getBooleanExtra(EXTRA_DIM_IN_DARK_MODE, false);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
View bubble1 = findViewById(R.id.preview_bubble_1);
|
||||
TextView bubble2 = findViewById(R.id.preview_bubble_2_text);
|
||||
adapter = new ChatWallpaperPreviewAdapter();
|
||||
colorizerView = findViewById(R.id.colorizer);
|
||||
bubble2 = findViewById(R.id.preview_bubble_2);
|
||||
viewPager = findViewById(R.id.preview_pager);
|
||||
|
||||
View submit = findViewById(R.id.preview_set_wallpaper);
|
||||
ChatWallpaperRepository repository = new ChatWallpaperRepository();
|
||||
ChatWallpaper selected = getIntent().getParcelableExtra(EXTRA_CHAT_WALLPAPER);
|
||||
boolean dim = getIntent().getBooleanExtra(EXTRA_DIM_IN_DARK_MODE, false);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
TextView bubble2Text = findViewById(R.id.preview_bubble_2_text);
|
||||
|
||||
toolbar.setNavigationOnClickListener(unused -> {
|
||||
finish();
|
||||
@@ -79,10 +94,23 @@ public class ChatWallpaperPreviewActivity extends PassphraseRequiredActivity {
|
||||
});
|
||||
|
||||
RecipientId recipientId = getIntent().getParcelableExtra(EXTRA_RECIPIENT_ID);
|
||||
if (recipientId != null) {
|
||||
|
||||
final ChatColors chatColors;
|
||||
if (recipientId != null && Recipient.live(recipientId).get().hasOwnChatColors()) {
|
||||
Recipient recipient = Recipient.live(recipientId).get();
|
||||
bubble1.getBackground().setColorFilter(recipient.getColor().toConversationColor(this), PorterDuff.Mode.SRC_IN);
|
||||
bubble2.setText(getString(R.string.ChatWallpaperPreviewActivity__set_wallpaper_for_s, recipient.getDisplayName(this)));
|
||||
bubble2Text.setText(getString(R.string.ChatWallpaperPreviewActivity__set_wallpaper_for_s, recipient.getDisplayName(this)));
|
||||
chatColors = recipient.getChatColors();
|
||||
bubble2.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
|
||||
updateChatColors(chatColors);
|
||||
});
|
||||
} else if (SignalStore.chatColorsValues().hasChatColors()) {
|
||||
chatColors = Objects.requireNonNull(SignalStore.chatColorsValues().getChatColors());
|
||||
bubble2.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
|
||||
updateChatColors(chatColors);
|
||||
});
|
||||
} else {
|
||||
onPageChanged = new OnPageChanged();
|
||||
viewPager.registerOnPageChangeCallback(onPageChanged);
|
||||
}
|
||||
|
||||
new FullscreenHelper(this).showSystemUI();
|
||||
@@ -90,6 +118,36 @@ public class ChatWallpaperPreviewActivity extends PassphraseRequiredActivity {
|
||||
WindowUtil.setLightNavigationBarFromTheme(this);
|
||||
}
|
||||
|
||||
@Override protected void onDestroy() {
|
||||
if (onPageChanged != null) {
|
||||
viewPager.unregisterOnPageChangeCallback(onPageChanged);
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private class OnPageChanged extends ViewPager2.OnPageChangeCallback {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
ChatWallpaperSelectionMappingModel model = (ChatWallpaperSelectionMappingModel) adapter.getCurrentList().get(position);
|
||||
|
||||
|
||||
updateChatColors(model.getWallpaper().getAutoChatColors());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChatColors(@NonNull ChatColors chatColors) {
|
||||
Drawable mask = chatColors.getChatBubbleMask();
|
||||
|
||||
colorizerView.setBackground(mask);
|
||||
|
||||
colorizerView.setProjections(
|
||||
Collections.singletonList(Projection.relativeToViewWithCommonRoot(bubble2, colorizerView, new Projection.Corners(ViewUtil.dpToPx(18))))
|
||||
);
|
||||
|
||||
bubble2.getBackground().setColorFilter(chatColors.getChatBubbleColorFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
@@ -6,6 +6,8 @@ import androidx.annotation.Nullable;
|
||||
import androidx.core.util.Consumer;
|
||||
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColorsPalette;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
@@ -17,6 +19,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
class ChatWallpaperRepository {
|
||||
@@ -32,30 +35,54 @@ class ChatWallpaperRepository {
|
||||
}
|
||||
}
|
||||
|
||||
@MainThread
|
||||
@NonNull ChatColors getCurrentChatColors(@Nullable RecipientId recipientId) {
|
||||
if (recipientId != null) {
|
||||
return Recipient.live(recipientId).get().getChatColors();
|
||||
} else if (SignalStore.chatColorsValues().hasChatColors()) {
|
||||
return Objects.requireNonNull(SignalStore.chatColorsValues().getChatColors());
|
||||
} else if (SignalStore.wallpaper().hasWallpaperSet()) {
|
||||
return Objects.requireNonNull(SignalStore.wallpaper().getWallpaper()).getAutoChatColors();
|
||||
} else {
|
||||
return ChatColorsPalette.Bubbles.getDefault();
|
||||
}
|
||||
}
|
||||
|
||||
void getAllWallpaper(@NonNull Consumer<List<ChatWallpaper>> consumer) {
|
||||
EXECUTOR.execute(() -> {
|
||||
List<ChatWallpaper> wallpapers = new ArrayList<>(ChatWallpaper.BUILTINS);
|
||||
List<ChatWallpaper> wallpapers = new ArrayList<>(ChatWallpaper.BuiltIns.INSTANCE.getAllBuiltIns());
|
||||
|
||||
wallpapers.addAll(WallpaperStorage.getAll(ApplicationDependencies.getApplication()));
|
||||
consumer.accept(wallpapers);
|
||||
});
|
||||
}
|
||||
|
||||
void saveWallpaper(@Nullable RecipientId recipientId, @Nullable ChatWallpaper chatWallpaper) {
|
||||
void saveWallpaper(@Nullable RecipientId recipientId, @Nullable ChatWallpaper chatWallpaper, @NonNull Runnable onWallpaperSaved) {
|
||||
if (recipientId != null) {
|
||||
//noinspection CodeBlock2Expr
|
||||
EXECUTOR.execute(() -> {
|
||||
DatabaseFactory.getRecipientDatabase(ApplicationDependencies.getApplication()).setWallpaper(recipientId, chatWallpaper);
|
||||
onWallpaperSaved.run();
|
||||
});
|
||||
} else {
|
||||
SignalStore.wallpaper().setWallpaper(ApplicationDependencies.getApplication(), chatWallpaper);
|
||||
onWallpaperSaved.run();
|
||||
}
|
||||
}
|
||||
|
||||
void resetAllWallpaper() {
|
||||
void resetAllWallpaper(@NonNull Runnable onWallpaperReset) {
|
||||
SignalStore.wallpaper().setWallpaper(ApplicationDependencies.getApplication(), null);
|
||||
EXECUTOR.execute(() -> {
|
||||
DatabaseFactory.getRecipientDatabase(ApplicationDependencies.getApplication()).resetAllWallpaper();
|
||||
onWallpaperReset.run();
|
||||
});
|
||||
}
|
||||
|
||||
void resetAllChatColors(@NonNull Runnable onColorsReset) {
|
||||
SignalStore.chatColorsValues().setChatColors(null);
|
||||
EXECUTOR.execute(() -> {
|
||||
DatabaseFactory.getRecipientDatabase(ApplicationDependencies.getApplication()).clearAllColors();
|
||||
onColorsReset.run();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,4 +106,16 @@ class ChatWallpaperRepository {
|
||||
SignalStore.wallpaper().setDimInDarkTheme(dimInDarkTheme);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearChatColor(@Nullable RecipientId recipientId, @NonNull Runnable onChatColorCleared) {
|
||||
if (recipientId == null) {
|
||||
SignalStore.chatColorsValues().setChatColors(null);
|
||||
onChatColorCleared.run();
|
||||
} else {
|
||||
EXECUTOR.execute(() -> {
|
||||
DatabaseFactory.getRecipientDatabase(ApplicationDependencies.getApplication()).clearColor(recipientId);
|
||||
onChatColorCleared.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
package org.thoughtcrime.securesms.wallpaper;
|
||||
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.util.MappingAdapter;
|
||||
|
||||
class ChatWallpaperSelectionAdapter extends MappingAdapter {
|
||||
ChatWallpaperSelectionAdapter(@Nullable ChatWallpaperViewHolder.EventListener eventListener, @NonNull DisplayMetrics windowDisplayMetrics) {
|
||||
registerFactory(ChatWallpaperSelectionMappingModel.class, ChatWallpaperViewHolder.createFactory(R.layout.chat_wallpaper_selection_fragment_adapter_item, eventListener, windowDisplayMetrics));
|
||||
ChatWallpaperSelectionAdapter(@Nullable ChatWallpaperViewHolder.EventListener eventListener) {
|
||||
registerFactory(ChatWallpaperSelectionMappingModel.class, ChatWallpaperViewHolder.createFactory(R.layout.chat_wallpaper_selection_fragment_adapter_item, eventListener, null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -12,14 +11,12 @@ import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.flexbox.FlexboxLayoutManager;
|
||||
import com.google.android.flexbox.JustifyContent;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.wallpaper.crop.WallpaperImageSelectionActivity;
|
||||
@@ -37,24 +34,22 @@ public class ChatWallpaperSelectionFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
Toolbar toolbar = view.findViewById(R.id.toolbar);
|
||||
View chooseFromPhotos = view.findViewById(R.id.chat_wallpaper_choose_from_photos);
|
||||
RecyclerView recyclerView = view.findViewById(R.id.chat_wallpaper_recycler);
|
||||
FlexboxLayoutManager flexboxLayoutManager = new FlexboxLayoutManager(requireContext());
|
||||
|
||||
chooseFromPhotos.setOnClickListener(unused -> {
|
||||
askForPermissionIfNeededAndLaunchPhotoSelection();
|
||||
});
|
||||
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
requireActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||
toolbar.setTitle(R.string.preferences__chat_color_and_wallpaper);
|
||||
toolbar.setNavigationOnClickListener(nav -> Navigation.findNavController(nav).popBackStack());
|
||||
|
||||
@SuppressWarnings("CodeBlock2Expr")
|
||||
ChatWallpaperSelectionAdapter adapter = new ChatWallpaperSelectionAdapter(chatWallpaper -> {
|
||||
startActivityForResult(ChatWallpaperPreviewActivity.create(requireActivity(), chatWallpaper, viewModel.getRecipientId(), viewModel.getDimInDarkTheme().getValue()), CHOOSE_WALLPAPER);
|
||||
}, displayMetrics);
|
||||
});
|
||||
|
||||
flexboxLayoutManager.setJustifyContent(JustifyContent.CENTER);
|
||||
recyclerView.setLayoutManager(flexboxLayoutManager);
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.addItemDecoration(new ChatWallpaperAlignmentDecoration());
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.util.DisplayMetricsUtil;
|
||||
import org.thoughtcrime.securesms.util.MappingAdapter;
|
||||
@@ -16,18 +18,22 @@ import org.thoughtcrime.securesms.util.MappingViewHolder;
|
||||
|
||||
class ChatWallpaperViewHolder extends MappingViewHolder<ChatWallpaperSelectionMappingModel> {
|
||||
|
||||
private final ImageView preview;
|
||||
private final View dimmer;
|
||||
private final EventListener eventListener;
|
||||
private final AspectRatioFrameLayout frame;
|
||||
private final ImageView preview;
|
||||
private final View dimmer;
|
||||
private final EventListener eventListener;
|
||||
|
||||
public ChatWallpaperViewHolder(@NonNull View itemView, @Nullable EventListener eventListener, @Nullable DisplayMetrics windowDisplayMetrics) {
|
||||
super(itemView);
|
||||
this.frame = itemView.findViewById(R.id.chat_wallpaper_preview_frame);
|
||||
this.preview = itemView.findViewById(R.id.chat_wallpaper_preview);
|
||||
this.dimmer = itemView.findViewById(R.id.chat_wallpaper_dim);
|
||||
this.eventListener = eventListener;
|
||||
|
||||
if (windowDisplayMetrics != null) {
|
||||
DisplayMetricsUtil.forceAspectRatioToScreenByAdjustingHeight(windowDisplayMetrics, itemView);
|
||||
} else if (frame != null) {
|
||||
frame.setAspectRatio(1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,17 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.Transformations;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.MappingModel;
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
||||
@@ -26,7 +30,10 @@ public class ChatWallpaperViewModel extends ViewModel {
|
||||
private final MutableLiveData<List<ChatWallpaper>> builtins = new MutableLiveData<>();
|
||||
private final MutableLiveData<Boolean> dimInDarkTheme = new MutableLiveData<>();
|
||||
private final MutableLiveData<Boolean> enableWallpaperControls = new MutableLiveData<>();
|
||||
private final MutableLiveData<ChatColors> chatColors = new MutableLiveData<>();
|
||||
private final RecipientId recipientId;
|
||||
private final LiveRecipient liveRecipient;
|
||||
private final RecipientForeverObserver recipientObserver = r -> refreshChatColors();
|
||||
|
||||
private ChatWallpaperViewModel(@Nullable RecipientId recipientId) {
|
||||
this.recipientId = recipientId;
|
||||
@@ -35,12 +42,30 @@ public class ChatWallpaperViewModel extends ViewModel {
|
||||
dimInDarkTheme.setValue(currentWallpaper == null || currentWallpaper.getDimLevelForDarkTheme() > 0f);
|
||||
enableWallpaperControls.setValue(hasClearableWallpaper());
|
||||
wallpaper.setValue(Optional.fromNullable(currentWallpaper));
|
||||
|
||||
if (recipientId != null) {
|
||||
liveRecipient = Recipient.live(recipientId);
|
||||
liveRecipient.observeForever(recipientObserver);
|
||||
} else {
|
||||
liveRecipient = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
if (liveRecipient != null) {
|
||||
liveRecipient.removeForeverObserver(recipientObserver);
|
||||
}
|
||||
}
|
||||
|
||||
void refreshWallpaper() {
|
||||
repository.getAllWallpaper(builtins::postValue);
|
||||
}
|
||||
|
||||
void refreshChatColors() {
|
||||
chatColors.postValue(repository.getCurrentChatColors(recipientId));
|
||||
}
|
||||
|
||||
void setDimInDarkTheme(boolean shouldDimInDarkTheme) {
|
||||
dimInDarkTheme.setValue(shouldDimInDarkTheme);
|
||||
|
||||
@@ -59,7 +84,7 @@ public class ChatWallpaperViewModel extends ViewModel {
|
||||
boolean dimInDarkTheme = this.dimInDarkTheme.getValue();
|
||||
|
||||
if (!wallpaper.isPresent()) {
|
||||
repository.saveWallpaper(recipientId, null);
|
||||
repository.saveWallpaper(recipientId, null, this::refreshChatColors);
|
||||
|
||||
if (recipientId != null) {
|
||||
ChatWallpaper globalWallpaper = SignalStore.wallpaper().getWallpaper();
|
||||
@@ -77,12 +102,12 @@ public class ChatWallpaperViewModel extends ViewModel {
|
||||
Optional<ChatWallpaper> updated = wallpaper.transform(paper -> ChatWallpaperFactory.updateWithDimming(paper, dimInDarkTheme ? ChatWallpaper.FIXED_DIM_LEVEL_FOR_DARK_THEME : 0f));
|
||||
|
||||
if (updated.isPresent()) {
|
||||
repository.saveWallpaper(recipientId, updated.get());
|
||||
repository.saveWallpaper(recipientId, updated.get(), this::refreshChatColors);
|
||||
}
|
||||
}
|
||||
|
||||
void resetAllWallpaper() {
|
||||
repository.resetAllWallpaper();
|
||||
repository.resetAllWallpaper(this::refreshChatColors);
|
||||
}
|
||||
|
||||
@Nullable RecipientId getRecipientId() {
|
||||
@@ -92,6 +117,10 @@ public class ChatWallpaperViewModel extends ViewModel {
|
||||
@NonNull LiveData<Optional<ChatWallpaper>> getCurrentWallpaper() {
|
||||
return wallpaper;
|
||||
}
|
||||
|
||||
@NonNull LiveData<ChatColors> getCurrentChatColors() {
|
||||
return chatColors;
|
||||
}
|
||||
|
||||
@NonNull LiveData<List<MappingModel<?>>> getWallpapers() {
|
||||
return LiveDataUtil.combineLatest(builtins, dimInDarkTheme, (wallpapers, dimInDarkMode) ->
|
||||
@@ -113,11 +142,19 @@ public class ChatWallpaperViewModel extends ViewModel {
|
||||
return recipientId == null;
|
||||
}
|
||||
|
||||
void clearChatColor() {
|
||||
repository.clearChatColor(recipientId, this::refreshChatColors);
|
||||
}
|
||||
|
||||
private boolean hasClearableWallpaper() {
|
||||
return (isGlobal() && SignalStore.wallpaper().hasWallpaperSet()) ||
|
||||
(recipientId != null && Recipient.live(recipientId).get().hasOwnWallpaper());
|
||||
}
|
||||
|
||||
public void resetAllChatColors() {
|
||||
repository.resetAllChatColors(this::refreshChatColors);
|
||||
}
|
||||
|
||||
public static class Factory implements ViewModelProvider.Factory {
|
||||
|
||||
private final RecipientId recipientId;
|
||||
|
||||
@@ -1,61 +1,53 @@
|
||||
package org.thoughtcrime.securesms.wallpaper;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.components.RotatableGradientDrawable;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.Wallpaper;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
final class GradientChatWallpaper implements ChatWallpaper, Parcelable {
|
||||
public final class GradientChatWallpaper implements ChatWallpaper, Parcelable {
|
||||
|
||||
public static final ChatWallpaper GRADIENT_1 = new GradientChatWallpaper(167.96f,
|
||||
public static final ChatWallpaper SUNSET = new GradientChatWallpaper(168f,
|
||||
new int[] { 0xFFF3DC47, 0xFFF3DA47, 0xFFF2D546, 0xFFF2CC46, 0xFFF1C146, 0xFFEFB445, 0xFFEEA544, 0xFFEC9644, 0xFFEB8743, 0xFFE97743, 0xFFE86942, 0xFFE65C41, 0xFFE55041, 0xFFE54841, 0xFFE44240, 0xFFE44040 },
|
||||
new float[] { 0.0f, 0.0807f, 0.1554f, 0.225f, 0.2904f, 0.3526f, 0.4125f, 0.471f, 0.529f, 0.5875f, 0.6474f, 0.7096f, 0.775f, 0.8446f, 0.9193f, 1f },
|
||||
0f);
|
||||
public static final ChatWallpaper GRADIENT_2 = new GradientChatWallpaper(180f,
|
||||
public static final ChatWallpaper NOIR = new GradientChatWallpaper(180f,
|
||||
new int[] { 0xFF16161D, 0xFF17171E, 0xFF1A1A22, 0xFF1F1F28, 0xFF26262F, 0xFF2D2D38, 0xFF353542, 0xFF3E3E4C, 0xFF474757, 0xFF4F4F61, 0xFF57576B, 0xFF5F5F74, 0xFF65657C, 0xFF6A6A82, 0xFF6D6D85, 0xFF6E6E87 },
|
||||
new float[] { 0.0000f, 0.0807f, 0.1554f, 0.2250f, 0.2904f, 0.3526f, 0.4125f, 0.4710f, 0.5290f, 0.5875f, 0.6474f, 0.7096f, 0.7750f, 0.8446f, 0.9193f, 1.0000f },
|
||||
0f);
|
||||
public static final ChatWallpaper GRADIENT_3 = new GradientChatWallpaper(192.04f,
|
||||
public static final ChatWallpaper HEATMAP = new GradientChatWallpaper(192f,
|
||||
new int[] { 0xFFF53844, 0xFFF33845, 0xFFEC3848, 0xFFE2384C, 0xFFD63851, 0xFFC73857, 0xFFB6385E, 0xFFA43866, 0xFF93376D, 0xFF813775, 0xFF70377C, 0xFF613782, 0xFF553787, 0xFF4B378B, 0xFF44378E, 0xFF42378F },
|
||||
new float[] { 0.0000f, 0.0075f, 0.0292f, 0.0637f, 0.1097f, 0.1659f, 0.2310f, 0.3037f, 0.3827f, 0.4666f, 0.5541f, 0.6439f, 0.7347f, 0.8252f, 0.9141f, 1.0000f },
|
||||
0f);
|
||||
public static final ChatWallpaper GRADIENT_4 = new GradientChatWallpaper(180f,
|
||||
public static final ChatWallpaper AQUA = new GradientChatWallpaper(180f,
|
||||
new int[] { 0xFF0093E9, 0xFF0294E9, 0xFF0696E7, 0xFF0D99E5, 0xFF169EE3, 0xFF21A3E0, 0xFF2DA8DD, 0xFF3AAEDA, 0xFF46B5D6, 0xFF53BBD3, 0xFF5FC0D0, 0xFF6AC5CD, 0xFF73CACB, 0xFF7ACDC9, 0xFF7ECFC7, 0xFF80D0C7 },
|
||||
new float[] { 0.0000f, 0.0807f, 0.1554f, 0.2250f, 0.2904f, 0.3526f, 0.4125f, 0.4710f, 0.5290f, 0.5875f, 0.6474f, 0.7096f, 0.7750f, 0.8446f, 0.9193f, 1.0000f },
|
||||
0f);
|
||||
public static final ChatWallpaper GRADIENT_5 = new GradientChatWallpaper(192.04f,
|
||||
public static final ChatWallpaper IRIDESCENT = new GradientChatWallpaper(192f,
|
||||
new int[] { 0xFFF04CE6, 0xFFEE4BE6, 0xFFE54AE5, 0xFFD949E5, 0xFFC946E4, 0xFFB644E3, 0xFFA141E3, 0xFF8B3FE2, 0xFF743CE1, 0xFF5E39E0, 0xFF4936DF, 0xFF3634DE, 0xFF2632DD, 0xFF1930DD, 0xFF112FDD, 0xFF0E2FDD },
|
||||
new float[] { 0.0000f, 0.0807f, 0.1554f, 0.2250f, 0.2904f, 0.3526f, 0.4125f, 0.4710f, 0.5290f, 0.5875f, 0.6474f, 0.7096f, 0.7750f, 0.8446f, 0.9193f, 1.0000f },
|
||||
0f);
|
||||
public static final ChatWallpaper GRADIENT_6 = new GradientChatWallpaper(180f,
|
||||
public static final ChatWallpaper MONSTERA = new GradientChatWallpaper(180f,
|
||||
new int[] { 0xFF65CDAC, 0xFF64CDAB, 0xFF60CBA8, 0xFF5BC8A3, 0xFF55C49D, 0xFF4DC096, 0xFF45BB8F, 0xFF3CB687, 0xFF33B17F, 0xFF2AAC76, 0xFF21A76F, 0xFF1AA268, 0xFF139F62, 0xFF0E9C5E, 0xFF0B9A5B, 0xFF0A995A },
|
||||
new float[] { 0.0000f, 0.0807f, 0.1554f, 0.2250f, 0.2904f, 0.3526f, 0.4125f, 0.4710f, 0.5290f, 0.5875f, 0.6474f, 0.7096f, 0.7750f, 0.8446f, 0.9193f, 1.0000f },
|
||||
0f);
|
||||
public static final ChatWallpaper GRADIENT_7 = new GradientChatWallpaper(180f,
|
||||
public static final ChatWallpaper BLISS = new GradientChatWallpaper(180f,
|
||||
new int[] { 0xFFD8E1FA, 0xFFD8E0F9, 0xFFD8DEF7, 0xFFD8DBF3, 0xFFD8D6EE, 0xFFD7D1E8, 0xFFD7CCE2, 0xFFD7C6DB, 0xFFD7BFD4, 0xFFD7B9CD, 0xFFD6B4C7, 0xFFD6AFC1, 0xFFD6AABC, 0xFFD6A7B8, 0xFFD6A5B6, 0xFFD6A4B5 },
|
||||
new float[] { 0.0000f, 0.0807f, 0.1554f, 0.2250f, 0.2904f, 0.3526f, 0.4125f, 0.4710f, 0.5290f, 0.5875f, 0.6474f, 0.7096f, 0.7750f, 0.8446f, 0.9193f, 1.0000f },
|
||||
0f);
|
||||
public static final ChatWallpaper GRADIENT_8 = new GradientChatWallpaper(180f,
|
||||
public static final ChatWallpaper SKY = new GradientChatWallpaper(180f,
|
||||
new int[] { 0xFFD8EBFD, 0xFFD7EAFD, 0xFFD5E9FD, 0xFFD2E7FD, 0xFFCDE5FD, 0xFFC8E3FD, 0xFFC3E0FD, 0xFFBDDDFC, 0xFFB7DAFC, 0xFFB2D7FC, 0xFFACD4FC, 0xFFA7D1FC, 0xFFA3CFFB, 0xFFA0CDFB, 0xFF9ECCFB, 0xFF9DCCFB },
|
||||
new float[] { 0.0000f, 0.0807f, 0.1554f, 0.2250f, 0.2904f, 0.3526f, 0.4125f, 0.4710f, 0.5290f, 0.5875f, 0.6474f, 0.7096f, 0.7750f, 0.8446f, 0.9193f, 1.0000f },
|
||||
0f);
|
||||
public static final ChatWallpaper GRADIENT_9 = new GradientChatWallpaper(192.04f,
|
||||
public static final ChatWallpaper PEACH = new GradientChatWallpaper(192f,
|
||||
new int[] { 0xFFFFE5C2, 0xFFFFE4C1, 0xFFFFE2BF, 0xFFFFDFBD, 0xFFFEDBB9, 0xFFFED6B5, 0xFFFED1B1, 0xFFFDCCAC, 0xFFFDC6A8, 0xFFFDC0A3, 0xFFFCBB9F, 0xFFFCB69B, 0xFFFCB297, 0xFFFCAF95, 0xFFFCAD93, 0xFFFCAC92 },
|
||||
new float[] { 0.0000f, 0.0807f, 0.1554f, 0.2250f, 0.2904f, 0.3526f, 0.4125f, 0.4710f, 0.5290f, 0.5875f, 0.6474f, 0.7096f, 0.7750f, 0.8446f, 0.9193f, 1.0000f },
|
||||
0f);
|
||||
@@ -107,6 +99,17 @@ final class GradientChatWallpaper implements ChatWallpaper, Parcelable {
|
||||
imageView.setImageDrawable(buildDrawable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameSource(@NonNull ChatWallpaper chatWallpaper) {
|
||||
if (this == chatWallpaper) return true;
|
||||
if (getClass() != chatWallpaper.getClass()) return false;
|
||||
GradientChatWallpaper that = (GradientChatWallpaper) chatWallpaper;
|
||||
|
||||
return Float.compare(that.degrees, degrees) == 0 &&
|
||||
Arrays.equals(colors, that.colors) &&
|
||||
Arrays.equals(positions, that.positions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Wallpaper serialize() {
|
||||
Wallpaper.LinearGradient.Builder builder = Wallpaper.LinearGradient.newBuilder();
|
||||
@@ -157,96 +160,4 @@ final class GradientChatWallpaper implements ChatWallpaper, Parcelable {
|
||||
return new GradientChatWallpaper[size];
|
||||
}
|
||||
};
|
||||
|
||||
private static final class RotatableGradientDrawable extends Drawable {
|
||||
|
||||
private final float degrees;
|
||||
private final int[] colors;
|
||||
private final float[] positions;
|
||||
|
||||
private final Rect fillRect = new Rect();
|
||||
private final Paint fillPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
|
||||
|
||||
private RotatableGradientDrawable(float degrees, int[] colors, @Nullable float[] positions) {
|
||||
this.degrees = degrees + 225f;
|
||||
this.colors = colors;
|
||||
this.positions = positions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBounds(int left, int top, int right, int bottom) {
|
||||
super.setBounds(left, top, right, bottom);
|
||||
|
||||
Point topLeft = new Point(left, top);
|
||||
Point topRight = new Point(right, top);
|
||||
Point bottomLeft = new Point(left, bottom);
|
||||
Point bottomRight = new Point(right, bottom);
|
||||
Point origin = new Point(getBounds().width() / 2, getBounds().height() / 2);
|
||||
|
||||
Point rotationTopLeft = cornerPrime(origin, topLeft, degrees);
|
||||
Point rotationTopRight = cornerPrime(origin, topRight, degrees);
|
||||
Point rotationBottomLeft = cornerPrime(origin, bottomLeft, degrees);
|
||||
Point rotationBottomRight = cornerPrime(origin, bottomRight, degrees);
|
||||
|
||||
fillRect.left = Integer.MAX_VALUE;
|
||||
fillRect.top = Integer.MAX_VALUE;
|
||||
fillRect.right = Integer.MIN_VALUE;
|
||||
fillRect.bottom = Integer.MIN_VALUE;
|
||||
|
||||
for (Point point : Arrays.asList(topLeft, topRight, bottomLeft, bottomRight, rotationTopLeft, rotationTopRight, rotationBottomLeft, rotationBottomRight)) {
|
||||
if (point.x < fillRect.left) {
|
||||
fillRect.left = point.x;
|
||||
}
|
||||
|
||||
if (point.x > fillRect.right) {
|
||||
fillRect.right = point.x;
|
||||
}
|
||||
|
||||
if (point.y < fillRect.top) {
|
||||
fillRect.top = point.y;
|
||||
}
|
||||
|
||||
if (point.y > fillRect.bottom) {
|
||||
fillRect.bottom = point.y;
|
||||
}
|
||||
}
|
||||
|
||||
fillPaint.setShader(new LinearGradient(fillRect.left, fillRect.top, fillRect.right, fillRect.bottom, colors, positions, Shader.TileMode.CLAMP));
|
||||
}
|
||||
|
||||
private static Point cornerPrime(@NonNull Point origin, @NonNull Point corner, float degrees) {
|
||||
return new Point(xPrime(origin, corner, Math.toRadians(degrees)), yPrime(origin, corner, Math.toRadians(degrees)));
|
||||
}
|
||||
|
||||
private static int xPrime(@NonNull Point origin, @NonNull Point corner, double theta) {
|
||||
return (int) Math.ceil(((corner.x - origin.x) * Math.cos(theta)) - ((corner.y - origin.y) * Math.sin(theta)) + origin.x);
|
||||
}
|
||||
|
||||
private static int yPrime(@NonNull Point origin, @NonNull Point corner, double theta) {
|
||||
return (int) Math.ceil(((corner.x - origin.x) * Math.sin(theta)) + ((corner.y - origin.y) * Math.cos(theta)) + origin.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
int save = canvas.save();
|
||||
canvas.rotate(degrees, getBounds().width() / 2f, getBounds().height() / 2f);
|
||||
canvas.drawRect(fillRect, fillPaint);
|
||||
canvas.restoreToCount(save);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
// Not supported
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
// Not supported
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.OPAQUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,20 +12,20 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.Wallpaper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
final class SingleColorChatWallpaper implements ChatWallpaper, Parcelable {
|
||||
public final class SingleColorChatWallpaper implements ChatWallpaper, Parcelable {
|
||||
|
||||
public static final ChatWallpaper SOLID_1 = new SingleColorChatWallpaper(0xFFE26983, 0f);
|
||||
public static final ChatWallpaper SOLID_2 = new SingleColorChatWallpaper(0xFFDF9171, 0f);
|
||||
public static final ChatWallpaper SOLID_3 = new SingleColorChatWallpaper(0xFF9E9887, 0f);
|
||||
public static final ChatWallpaper SOLID_4 = new SingleColorChatWallpaper(0xFF89AE8F, 0f);
|
||||
public static final ChatWallpaper SOLID_5 = new SingleColorChatWallpaper(0xFF32C7E2, 0f);
|
||||
public static final ChatWallpaper SOLID_6 = new SingleColorChatWallpaper(0xFF7C99B6, 0f);
|
||||
public static final ChatWallpaper SOLID_7 = new SingleColorChatWallpaper(0xFFC988E7, 0f);
|
||||
public static final ChatWallpaper SOLID_8 = new SingleColorChatWallpaper(0xFFE297C3, 0f);
|
||||
public static final ChatWallpaper SOLID_9 = new SingleColorChatWallpaper(0xFFA2A2AA, 0f);
|
||||
public static final ChatWallpaper SOLID_10 = new SingleColorChatWallpaper(0xFF146148, 0f);
|
||||
public static final ChatWallpaper SOLID_11 = new SingleColorChatWallpaper(0xFF403B91, 0f);
|
||||
public static final ChatWallpaper SOLID_12 = new SingleColorChatWallpaper(0xFF624249, 0f);
|
||||
public static final ChatWallpaper BLUSH = new SingleColorChatWallpaper(0xFFE26983, 0f);
|
||||
public static final ChatWallpaper COPPER = new SingleColorChatWallpaper(0xFFDF9171, 0f);
|
||||
public static final ChatWallpaper DUST = new SingleColorChatWallpaper(0xFF9E9887, 0f);
|
||||
public static final ChatWallpaper CELADON = new SingleColorChatWallpaper(0xFF89AE8F, 0f);
|
||||
public static final ChatWallpaper RAINFOREST = new SingleColorChatWallpaper(0xFF146148, 0f);
|
||||
public static final ChatWallpaper PACIFIC = new SingleColorChatWallpaper(0xFF32C7E2, 0f);
|
||||
public static final ChatWallpaper FROST = new SingleColorChatWallpaper(0xFF7C99B6, 0f);
|
||||
public static final ChatWallpaper NAVY = new SingleColorChatWallpaper(0xFF403B91, 0f);
|
||||
public static final ChatWallpaper LILAC = new SingleColorChatWallpaper(0xFFC988E7, 0f);
|
||||
public static final ChatWallpaper PINK = new SingleColorChatWallpaper(0xFFE297C3, 0f);
|
||||
public static final ChatWallpaper EGGPLANT = new SingleColorChatWallpaper(0xFF624249, 0f);
|
||||
public static final ChatWallpaper SILVER = new SingleColorChatWallpaper(0xFFA2A2AA, 0f);
|
||||
|
||||
private final @ColorInt int color;
|
||||
private final float dimLevelInDarkTheme;
|
||||
@@ -50,6 +50,15 @@ final class SingleColorChatWallpaper implements ChatWallpaper, Parcelable {
|
||||
imageView.setImageDrawable(new ColorDrawable(color));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameSource(@NonNull ChatWallpaper chatWallpaper) {
|
||||
if (this == chatWallpaper) return true;
|
||||
if (getClass() != chatWallpaper.getClass()) return false;
|
||||
SingleColorChatWallpaper that = (SingleColorChatWallpaper) chatWallpaper;
|
||||
|
||||
return color == that.color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Wallpaper serialize() {
|
||||
Wallpaper.SingleColor.Builder builder = Wallpaper.SingleColor.newBuilder();
|
||||
|
||||
@@ -15,7 +15,10 @@ import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColorsPalette;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.Wallpaper;
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
@@ -78,6 +81,15 @@ final class UriChatWallpaper implements ChatWallpaper, Parcelable {
|
||||
dest.writeFloat(dimLevelInDarkTheme);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameSource(@NonNull ChatWallpaper chatWallpaper) {
|
||||
if (this == chatWallpaper) return true;
|
||||
if (getClass() != chatWallpaper.getClass()) return false;
|
||||
UriChatWallpaper that = (UriChatWallpaper) chatWallpaper;
|
||||
|
||||
return uri.equals(that.uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -26,6 +26,7 @@ import androidx.lifecycle.ViewModelProviders;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.BaseActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerView;
|
||||
import org.thoughtcrime.securesms.imageeditor.ImageEditorView;
|
||||
import org.thoughtcrime.securesms.imageeditor.model.EditorElement;
|
||||
import org.thoughtcrime.securesms.imageeditor.model.EditorModel;
|
||||
@@ -34,10 +35,13 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.scribbles.UriGlideRenderer;
|
||||
import org.thoughtcrime.securesms.util.AsynchronousCallback;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.Projection;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaperPreviewActivity;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -84,10 +88,11 @@ public final class WallpaperCropActivity extends BaseActivity {
|
||||
viewModel = ViewModelProviders.of(this, factory).get(WallpaperCropViewModel.class);
|
||||
|
||||
imageEditor = findViewById(R.id.image_editor);
|
||||
View receivedBubble = findViewById(R.id.preview_bubble_1);
|
||||
TextView bubble2Text = findViewById(R.id.chat_wallpaper_bubble2_text);
|
||||
View setWallPaper = findViewById(R.id.preview_set_wallpaper);
|
||||
SwitchCompat blur = findViewById(R.id.preview_blur);
|
||||
View sentBubble = findViewById(R.id.preview_bubble_2);
|
||||
TextView bubble2Text = findViewById(R.id.chat_wallpaper_bubble2_text);
|
||||
View setWallPaper = findViewById(R.id.preview_set_wallpaper);
|
||||
SwitchCompat blur = findViewById(R.id.preview_blur);
|
||||
ColorizerView colorizerView = findViewById(R.id.colorizer);
|
||||
|
||||
setupImageEditor(inputImage);
|
||||
|
||||
@@ -115,9 +120,14 @@ public final class WallpaperCropActivity extends BaseActivity {
|
||||
bubble2Text.setText(R.string.WallpaperCropActivity__set_wallpaper_for_all_chats);
|
||||
} else {
|
||||
bubble2Text.setText(getString(R.string.WallpaperCropActivity__set_wallpaper_for_s, r.getDisplayName(this)));
|
||||
receivedBubble.getBackground().setColorFilter(r.getColor().toConversationColor(this), PorterDuff.Mode.SRC_IN);
|
||||
sentBubble.getBackground().setColorFilter(r.getChatColors().getChatBubbleColorFilter());
|
||||
colorizerView.setBackground(r.getChatColors().getChatBubbleMask());
|
||||
}
|
||||
});
|
||||
|
||||
sentBubble.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
|
||||
colorizerView.setProjections(Collections.singletonList(Projection.relativeToViewWithCommonRoot(sentBubble, colorizerView, new Projection.Corners(ViewUtil.dpToPx(18)))));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user