Update chat colors.

This commit is contained in:
Alex Hart
2021-05-03 11:34:41 -03:00
committed by Greyson Parrelli
parent 36fe150678
commit bcc5d485ab
164 changed files with 5817 additions and 1476 deletions

View File

@@ -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);
}
}
}

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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();
});
}
}
}

View File

@@ -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));
}
}

View File

@@ -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());

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -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