Improve conversation update message stylings.

This commit is contained in:
Greyson Parrelli 2020-10-22 10:59:23 -04:00 committed by Cody Henthorne
parent 90f20c36c5
commit 9c97cd8816
53 changed files with 757 additions and 369 deletions

View file

@ -1,23 +1,18 @@
package org.thoughtcrime.securesms.conversation;
import android.content.Context;
import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.text.Spannable;
import android.text.SpannableString;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.Transformations;
import org.thoughtcrime.securesms.BindableConversationItem;
import org.thoughtcrime.securesms.R;
@ -30,10 +25,7 @@ import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.whispersystems.libsignal.util.guava.Optional;
@ -50,15 +42,12 @@ public final class ConversationUpdateItem extends LinearLayout
private Set<ConversationMessage> batchSelected;
private ImageView icon;
private TextView title;
private TextView body;
private TextView date;
private LiveRecipient sender;
private ConversationMessage conversationMessage;
private MessageRecord messageRecord;
private Locale locale;
private LiveData<SpannableString> displayBody;
private LiveData<Spannable> displayBody;
private final UpdateObserver updateObserver = new UpdateObserver();
private final SenderObserver senderObserver = new SenderObserver();
@ -74,11 +63,7 @@ public final class ConversationUpdateItem extends LinearLayout
@Override
public void onFinishInflate() {
super.onFinishInflate();
this.icon = findViewById(R.id.conversation_update_icon);
this.title = findViewById(R.id.conversation_update_title);
this.body = findViewById(R.id.conversation_update_body);
this.date = findViewById(R.id.conversation_update_date);
this.body = findViewById(R.id.conversation_update_body);
this.setOnClickListener(new InternalClickListener(null));
}
@ -117,22 +102,18 @@ public final class ConversationUpdateItem extends LinearLayout
observeSender(lifecycleOwner, messageRecord.getIndividualRecipient());
UpdateDescription updateDescription = Objects.requireNonNull(messageRecord.getUpdateDisplayBody(getContext()));
LiveData<String> liveUpdateMessage = LiveUpdateMessage.fromMessageDescription(updateDescription);
LiveData<SpannableString> spannableStringMessage = toSpannable(loading(liveUpdateMessage));
UpdateDescription updateDescription = Objects.requireNonNull(messageRecord.getUpdateDisplayBody(getContext()));
LiveData<Spannable> liveUpdateMessage = LiveUpdateMessage.fromMessageDescription(getContext(), updateDescription);
LiveData<Spannable> spannableMessage = loading(liveUpdateMessage);
present(conversationMessage);
observeDisplayBody(lifecycleOwner, spannableStringMessage);
observeDisplayBody(lifecycleOwner, spannableMessage);
}
/** After a short delay, if the main data hasn't shown yet, then a loading message is displayed. */
private @NonNull LiveData<String> loading(@NonNull LiveData<String> string) {
return LiveDataUtil.until(string, LiveDataUtil.delay(250, getContext().getString(R.string.ConversationUpdateItem_loading)));
}
private static LiveData<SpannableString> toSpannable(LiveData<String> loading) {
return Transformations.map(loading, source -> source == null ? null : new SpannableString(source));
private @NonNull LiveData<Spannable> loading(@NonNull LiveData<Spannable> string) {
return LiveDataUtil.until(string, LiveDataUtil.delay(250, new SpannableString(getContext().getString(R.string.ConversationUpdateItem_loading))));
}
@Override
@ -152,7 +133,7 @@ public final class ConversationUpdateItem extends LinearLayout
}
}
private void observeDisplayBody(@NonNull LifecycleOwner lifecycleOwner, @Nullable LiveData<SpannableString> displayBody) {
private void observeDisplayBody(@NonNull LifecycleOwner lifecycleOwner, @Nullable LiveData<Spannable> displayBody) {
if (this.displayBody != displayBody) {
if (this.displayBody != null) {
this.displayBody.removeObserver(updateObserver);
@ -176,98 +157,10 @@ public final class ConversationUpdateItem extends LinearLayout
}
private void present(ConversationMessage conversationMessage) {
MessageRecord messageRecord = conversationMessage.getMessageRecord();
if (messageRecord.isGroupAction()) setGroupRecord();
else if (messageRecord.isCallLog()) setCallRecord(messageRecord);
else if (messageRecord.isJoined()) setJoinedRecord();
else if (messageRecord.isExpirationTimerUpdate()) setTimerRecord(messageRecord);
else if (messageRecord.isEndSession()) setEndSessionRecord();
else if (messageRecord.isIdentityUpdate()) setIdentityRecord();
else if (messageRecord.isIdentityVerified() ||
messageRecord.isIdentityDefault()) setIdentityVerifyUpdate(messageRecord);
else if (messageRecord.isProfileChange()) setProfileNameChangeRecord();
else throw new AssertionError("Neither group nor log nor joined.");
if (batchSelected.contains(conversationMessage)) setSelected(true);
else setSelected(false);
}
private void setCallRecord(MessageRecord messageRecord) {
if (messageRecord.isIncomingCall()) icon.setImageResource(R.drawable.ic_call_received_grey600_24dp);
else if (messageRecord.isOutgoingCall()) icon.setImageResource(R.drawable.ic_call_made_grey600_24dp);
else icon.setImageResource(R.drawable.ic_call_missed_grey600_24dp);
date.setText(DateUtils.getExtendedRelativeTimeSpanString(getContext(), locale, messageRecord.getDateSent()));
title.setVisibility(GONE);
date.setVisibility(View.VISIBLE);
}
private void setTimerRecord(final MessageRecord messageRecord) {
if (messageRecord.getExpiresIn() > 0) {
icon.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.ic_timer_24));
} else {
icon.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.ic_timer_disabled_24));
}
icon.setColorFilter(getIconTintFilter());
title.setText(ExpirationUtil.getExpirationDisplayValue(getContext(), (int)(messageRecord.getExpiresIn() / 1000)));
title.setVisibility(VISIBLE);
date.setVisibility(GONE);
}
private ColorFilter getIconTintFilter() {
return new PorterDuffColorFilter(ThemeUtil.getThemedColor(getContext(), R.attr.icon_tint), PorterDuff.Mode.SRC_IN);
}
private void setIdentityRecord() {
icon.setImageDrawable(ThemeUtil.getThemedDrawable(getContext(), R.attr.safety_number_icon));
icon.setColorFilter(getIconTintFilter());
title.setVisibility(GONE);
date.setVisibility(GONE);
}
private void setIdentityVerifyUpdate(final MessageRecord messageRecord) {
if (messageRecord.isIdentityVerified()) icon.setImageResource(R.drawable.ic_check_white_24dp);
else icon.setImageResource(R.drawable.ic_info_outline_white_24);
icon.setColorFilter(getIconTintFilter());
title.setVisibility(GONE);
date.setVisibility(GONE);
}
private void setProfileNameChangeRecord() {
icon.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.ic_profile_outline_20));
icon.setColorFilter(getIconTintFilter());
title.setVisibility(GONE);
date.setVisibility(GONE);
}
private void setGroupRecord() {
icon.setImageDrawable(ThemeUtil.getThemedDrawable(getContext(), R.attr.menu_group_icon));
icon.clearColorFilter();
title.setVisibility(GONE);
date.setVisibility(GONE);
}
private void setJoinedRecord() {
icon.setImageResource(R.drawable.ic_favorite_grey600_24dp);
icon.clearColorFilter();
title.setVisibility(GONE);
date.setVisibility(GONE);
}
private void setEndSessionRecord() {
icon.setImageResource(R.drawable.ic_refresh_white_24dp);
icon.setColorFilter(getIconTintFilter());
}
@Override
public void setOnClickListener(View.OnClickListener l) {
super.setOnClickListener(new InternalClickListener(l));
@ -281,10 +174,10 @@ public final class ConversationUpdateItem extends LinearLayout
}
}
private final class UpdateObserver implements Observer<SpannableString> {
private final class UpdateObserver implements Observer<Spannable> {
@Override
public void onChanged(SpannableString update) {
public void onChanged(Spannable update) {
setBodyText(update);
}
}

View file

@ -29,6 +29,7 @@ import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
@ -423,65 +424,65 @@ public final class ConversationListItem extends RelativeLayout
private static @NonNull LiveData<SpannableString> getThreadDisplayBody(@NonNull Context context, @NonNull ThreadRecord thread) {
if (!thread.isMessageRequestAccepted()) {
return emphasisAdded(context.getString(R.string.ThreadRecord_message_request));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_message_request));
} else if (SmsDatabase.Types.isGroupUpdate(thread.getType())) {
if (thread.getRecipient().isPushV2Group()) {
return emphasisAdded(MessageRecord.getGv2ChangeDescription(context, thread.getBody()));
return emphasisAdded(context, MessageRecord.getGv2ChangeDescription(context, thread.getBody()));
} else {
return emphasisAdded(context.getString(R.string.ThreadRecord_group_updated));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_group_updated));
}
} else if (SmsDatabase.Types.isGroupQuit(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_left_the_group));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_left_the_group));
} else if (SmsDatabase.Types.isKeyExchangeType(thread.getType())) {
return emphasisAdded(context.getString(R.string.ConversationListItem_key_exchange_message));
return emphasisAdded(context, context.getString(R.string.ConversationListItem_key_exchange_message));
} else if (SmsDatabase.Types.isFailedDecryptType(thread.getType())) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_bad_encrypted_message));
return emphasisAdded(context, context.getString(R.string.MessageDisplayHelper_bad_encrypted_message));
} else if (SmsDatabase.Types.isNoRemoteSessionType(thread.getType())) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
return emphasisAdded(context, context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
} else if (SmsDatabase.Types.isEndSessionType(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_secure_session_reset));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_secure_session_reset));
} else if (MmsSmsColumns.Types.isLegacyType(thread.getType())) {
return emphasisAdded(context.getString(R.string.MessageRecord_message_encrypted_with_a_legacy_protocol_version_that_is_no_longer_supported));
return emphasisAdded(context, context.getString(R.string.MessageRecord_message_encrypted_with_a_legacy_protocol_version_that_is_no_longer_supported));
} else if (MmsSmsColumns.Types.isDraftMessageType(thread.getType())) {
String draftText = context.getString(R.string.ThreadRecord_draft);
return emphasisAdded(draftText + " " + thread.getBody());
return emphasisAdded(context, draftText + " " + thread.getBody());
} else if (SmsDatabase.Types.isOutgoingCall(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_called));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_called));
} else if (SmsDatabase.Types.isIncomingCall(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_called_you));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_called_you));
} else if (SmsDatabase.Types.isMissedCall(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_missed_call));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_missed_call));
} else if (SmsDatabase.Types.isJoinedType(thread.getType())) {
return emphasisAdded(recipientToStringAsync(thread.getRecipient().getId(), r -> context.getString(R.string.ThreadRecord_s_is_on_signal, r.getDisplayName(context))));
return emphasisAdded(recipientToStringAsync(thread.getRecipient().getId(), r -> new SpannableString(context.getString(R.string.ThreadRecord_s_is_on_signal, r.getDisplayName(context)))));
} else if (SmsDatabase.Types.isExpirationTimerUpdate(thread.getType())) {
int seconds = (int)(thread.getExpiresIn() / 1000);
if (seconds <= 0) {
return emphasisAdded(context.getString(R.string.ThreadRecord_disappearing_messages_disabled));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_disappearing_messages_disabled));
}
String time = ExpirationUtil.getExpirationDisplayValue(context, seconds);
return emphasisAdded(context.getString(R.string.ThreadRecord_disappearing_message_time_updated_to_s, time));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_disappearing_message_time_updated_to_s, time));
} else if (SmsDatabase.Types.isIdentityUpdate(thread.getType())) {
return emphasisAdded(recipientToStringAsync(thread.getRecipient().getId(), r -> {
if (r.isGroup()) {
return context.getString(R.string.ThreadRecord_safety_number_changed);
return new SpannableString(context.getString(R.string.ThreadRecord_safety_number_changed));
} else {
return context.getString(R.string.ThreadRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context));
return new SpannableString(context.getString(R.string.ThreadRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)));
}
}));
} else if (SmsDatabase.Types.isIdentityVerified(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_you_marked_verified));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_you_marked_verified));
} else if (SmsDatabase.Types.isIdentityDefault(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_you_marked_unverified));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_you_marked_unverified));
} else if (SmsDatabase.Types.isUnsupportedMessageType(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_message_could_not_be_processed));
return emphasisAdded(context, context.getString(R.string.ThreadRecord_message_could_not_be_processed));
} else if (SmsDatabase.Types.isProfileChange(thread.getType())) {
return emphasisAdded("");
return emphasisAdded(context, "");
} else {
ThreadDatabase.Extra extra = thread.getExtra();
if (extra != null && extra.isViewOnce()) {
return emphasisAdded(getViewOnceDescription(context, thread.getContentType()));
return emphasisAdded(context, getViewOnceDescription(context, thread.getContentType()));
} else if (extra != null && extra.isRemoteDelete()) {
return emphasisAdded(context.getString(thread.isOutgoing() ? R.string.ThreadRecord_you_deleted_this_message : R.string.ThreadRecord_this_message_was_deleted));
return emphasisAdded(context, context.getString(thread.isOutgoing() ? R.string.ThreadRecord_you_deleted_this_message : R.string.ThreadRecord_this_message_was_deleted));
} else {
return LiveDataUtil.just(new SpannableString(removeNewlines(thread.getBody())));
}
@ -500,15 +501,15 @@ public final class ConversationListItem extends RelativeLayout
}
}
private static @NonNull LiveData<SpannableString> emphasisAdded(@NonNull String string) {
return emphasisAdded(UpdateDescription.staticDescription(string));
private static @NonNull LiveData<SpannableString> emphasisAdded(@NonNull Context context, @NonNull String string) {
return emphasisAdded(context, UpdateDescription.staticDescription(string, 0, 0));
}
private static @NonNull LiveData<SpannableString> emphasisAdded(@NonNull UpdateDescription description) {
return emphasisAdded(LiveUpdateMessage.fromMessageDescription(description));
private static @NonNull LiveData<SpannableString> emphasisAdded(@NonNull Context context, @NonNull UpdateDescription description) {
return emphasisAdded(LiveUpdateMessage.fromMessageDescription(context, description));
}
private static @NonNull LiveData<SpannableString> emphasisAdded(@NonNull LiveData<String> description) {
private static @NonNull LiveData<SpannableString> emphasisAdded(@NonNull LiveData<Spannable> description) {
return Transformations.map(description, sequence -> {
SpannableString spannable = new SpannableString(sequence);
spannable.setSpan(new StyleSpan(Typeface.ITALIC),

View file

@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@ -63,22 +64,22 @@ final class GroupsV2UpdateMessageProducer {
UpdateDescription describeNewGroup(@NonNull DecryptedGroup group, @NonNull DecryptedGroupChange decryptedGroupChange) {
Optional<DecryptedPendingMember> selfPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfUuid);
if (selfPending.isPresent()) {
return updateDescription(selfPending.get().getAddedByUuid(), inviteBy -> context.getString(R.string.MessageRecord_s_invited_you_to_the_group, inviteBy));
return updateDescription(selfPending.get().getAddedByUuid(), inviteBy -> context.getString(R.string.MessageRecord_s_invited_you_to_the_group, inviteBy), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16);
}
ByteString foundingMemberUuid = decryptedGroupChange.getEditor();
if (!foundingMemberUuid.isEmpty()) {
if (selfUuidBytes.equals(foundingMemberUuid)) {
return updateDescription(context.getString(R.string.MessageRecord_you_created_the_group));
return updateDescription(context.getString(R.string.MessageRecord_you_created_the_group), R.drawable.ic_update_group_light_16, R.drawable.ic_update_group_dark_16);
} else {
return updateDescription(foundingMemberUuid, creator -> context.getString(R.string.MessageRecord_s_added_you, creator));
return updateDescription(foundingMemberUuid, creator -> context.getString(R.string.MessageRecord_s_added_you, creator), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16);
}
}
if (DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfUuid).isPresent()) {
return updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group));
return updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16);
} else {
return updateDescription(context.getString(R.string.MessageRecord_group_updated));
return updateDescription(context.getString(R.string.MessageRecord_group_updated), R.drawable.ic_update_group_light_16, R.drawable.ic_update_group_dark_16);
}
}
@ -146,14 +147,14 @@ final class GroupsV2UpdateMessageProducer {
boolean editorIsYou = change.getEditor().equals(selfUuidBytes);
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_updated_group)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_updated_group), R.drawable.ic_update_group_light_16, R.drawable.ic_update_group_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), (editor) -> context.getString(R.string.MessageRecord_s_updated_group, editor)));
updates.add(updateDescription(change.getEditor(), (editor) -> context.getString(R.string.MessageRecord_s_updated_group, editor), R.drawable.ic_update_group_light_16, R.drawable.ic_update_group_dark_16));
}
}
private void describeUnknownEditorUnknownChange(@NonNull List<UpdateDescription> updates) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_was_updated)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_was_updated), R.drawable.ic_update_group_light_16, R.drawable.ic_update_group_dark_16));
}
private void describeMemberAdditions(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
@ -164,18 +165,18 @@ final class GroupsV2UpdateMessageProducer {
if (editorIsYou) {
if (newMemberIsYou) {
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group_via_the_group_link)));
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group_via_the_group_link), R.drawable.ic_update_group_accept_light_16, R.drawable.ic_update_group_accept_dark_16));
} else {
updates.add(updateDescription(member.getUuid(), added -> context.getString(R.string.MessageRecord_you_added_s, added)));
updates.add(updateDescription(member.getUuid(), added -> context.getString(R.string.MessageRecord_you_added_s, added), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
}
} else {
if (newMemberIsYou) {
updates.add(0, updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_added_you, editor)));
updates.add(0, updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_added_you, editor), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
} else {
if (member.getUuid().equals(change.getEditor())) {
updates.add(updateDescription(member.getUuid(), newMember -> context.getString(R.string.MessageRecord_s_joined_the_group_via_the_group_link, newMember)));
updates.add(updateDescription(member.getUuid(), newMember -> context.getString(R.string.MessageRecord_s_joined_the_group_via_the_group_link, newMember), R.drawable.ic_update_group_accept_light_16, R.drawable.ic_update_group_accept_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), member.getUuid(), (editor, newMember) -> context.getString(R.string.MessageRecord_s_added_s, editor, newMember)));
updates.add(updateDescription(change.getEditor(), member.getUuid(), (editor, newMember) -> context.getString(R.string.MessageRecord_s_added_s, editor, newMember), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
}
}
}
@ -187,9 +188,9 @@ final class GroupsV2UpdateMessageProducer {
boolean newMemberIsYou = member.getUuid().equals(selfUuidBytes);
if (newMemberIsYou) {
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group)));
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
} else {
updates.add(updateDescription(member.getUuid(), newMember -> context.getString(R.string.MessageRecord_s_joined_the_group, newMember)));
updates.add(updateDescription(member.getUuid(), newMember -> context.getString(R.string.MessageRecord_s_joined_the_group, newMember), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
}
}
}
@ -202,18 +203,18 @@ final class GroupsV2UpdateMessageProducer {
if (editorIsYou) {
if (removedMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_left_the_group)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_left_the_group), R.drawable.ic_update_group_leave_light_16, R.drawable.ic_update_group_leave_dark_16));
} else {
updates.add(updateDescription(member, removedMember -> context.getString(R.string.MessageRecord_you_removed_s, removedMember)));
updates.add(updateDescription(member, removedMember -> context.getString(R.string.MessageRecord_you_removed_s, removedMember), R.drawable.ic_update_group_remove_light_16, R.drawable.ic_update_group_remove_dark_16));
}
} else {
if (removedMemberIsYou) {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_removed_you_from_the_group, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_removed_you_from_the_group, editor), R.drawable.ic_update_group_remove_light_16, R.drawable.ic_update_group_remove_dark_16));
} else {
if (member.equals(change.getEditor())) {
updates.add(updateDescription(member, leavingMember -> context.getString(R.string.MessageRecord_s_left_the_group, leavingMember)));
updates.add(updateDescription(member, leavingMember -> context.getString(R.string.MessageRecord_s_left_the_group, leavingMember), R.drawable.ic_update_group_leave_light_16, R.drawable.ic_update_group_leave_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), member, (editor, removedMember) -> context.getString(R.string.MessageRecord_s_removed_s, editor, removedMember)));
updates.add(updateDescription(change.getEditor(), member, (editor, removedMember) -> context.getString(R.string.MessageRecord_s_removed_s, editor, removedMember), R.drawable.ic_update_group_remove_light_16, R.drawable.ic_update_group_remove_dark_16));
}
}
}
@ -225,9 +226,9 @@ final class GroupsV2UpdateMessageProducer {
boolean removedMemberIsYou = member.equals(selfUuidBytes);
if (removedMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_no_longer_in_the_group)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_no_longer_in_the_group), R.drawable.ic_update_group_leave_light_16, R.drawable.ic_update_group_leave_dark_16));
} else {
updates.add(updateDescription(member, oldMember -> context.getString(R.string.MessageRecord_s_is_no_longer_in_the_group, oldMember)));
updates.add(updateDescription(member, oldMember -> context.getString(R.string.MessageRecord_s_is_no_longer_in_the_group, oldMember), R.drawable.ic_update_group_leave_light_16, R.drawable.ic_update_group_leave_dark_16));
}
}
}
@ -239,23 +240,23 @@ final class GroupsV2UpdateMessageProducer {
boolean changedMemberIsYou = roleChange.getUuid().equals(selfUuidBytes);
if (roleChange.getRole() == Member.Role.ADMINISTRATOR) {
if (editorIsYou) {
updates.add(updateDescription(roleChange.getUuid(), newAdmin -> context.getString(R.string.MessageRecord_you_made_s_an_admin, newAdmin)));
updates.add(updateDescription(roleChange.getUuid(), newAdmin -> context.getString(R.string.MessageRecord_you_made_s_an_admin, newAdmin), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
if (changedMemberIsYou) {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_made_you_an_admin, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_made_you_an_admin, editor), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), roleChange.getUuid(), (editor, newAdmin) -> context.getString(R.string.MessageRecord_s_made_s_an_admin, editor, newAdmin)));
updates.add(updateDescription(change.getEditor(), roleChange.getUuid(), (editor, newAdmin) -> context.getString(R.string.MessageRecord_s_made_s_an_admin, editor, newAdmin), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
} else {
if (editorIsYou) {
updates.add(updateDescription(roleChange.getUuid(), oldAdmin -> context.getString(R.string.MessageRecord_you_revoked_admin_privileges_from_s, oldAdmin)));
updates.add(updateDescription(roleChange.getUuid(), oldAdmin -> context.getString(R.string.MessageRecord_you_revoked_admin_privileges_from_s, oldAdmin), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
if (changedMemberIsYou) {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_revoked_your_admin_privileges, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_revoked_your_admin_privileges, editor), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), roleChange.getUuid(), (editor, oldAdmin) -> context.getString(R.string.MessageRecord_s_revoked_admin_privileges_from_s, editor, oldAdmin)));
updates.add(updateDescription(change.getEditor(), roleChange.getUuid(), (editor, oldAdmin) -> context.getString(R.string.MessageRecord_s_revoked_admin_privileges_from_s, editor, oldAdmin), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
}
@ -268,15 +269,15 @@ final class GroupsV2UpdateMessageProducer {
if (roleChange.getRole() == Member.Role.ADMINISTRATOR) {
if (changedMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_now_an_admin)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_now_an_admin), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(roleChange.getUuid(), newAdmin -> context.getString(R.string.MessageRecord_s_is_now_an_admin, newAdmin)));
updates.add(updateDescription(roleChange.getUuid(), newAdmin -> context.getString(R.string.MessageRecord_s_is_now_an_admin, newAdmin), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
} else {
if (changedMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_no_longer_an_admin)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_no_longer_an_admin), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(roleChange.getUuid(), oldAdmin -> context.getString(R.string.MessageRecord_s_is_no_longer_an_admin, oldAdmin)));
updates.add(updateDescription(roleChange.getUuid(), oldAdmin -> context.getString(R.string.MessageRecord_s_is_no_longer_an_admin, oldAdmin), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
}
@ -290,10 +291,10 @@ final class GroupsV2UpdateMessageProducer {
boolean newMemberIsYou = invitee.getUuid().equals(selfUuidBytes);
if (newMemberIsYou) {
updates.add(0, updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_invited_you_to_the_group, editor)));
updates.add(0, updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_invited_you_to_the_group, editor), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
} else {
if (editorIsYou) {
updates.add(updateDescription(invitee.getUuid(), newInvitee -> context.getString(R.string.MessageRecord_you_invited_s_to_the_group, newInvitee)));
updates.add(updateDescription(invitee.getUuid(), newInvitee -> context.getString(R.string.MessageRecord_you_invited_s_to_the_group, newInvitee), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
} else {
notYouInviteCount++;
}
@ -302,7 +303,7 @@ final class GroupsV2UpdateMessageProducer {
if (notYouInviteCount > 0) {
final int notYouInviteCountFinalCopy = notYouInviteCount;
updates.add(updateDescription(change.getEditor(), editor -> context.getResources().getQuantityString(R.plurals.MessageRecord_s_invited_members, notYouInviteCountFinalCopy, editor, notYouInviteCountFinalCopy)));
updates.add(updateDescription(change.getEditor(), editor -> context.getResources().getQuantityString(R.plurals.MessageRecord_s_invited_members, notYouInviteCountFinalCopy, editor, notYouInviteCountFinalCopy), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
}
}
@ -316,9 +317,9 @@ final class GroupsV2UpdateMessageProducer {
UUID uuid = UuidUtil.fromByteStringOrUnknown(invitee.getAddedByUuid());
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_were_invited_to_the_group)));
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_were_invited_to_the_group), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
} else {
updates.add(0, updateDescription(invitee.getAddedByUuid(), editor -> context.getString(R.string.MessageRecord_s_invited_you_to_the_group, editor)));
updates.add(0, updateDescription(invitee.getAddedByUuid(), editor -> context.getString(R.string.MessageRecord_s_invited_you_to_the_group, editor), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
}
} else {
notYouInviteCount++;
@ -326,7 +327,7 @@ final class GroupsV2UpdateMessageProducer {
}
if (notYouInviteCount > 0) {
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_d_people_were_invited_to_the_group, notYouInviteCount, notYouInviteCount)));
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_d_people_were_invited_to_the_group, notYouInviteCount, notYouInviteCount), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
}
}
@ -338,12 +339,12 @@ final class GroupsV2UpdateMessageProducer {
boolean decline = invitee.getUuid().equals(change.getEditor());
if (decline) {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_declined_the_invitation_to_the_group)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_declined_the_invitation_to_the_group), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
} else {
updates.add(updateDescription(context.getString(R.string.MessageRecord_someone_declined_an_invitation_to_the_group)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_someone_declined_an_invitation_to_the_group), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
}
} else if (invitee.getUuid().equals(selfUuidBytes)) {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_revoked_your_invitation_to_the_group, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_revoked_your_invitation_to_the_group, editor), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
} else {
notDeclineCount++;
}
@ -351,10 +352,10 @@ final class GroupsV2UpdateMessageProducer {
if (notDeclineCount > 0) {
if (editorIsYou) {
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_you_revoked_invites, notDeclineCount, notDeclineCount)));
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_you_revoked_invites, notDeclineCount, notDeclineCount), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
} else {
final int notDeclineCountFinalCopy = notDeclineCount;
updates.add(updateDescription(change.getEditor(), editor -> context.getResources().getQuantityString(R.plurals.MessageRecord_s_revoked_invites, notDeclineCountFinalCopy, editor, notDeclineCountFinalCopy)));
updates.add(updateDescription(change.getEditor(), editor -> context.getResources().getQuantityString(R.plurals.MessageRecord_s_revoked_invites, notDeclineCountFinalCopy, editor, notDeclineCountFinalCopy), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
}
}
}
@ -366,14 +367,14 @@ final class GroupsV2UpdateMessageProducer {
boolean inviteeWasYou = invitee.getUuid().equals(selfUuidBytes);
if (inviteeWasYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_an_admin_revoked_your_invitation_to_the_group)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_an_admin_revoked_your_invitation_to_the_group), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
} else {
notDeclineCount++;
}
}
if (notDeclineCount > 0) {
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_d_invitations_were_revoked, notDeclineCount, notDeclineCount)));
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_d_invitations_were_revoked, notDeclineCount, notDeclineCount), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
}
}
@ -386,18 +387,18 @@ final class GroupsV2UpdateMessageProducer {
if (editorIsYou) {
if (newMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_accepted_invite)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_accepted_invite), R.drawable.ic_update_group_accept_light_16, R.drawable.ic_update_group_accept_dark_16));
} else {
updates.add(updateDescription(uuid, newPromotedMember -> context.getString(R.string.MessageRecord_you_added_invited_member_s, newPromotedMember)));
updates.add(updateDescription(uuid, newPromotedMember -> context.getString(R.string.MessageRecord_you_added_invited_member_s, newPromotedMember), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
}
} else {
if (newMemberIsYou) {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_added_you, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_added_you, editor), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_light_16));
} else {
if (uuid.equals(change.getEditor())) {
updates.add(updateDescription(uuid, newAcceptedMember -> context.getString(R.string.MessageRecord_s_accepted_invite, newAcceptedMember)));
updates.add(updateDescription(uuid, newAcceptedMember -> context.getString(R.string.MessageRecord_s_accepted_invite, newAcceptedMember), R.drawable.ic_update_group_accept_light_16, R.drawable.ic_update_group_accept_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), uuid, (editor, newAcceptedMember) -> context.getString(R.string.MessageRecord_s_added_invited_member_s, editor, newAcceptedMember)));
updates.add(updateDescription(change.getEditor(), uuid, (editor, newAcceptedMember) -> context.getString(R.string.MessageRecord_s_added_invited_member_s, editor, newAcceptedMember), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
}
}
}
@ -410,9 +411,9 @@ final class GroupsV2UpdateMessageProducer {
boolean newMemberIsYou = uuid.equals(selfUuidBytes);
if (newMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
} else {
updates.add(updateDescription(uuid, newMemberName -> context.getString(R.string.MessageRecord_s_joined_the_group, newMemberName)));
updates.add(updateDescription(uuid, newMemberName -> context.getString(R.string.MessageRecord_s_joined_the_group, newMemberName), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16));
}
}
}
@ -423,16 +424,16 @@ final class GroupsV2UpdateMessageProducer {
if (change.hasNewTitle()) {
String newTitle = StringUtil.isolateBidi(change.getNewTitle().getValue());
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_name_to_s, newTitle)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_name_to_s, newTitle), R.drawable.ic_update_group_name_light_16, R.drawable.ic_update_group_name_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_changed_the_group_name_to_s, editor, newTitle)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_changed_the_group_name_to_s, editor, newTitle), R.drawable.ic_update_group_name_light_16, R.drawable.ic_update_group_name_dark_16));
}
}
}
private void describeUnknownEditorNewTitle(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
if (change.hasNewTitle()) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_name_has_changed_to_s, StringUtil.isolateBidi(change.getNewTitle().getValue()))));
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_name_has_changed_to_s, StringUtil.isolateBidi(change.getNewTitle().getValue())), R.drawable.ic_update_group_name_light_16, R.drawable.ic_update_group_name_dark_16));
}
}
@ -441,16 +442,16 @@ final class GroupsV2UpdateMessageProducer {
if (change.hasNewAvatar()) {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_avatar)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_avatar), R.drawable.ic_update_group_avatar_light_16, R.drawable.ic_update_group_avatar_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_changed_the_group_avatar, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_changed_the_group_avatar, editor), R.drawable.ic_update_group_avatar_light_16, R.drawable.ic_update_group_avatar_dark_16));
}
}
}
private void describeUnknownEditorNewAvatar(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
if (change.hasNewAvatar()) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_group_avatar_has_been_changed)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_group_avatar_has_been_changed), R.drawable.ic_update_group_avatar_light_16, R.drawable.ic_update_group_avatar_dark_16));
}
}
@ -460,9 +461,9 @@ final class GroupsV2UpdateMessageProducer {
if (change.hasNewTimer()) {
String time = ExpirationUtil.getExpirationDisplayValue(context, change.getNewTimer().getDuration());
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time), R.drawable.ic_update_timer_light_16, R.drawable.ic_update_timer_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, editor, time)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, editor, time), R.drawable.ic_update_timer_light_16, R.drawable.ic_update_timer_dark_16));
}
}
}
@ -470,7 +471,7 @@ final class GroupsV2UpdateMessageProducer {
private void describeUnknownEditorNewTimer(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
if (change.hasNewTimer()) {
String time = ExpirationUtil.getExpirationDisplayValue(context, change.getNewTimer().getDuration());
updates.add(updateDescription(context.getString(R.string.MessageRecord_disappearing_message_time_set_to_s, time)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_disappearing_message_time_set_to_s, time), R.drawable.ic_update_timer_light_16, R.drawable.ic_update_timer_dark_16));
}
}
@ -480,9 +481,9 @@ final class GroupsV2UpdateMessageProducer {
if (change.getNewAttributeAccess() != AccessControl.AccessRequired.UNKNOWN) {
String accessLevel = GV2AccessLevelUtil.toString(context, change.getNewAttributeAccess());
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_who_can_edit_group_info_to_s, accessLevel)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_who_can_edit_group_info_to_s, accessLevel), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_changed_who_can_edit_group_info_to_s, editor, accessLevel)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_changed_who_can_edit_group_info_to_s, editor, accessLevel), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
}
@ -490,7 +491,7 @@ final class GroupsV2UpdateMessageProducer {
private void describeUnknownEditorNewAttributeAccess(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
if (change.getNewAttributeAccess() != AccessControl.AccessRequired.UNKNOWN) {
String accessLevel = GV2AccessLevelUtil.toString(context, change.getNewAttributeAccess());
updates.add(updateDescription(context.getString(R.string.MessageRecord_who_can_edit_group_info_has_been_changed_to_s, accessLevel)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_who_can_edit_group_info_has_been_changed_to_s, accessLevel), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
@ -500,9 +501,9 @@ final class GroupsV2UpdateMessageProducer {
if (change.getNewMemberAccess() != AccessControl.AccessRequired.UNKNOWN) {
String accessLevel = GV2AccessLevelUtil.toString(context, change.getNewMemberAccess());
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_who_can_edit_group_membership_to_s, accessLevel)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_who_can_edit_group_membership_to_s, accessLevel), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_changed_who_can_edit_group_membership_to_s, editor, accessLevel)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_changed_who_can_edit_group_membership_to_s, editor, accessLevel), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
}
@ -510,7 +511,7 @@ final class GroupsV2UpdateMessageProducer {
private void describeUnknownEditorNewMembershipAccess(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
if (change.getNewMemberAccess() != AccessControl.AccessRequired.UNKNOWN) {
String accessLevel = GV2AccessLevelUtil.toString(context, change.getNewMemberAccess());
updates.add(updateDescription(context.getString(R.string.MessageRecord_who_can_edit_group_membership_has_been_changed_to_s, accessLevel)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_who_can_edit_group_membership_has_been_changed_to_s, accessLevel), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
@ -532,15 +533,15 @@ final class GroupsV2UpdateMessageProducer {
groupLinkEnabled = true;
if (editorIsYou) {
if (previousAccessControl == AccessControl.AccessRequired.ADMINISTRATOR) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_off_admin_approval_for_the_group_link)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_off_admin_approval_for_the_group_link), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_on_the_group_link_with_admin_approval_off)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_on_the_group_link_with_admin_approval_off), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
} else {
if (previousAccessControl == AccessControl.AccessRequired.ADMINISTRATOR) {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_turned_off_admin_approval_for_the_group_link, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_turned_off_admin_approval_for_the_group_link, editor), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_turned_on_the_group_link_with_admin_approval_off, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_turned_on_the_group_link_with_admin_approval_off, editor), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
break;
@ -548,32 +549,32 @@ final class GroupsV2UpdateMessageProducer {
groupLinkEnabled = true;
if (editorIsYou) {
if (previousAccessControl == AccessControl.AccessRequired.ANY) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_on_admin_approval_for_the_group_link)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_on_admin_approval_for_the_group_link), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_on_the_group_link_with_admin_approval_on)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_on_the_group_link_with_admin_approval_on), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
} else {
if (previousAccessControl == AccessControl.AccessRequired.ANY) {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_turned_on_admin_approval_for_the_group_link, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_turned_on_admin_approval_for_the_group_link, editor), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_turned_on_the_group_link_with_admin_approval_on, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_turned_on_the_group_link_with_admin_approval_on, editor), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
break;
case UNSATISFIABLE:
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_off_the_group_link)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_off_the_group_link), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_turned_off_the_group_link, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_turned_off_the_group_link, editor), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
break;
}
if (!groupLinkEnabled && change.getNewInviteLinkPassword().size() > 0) {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_reset_the_group_link)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_reset_the_group_link), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_reset_the_group_link, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_reset_the_group_link, editor), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
}
@ -591,25 +592,25 @@ final class GroupsV2UpdateMessageProducer {
switch (change.getNewInviteLinkAccess()) {
case ANY:
if (previousAccessControl == AccessControl.AccessRequired.ADMINISTRATOR) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_admin_approval_for_the_group_link_has_been_turned_off)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_admin_approval_for_the_group_link_has_been_turned_off), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_turned_on_with_admin_approval_off)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_turned_on_with_admin_approval_off), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
break;
case ADMINISTRATOR:
if (previousAccessControl == AccessControl.AccessRequired.ANY) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_admin_approval_for_the_group_link_has_been_turned_on)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_admin_approval_for_the_group_link_has_been_turned_on), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
} else {
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_turned_on_with_admin_approval_on)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_turned_on_with_admin_approval_on), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
break;
case UNSATISFIABLE:
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_turned_off)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_turned_off), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
break;
}
if (change.getNewInviteLinkPassword().size() > 0) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_reset)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_reset), R.drawable.ic_update_group_role_light_16, R.drawable.ic_update_group_role_dark_16));
}
}
@ -618,9 +619,9 @@ final class GroupsV2UpdateMessageProducer {
boolean requestingMemberIsYou = member.getUuid().equals(selfUuidBytes);
if (requestingMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_sent_a_request_to_join_the_group)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_sent_a_request_to_join_the_group), R.drawable.ic_update_group_light_16, R.drawable.ic_update_group_dark_16));
} else {
updates.add(updateDescription(member.getUuid(), requesting -> context.getString(R.string.MessageRecord_s_requested_to_join_via_the_group_link, requesting)));
updates.add(updateDescription(member.getUuid(), requesting -> context.getString(R.string.MessageRecord_s_requested_to_join_via_the_group_link, requesting), R.drawable.ic_update_group_light_16, R.drawable.ic_update_group_dark_16));
}
}
}
@ -630,14 +631,14 @@ final class GroupsV2UpdateMessageProducer {
boolean requestingMemberIsYou = requestingMember.getUuid().equals(selfUuidBytes);
if (requestingMemberIsYou) {
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_approved_your_request_to_join_the_group, editor)));
updates.add(updateDescription(change.getEditor(), editor -> context.getString(R.string.MessageRecord_s_approved_your_request_to_join_the_group, editor), R.drawable.ic_update_group_accept_light_16, R.drawable.ic_update_group_accept_dark_16));
} else {
boolean editorIsYou = change.getEditor().equals(selfUuidBytes);
if (editorIsYou) {
updates.add(updateDescription(requestingMember.getUuid(), requesting -> context.getString(R.string.MessageRecord_you_approved_a_request_to_join_the_group_from_s, requesting)));
updates.add(updateDescription(requestingMember.getUuid(), requesting -> context.getString(R.string.MessageRecord_you_approved_a_request_to_join_the_group_from_s, requesting), R.drawable.ic_update_group_accept_light_16, R.drawable.ic_update_group_accept_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), requestingMember.getUuid(), (editor, requesting) -> context.getString(R.string.MessageRecord_s_approved_a_request_to_join_the_group_from_s, editor, requesting)));
updates.add(updateDescription(change.getEditor(), requestingMember.getUuid(), (editor, requesting) -> context.getString(R.string.MessageRecord_s_approved_a_request_to_join_the_group_from_s, editor, requesting), R.drawable.ic_update_group_accept_light_16, R.drawable.ic_update_group_accept_dark_16));
}
}
}
@ -648,9 +649,9 @@ final class GroupsV2UpdateMessageProducer {
boolean requestingMemberIsYou = requestingMember.getUuid().equals(selfUuidBytes);
if (requestingMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_approved)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_approved), R.drawable.ic_update_group_accept_light_16, R.drawable.ic_update_group_accept_dark_16));
} else {
updates.add(updateDescription(requestingMember.getUuid(), requesting -> context.getString(R.string.MessageRecord_a_request_to_join_the_group_from_s_has_been_approved, requesting)));
updates.add(updateDescription(requestingMember.getUuid(), requesting -> context.getString(R.string.MessageRecord_a_request_to_join_the_group_from_s_has_been_approved, requesting), R.drawable.ic_update_group_accept_light_16, R.drawable.ic_update_group_accept_dark_16));
}
}
}
@ -663,17 +664,17 @@ final class GroupsV2UpdateMessageProducer {
if (requestingMemberIsYou) {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_canceled_your_request_to_join_the_group)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_canceled_your_request_to_join_the_group), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
} else {
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_denied_by_an_admin)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_denied_by_an_admin), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
}
} else {
boolean editorIsCanceledMember = change.getEditor().equals(requestingMember);
if (editorIsCanceledMember) {
updates.add(updateDescription(requestingMember, editorRequesting -> context.getString(R.string.MessageRecord_s_canceled_their_request_to_join_the_group, editorRequesting)));
updates.add(updateDescription(requestingMember, editorRequesting -> context.getString(R.string.MessageRecord_s_canceled_their_request_to_join_the_group, editorRequesting), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
} else {
updates.add(updateDescription(change.getEditor(), requestingMember, (editor, requesting) -> context.getString(R.string.MessageRecord_s_denied_a_request_to_join_the_group_from_s, editor, requesting)));
updates.add(updateDescription(change.getEditor(), requestingMember, (editor, requesting) -> context.getString(R.string.MessageRecord_s_denied_a_request_to_join_the_group_from_s, editor, requesting), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
}
}
}
@ -684,9 +685,9 @@ final class GroupsV2UpdateMessageProducer {
boolean requestingMemberIsYou = requestingMember.equals(selfUuidBytes);
if (requestingMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_denied_by_an_admin)));
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_denied_by_an_admin), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
} else {
updates.add(updateDescription(requestingMember, requesting -> context.getString(R.string.MessageRecord_a_request_to_join_the_group_from_s_has_been_denied, requesting)));
updates.add(updateDescription(requestingMember, requesting -> context.getString(R.string.MessageRecord_a_request_to_join_the_group_from_s_has_been_denied, requesting), R.drawable.ic_update_group_decline_light_16, R.drawable.ic_update_group_decline_dark_16));
}
}
}
@ -709,20 +710,32 @@ final class GroupsV2UpdateMessageProducer {
String create(String arg1, String arg2);
}
private static UpdateDescription updateDescription(@NonNull String string) {
return UpdateDescription.staticDescription(string);
private static UpdateDescription updateDescription(@NonNull String string,
@DrawableRes int lightIconResource,
@DrawableRes int darkIconResource)
{
return UpdateDescription.staticDescription(string, lightIconResource, darkIconResource);
}
private UpdateDescription updateDescription(@NonNull ByteString uuid1Bytes, @NonNull StringFactory1Arg stringFactory) {
private UpdateDescription updateDescription(@NonNull ByteString uuid1Bytes,
@NonNull StringFactory1Arg stringFactory,
@DrawableRes int lightIconResource,
@DrawableRes int darkIconResource)
{
UUID uuid1 = UuidUtil.fromByteStringOrUnknown(uuid1Bytes);
return UpdateDescription.mentioning(Collections.singletonList(uuid1), () -> stringFactory.create(descriptionStrategy.describe(uuid1)));
return UpdateDescription.mentioning(Collections.singletonList(uuid1), () -> stringFactory.create(descriptionStrategy.describe(uuid1)), lightIconResource, darkIconResource);
}
private UpdateDescription updateDescription(@NonNull ByteString uuid1Bytes, @NonNull ByteString uuid2Bytes, @NonNull StringFactory2Args stringFactory) {
private UpdateDescription updateDescription(@NonNull ByteString uuid1Bytes,
@NonNull ByteString uuid2Bytes,
@NonNull StringFactory2Args stringFactory,
@DrawableRes int lightIconResource,
@DrawableRes int darkIconResource)
{
UUID uuid1 = UuidUtil.fromByteStringOrUnknown(uuid1Bytes);
UUID uuid2 = UuidUtil.fromByteStringOrUnknown(uuid2Bytes);
return UpdateDescription.mentioning(Arrays.asList(uuid1, uuid2), () -> stringFactory.create(descriptionStrategy.describe(uuid1), descriptionStrategy.describe(uuid2)));
return UpdateDescription.mentioning(Arrays.asList(uuid1, uuid2), () -> stringFactory.create(descriptionStrategy.describe(uuid1), descriptionStrategy.describe(uuid2)), lightIconResource, darkIconResource);
}
}

View file

@ -1,13 +1,24 @@
package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LiveData;
import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.SpanUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.whispersystems.libsignal.util.guava.Function;
@ -20,9 +31,9 @@ public final class LiveUpdateMessage {
* recreates the string asynchronously when they change.
*/
@AnyThread
public static LiveData<String> fromMessageDescription(@NonNull UpdateDescription updateDescription) {
public static LiveData<Spannable> fromMessageDescription(@NonNull Context context, @NonNull UpdateDescription updateDescription) {
if (updateDescription.isStringStatic()) {
return LiveDataUtil.just(updateDescription.getStaticString());
return LiveDataUtil.just(toSpannable(context, updateDescription, updateDescription.getStaticString()));
}
List<LiveData<Recipient>> allMentionedRecipients = Stream.of(updateDescription.getMentioned())
@ -32,16 +43,30 @@ public final class LiveUpdateMessage {
LiveData<?> mentionedRecipientChangeStream = allMentionedRecipients.isEmpty() ? LiveDataUtil.just(new Object())
: LiveDataUtil.merge(allMentionedRecipients);
return LiveDataUtil.mapAsync(mentionedRecipientChangeStream, event -> updateDescription.getString());
return LiveDataUtil.mapAsync(mentionedRecipientChangeStream, event -> toSpannable(context, updateDescription, updateDescription.getString()));
}
/**
* Observes a single recipient and recreates the string asynchronously when they change.
*/
public static LiveData<String> recipientToStringAsync(@NonNull RecipientId recipientId,
@NonNull Function<Recipient, String> createStringInBackground)
public static LiveData<Spannable> recipientToStringAsync(@NonNull RecipientId recipientId,
@NonNull Function<Recipient, Spannable> createStringInBackground)
{
return LiveDataUtil.mapAsync(Recipient.live(recipientId).getLiveData(), createStringInBackground);
}
private static @NonNull Spannable toSpannable(@NonNull Context context, @NonNull UpdateDescription updateDescription, @NonNull String string) {
boolean isDarkTheme = ThemeUtil.isDarkTheme(context);
int drawableResource = isDarkTheme ? updateDescription.getDarkIconResource() : updateDescription.getLightIconResource();
if (drawableResource == 0) {
return new SpannableString(string);
} else {
Drawable drawable = ContextCompat.getDrawable(context, drawableResource);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.setColorFilter(ThemeUtil.getThemedColor(context, R.attr.conversation_item_update_text_color), PorterDuff.Mode.SRC_ATOP);
return new SpannableStringBuilder().append(SpanUtil.buildImageSpan(drawable)).append(" ").append(string);
}
}
}

View file

@ -22,6 +22,7 @@ import android.text.SpannableString;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -38,6 +39,7 @@ import org.thoughtcrime.securesms.profiles.ProfileName;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.StringUtil;
@ -48,6 +50,7 @@ import org.whispersystems.signalservice.api.util.UuidUtil;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
/**
@ -127,43 +130,43 @@ public abstract class MessageRecord extends DisplayRecord {
if (isGroupUpdate() && isGroupV2()) {
return getGv2ChangeDescription(context, getBody());
} else if (isGroupUpdate() && isOutgoing()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_you_updated_group));
return staticUpdateDescription(context.getString(R.string.MessageRecord_you_updated_group), R.drawable.ic_update_group_light_16, R.drawable.ic_update_group_dark_16);
} else if (isGroupUpdate()) {
return fromRecipient(getIndividualRecipient(), r -> GroupUtil.getNonV2GroupDescription(context, getBody()).toString(r));
return fromRecipient(getIndividualRecipient(), r -> GroupUtil.getNonV2GroupDescription(context, getBody()).toString(r), R.drawable.ic_update_group_light_16, R.drawable.ic_update_group_dark_16);
} else if (isGroupQuit() && isOutgoing()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_left_group));
return staticUpdateDescription(context.getString(R.string.MessageRecord_left_group), R.drawable.ic_update_group_leave_light_16, R.drawable.ic_update_group_leave_dark_16);
} else if (isGroupQuit()) {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.ConversationItem_group_action_left, r.getDisplayName(context)));
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.ConversationItem_group_action_left, r.getDisplayName(context)), R.drawable.ic_update_group_leave_light_16, R.drawable.ic_update_group_leave_dark_16);
} else if (isIncomingCall()) {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_called_you, r.getDisplayName(context)));
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_called_you_date, r.getDisplayName(context), getCallDateString()), R.drawable.ic_update_audio_call_incoming_light_16, R.drawable.ic_update_audio_call_incoming_dark_16);
} else if (isOutgoingCall()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_you_called));
return staticUpdateDescription(context.getString(R.string.MessageRecord_you_called_date, getCallDateString()), R.drawable.ic_update_audio_call_outgoing_light_16, R.drawable.ic_update_audio_call_outgoing_dark_16);
} else if (isMissedCall()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_missed_call));
return staticUpdateDescription(context.getString(R.string.MessageRecord_missed_call_date, getCallDateString()), R.drawable.ic_update_audio_call_missed_light_16, R.drawable.ic_update_audio_call_missed_dark_16);
} else if (isJoined()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_s_joined_signal, getIndividualRecipient().getDisplayName(context)));
return staticUpdateDescription(context.getString(R.string.MessageRecord_s_joined_signal, getIndividualRecipient().getDisplayName(context)), R.drawable.ic_update_group_add_light_16, R.drawable.ic_update_group_add_dark_16);
} else if (isExpirationTimerUpdate()) {
int seconds = (int)(getExpiresIn() / 1000);
if (seconds <= 0) {
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_disabled_disappearing_messages))
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, r.getDisplayName(context)));
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_disabled_disappearing_messages), R.drawable.ic_update_timer_disabled_light_16, R.drawable.ic_update_timer_disabled_dark_16)
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, r.getDisplayName(context)), R.drawable.ic_update_timer_disabled_light_16, R.drawable.ic_update_timer_disabled_dark_16);
}
String time = ExpirationUtil.getExpirationDisplayValue(context, seconds);
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time))
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, r.getDisplayName(context), time));
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time), R.drawable.ic_update_timer_light_16, R.drawable.ic_update_timer_dark_16)
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, r.getDisplayName(context), time), R.drawable.ic_update_timer_light_16, R.drawable.ic_update_timer_dark_16);
} else if (isIdentityUpdate()) {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)));
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_light_16, R.drawable.ic_update_safety_number_dark_16);
} else if (isIdentityVerified()) {
if (isOutgoing()) return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified, r.getDisplayName(context)));
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified_from_another_device, r.getDisplayName(context)));
if (isOutgoing()) return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified, r.getDisplayName(context)), R.drawable.ic_update_verified_light_16, R.drawable.ic_update_verified_dark_16);
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_verified_light_16, R.drawable.ic_update_verified_dark_16);
} else if (isIdentityDefault()) {
if (isOutgoing()) return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified, r.getDisplayName(context)));
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device, r.getDisplayName(context)));
if (isOutgoing()) return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified, r.getDisplayName(context)), R.drawable.ic_update_info_light_16, R.drawable.ic_update_info_dark_16);
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_info_light_16, R.drawable.ic_update_info_dark_16);
} else if (isProfileChange()) {
return staticUpdateDescription(getProfileChangeDescription(context));
return staticUpdateDescription(getProfileChangeDescription(context), R.drawable.ic_update_profile_light_16, R.drawable.ic_update_profile_dark_16);
} else if (isEndSession()) {
if (isOutgoing()) return staticUpdateDescription(context.getString(R.string.SmsMessageRecord_secure_session_reset));
else return fromRecipient(getIndividualRecipient(), r-> context.getString(R.string.SmsMessageRecord_secure_session_reset_s, r.getDisplayName(context)));
if (isOutgoing()) return staticUpdateDescription(context.getString(R.string.SmsMessageRecord_secure_session_reset), R.drawable.ic_update_info_light_16, R.drawable.ic_update_info_dark_16);
else return fromRecipient(getIndividualRecipient(), r-> context.getString(R.string.SmsMessageRecord_secure_session_reset_s, r.getDisplayName(context)), R.drawable.ic_update_info_light_16, R.drawable.ic_update_info_dark_16);
}
return null;
@ -183,7 +186,7 @@ public abstract class MessageRecord extends DisplayRecord {
}
} catch (IOException e) {
Log.w(TAG, "GV2 Message update detail could not be read", e);
return staticUpdateDescription(context.getString(R.string.MessageRecord_group_updated));
return staticUpdateDescription(context.getString(R.string.MessageRecord_group_updated), R.drawable.ic_update_group_light_16, R.drawable.ic_update_group_dark_16);
}
}
@ -210,12 +213,26 @@ public abstract class MessageRecord extends DisplayRecord {
}
}
private static @NonNull UpdateDescription fromRecipient(@NonNull Recipient recipient, @NonNull Function<Recipient, String> stringFunction) {
return UpdateDescription.mentioning(Collections.singletonList(recipient.getUuid().or(UuidUtil.UNKNOWN_UUID)), () -> stringFunction.apply(recipient.resolve()));
private @NonNull String getCallDateString() {
return DateUtils.getBriefExactTimeString(Locale.getDefault(), getDateSent());
}
private static @NonNull UpdateDescription staticUpdateDescription(@NonNull String string) {
return UpdateDescription.staticDescription(string);
private static @NonNull UpdateDescription fromRecipient(@NonNull Recipient recipient,
@NonNull Function<Recipient, String> stringGenerator,
@DrawableRes int lightIconResource,
@DrawableRes int darkIconResource)
{
return UpdateDescription.mentioning(Collections.singletonList(recipient.getUuid().or(UuidUtil.UNKNOWN_UUID)),
() -> stringGenerator.apply(recipient.resolve()),
lightIconResource,
darkIconResource);
}
private static @NonNull UpdateDescription staticUpdateDescription(@NonNull String string,
@DrawableRes int lightIconResource,
@DrawableRes int darkIconResource)
{
return UpdateDescription.staticDescription(string, lightIconResource, darkIconResource);
}
private @NonNull String getProfileChangeDescription(@NonNull Context context) {

View file

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.database.model;
import androidx.annotation.AnyThread;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@ -28,17 +29,23 @@ public final class UpdateDescription {
private final Collection<UUID> mentioned;
private final StringFactory stringFactory;
private final String staticString;
private final int lightIconResource;
private final int darkIconResource;
private UpdateDescription(@NonNull Collection<UUID> mentioned,
@Nullable StringFactory stringFactory,
@Nullable String staticString)
@Nullable String staticString,
@DrawableRes int lightIconResource,
@DrawableRes int darkIconResource)
{
if (staticString == null && stringFactory == null) {
throw new AssertionError();
}
this.mentioned = mentioned;
this.stringFactory = stringFactory;
this.staticString = staticString;
this.mentioned = mentioned;
this.stringFactory = stringFactory;
this.staticString = staticString;
this.lightIconResource = lightIconResource;
this.darkIconResource = darkIconResource;
}
/**
@ -49,18 +56,25 @@ public final class UpdateDescription {
* @param stringFactory The background method for generating the string.
*/
public static UpdateDescription mentioning(@NonNull Collection<UUID> mentioned,
@NonNull StringFactory stringFactory)
@NonNull StringFactory stringFactory,
@DrawableRes int lightIconResource,
@DrawableRes int darkIconResource)
{
return new UpdateDescription(UuidUtil.filterKnown(mentioned),
stringFactory,
null);
null,
lightIconResource,
darkIconResource);
}
/**
* Create an update description that's string value is fixed.
*/
public static UpdateDescription staticDescription(@NonNull String staticString) {
return new UpdateDescription(Collections.emptyList(), null, staticString);
public static UpdateDescription staticDescription(@NonNull String staticString,
@DrawableRes int lightIconResource,
@DrawableRes int darkIconResource)
{
return new UpdateDescription(Collections.emptyList(), null, staticString, lightIconResource, darkIconResource);
}
public boolean isStringStatic() {
@ -93,6 +107,14 @@ public final class UpdateDescription {
return mentioned;
}
public @DrawableRes int getLightIconResource() {
return lightIconResource;
}
public @DrawableRes int getDarkIconResource() {
return darkIconResource;
}
public static UpdateDescription concatWithNewLines(@NonNull List<UpdateDescription> updateDescriptions) {
if (updateDescriptions.size() == 0) {
throw new AssertionError();
@ -103,7 +125,9 @@ public final class UpdateDescription {
}
if (allAreStatic(updateDescriptions)) {
return UpdateDescription.staticDescription(concatStaticLines(updateDescriptions));
return UpdateDescription.staticDescription(concatStaticLines(updateDescriptions),
updateDescriptions.get(0).getLightIconResource(),
updateDescriptions.get(0).getDarkIconResource());
}
Set<UUID> allMentioned = new HashSet<>();
@ -112,7 +136,10 @@ public final class UpdateDescription {
allMentioned.addAll(updateDescription.getMentioned());
}
return UpdateDescription.mentioning(allMentioned, () -> concatLines(updateDescriptions));
return UpdateDescription.mentioning(allMentioned,
() -> concatLines(updateDescriptions),
updateDescriptions.get(0).getLightIconResource(),
updateDescriptions.get(0).getDarkIconResource());
}
private static boolean allAreStatic(@NonNull Collection<UpdateDescription> updateDescriptions) {

View file

@ -27,6 +27,7 @@ import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.logging.Log;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@ -40,8 +41,9 @@ import java.util.concurrent.TimeUnit;
public class DateUtils extends android.text.format.DateUtils {
@SuppressWarnings("unused")
private static final String TAG = DateUtils.class.getSimpleName();
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");
private static final String TAG = DateUtils.class.getSimpleName();
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");
private static final SimpleDateFormat BRIEF_EXACT_FORMAT = new SimpleDateFormat();
private static boolean isWithin(final long millis, final long span, final TimeUnit unit) {
return System.currentTimeMillis() - millis <= unit.toMillis(span);
@ -172,6 +174,16 @@ public class DateUtils extends android.text.format.DateUtils {
return getExtendedRelativeTimeSpanString(context, locale, t1).equals(getExtendedRelativeTimeSpanString(context, locale, t2));
}
public static String getBriefExactTimeString(@NonNull Locale locale, long timestamp) {
SimpleDateFormat format = new SimpleDateFormat(getLocalizedPattern("MMM dd, hh:mm a", locale), locale);
DateFormatSymbols symbols = new DateFormatSymbols(locale);
symbols.setAmPmStrings(new String[] { "am", "pm"});
format.setDateFormatSymbols(symbols);
return format.format(timestamp);
}
private static String getLocalizedPattern(String template, Locale locale) {
return DateFormat.getBestDateTimePattern(locale, template);
}

View file

@ -1,11 +1,14 @@
package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.DynamicDrawableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.text.style.RelativeSizeSpan;
@ -14,6 +17,9 @@ import android.text.style.URLSpan;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import org.thoughtcrime.securesms.R;
public class SpanUtil {
@ -50,4 +56,12 @@ public class SpanUtil {
spannable.setSpan(new ForegroundColorSpan(color), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable;
}
public static CharSequence buildImageSpan(@NonNull Drawable drawable) {
SpannableString imageSpan = new SpannableString(" ");
imageSpan.setSpan(new ImageSpan(drawable, DynamicDrawableSpan.ALIGN_CENTER), 0, imageSpan.length(), 0);
return imageSpan;
}
}

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M3.13,2.52C3.4028,2.3798 3.7171,2.3431 4.0149,2.4166C4.3127,2.4902 4.5738,2.669 4.75,2.92L6.13,4.92C6.3038,5.1635 6.386,5.4605 6.3622,5.7587C6.3384,6.0569 6.2102,6.3372 6,6.55C5.77,6.77 5.61,6.92 5.4,7.09C5.3291,7.1389 5.2687,7.2015 5.2226,7.2742C5.1764,7.3469 5.1454,7.4282 5.1314,7.5131C5.1174,7.5981 5.1207,7.685 5.1411,7.7687C5.1614,7.8523 5.1985,7.931 5.25,8C5.6459,8.5158 6.0769,9.0037 6.54,9.46C7.0124,9.925 7.517,10.356 8.05,10.75C8.1822,10.8418 8.3441,10.8804 8.5035,10.8582C8.6628,10.8359 8.808,10.7545 8.91,10.63C9.08,10.42 9.23,10.26 9.45,10.03C9.6603,9.8101 9.9425,9.673 10.2453,9.6437C10.5481,9.6143 10.8514,9.6946 11.1,9.87L13.1,11.25C13.3511,11.4262 13.5299,11.6873 13.6034,11.9851C13.6769,12.2829 13.6402,12.5972 13.5,12.87C13.2766,13.3393 12.9313,13.74 12.5,14.03C12.0388,14.3257 11.5084,14.496 10.9612,14.5241C10.4141,14.5521 9.8691,14.437 9.38,14.19C7.6556,13.5308 6.09,12.5148 4.7854,11.2085C3.4809,9.9023 2.467,8.3352 1.81,6.61C1.5674,6.1184 1.4574,5.572 1.4907,5.0248C1.524,4.4776 1.6996,3.9486 2,3.49C2.2858,3.0738 2.6753,2.7395 3.13,2.52ZM14.85,1.85L14.15,1.15L10,5.29V2H9V7H14V6H10.71L14.85,1.85Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M10.31,15C9.7498,14.9893 9.1954,14.8845 8.67,14.69C6.9971,14.0455 5.4778,13.0576 4.2101,11.7899C2.9424,10.5222 1.9545,9.0029 1.31,7.33C1.0674,6.8003 0.9605,6.2186 0.9989,5.6372C1.0373,5.0559 1.2198,4.4932 1.53,4C1.8415,3.569 2.258,3.2248 2.74,3C3.1045,2.8038 3.5281,2.7473 3.9313,2.8412C4.3346,2.9351 4.6897,3.1729 4.93,3.51L6.22,5.28C6.451,5.6112 6.5557,6.014 6.5154,6.4158C6.475,6.8175 6.2922,7.1914 6,7.47L5.43,8C5.417,8.0173 5.41,8.0384 5.41,8.06C5.41,8.0817 5.417,8.1027 5.43,8.12C5.7663,8.5932 6.1409,9.038 6.55,9.45C6.9636,9.8734 7.4118,10.2614 7.89,10.61C7.9073,10.623 7.9283,10.63 7.95,10.63C7.9716,10.63 7.9927,10.623 8.01,10.61C8.18,10.42 8.32,10.26 8.53,10.04C8.8086,9.7478 9.1826,9.565 9.5843,9.5246C9.986,9.4843 10.3888,9.5891 10.72,9.82L12.56,11.11C12.8898,11.3442 13.1247,11.689 13.222,12.0817C13.3192,12.4744 13.2724,12.8889 13.09,13.25C12.842,13.7467 12.4657,14.1679 12,14.47C11.5051,14.8174 10.9146,15.0026 10.31,15ZM2.31,4.54C2.0884,4.9103 1.9672,5.332 1.9584,5.7634C1.9496,6.1948 2.0536,6.6211 2.26,7C2.8467,8.5365 3.7534,9.9307 4.92,11.09C6.0774,12.2518 7.468,13.155 9,13.74C9.3812,13.9386 9.8074,14.0347 10.2369,14.0189C10.6664,14.0032 11.0844,13.876 11.45,13.65C11.7615,13.4359 12.01,13.1425 12.17,12.8C12.2564,12.6508 12.2838,12.4746 12.2468,12.3062C12.2098,12.1377 12.111,11.9893 11.97,11.89L10.14,10.6C10.0078,10.5064 9.8465,10.4629 9.6852,10.4776C9.5239,10.4923 9.3731,10.5641 9.26,10.68L8.76,11.23C8.584,11.4417 8.3339,11.5782 8.0607,11.6117C7.7875,11.6451 7.5118,11.573 7.29,11.41C6.7772,11.0288 6.2926,10.6111 5.84,10.16C5.3889,9.7074 4.9712,9.2228 4.59,8.71C4.4264,8.4866 4.354,8.2093 4.3874,7.9344C4.4208,7.6596 4.5576,7.4077 4.77,7.23L5.32,6.74C5.4359,6.6269 5.5077,6.4761 5.5224,6.3148C5.5371,6.1535 5.4937,5.9922 5.4,5.86L4.11,4C4.0197,3.863 3.8815,3.7645 3.7225,3.7238C3.5635,3.6832 3.395,3.7032 3.25,3.78C2.887,3.9383 2.5754,4.1945 2.35,4.52L2.31,4.54ZM14.81,1.85L14.11,1.15L10,5.29V2H9V7H14V6H10.71L14.81,1.85Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M3.13,2.52C3.4028,2.3798 3.7171,2.3431 4.0149,2.4166C4.3127,2.4902 4.5738,2.669 4.75,2.92L6.13,4.92C6.3038,5.1635 6.386,5.4605 6.3622,5.7587C6.3384,6.0569 6.2102,6.3372 6,6.55C5.77,6.77 5.61,6.92 5.4,7.09C5.3291,7.1389 5.2687,7.2015 5.2226,7.2742C5.1764,7.3469 5.1454,7.4282 5.1314,7.5131C5.1174,7.5981 5.1207,7.685 5.1411,7.7687C5.1614,7.8523 5.1985,7.931 5.25,8C5.6459,8.5158 6.0769,9.0037 6.54,9.46C7.0124,9.925 7.517,10.356 8.05,10.75C8.1822,10.8418 8.3441,10.8804 8.5035,10.8582C8.6628,10.8359 8.808,10.7545 8.91,10.63C9.08,10.42 9.23,10.26 9.45,10.03C9.6603,9.8101 9.9425,9.673 10.2453,9.6437C10.5481,9.6143 10.8514,9.6946 11.1,9.87L13.1,11.25C13.3511,11.4262 13.5299,11.6873 13.6034,11.9851C13.6769,12.2829 13.6402,12.5972 13.5,12.87C13.2766,13.3393 12.9313,13.74 12.5,14.03C12.0388,14.3257 11.5084,14.496 10.9612,14.5241C10.4141,14.5521 9.8691,14.437 9.38,14.19C7.6556,13.5308 6.09,12.5148 4.7854,11.2085C3.4809,9.9023 2.467,8.3352 1.81,6.61C1.5674,6.1184 1.4574,5.572 1.4907,5.0248C1.524,4.4776 1.6996,3.9486 2,3.49C2.2858,3.0738 2.6753,2.7395 3.13,2.52ZM14.35,2.35L13.65,1.65L11.5,3.79L9.35,1.65L8.65,2.35L10.79,4.5L8.65,6.65L9.35,7.35L11.5,5.21L13.65,7.35L14.35,6.65L12.21,4.5L14.35,2.35Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M10.31,15C9.7498,14.9893 9.1954,14.8845 8.67,14.69C6.9978,14.044 5.4788,13.0563 4.21,11.79C2.9462,10.5192 1.9589,9.0007 1.31,7.33C1.0674,6.8003 0.9605,6.2186 0.9989,5.6372C1.0373,5.0559 1.2198,4.4932 1.53,4C1.8415,3.569 2.258,3.2248 2.74,3C3.1045,2.8038 3.5281,2.7473 3.9313,2.8412C4.3346,2.9351 4.6897,3.1729 4.93,3.51L6.22,5.28C6.451,5.6112 6.5557,6.014 6.5154,6.4158C6.475,6.8175 6.2922,7.1914 6,7.47L5.43,8C5.417,8.0173 5.41,8.0384 5.41,8.06C5.41,8.0817 5.417,8.1027 5.43,8.12C5.7663,8.5932 6.1409,9.038 6.55,9.45C6.9636,9.8734 7.4118,10.2614 7.89,10.61C7.89,10.61 7.97,10.61 8.01,10.61C8.18,10.41 8.32,10.26 8.53,10.04C8.8086,9.7478 9.1826,9.565 9.5843,9.5246C9.986,9.4843 10.3888,9.5891 10.72,9.82L12.56,11.11C12.8898,11.3442 13.1247,11.689 13.222,12.0817C13.3192,12.4744 13.2724,12.8889 13.09,13.25C12.842,13.7467 12.4657,14.1679 12,14.47C11.5051,14.8174 10.9146,15.0026 10.31,15ZM3.55,3.73C3.4457,3.7282 3.3426,3.7522 3.25,3.8C2.887,3.9583 2.5754,4.2145 2.35,4.54C2.1221,4.9068 1.994,5.3266 1.9782,5.7581C1.9624,6.1895 2.0596,6.6176 2.26,7C2.8467,8.5365 3.7534,9.9307 4.92,11.09C6.0774,12.2518 7.468,13.155 9,13.74C9.3812,13.9386 9.8074,14.0347 10.2369,14.0189C10.6664,14.0032 11.0844,13.876 11.45,13.65C11.7615,13.4359 12.01,13.1425 12.17,12.8C12.2564,12.6508 12.2838,12.4746 12.2468,12.3062C12.2098,12.1377 12.111,11.9893 11.97,11.89L10.14,10.6C10.0078,10.5064 9.8465,10.4629 9.6852,10.4776C9.5239,10.4923 9.3731,10.5641 9.26,10.68L8.76,11.23C8.584,11.4417 8.3339,11.5782 8.0607,11.6117C7.7875,11.6451 7.5118,11.573 7.29,11.41C6.7772,11.0288 6.2926,10.6111 5.84,10.16C5.3889,9.7074 4.9712,9.2228 4.59,8.71C4.427,8.4882 4.3549,8.2125 4.3883,7.9393C4.4218,7.6661 4.5583,7.416 4.77,7.24L5.32,6.74C5.4359,6.6269 5.5077,6.4761 5.5224,6.3148C5.5371,6.1535 5.4937,5.9922 5.4,5.86L4.11,4C4.0454,3.9131 3.9607,3.8432 3.8632,3.7961C3.7657,3.7491 3.6582,3.7264 3.55,3.73ZM14.35,2.35L13.65,1.65L11.5,3.79L9.35,1.65L8.65,2.35L10.79,4.5L8.65,6.65L9.35,7.35L11.5,5.21L13.65,7.35L14.35,6.65L12.21,4.5L14.35,2.35Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M14,2V7H13V3.71L8.85,7.85L8.15,7.15L12.29,3H9V2H14ZM2,3.49C1.7043,3.9512 1.534,4.4816 1.506,5.0288C1.4779,5.5759 1.593,6.1209 1.84,6.61C2.4981,8.3362 3.5136,9.9038 4.8199,11.2101C6.1262,12.5165 7.6938,13.5319 9.42,14.19C9.9078,14.427 10.4486,14.5341 10.99,14.5008C11.5313,14.4675 12.0549,14.295 12.51,14C12.9413,13.7099 13.2866,13.3093 13.51,12.84C13.6502,12.5672 13.6869,12.2529 13.6134,11.9551C13.5399,11.6573 13.3611,11.3962 13.11,11.22L11.11,9.84C10.8606,9.6619 10.5552,9.58 10.2501,9.6094C9.945,9.6388 9.6608,9.7775 9.45,10C9.23,10.23 9.08,10.39 8.91,10.6C8.808,10.7245 8.6629,10.8059 8.5035,10.8282C8.3441,10.8504 8.1822,10.8118 8.05,10.72C7.518,10.3356 7.0134,9.9146 6.54,9.46C6.0769,9.0036 5.6459,8.5158 5.25,8C5.1582,7.8678 5.1196,7.7059 5.1418,7.5465C5.1641,7.3872 5.2456,7.242 5.37,7.14C5.58,6.97 5.74,6.82 5.97,6.6C6.2032,6.3872 6.3488,6.0952 6.3783,5.7809C6.4079,5.4666 6.3194,5.1526 6.13,4.9L4.75,2.9C4.5738,2.6489 4.3127,2.4701 4.0149,2.3966C3.7171,2.3231 3.4028,2.3598 3.13,2.5C2.6729,2.725 2.2832,3.0665 2,3.49Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M10.31,15C9.7498,14.9893 9.1954,14.8845 8.67,14.69C6.9971,14.0455 5.4778,13.0576 4.2101,11.7899C2.9424,10.5222 1.9545,9.0029 1.31,7.33C1.0674,6.8003 0.9605,6.2185 0.9989,5.6372C1.0373,5.0558 1.2198,4.4932 1.53,4C1.8415,3.569 2.258,3.2248 2.74,3C3.1045,2.8038 3.5281,2.7473 3.9313,2.8412C4.3346,2.9351 4.6897,3.1729 4.93,3.51L6.22,5.28C6.451,5.6111 6.5557,6.014 6.5154,6.4157C6.475,6.8174 6.2922,7.1914 6,7.47L5.43,8C5.417,8.0173 5.41,8.0384 5.41,8.06C5.41,8.0816 5.417,8.1027 5.43,8.12C5.7663,8.5932 6.1409,9.038 6.55,9.45C6.9636,9.8733 7.4118,10.2613 7.89,10.61C7.9073,10.623 7.9283,10.63 7.95,10.63C7.9716,10.63 7.9927,10.623 8.01,10.61C8.18,10.42 8.32,10.26 8.53,10.04C8.8086,9.7478 9.1826,9.565 9.5843,9.5246C9.986,9.4843 10.3888,9.589 10.72,9.82L12.56,11.11C12.8898,11.3442 13.1247,11.689 13.222,12.0817C13.3192,12.4744 13.2724,12.8889 13.09,13.25C12.842,13.7467 12.4657,14.1679 12,14.47C11.5051,14.8174 10.9146,15.0026 10.31,15ZM2.31,4.54C2.0884,4.9103 1.9672,5.3319 1.9584,5.7634C1.9496,6.1948 2.0536,6.621 2.26,7C2.8467,8.5365 3.7534,9.9307 4.92,11.09C6.0774,12.2518 7.468,13.155 9,13.74C9.3812,13.9386 9.8074,14.0347 10.2369,14.0189C10.6664,14.0031 11.0844,13.876 11.45,13.65C11.7615,13.4359 12.01,13.1424 12.17,12.8C12.2564,12.6508 12.2838,12.4746 12.2468,12.3061C12.2098,12.1377 12.111,11.9893 11.97,11.89L10.14,10.6C10.0078,10.5063 9.8465,10.4629 9.6852,10.4776C9.5239,10.4923 9.3731,10.564 9.26,10.68L8.76,11.23C8.584,11.4417 8.3339,11.5782 8.0607,11.6116C7.7875,11.6451 7.5118,11.573 7.29,11.41C6.7772,11.0288 6.2926,10.611 5.84,10.16C5.3889,9.7074 4.9712,9.2228 4.59,8.71C4.4264,8.4866 4.354,8.2093 4.3874,7.9344C4.4208,7.6595 4.5576,7.4077 4.77,7.23L5.32,6.74C5.4359,6.6269 5.5077,6.4761 5.5224,6.3148C5.5371,6.1534 5.4937,5.9922 5.4,5.86L4.11,4C4.0197,3.863 3.8815,3.7645 3.7225,3.7238C3.5635,3.6831 3.395,3.7032 3.25,3.78C2.887,3.9382 2.5754,4.1945 2.35,4.52L2.31,4.54ZM9,2V3H12.29L8.15,7.15L8.85,7.85L13,3.71V7H14V2H9Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M11,3C10.4872,3 9.986,3.1549 9.5596,3.4452C9.1333,3.7354 8.801,4.148 8.6048,4.6307C8.4085,5.1133 8.3572,5.6444 8.4572,6.1568C8.5573,6.6693 8.8042,7.1399 9.1668,7.5093C9.5293,7.8788 9.9913,8.1303 10.4942,8.2323C10.9971,8.3342 11.5184,8.2819 11.9921,8.082C12.4659,7.882 12.8708,7.5434 13.1557,7.109C13.4405,6.6747 13.5926,6.1639 13.5926,5.6415C13.5926,4.9409 13.3194,4.2691 12.8332,3.7737C12.347,3.2783 11.6876,3 11,3ZM13.6215,8.3034C13.2781,8.6557 12.8696,8.9353 12.4197,9.126C11.9698,9.3168 11.4873,9.415 11,9.415C10.5127,9.415 10.0302,9.3168 9.5803,9.126C9.1304,8.9353 8.7219,8.6557 8.3785,8.3034C7.6861,8.5432 7.0846,8.9976 6.6581,9.6028C6.2317,10.2081 6.0016,10.9341 6,11.6792V12.2453C6,12.4454 6.078,12.6374 6.217,12.7789C6.3559,12.9205 6.5443,13 6.7407,13H15.2593C15.4557,13 15.6441,12.9205 15.783,12.7789C15.922,12.6374 16,12.4454 16,12.2453V11.6792C15.9984,10.9341 15.7683,10.2081 15.3419,9.6028C14.9154,8.9976 14.3139,8.5432 13.6215,8.3034ZM5.9749,5.2322L6.682,5.9394L3.1465,9.4749L3.1465,9.4749L2.4394,10.182L2.4393,10.182L1.7322,9.4749L0.318,8.0607L1.0251,7.3536L2.4393,8.7678L5.9749,5.2322Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M13.283,8.4211C13.6989,7.9623 13.9756,7.3883 14.0793,6.7696C14.1829,6.1509 14.1089,5.5145 13.8664,4.9385C13.6238,4.3626 13.2233,3.8723 12.714,3.5279C12.2047,3.1835 11.6089,3 10.9999,3C10.3908,3 9.795,3.1835 9.2857,3.5279C8.7765,3.8723 8.3759,4.3626 8.1334,4.9385C7.8908,5.5145 7.8168,6.1509 7.9204,6.7696C8.0241,7.3883 8.3009,7.9623 8.7167,8.4211C7.946,8.6021 7.2576,9.0474 6.7641,9.684C6.2706,10.3207 6.0012,11.111 5.9999,11.926V13H6.9374V11.926C6.9382,11.2285 7.2073,10.5599 7.6857,10.0668C8.1641,9.5736 8.8127,9.2962 9.4892,9.2954H12.5105C13.187,9.2962 13.8356,9.5736 14.314,10.0668C14.7924,10.5599 15.0615,11.2285 15.0624,11.926V13H15.9999V11.926C15.9986,11.111 15.7291,10.3207 15.2356,9.684C14.7421,9.0474 14.0538,8.6021 13.283,8.4211ZM10.9999,8.49C10.5672,8.49 10.1443,8.3577 9.7845,8.11C9.4248,7.8622 9.1444,7.51 8.9789,7.0979C8.8133,6.6859 8.77,6.2325 8.8544,5.7951C8.9388,5.3576 9.1471,4.9558 9.4531,4.6405C9.759,4.3251 10.1488,4.1103 10.5731,4.0233C10.9974,3.9363 11.4373,3.981 11.837,4.1516C12.2367,4.3223 12.5783,4.6113 12.8187,4.9822C13.0591,5.353 13.1874,5.789 13.1874,6.235C13.1874,6.833 12.9569,7.4066 12.5467,7.8295C12.1364,8.2524 11.58,8.49 10.9999,8.49ZM5.9749,5.2322L6.682,5.9394L3.1465,9.4749L3.1465,9.4749L2.4394,10.182L2.4394,10.182L1.7323,9.4749L0.3181,8.0607L1.0252,7.3536L2.4394,8.7678L5.9749,5.2322Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="16dp"
android:viewportWidth="18"
android:viewportHeight="16">
<path
android:pathData="M10,3C9.4872,3 8.986,3.1549 8.5596,3.4452C8.1333,3.7354 7.801,4.148 7.6048,4.6307C7.4085,5.1133 7.3572,5.6444 7.4572,6.1568C7.5573,6.6693 7.8042,7.1399 8.1668,7.5093C8.5293,7.8788 8.9913,8.1303 9.4942,8.2323C9.9971,8.3342 10.5184,8.2819 10.9921,8.082C11.4659,7.882 11.8708,7.5434 12.1557,7.109C12.4405,6.6747 12.5926,6.1639 12.5926,5.6415C12.5926,4.9409 12.3194,4.2691 11.8332,3.7737C11.347,3.2783 10.6876,3 10,3ZM12.6215,8.3034C12.2781,8.6557 11.8696,8.9353 11.4197,9.126C10.9698,9.3168 10.4873,9.415 10,9.415C9.5127,9.415 9.0302,9.3168 8.5803,9.126C8.1304,8.9353 7.7219,8.6557 7.3785,8.3034C6.6861,8.5432 6.0846,8.9976 5.6581,9.6028C5.2317,10.2081 5.0016,10.9341 5,11.6792V12.2453C5,12.4454 5.078,12.6374 5.217,12.7789C5.3559,12.9205 5.5443,13 5.7407,13H14.2593C14.4557,13 14.6441,12.9205 14.783,12.7789C14.922,12.6374 15,12.4454 15,12.2453V11.6792C14.9984,10.9341 14.7683,10.2081 14.3419,9.6028C13.9154,8.9976 13.3139,8.5432 12.6215,8.3034Z"
android:fillColor="#000000"/>
<path
android:pathData="M5,6.8H3.2V5H2.8V6.8H1V7.2H2.8V9H3.2V7.2H5V6.8Z"
android:strokeWidth="0.5"
android:fillColor="#000000"
android:strokeColor="#000000"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M12.2831,8.4211C12.699,7.9623 12.9758,7.3883 13.0794,6.7696C13.1831,6.1509 13.1091,5.5145 12.8665,4.9385C12.6239,4.3626 12.2234,3.8723 11.7141,3.5279C11.2049,3.1835 10.6091,3 10,3C9.3909,3 8.7951,3.1835 8.2859,3.5279C7.7766,3.8723 7.3761,4.3626 7.1335,4.9385C6.8909,5.5145 6.8169,6.1509 6.9206,6.7696C7.0242,7.3883 7.301,7.9623 7.7169,8.4211C6.9461,8.6021 6.2577,9.0474 5.7642,9.684C5.2707,10.3207 5.0013,11.111 5,11.926V13H5.9375V11.926C5.9383,11.2285 6.2074,10.5599 6.6858,10.0668C7.1642,9.5736 7.8128,9.2962 8.4894,9.2954H11.5106C12.1872,9.2962 12.8358,9.5736 13.3142,10.0668C13.7926,10.5599 14.0617,11.2285 14.0625,11.926V13H15V11.926C14.9987,11.111 14.7293,10.3207 14.2358,9.684C13.7423,9.0474 13.0539,8.6021 12.2831,8.4211ZM10,8.49C9.5674,8.49 9.1444,8.3577 8.7847,8.11C8.425,7.8622 8.1446,7.51 7.979,7.0979C7.8134,6.6859 7.7701,6.2325 7.8545,5.7951C7.9389,5.3576 8.1473,4.9558 8.4532,4.6405C8.7591,4.3251 9.1489,4.1103 9.5732,4.0233C9.9976,3.9363 10.4374,3.981 10.8371,4.1516C11.2368,4.3223 11.5785,4.6113 11.8188,4.9822C12.0592,5.353 12.1875,5.789 12.1875,6.235C12.1875,6.833 11.957,7.4066 11.5468,7.8295C11.1366,8.2524 10.5802,8.49 10,8.49Z"
android:fillColor="#000000"/>
<path
android:pathData="M5,6.8H3.2V5H2.8V6.8H1V7.2H2.8V9H3.2V7.2H5V6.8Z"
android:strokeWidth="0.5"
android:fillColor="#000000"
android:strokeColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M11.6667,1.3333H4.3333C3.5377,1.3333 2.7746,1.6494 2.212,2.212C1.6494,2.7746 1.3333,3.5377 1.3333,4.3333V11.6666C1.3333,12.4623 1.6494,13.2254 2.212,13.788C2.7746,14.3506 3.5377,14.6666 4.3333,14.6666H11.6667C12.4623,14.6666 13.2254,14.3506 13.788,13.788C14.3506,13.2254 14.6667,12.4623 14.6667,11.6666V4.3333C14.6667,3.5377 14.3506,2.7746 13.788,2.212C13.2254,1.6494 12.4623,1.3333 11.6667,1.3333ZM13.6667,8.8333L13.2527,8.212L10.6667,5.626L9.1387,7.1547L10.714,8.7333L10.2427,9.2046L6,4.9593L2.7473,8.212L2.3333,8.8333V4.3333C2.3333,3.8029 2.544,3.2942 2.9191,2.9191C3.2942,2.544 3.8029,2.3333 4.3333,2.3333H11.6667C12.1971,2.3333 12.7058,2.544 13.0809,2.9191C13.4559,3.2942 13.6667,3.8029 13.6667,4.3333V8.8333Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M11.6667,1.3333H4.3333C3.5377,1.3333 2.7746,1.6494 2.212,2.212C1.6494,2.7746 1.3333,3.5377 1.3333,4.3333V11.6666C1.3333,12.4623 1.6494,13.2254 2.212,13.788C2.7746,14.3506 3.5377,14.6666 4.3333,14.6666H11.6667C12.4623,14.6666 13.2254,14.3506 13.788,13.788C14.3506,13.2254 14.6667,12.4623 14.6667,11.6666V4.3333C14.6667,3.5377 14.3506,2.7746 13.788,2.212C13.2254,1.6494 12.4623,1.3333 11.6667,1.3333ZM4.3333,2.3333H11.6667C12.1971,2.3333 12.7058,2.544 13.0809,2.9191C13.456,3.2942 13.6667,3.8029 13.6667,4.3333V8.8333L13.2527,8.212L10.6667,5.626L8.6667,7.626L6,4.9593L2.7473,8.212L2.3333,8.8333V4.3333C2.3333,3.8029 2.5441,3.2942 2.9191,2.9191C3.2942,2.544 3.8029,2.3333 4.3333,2.3333ZM11.6667,13.6666H4.3333C3.8029,13.6666 3.2942,13.4559 2.9191,13.0809C2.5441,12.7058 2.3333,12.1971 2.3333,11.6666V10.0406L6,6.374L9.98,10.3533L10.6867,9.6467L9.374,8.3333L10.6667,7.0406L13.6667,10.0406V11.6666C13.6667,12.1971 13.456,12.7058 13.0809,13.0809C12.7058,13.4559 12.1971,13.6666 11.6667,13.6666Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M5.1667,5.1666C4.7052,5.1666 4.2541,5.3035 3.8703,5.5599C3.4866,5.8163 3.1876,6.1807 3.011,6.607C2.8344,7.0334 2.7881,7.5026 2.8782,7.9552C2.9682,8.4078 3.1904,8.8236 3.5168,9.1499C3.8431,9.4762 4.2588,9.6985 4.7115,9.7885C5.1641,9.8785 5.6332,9.8323 6.0596,9.6557C6.486,9.4791 6.8504,9.18 7.1068,8.7963C7.3632,8.4126 7.5,7.9615 7.5,7.5C7.5,6.8811 7.2542,6.2877 6.8166,5.8501C6.379,5.4125 5.7855,5.1666 5.1667,5.1666ZM7.526,9.8513C7.2169,10.1625 6.8493,10.4095 6.4444,10.578C6.0395,10.7465 5.6053,10.8333 5.1667,10.8333C4.7281,10.8333 4.2938,10.7465 3.8889,10.578C3.484,10.4095 3.1164,10.1625 2.8073,9.8513C2.1842,10.0632 1.6428,10.4645 1.259,10.9992C0.8752,11.5338 0.6681,12.1751 0.6667,12.8333V13.3333C0.6667,13.5101 0.7369,13.6797 0.8619,13.8047C0.987,13.9297 1.1565,14 1.3333,14H9C9.1768,14 9.3464,13.9297 9.4714,13.8047C9.5964,13.6797 9.6667,13.5101 9.6667,13.3333V12.8333C9.6653,12.1751 9.4582,11.5338 9.0744,10.9992C8.6905,10.4645 8.1492,10.0632 7.526,9.8513ZM10.8333,1.8333C10.3718,1.8333 9.9207,1.9702 9.537,2.2266C9.1533,2.4829 8.8542,2.8474 8.6776,3.2737C8.501,3.7001 8.4548,4.1692 8.5448,4.6219C8.6349,5.0745 8.8571,5.4902 9.1834,5.8166C9.5097,6.1429 9.9255,6.3651 10.3781,6.4552C10.8307,6.5452 11.2999,6.499 11.7263,6.3224C12.1526,6.1458 12.517,5.8467 12.7734,5.463C13.0298,5.0793 13.1667,4.6281 13.1667,4.1666C13.1667,3.5478 12.9208,2.9543 12.4833,2.5167C12.0457,2.0791 11.4522,1.8333 10.8333,1.8333ZM13.1927,6.518C12.8838,6.8289 12.5166,7.0757 12.112,7.2442C11.7075,7.4128 11.2736,7.4997 10.8354,7.5C10.3971,7.5003 9.9631,7.414 9.5583,7.246C9.1536,7.0781 8.786,6.8318 8.4767,6.5213C8.4347,6.536 8.3893,6.5433 8.348,6.5593C8.478,6.9602 8.5254,7.3833 8.4873,7.8031C8.4491,8.2228 8.3262,8.6304 8.126,9.0013C8.925,9.3435 9.598,9.9255 10.052,10.6666H14.6667C14.8435,10.6666 15.0131,10.5964 15.1381,10.4714C15.2631,10.3464 15.3333,10.1768 15.3333,10V9.5C15.3319,8.8418 15.1248,8.2005 14.741,7.6658C14.3572,7.1311 13.8158,6.7298 13.1927,6.518Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M10,3C9.4872,3 8.986,3.1549 8.5596,3.4452C8.1333,3.7354 7.801,4.148 7.6048,4.6307C7.4085,5.1133 7.3572,5.6444 7.4572,6.1568C7.5573,6.6693 7.8042,7.1399 8.1668,7.5093C8.5293,7.8788 8.9913,8.1303 9.4942,8.2323C9.9971,8.3342 10.5184,8.2819 10.9921,8.082C11.4659,7.882 11.8708,7.5434 12.1557,7.109C12.4405,6.6747 12.5926,6.1639 12.5926,5.6415C12.5926,4.9409 12.3194,4.2691 11.8332,3.7737C11.347,3.2783 10.6876,3 10,3ZM12.6215,8.3034C12.2781,8.6557 11.8696,8.9353 11.4197,9.126C10.9698,9.3168 10.4873,9.415 10,9.415C9.5127,9.415 9.0302,9.3168 8.5803,9.126C8.1304,8.9353 7.7219,8.6557 7.3785,8.3034C6.6861,8.5432 6.0846,8.9976 5.6581,9.6028C5.2317,10.2081 5.0016,10.9341 5,11.6792V12.2453C5,12.4454 5.078,12.6374 5.217,12.7789C5.3559,12.9205 5.5443,13 5.7407,13H14.2593C14.4557,13 14.6441,12.9205 14.783,12.7789C14.922,12.6374 15,12.4454 15,12.2453V11.6792C14.9984,10.9341 14.7683,10.2081 14.3419,9.6028C13.9154,8.9976 13.3139,8.5432 12.6215,8.3034Z"
android:fillColor="#000000"/>
<path
android:pathData="M4.5556,8.2728L3.2828,7L4.5556,5.7272L4.2728,5.4444L3,6.7172L1.7272,5.4444L1.4444,5.7272L2.7172,7L1.4444,8.2728L1.7272,8.5556L3,7.2828L4.2728,8.5556L4.5556,8.2728Z"
android:strokeWidth="0.5"
android:fillColor="#000000"
android:strokeColor="#000000"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M12.2831,8.4211C12.699,7.9623 12.9758,7.3883 13.0794,6.7696C13.1831,6.1509 13.1091,5.5145 12.8665,4.9385C12.6239,4.3626 12.2234,3.8723 11.7141,3.5279C11.2049,3.1835 10.6091,3 10,3C9.3909,3 8.7951,3.1835 8.2859,3.5279C7.7766,3.8723 7.3761,4.3626 7.1335,4.9385C6.8909,5.5145 6.8169,6.1509 6.9206,6.7696C7.0242,7.3883 7.301,7.9623 7.7169,8.4211C6.9461,8.6021 6.2577,9.0474 5.7642,9.684C5.2707,10.3207 5.0013,11.111 5,11.926V13H5.9375V11.926C5.9383,11.2285 6.2074,10.5599 6.6858,10.0668C7.1642,9.5736 7.8128,9.2962 8.4894,9.2954H11.5106C12.1872,9.2962 12.8358,9.5736 13.3142,10.0668C13.7926,10.5599 14.0617,11.2285 14.0625,11.926V13H15V11.926C14.9987,11.111 14.7293,10.3207 14.2358,9.684C13.7423,9.0474 13.0539,8.6021 12.2831,8.4211ZM10,8.49C9.5674,8.49 9.1444,8.3577 8.7847,8.11C8.425,7.8622 8.1446,7.51 7.979,7.0979C7.8134,6.6859 7.7701,6.2325 7.8545,5.7951C7.9389,5.3576 8.1473,4.9558 8.4532,4.6405C8.7591,4.3251 9.1489,4.1103 9.5732,4.0233C9.9976,3.9363 10.4374,3.981 10.8371,4.1516C11.2368,4.3223 11.5785,4.6113 11.8188,4.9822C12.0592,5.353 12.1875,5.789 12.1875,6.235C12.1875,6.833 11.957,7.4066 11.5468,7.8295C11.1366,8.2524 10.5802,8.49 10,8.49Z"
android:fillColor="#000000"/>
<path
android:pathData="M4.5556,8.2728L3.2828,7L4.5556,5.7272L4.2728,5.4444L3,6.7172L1.7272,5.4444L1.4444,5.7272L2.7172,7L1.4444,8.2728L1.7272,8.5556L3,7.2828L4.2728,8.5556L4.5556,8.2728Z"
android:strokeWidth="0.5"
android:fillColor="#000000"
android:strokeColor="#000000"/>
</vector>

View file

@ -0,0 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M7,2C5.8954,2 5,2.8954 5,4V7.5H9.371L8.671,7.1L7.257,5.689L7.957,4.979L11,8L7.957,11.021L7.252,10.311L8.675,8.9L9.375,8.5H5V13H13V4C13,2.8954 12.1046,2 11,2H7Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<group>
<clip-path
android:pathData="M7,2C5.8954,2 5,2.8954 5,4V7.5H9.371L8.671,7.1L7.257,5.689L7.957,4.979L11,8L7.957,11.021L7.252,10.311L8.675,8.9L9.375,8.5H5V13H13V4C13,2.8954 12.1046,2 11,2H7Z"
android:fillType="evenOdd"/>
<path
android:pathData="M5,7.5H4V8.5H5V7.5ZM9.371,7.5V8.5H13.1366L9.8671,6.6318L9.371,7.5ZM8.671,7.1L7.9646,7.8079L8.0591,7.9021L8.1749,7.9682L8.671,7.1ZM7.257,5.689L6.5449,4.9869L5.847,5.6947L6.5506,6.3969L7.257,5.689ZM7.957,4.979L8.6615,4.2693L7.9494,3.5624L7.2449,4.2769L7.957,4.979ZM11,8L11.7045,8.7097L12.4194,8L11.7045,7.2903L11,8ZM7.957,11.021L7.2474,11.7256L7.9519,12.4351L8.6615,11.7307L7.957,11.021ZM7.252,10.311L6.5479,9.6009L5.8373,10.3055L6.5424,11.0156L7.252,10.311ZM8.675,8.9L8.1789,8.0318L8.0645,8.0971L7.9709,8.1899L8.675,8.9ZM9.375,8.5L9.8711,9.3682L13.1406,7.5H9.375V8.5ZM5,8.5V7.5H4V8.5H5ZM5,13H4V14H5V13ZM13,13V14H14V13H13ZM6,4C6,3.4477 6.4477,3 7,3V1C5.3432,1 4,2.3431 4,4H6ZM6,7.5V4H4V7.5H6ZM9.371,6.5H5V8.5H9.371V6.5ZM8.1749,7.9682L8.8749,8.3682L9.8671,6.6318L9.1671,6.2318L8.1749,7.9682ZM6.5506,6.3969L7.9646,7.8079L9.3774,6.3921L7.9634,4.9812L6.5506,6.3969ZM7.2449,4.2769L6.5449,4.9869L7.9691,6.3911L8.6691,5.6811L7.2449,4.2769ZM11.7045,7.2903L8.6615,4.2693L7.2525,5.6887L10.2955,8.7097L11.7045,7.2903ZM8.6615,11.7307L11.7045,8.7097L10.2955,7.2903L7.2525,10.3113L8.6615,11.7307ZM6.5424,11.0156L7.2474,11.7256L8.6666,10.3164L7.9616,9.6064L6.5424,11.0156ZM7.9709,8.1899L6.5479,9.6009L7.9561,11.0211L9.3791,9.6101L7.9709,8.1899ZM8.8789,7.6318L8.1789,8.0318L9.1711,9.7683L9.8711,9.3682L8.8789,7.6318ZM5,9.5H9.375V7.5H5V9.5ZM6,13V8.5H4V13H6ZM13,12H5V14H13V12ZM12,4V13H14V4H12ZM11,3C11.5523,3 12,3.4477 12,4H14C14,2.3431 12.6569,1 11,1V3ZM7,3H11V1H7V3Z"
android:fillColor="#000000"/>
</group>
<path
android:pathData="M2,7.5h3v1h-3z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M6,9.5V13H5V9.5H6ZM11,2H7C6.4696,2 5.9609,2.2107 5.5858,2.5858C5.2107,2.9609 5,3.4696 5,4V6.5H6V4C6,3.7348 6.1054,3.4804 6.2929,3.2929C6.4804,3.1054 6.7348,3 7,3H11C11.2652,3 11.5196,3.1054 11.7071,3.2929C11.8946,3.4804 12,3.7348 12,4V13H13V4C13,3.4696 12.7893,2.9609 12.4142,2.5858C12.0391,2.2107 11.5304,2 11,2ZM7.957,4.979L7.257,5.689L8.671,7.1L9.371,7.5H2V8.5H9.375L8.675,8.9L7.252,10.311L7.957,11.021L11,8L7.957,4.979Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M12.9192,6.3688C13.2038,5.9476 13.3683,5.457 13.3953,4.9494C13.4222,4.4418 13.3104,3.9365 13.072,3.4876C12.8336,3.0387 12.4774,2.6632 12.0418,2.4013C11.6062,2.1395 11.1075,2.0011 10.5992,2.0011C10.0909,2.0011 9.5922,2.1395 9.1566,2.4013C8.721,2.6632 8.3648,3.0387 8.1264,3.4876C7.8879,3.9365 7.7762,4.4418 7.8031,4.9494C7.83,5.457 7.9946,5.9476 8.2792,6.3688C8.1121,6.4223 7.9497,6.4894 7.7936,6.5696C7.6027,6.2473 7.349,5.9666 7.0475,5.7443C6.7461,5.522 6.403,5.3625 6.0387,5.2754C5.6744,5.1883 5.2963,5.1753 4.9269,5.2371C4.5574,5.299 4.2042,5.4345 3.8882,5.6355C3.5721,5.8366 3.2997,6.0991 3.0871,6.4075C2.8745,6.7159 2.7261,7.0639 2.6506,7.4308C2.5752,7.7977 2.5742,8.176 2.6478,8.5433C2.7215,8.9106 2.8681,9.2593 3.0792,9.5688C2.4199,9.7766 1.8437,10.1888 1.434,10.7456C1.0243,11.3024 0.8023,11.9751 0.8,12.6664V13.6H2V12.6664C2.0006,12.1185 2.2185,11.5933 2.6059,11.2059C2.9933,10.8185 3.5185,10.6006 4.0664,10.6H6.7336C7.2814,10.6006 7.8067,10.8185 8.194,11.2059C8.5814,11.5933 8.7993,12.1185 8.8,12.6664V13.6H10V12.6664C9.9979,11.9748 9.7755,11.3018 9.3651,10.7451C8.9547,10.1884 8.3776,9.7769 7.7176,9.5704C8.0325,9.1073 8.2007,8.56 8.2,8C8.1956,7.9065 8.1862,7.8133 8.172,7.7208C8.499,7.5124 8.8786,7.4014 9.2664,7.4008H11.9336C12.4813,7.4014 13.0064,7.6192 13.3938,8.0064C13.7811,8.3936 13.9991,8.9187 14,9.4664V10.4H15.2V9.4664C15.1976,8.7749 14.9753,8.102 14.5653,7.5452C14.1553,6.9884 13.5788,6.5764 12.9192,6.3688ZM5.4,9.6C5.0835,9.6 4.7742,9.5061 4.5111,9.3303C4.248,9.1545 4.0429,8.9046 3.9218,8.6123C3.8007,8.3199 3.769,7.9982 3.8307,7.6878C3.8925,7.3775 4.0448,7.0924 4.2686,6.8686C4.4924,6.6448 4.7775,6.4925 5.0878,6.4307C5.3982,6.369 5.7199,6.4007 6.0123,6.5218C6.3046,6.6429 6.5545,6.8479 6.7303,7.1111C6.9061,7.3742 7,7.6835 7,8C7,8.4243 6.8314,8.8313 6.5314,9.1313C6.2313,9.4314 5.8243,9.6 5.4,9.6ZM10.6,6.4C10.2835,6.4 9.9742,6.3061 9.7111,6.1303C9.448,5.9545 9.2429,5.7046 9.1218,5.4123C9.0007,5.1199 8.969,4.7982 9.0307,4.4878C9.0925,4.1775 9.2449,3.8924 9.4686,3.6686C9.6924,3.4448 9.9775,3.2924 10.2878,3.2307C10.5982,3.169 10.9199,3.2007 11.2123,3.3218C11.5046,3.4429 11.7545,3.6479 11.9303,3.9111C12.1061,4.1742 12.2,4.4835 12.2,4.8C12.2,5.2243 12.0314,5.6313 11.7314,5.9313C11.4313,6.2314 11.0243,6.4 10.6,6.4Z"
android:strokeWidth="0.25"
android:fillColor="#000000" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M14.374,4.4546L12.724,6.1046L9.8954,3.276L11.5454,1.626C11.7329,1.4385 11.9872,1.3332 12.2524,1.3332C12.5175,1.3332 12.7718,1.4385 12.9594,1.626L14.374,3.0406C14.5615,3.2282 14.6668,3.4825 14.6668,3.7476C14.6668,4.0128 14.5615,4.2671 14.374,4.4546ZM2.286,11.0873L1.5447,14.0506C1.5306,14.1066 1.5313,14.1652 1.5466,14.2208C1.5619,14.2763 1.5914,14.327 1.6322,14.3678C1.673,14.4086 1.7236,14.4381 1.7792,14.4534C1.8348,14.4687 1.8934,14.4694 1.9494,14.4553L4.9127,13.714C5.0892,13.6705 5.2506,13.5797 5.3794,13.4513L12.0187,6.812L9.188,3.9833L2.5487,10.6226C2.4207,10.7509 2.3299,10.9115 2.286,11.0873Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M14.3728,3.0406L12.9581,1.626C12.7706,1.4385 12.5163,1.3332 12.2511,1.3332C11.9859,1.3332 11.7316,1.4385 11.5441,1.626L2.5474,10.6226C2.4191,10.7514 2.3283,10.9128 2.2848,11.0893L1.5434,14.0506C1.5293,14.1066 1.53,14.1652 1.5453,14.2208C1.5607,14.2763 1.5902,14.327 1.631,14.3678C1.6717,14.4086 1.7224,14.4381 1.778,14.4534C1.8336,14.4687 1.8922,14.4694 1.9481,14.4553L4.9114,13.714C5.088,13.6705 5.2493,13.5797 5.3781,13.4513L14.3781,4.4546C14.5649,4.2664 14.6692,4.0117 14.6682,3.7465C14.6672,3.4814 14.5609,3.2275 14.3728,3.0406ZM4.6688,12.744L2.7834,13.2153L3.2548,11.3333L9.7694,4.818L11.1841,6.2326L4.6688,12.744ZM11.8908,5.522L10.4768,4.108L12.2514,2.3333L13.6654,3.7473L11.8908,5.522Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M10,3C9.4872,3 8.986,3.1549 8.5596,3.4452C8.1333,3.7354 7.801,4.148 7.6048,4.6307C7.4085,5.1133 7.3572,5.6444 7.4572,6.1568C7.5573,6.6693 7.8042,7.1399 8.1668,7.5093C8.5293,7.8788 8.9913,8.1303 9.4942,8.2323C9.9971,8.3342 10.5184,8.2819 10.9921,8.082C11.4659,7.882 11.8708,7.5434 12.1557,7.109C12.4405,6.6747 12.5926,6.1639 12.5926,5.6415C12.5926,4.9409 12.3194,4.2691 11.8332,3.7737C11.347,3.2783 10.6876,3 10,3ZM12.6215,8.3034C12.2781,8.6557 11.8696,8.9353 11.4197,9.126C10.9698,9.3168 10.4873,9.415 10,9.415C9.5127,9.415 9.0302,9.3168 8.5803,9.126C8.1304,8.9353 7.7219,8.6557 7.3785,8.3034C6.6861,8.5432 6.0846,8.9976 5.6581,9.6028C5.2317,10.2081 5.0016,10.9341 5,11.6792V12.2453C5,12.4454 5.078,12.6374 5.217,12.7789C5.3559,12.9205 5.5443,13 5.7407,13H14.2593C14.4557,13 14.6441,12.9205 14.783,12.7789C14.922,12.6374 15,12.4454 15,12.2453V11.6792C14.9984,10.9341 14.7683,10.2081 14.3419,9.6028C13.9154,8.9976 13.3139,8.5432 12.6215,8.3034Z"
android:fillColor="#000000"/>
<path
android:pathData="M4.5,6.8H2.925V7.05H2.575V6.8H1V7.3H2.575V7.05H2.925V7.3H4.5V6.8Z"
android:fillColor="#000000"/>
<path
android:pathData="M2.925,7.05V6.8H4.5V7.3H2.925V7.05ZM2.925,7.05H2.575M2.575,7.05V6.8H1V7.3H2.575V7.05Z"
android:strokeWidth="0.5"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
</vector>

View file

@ -0,0 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M12.2831,8.4211C12.699,7.9623 12.9758,7.3883 13.0794,6.7696C13.1831,6.1509 13.1091,5.5145 12.8665,4.9385C12.6239,4.3626 12.2234,3.8723 11.7141,3.5279C11.2049,3.1835 10.6091,3 10,3C9.3909,3 8.7951,3.1835 8.2859,3.5279C7.7766,3.8723 7.3761,4.3626 7.1335,4.9385C6.8909,5.5145 6.8169,6.1509 6.9206,6.7696C7.0242,7.3883 7.301,7.9623 7.7169,8.4211C6.9461,8.6021 6.2577,9.0474 5.7642,9.684C5.2707,10.3207 5.0013,11.111 5,11.926V13H5.9375V11.926C5.9383,11.2285 6.2074,10.5599 6.6858,10.0668C7.1642,9.5736 7.8128,9.2962 8.4894,9.2954H11.5106C12.1872,9.2962 12.8358,9.5736 13.3142,10.0668C13.7926,10.5599 14.0617,11.2285 14.0625,11.926V13H15V11.926C14.9987,11.111 14.7293,10.3207 14.2358,9.684C13.7423,9.0474 13.0539,8.6021 12.2831,8.4211ZM10,8.49C9.5674,8.49 9.1444,8.3577 8.7847,8.11C8.425,7.8622 8.1446,7.51 7.979,7.0979C7.8134,6.6859 7.7701,6.2325 7.8545,5.7951C7.9389,5.3576 8.1473,4.9558 8.4532,4.6405C8.7591,4.3251 9.1489,4.1103 9.5732,4.0233C9.9976,3.9363 10.4374,3.981 10.8371,4.1516C11.2368,4.3223 11.5785,4.6113 11.8188,4.9822C12.0592,5.353 12.1875,5.789 12.1875,6.235C12.1875,6.833 11.957,7.4066 11.5468,7.8295C11.1366,8.2524 10.5802,8.49 10,8.49Z"
android:fillColor="#000000"/>
<path
android:pathData="M4.5,6.8H2.925V7.05H2.575V6.8H1V7.3H2.575V7.05H2.925V7.3H4.5V6.8Z"
android:fillColor="#000000"/>
<path
android:pathData="M2.925,7.05V6.8H4.5V7.3H2.925V7.05ZM2.925,7.05H2.575M2.575,7.05V6.8H1V7.3H2.575V7.05Z"
android:strokeWidth="0.5"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M2.25,4H6V13.25C5.9974,13.4481 5.9176,13.6374 5.7775,13.7775C5.6374,13.9176 5.4481,13.9974 5.25,14H4.75C4.5519,13.9974 4.3626,13.9176 4.2225,13.7775C4.0824,13.6374 4.0026,13.4481 4,13.25V10H2.25C1.9185,10 1.6005,9.8683 1.3661,9.6339C1.1317,9.3995 1,9.0815 1,8.75V5.25C1,4.9185 1.1317,4.6006 1.3661,4.3661C1.6005,4.1317 1.9185,4 2.25,4ZM13.54,1.94C13.4053,1.8819 13.2564,1.8652 13.1122,1.8919C12.968,1.9186 12.8349,1.9876 12.73,2.09C11.615,3.2426 10.1019,3.9258 8.5,4H7V10H8.5C10.1019,10.0742 11.615,10.7574 12.73,11.91C12.7986,11.9776 12.8798,12.0309 12.969,12.0669C13.0583,12.103 13.1538,12.121 13.25,12.12C13.3498,12.1203 13.4485,12.0999 13.54,12.06C13.676,12.003 13.7922,11.9071 13.874,11.7844C13.9559,11.6616 13.9997,11.5175 14,11.37V2.63C13.9997,2.4825 13.9559,2.3384 13.874,2.2157C13.7922,2.0929 13.676,1.9971 13.54,1.94Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M14.117,2C14.0399,2.0002 13.9658,2.0294 13.9094,2.0818L10.7086,5.0142H3.2721C2.9434,5.0142 2.6281,5.1448 2.3957,5.3773C2.1633,5.6097 2.0327,5.925 2.0327,6.2537V9.3522C2.0327,9.6809 2.1633,9.9962 2.3957,10.2286C2.6281,10.461 2.9434,10.5916 3.2721,10.5916H10.7086L13.9075,13.5241C13.9639,13.5765 14.0381,13.6057 14.1151,13.6059C14.1973,13.6059 14.2761,13.5732 14.3342,13.5151C14.3923,13.457 14.425,13.3782 14.425,13.296V2.3105C14.4251,2.2285 14.3928,2.1498 14.3351,2.0916C14.2774,2.0334 14.1989,2.0005 14.117,2ZM13.6522,12.2958L12.7784,11.2281L11.0699,9.6621H3.2721C3.1899,9.6621 3.1111,9.6294 3.053,9.5713C2.9949,9.5132 2.9622,9.4344 2.9622,9.3522V6.2537C2.9622,6.1715 2.9949,6.0927 3.053,6.0346C3.1111,5.9765 3.1899,5.9438 3.2721,5.9438H11.0699L12.7784,4.3778L13.6522,3.3101L13.4973,5.0142V10.5916L13.6522,12.2958Z"
android:fillColor="#000000"/>
<path
android:pathData="M5.7509,5.3241h0.9296v8.6759h-0.9296z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M8,0.6666C6.5496,0.6666 5.1318,1.0967 3.9258,1.9025C2.7199,2.7083 1.7799,3.8536 1.2249,5.1936C0.6698,6.5336 0.5246,8.0081 0.8076,9.4306C1.0905,10.8531 1.789,12.1598 2.8145,13.1854C3.8401,14.211 5.1468,14.9094 6.5693,15.1924C7.9919,15.4753 9.4663,15.3301 10.8063,14.7751C12.1463,14.22 13.2916,13.2801 14.0974,12.0741C14.9032,10.8682 15.3333,9.4504 15.3333,8C15.3333,6.055 14.5607,4.1898 13.1854,2.8145C11.8102,1.4392 9.9449,0.6666 8,0.6666ZM7.2933,3.9593C7.4332,3.8196 7.6114,3.7245 7.8053,3.686C7.9992,3.6475 8.2002,3.6673 8.3829,3.743C8.5655,3.8187 8.7216,3.9469 8.8315,4.1113C8.9413,4.2757 9,4.4689 9,4.6666C8.9998,4.8643 8.9411,5.0574 8.8312,5.2217C8.7213,5.386 8.5652,5.5141 8.3826,5.5897C8.1999,5.6653 7.999,5.6851 7.8052,5.6466C7.6113,5.6081 7.4332,5.513 7.2933,5.3733C7.1059,5.1858 7.0005,4.9315 7.0005,4.6663C7.0005,4.4011 7.1059,4.1468 7.2933,3.9593ZM10,12H6V11H7.6667V7.6666H6.3333V6.6666H8.6667V11H10V12Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M8,1.6666C9.2526,1.6666 10.4771,2.0381 11.5186,2.734C12.5601,3.4299 13.3719,4.419 13.8512,5.5763C14.3306,6.7336 14.456,8.007 14.2116,9.2355C13.9673,10.4641 13.3641,11.5926 12.4783,12.4783C11.5926,13.364 10.4641,13.9672 9.2356,14.2116C8.007,14.456 6.7336,14.3306 5.5763,13.8512C4.4191,13.3718 3.4299,12.5601 2.734,11.5186C2.0381,10.4771 1.6667,9.2526 1.6667,8C1.6686,6.3208 2.3365,4.7111 3.5238,3.5238C4.7111,2.3365 6.3209,1.6686 8,1.6666ZM8,0.6666C6.5496,0.6666 5.1318,1.0967 3.9258,1.9025C2.7199,2.7083 1.7799,3.8536 1.2249,5.1936C0.6698,6.5336 0.5246,8.0081 0.8076,9.4306C1.0905,10.8531 1.789,12.1598 2.8145,13.1854C3.8401,14.211 5.1468,14.9094 6.5693,15.1924C7.9919,15.4753 9.4663,15.3301 10.8063,14.7751C12.1463,14.22 13.2916,13.2801 14.0974,12.0741C14.9032,10.8682 15.3333,9.4504 15.3333,8C15.3333,6.055 14.5607,4.1898 13.1854,2.8145C11.8102,1.4392 9.9449,0.6666 8,0.6666ZM8,5.6666C8.2652,5.6666 8.5196,5.5613 8.7071,5.3737C8.8946,5.1862 9,4.9318 9,4.6666C9.0001,4.5021 8.9597,4.3401 8.8822,4.195C8.8048,4.0498 8.6927,3.926 8.556,3.8346C8.4192,3.7431 8.262,3.6868 8.0983,3.6706C7.9346,3.6544 7.7694,3.6789 7.6174,3.7418C7.4654,3.8047 7.3313,3.9042 7.227,4.0314C7.1226,4.1586 7.0512,4.3095 7.0192,4.4709C6.9871,4.6323 6.9954,4.799 7.0432,4.9564C7.091,5.1139 7.1769,5.257 7.2933,5.3733C7.3846,5.4682 7.4945,5.5432 7.6161,5.5937C7.7376,5.6442 7.8684,5.669 8,5.6666ZM8.6667,11V6.6666H6.3333V7.6666H7.6667V11H6V12H10V11H8.6667Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M10,3C9.4872,3 8.986,3.1549 8.5596,3.4452C8.1333,3.7354 7.801,4.148 7.6048,4.6307C7.4085,5.1133 7.3572,5.6444 7.4572,6.1568C7.5573,6.6693 7.8042,7.1399 8.1668,7.5093C8.5293,7.8788 8.9913,8.1303 9.4942,8.2323C9.9971,8.3342 10.5184,8.2819 10.9921,8.082C11.4659,7.882 11.8708,7.5434 12.1557,7.109C12.4405,6.6747 12.5926,6.1639 12.5926,5.6415C12.5926,4.9409 12.3194,4.2691 11.8332,3.7737C11.347,3.2783 10.6876,3 10,3ZM12.6215,8.3034C12.2781,8.6557 11.8696,8.9353 11.4197,9.126C10.9698,9.3168 10.4873,9.415 10,9.415C9.5127,9.415 9.0302,9.3168 8.5803,9.126C8.1304,8.9353 7.7219,8.6557 7.3785,8.3034C6.6861,8.5432 6.0846,8.9976 5.6581,9.6028C5.2317,10.2081 5.0016,10.9341 5,11.6792V12.2453C5,12.4454 5.078,12.6374 5.217,12.7789C5.3559,12.9205 5.5443,13 5.7407,13H14.2593C14.4557,13 14.6441,12.9205 14.783,12.7789C14.922,12.6374 15,12.4454 15,12.2453V11.6792C14.9984,10.9341 14.7683,10.2081 14.3419,9.6028C13.9154,8.9976 13.3139,8.5432 12.6215,8.3034Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M12.2831,8.4211C12.699,7.9623 12.9758,7.3883 13.0794,6.7696C13.1831,6.1509 13.1091,5.5145 12.8665,4.9385C12.6239,4.3626 12.2234,3.8723 11.7141,3.5279C11.2049,3.1835 10.6091,3 10,3C9.3909,3 8.7951,3.1835 8.2859,3.5279C7.7766,3.8723 7.3761,4.3626 7.1335,4.9385C6.8909,5.5145 6.8169,6.1509 6.9206,6.7696C7.0242,7.3883 7.301,7.9623 7.7169,8.4211C6.9461,8.6021 6.2577,9.0474 5.7642,9.684C5.2707,10.3207 5.0013,11.111 5,11.926V13H5.9375V11.926C5.9383,11.2285 6.2074,10.5599 6.6858,10.0668C7.1642,9.5736 7.8128,9.2962 8.4894,9.2954H11.5106C12.1872,9.2962 12.8358,9.5736 13.3142,10.0668C13.7926,10.5599 14.0617,11.2285 14.0625,11.926V13H15V11.926C14.9987,11.111 14.7293,10.3207 14.2358,9.684C13.7423,9.0474 13.0539,8.6021 12.2831,8.4211ZM10,8.49C9.5674,8.49 9.1444,8.3577 8.7847,8.11C8.425,7.8622 8.1446,7.51 7.979,7.0979C7.8134,6.6859 7.7701,6.2325 7.8545,5.7951C7.9389,5.3576 8.1473,4.9558 8.4532,4.6405C8.7591,4.3251 9.1489,4.1103 9.5732,4.0233C9.9976,3.9363 10.4374,3.981 10.8371,4.1516C11.2368,4.3223 11.5785,4.6113 11.8188,4.9822C12.0592,5.353 12.1875,5.789 12.1875,6.235C12.1875,6.833 11.957,7.4066 11.5468,7.8295C11.1366,8.2524 10.5802,8.49 10,8.49Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M8,10.349L5.076,7.424L5.924,6.576L8,8.651L13.68,2.971C11.5352,2.9273 9.4942,2.0394 8,0.5C8,0.5 6,3 1.5,3C1.5,10 5,13.227 8,15C9.9692,13.8873 11.6066,12.2704 12.744,10.3154C13.8815,8.3604 14.4779,6.1378 14.472,3.876L8,10.349Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M14.36,5.261C14.1631,7.2767 13.482,9.2149 12.3746,10.9106C11.2672,12.6063 9.7664,14.0093 8,15C5,13.227 1.5,10 1.5,3C6,3 8,0.5 8,0.5C9.2135,1.7645 10.8173,2.5838 12.553,2.826L11.708,3.671C10.3543,3.3559 9.0876,2.7434 8,1.878C6.4293,3.1133 4.5187,3.8394 2.524,3.959C2.809,9.652 5.624,12.313 7.994,13.824C9.3085,13.0175 10.4435,11.9498 11.3287,10.6869C12.2138,9.424 12.8303,7.9928 13.14,6.482L14.36,5.261ZM14.854,3.354L14.146,2.646L8,8.793L5.854,6.646L5.146,7.354L8,10.207L14.854,3.354Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M12.66,5.22C12.7899,5.1918 12.9098,5.1292 13.0072,5.0387C13.1045,4.9481 13.1757,4.8331 13.2132,4.7055C13.2506,4.578 13.2531,4.4427 13.2202,4.3139C13.1874,4.1851 13.1205,4.0675 13.0265,3.9735C12.9325,3.8795 12.8149,3.8126 12.6861,3.7798C12.5573,3.7469 12.422,3.7494 12.2945,3.7868C12.1669,3.8243 12.0519,3.8955 11.9613,3.9928C11.8708,4.0902 11.8082,4.2101 11.78,4.34C10.8603,3.5825 9.7358,3.1161 8.55,3L9,1H7L7.45,3C6.2642,3.1161 5.1397,3.5825 4.22,4.34C4.1918,4.2101 4.1292,4.0902 4.0387,3.9928C3.9481,3.8955 3.8331,3.8243 3.7055,3.7868C3.578,3.7494 3.4427,3.7469 3.3139,3.7798C3.1851,3.8126 3.0675,3.8795 2.9736,3.9735C2.8795,4.0675 2.8126,4.1851 2.7798,4.3139C2.7469,4.4427 2.7494,4.578 2.7868,4.7055C2.8244,4.8331 2.8955,4.9481 2.9928,5.0387C3.0902,5.1292 3.2101,5.1918 3.34,5.22C2.6259,6.1004 2.1759,7.1652 2.042,8.2908C1.9081,9.4165 2.0959,10.5571 2.5835,11.5805C3.0712,12.6038 3.8387,13.4681 4.7973,14.0732C5.756,14.6783 6.8664,14.9995 8,14.9995C9.1336,14.9995 10.244,14.6783 11.2027,14.0732C12.1613,13.4681 12.9289,12.6038 13.4165,11.5805C13.9041,10.5571 14.0919,9.4165 13.958,8.2908C13.8241,7.1652 13.3741,6.1004 12.66,5.22ZM8,4L7.9655,4.0001C7.9864,4 8.0073,4 8.0282,4.0001L8,4ZM8.6187,10.2854C8.7828,10.1213 8.875,9.8987 8.875,9.6667L8.2917,5H7.7083L7.125,9.6667C7.125,9.8987 7.2172,10.1213 7.3813,10.2854C7.5454,10.4495 7.7679,10.5417 8,10.5417C8.2321,10.5417 8.4546,10.4495 8.6187,10.2854Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M13.0072,5.0387C12.9098,5.1292 12.7899,5.1918 12.66,5.22C13.3741,6.1004 13.8241,7.1652 13.958,8.2908C14.0919,9.4165 13.9041,10.5571 13.4165,11.5805C13.2666,11.895 13.0903,12.1944 12.8902,12.476L14.7279,14.3137L14.0208,15.0208L12.2424,13.2424L2.9736,3.9735L2,3L2.7071,2.2929L4.5215,4.1073C5.3806,3.4869 6.3908,3.1037 7.45,3L7,1H9L8.55,3C9.7358,3.1161 10.8603,3.5825 11.78,4.34C11.8082,4.2101 11.8708,4.0902 11.9613,3.9928C12.0519,3.8955 12.1669,3.8243 12.2945,3.7868C12.422,3.7494 12.5573,3.7469 12.6861,3.7798C12.8149,3.8126 12.9325,3.8795 13.0265,3.9735C13.1205,4.0675 13.1874,4.1851 13.2202,4.3139C13.2531,4.4427 13.2506,4.578 13.2132,4.7055C13.1757,4.8331 13.1045,4.9481 13.0072,5.0387ZM3.1094,5.5236C2.5288,6.3405 2.1608,7.2916 2.042,8.2908C1.9081,9.4165 2.0959,10.5571 2.5835,11.5805C3.0712,12.6038 3.8387,13.4681 4.7973,14.0732C5.756,14.6783 6.8664,14.9995 8,14.9995C9.1336,14.9995 10.244,14.6783 11.2027,14.0732C11.2956,14.0146 11.3867,13.9535 11.4759,13.8901L3.1094,5.5236ZM7.4534,7.0392L7.7083,5H8.2917L8.7027,8.2885L7.4534,7.0392ZM7.9655,4.0001L8,4L8.0282,4.0001C8.0073,4 7.9864,4 7.9655,4.0001Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M11.47,13.89C10.4585,14.6149 9.2445,15.0033 8,15C6.4087,15 4.8826,14.3679 3.7574,13.2426C2.6321,12.1174 2,10.5913 2,9C2.0004,7.7576 2.3923,6.5469 3.12,5.54L3.83,6.25C3.2027,7.2109 2.9251,8.3584 3.0437,9.4999C3.1623,10.6413 3.6699,11.7072 4.4814,12.5186C5.2928,13.3301 6.3587,13.8377 7.5001,13.9563C8.6416,14.0749 9.7891,13.7973 10.75,13.17L11.47,13.89ZM14.71,14.29L14,15L2,3L2.71,2.29L4.53,4.12C5.3872,3.4951 6.3948,3.1086 7.45,3L7,1H9L8.55,3C9.7326,3.1074 10.8567,3.5633 11.78,4.31C11.8082,4.1801 11.8708,4.0602 11.9613,3.9628C12.0519,3.8655 12.1669,3.7943 12.2945,3.7569C12.422,3.7194 12.5573,3.7169 12.6861,3.7498C12.8149,3.7826 12.9325,3.8496 13.0265,3.9435C13.1204,4.0375 13.1874,4.1551 13.2202,4.2839C13.2531,4.4127 13.2506,4.548 13.2131,4.6755C13.1757,4.8031 13.1045,4.9181 13.0072,5.0087C12.9098,5.0992 12.7899,5.1618 12.66,5.19C13.4844,6.2077 13.9531,7.4672 13.9946,8.7763C14.0362,10.0854 13.6482,11.3721 12.89,12.44L14.71,14.29ZM13,9C12.999,8.0979 12.7539,7.2129 12.2907,6.4387C11.8275,5.6646 11.1636,5.0302 10.3691,4.6027C9.5747,4.1753 8.6795,3.9707 7.7783,4.0107C6.877,4.0507 6.0034,4.3338 5.25,4.83L7.49,7.08L7.75,5H8.25L8.66,8.24L12.17,11.75C12.7097,10.9342 12.9983,9.9781 13,9Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M12.66,5.22C12.7899,5.1918 12.9098,5.1292 13.0072,5.0387C13.1045,4.9481 13.1757,4.8331 13.2132,4.7055C13.2506,4.578 13.2531,4.4427 13.2202,4.3139C13.1874,4.1851 13.1205,4.0675 13.0265,3.9735C12.9325,3.8795 12.8149,3.8126 12.6861,3.7798C12.5573,3.7469 12.422,3.7494 12.2945,3.7868C12.1669,3.8243 12.0519,3.8955 11.9613,3.9928C11.8708,4.0902 11.8082,4.2101 11.78,4.34C10.8603,3.5825 9.7358,3.1161 8.55,3L9,1H7L7.45,3C6.2642,3.1161 5.1397,3.5825 4.22,4.34C4.1918,4.2101 4.1292,4.0902 4.0387,3.9928C3.9481,3.8955 3.8331,3.8243 3.7055,3.7868C3.578,3.7494 3.4427,3.7469 3.3139,3.7798C3.1851,3.8126 3.0675,3.8795 2.9736,3.9735C2.8795,4.0675 2.8126,4.1851 2.7798,4.3139C2.7469,4.4427 2.7494,4.578 2.7868,4.7055C2.8244,4.8331 2.8955,4.9481 2.9928,5.0387C3.0902,5.1292 3.2101,5.1918 3.34,5.22C2.6259,6.1004 2.1759,7.1652 2.042,8.2908C1.9081,9.4165 2.0959,10.5571 2.5835,11.5805C3.0712,12.6038 3.8387,13.4681 4.7973,14.0732C5.756,14.6783 6.8664,14.9995 8,14.9995C9.1336,14.9995 10.244,14.6783 11.2027,14.0732C12.1613,13.4681 12.9289,12.6038 13.4165,11.5805C13.9041,10.5571 14.0919,9.4165 13.958,8.2908C13.8241,7.1652 13.3741,6.1004 12.66,5.22ZM8,14C7.0111,14 6.0444,13.7068 5.2221,13.1573C4.3999,12.6079 3.759,11.827 3.3806,10.9134C3.0022,9.9998 2.9032,8.9944 3.0961,8.0246C3.289,7.0546 3.7652,6.1637 4.4645,5.4645C5.1637,4.7652 6.0546,4.289 7.0245,4.0961C7.9945,3.9032 8.9998,4.0022 9.9134,4.3806C10.8271,4.759 11.6079,5.3999 12.1574,6.2221C12.7068,7.0444 13,8.0111 13,9C13,9.6566 12.8707,10.3068 12.6194,10.9134C12.3681,11.52 11.9998,12.0712 11.5355,12.5355C11.0712,12.9998 10.52,13.3681 9.9134,13.6194C9.3068,13.8707 8.6566,14 8,14ZM8.75,9C8.75,9.1989 8.671,9.3897 8.5303,9.5303C8.3897,9.671 8.1989,9.75 8,9.75C7.8011,9.75 7.6103,9.671 7.4697,9.5303C7.329,9.3897 7.25,9.1989 7.25,9L7.75,5H8.25L8.75,9Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M6.1147,12.3333L1.9893,8.2086L2.6967,7.5013L6.1147,10.9193L13.3033,3.73L14.0107,4.4373L6.1147,12.3333Z"
android:strokeWidth="0.5"
android:fillColor="#000000"
android:strokeColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M6.1146,12.3333L1.9893,8.2086L2.6967,7.5013L6.1146,10.9193L13.3033,3.73L14.0107,4.4373L6.1146,12.3333Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M14.23,4.16C14.0024,4.063 13.7509,4.0369 13.5083,4.0851C13.2657,4.1333 13.0433,4.2535 12.87,4.43L11,6.29V4.75C10.9974,4.2867 10.8122,3.8431 10.4845,3.5155C10.1569,3.1878 9.7133,3.0026 9.25,3H2.75C2.2867,3.0026 1.8431,3.1878 1.5155,3.5155C1.1878,3.8431 1.0026,4.2867 1,4.75V11.25C1.0026,11.7133 1.1878,12.1569 1.5155,12.4845C1.8431,12.8122 2.2867,12.9974 2.75,13H9.25C9.7133,12.9974 10.1569,12.8122 10.4845,12.4845C10.8122,12.1569 10.9974,11.7133 11,11.25V9.71L12.87,11.57C12.9846,11.6872 13.1215,11.7803 13.2726,11.8439C13.4238,11.9074 13.5861,11.9401 13.75,11.94C13.9152,11.9406 14.0788,11.9066 14.23,11.84C14.4589,11.7477 14.6548,11.5887 14.7921,11.3836C14.9294,11.1785 15.0019,10.9368 15,10.69V5.31C15.0019,5.0632 14.9294,4.8215 14.7921,4.6164C14.6548,4.4113 14.4589,4.2523 14.23,4.16ZM10,11.25C9.9974,11.4481 9.9176,11.6374 9.7775,11.7775C9.6374,11.9176 9.4481,11.9974 9.25,12H2.75C2.5519,11.9974 2.3626,11.9176 2.2225,11.7775C2.0824,11.6374 2.0026,11.4481 2,11.25V4.75C2.0026,4.5519 2.0824,4.3626 2.2225,4.2225C2.3626,4.0824 2.5519,4.0026 2.75,4H9.25C9.4481,4.0026 9.6374,4.0824 9.7775,4.2225C9.9176,4.3626 9.9974,4.5519 10,4.75V11.25ZM14,10.69C14.0002,10.7388 13.9861,10.7866 13.9594,10.8274C13.9327,10.8683 13.8947,10.9005 13.85,10.92C13.8035,10.9398 13.7523,10.9456 13.7026,10.9367C13.6528,10.9278 13.6068,10.9046 13.57,10.87L11,8.29V7.71L13.57,5.13C13.6118,5.1033 13.6604,5.0891 13.71,5.0891C13.7596,5.0891 13.8082,5.1033 13.85,5.13C13.8947,5.1495 13.9327,5.1817 13.9594,5.2226C13.9861,5.2634 14.0002,5.3112 14,5.36V10.69ZM4.71,10H8V11H3V6H4V9.29L8.15,5.15L8.85,5.85L4.71,10Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M9,3H3C2.4696,3 1.9609,3.2107 1.5858,3.5858C1.2107,3.9609 1,4.4696 1,5V11C1,11.5304 1.2107,12.0391 1.5858,12.4142C1.9609,12.7893 2.4696,13 3,13H9C9.5304,13 10.0391,12.7893 10.4142,12.4142C10.7893,12.0391 11,11.5304 11,11V5C11,4.4696 10.7893,3.9609 10.4142,3.5858C10.0391,3.2107 9.5304,3 9,3ZM8,10V11H3V6H4V9.29L8.15,5.15L8.85,5.85L4.71,10H8ZM15,5.31V10.69C14.9999,10.8382 14.9558,10.9831 14.8734,11.1063C14.791,11.2295 14.6739,11.3256 14.5369,11.3823C14.4,11.439 14.2493,11.4538 14.1039,11.425C13.9585,11.3961 13.8249,11.3248 13.72,11.22L12,9.5V6.5L13.72,4.78C13.8249,4.6752 13.9585,4.6039 14.1039,4.575C14.2493,4.5462 14.4,4.561 14.5369,4.6177C14.6739,4.6744 14.791,4.7705 14.8734,4.8937C14.9558,5.0169 14.9999,5.1618 15,5.31Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M9,3H3C2.4696,3 1.9609,3.2107 1.5858,3.5858C1.2107,3.9609 1,4.4696 1,5V11C1,11.5304 1.2107,12.0391 1.5858,12.4142C1.9609,12.7893 2.4696,13 3,13H9C9.5304,13 10.0391,12.7893 10.4142,12.4142C10.7893,12.0391 11,11.5304 11,11V5C11,4.4696 10.7893,3.9609 10.4142,3.5858C10.0391,3.2107 9.5304,3 9,3ZM8.85,10.15L8.15,10.85L6,8.71L3.85,10.85L3.15,10.15L5.29,8L3.15,5.85L3.85,5.15L6,7.29L8.15,5.15L8.85,5.85L6.71,8L8.85,10.15ZM15,5.31V10.69C14.9999,10.8382 14.9558,10.9831 14.8734,11.1063C14.791,11.2295 14.6739,11.3256 14.5369,11.3823C14.4,11.439 14.2493,11.4538 14.1039,11.425C13.9585,11.3961 13.8249,11.3248 13.72,11.22L12,9.5V6.5L13.72,4.78C13.8249,4.6752 13.9585,4.6039 14.1039,4.575C14.2493,4.5462 14.4,4.561 14.5369,4.6177C14.6739,4.6744 14.791,4.7705 14.8734,4.8937C14.9558,5.0169 14.9999,5.1618 15,5.31Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M14.23,4.16C14.0024,4.063 13.7509,4.0369 13.5083,4.0851C13.2657,4.1333 13.0433,4.2535 12.87,4.43L11,6.29V4.75C10.9974,4.2867 10.8122,3.8431 10.4845,3.5155C10.1569,3.1878 9.7133,3.0026 9.25,3H2.75C2.2867,3.0026 1.8431,3.1878 1.5155,3.5155C1.1878,3.8431 1.0026,4.2867 1,4.75V11.25C1.0026,11.7133 1.1878,12.1569 1.5155,12.4845C1.8431,12.8122 2.2867,12.9974 2.75,13H9.25C9.7133,12.9974 10.1569,12.8122 10.4845,12.4845C10.8122,12.1569 10.9974,11.7133 11,11.25V9.71L12.87,11.57C12.9846,11.6872 13.1215,11.7803 13.2726,11.8439C13.4238,11.9074 13.5861,11.9401 13.75,11.94C13.9152,11.9406 14.0788,11.9066 14.23,11.84C14.4589,11.7477 14.6548,11.5887 14.7921,11.3836C14.9294,11.1785 15.0019,10.9368 15,10.69V5.31C15.0019,5.0632 14.9294,4.8215 14.7921,4.6164C14.6548,4.4113 14.4589,4.2523 14.23,4.16ZM10,11.25C9.9974,11.4481 9.9176,11.6374 9.7775,11.7775C9.6374,11.9176 9.4481,11.9974 9.25,12H2.75C2.5519,11.9974 2.3626,11.9176 2.2225,11.7775C2.0824,11.6374 2.0026,11.4481 2,11.25V4.75C2.0026,4.5519 2.0824,4.3626 2.2225,4.2225C2.3626,4.0824 2.5519,4.0026 2.75,4H9.25C9.4481,4.0026 9.6374,4.0824 9.7775,4.2225C9.9176,4.3626 9.9974,4.5519 10,4.75V11.25ZM14,10.69C14.0002,10.7388 13.9861,10.7866 13.9594,10.8274C13.9327,10.8683 13.8947,10.9005 13.85,10.92C13.8035,10.9398 13.7523,10.9456 13.7026,10.9367C13.6528,10.9278 13.6068,10.9046 13.57,10.87L11,8.29V7.71L13.57,5.13C13.6118,5.1033 13.6604,5.0891 13.71,5.0891C13.7596,5.0891 13.8082,5.1033 13.85,5.13C13.8947,5.1495 13.9327,5.1817 13.9594,5.2226C13.9861,5.2634 14.0002,5.3112 14,5.36V10.69ZM6.71,8L8.85,10.15L8.15,10.85L6,8.71L3.85,10.85L3.15,10.15L5.29,8L3.15,5.85L3.85,5.15L6,7.29L8.15,5.15L8.85,5.85L6.71,8Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M9,3H3C2.4696,3 1.9609,3.2107 1.5858,3.5858C1.2107,3.9609 1,4.4696 1,5V11C1,11.5304 1.2107,12.0391 1.5858,12.4142C1.9609,12.7893 2.4696,13 3,13H9C9.5304,13 10.0391,12.7893 10.4142,12.4142C10.7893,12.0391 11,11.5304 11,11V5C11,4.4696 10.7893,3.9609 10.4142,3.5858C10.0391,3.2107 9.5304,3 9,3ZM9,10H8V6.71L3.85,10.85L3.15,10.15L7.29,6H4V5H9V10ZM15,5.31V10.69C14.9999,10.8382 14.9558,10.9831 14.8734,11.1063C14.791,11.2295 14.6739,11.3256 14.5369,11.3823C14.4,11.439 14.2493,11.4538 14.1039,11.425C13.9585,11.3961 13.8249,11.3248 13.72,11.22L12,9.5V6.5L13.72,4.78C13.8249,4.6752 13.9585,4.6039 14.1039,4.575C14.2493,4.5462 14.4,4.561 14.5369,4.6177C14.6739,4.6744 14.791,4.7705 14.8734,4.8937C14.9558,5.0169 14.9999,5.1618 15,5.31Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M14.23,4.16C14.0024,4.063 13.7509,4.0369 13.5083,4.0851C13.2657,4.1333 13.0433,4.2535 12.87,4.43L11,6.29V4.75C10.9974,4.2867 10.8122,3.8431 10.4845,3.5155C10.1569,3.1878 9.7133,3.0026 9.25,3H2.75C2.2867,3.0026 1.8431,3.1878 1.5155,3.5155C1.1878,3.8431 1.0026,4.2867 1,4.75V11.25C1.0026,11.7133 1.1878,12.1569 1.5155,12.4845C1.8431,12.8122 2.2867,12.9974 2.75,13H9.25C9.7133,12.9974 10.1569,12.8122 10.4845,12.4845C10.8122,12.1569 10.9974,11.7133 11,11.25V9.71L12.87,11.57C12.9846,11.6872 13.1215,11.7803 13.2726,11.8439C13.4238,11.9074 13.5861,11.9401 13.75,11.94C13.9152,11.9406 14.0788,11.9066 14.23,11.84C14.4589,11.7477 14.6548,11.5887 14.7921,11.3836C14.9294,11.1785 15.0019,10.9368 15,10.69V5.31C15.0019,5.0632 14.9294,4.8215 14.7921,4.6164C14.6548,4.4113 14.4589,4.2523 14.23,4.16ZM10,11.25C9.9974,11.4481 9.9176,11.6374 9.7775,11.7775C9.6374,11.9176 9.4481,11.9974 9.25,12H2.75C2.5519,11.9974 2.3626,11.9176 2.2225,11.7775C2.0824,11.6374 2.0026,11.4481 2,11.25V4.75C2.0026,4.5519 2.0824,4.3626 2.2225,4.2225C2.3626,4.0824 2.5519,4.0026 2.75,4H9.25C9.4481,4.0026 9.6374,4.0824 9.7775,4.2225C9.9176,4.3626 9.9974,4.5519 10,4.75V11.25ZM14,10.69C14.0002,10.7388 13.9861,10.7866 13.9594,10.8274C13.9327,10.8683 13.8947,10.9005 13.85,10.92C13.8035,10.9398 13.7523,10.9456 13.7026,10.9367C13.6528,10.9278 13.6068,10.9046 13.57,10.87L11,8.29V7.71L13.57,5.13C13.6118,5.1033 13.6604,5.0891 13.71,5.0891C13.7596,5.0891 13.8082,5.1033 13.85,5.13C13.8947,5.1495 13.9327,5.1817 13.9594,5.2226C13.9861,5.2634 14.0002,5.3112 14,5.36V10.69ZM9,5V10H8V6.71L3.85,10.85L3.15,10.15L7.29,6H4V5H9Z"
android:fillColor="#000000"/>
</vector>

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.conversation.ConversationUpdateItem xmlns:android="http://schemas.android.com/apk/res/android"
<org.thoughtcrime.securesms.conversation.ConversationUpdateItem
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/conversation_update_item"
@ -14,62 +15,13 @@
android:paddingEnd="28dp"
android:paddingTop="8dp">
<LinearLayout
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/conversation_update_body"
style="@style/Signal.Text.Preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="7dp"
android:layout_marginTop="12dp"
android:gravity="center">
<ImageView
android:id="@+id/conversation_update_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="6dp"
app:srcCompat="@drawable/ic_timer_24" />
<TextView
android:id="@+id/conversation_update_title"
style="@style/Signal.Text.Caption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?conversation_item_update_text_color"
tools:text="1 hour" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="7dp"
android:gravity="center"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/conversation_update_body"
style="@style/Signal.Text.Preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="?attr/conversation_item_update_text_color"
tools:text="Gwen Stacy set the disappearing message timer to 1 hour" />
<TextView
android:id="@+id/conversation_update_date"
style="@style/Signal.Text.Caption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="6dp"
android:autoLink="none"
android:gravity="center"
android:linksClickable="false"
android:minWidth="15sp"
android:textColor="?conversation_item_update_text_color"
tools:text="30 min ago" />
</LinearLayout>
android:textColor="?attr/conversation_item_update_text_color"
tools:text="Gwen Stacy set the disappearing message timer to 1 hour" />
</org.thoughtcrime.securesms.conversation.ConversationUpdateItem>

View file

@ -937,13 +937,11 @@
<string name="MessageRecord_left_group">You have left the group.</string>
<string name="MessageRecord_you_updated_group">You updated the group.</string>
<string name="MessageRecord_the_group_was_updated">The group was updated.</string>
<string name="MessageRecord_you_called">You called</string>
<string name="MessageRecord_called_you">Contact called</string>
<string name="MessageRecord_missed_call">Missed call</string>
<string name="MessageRecord_you_called_date">You called • %1$s</string>
<string name="MessageRecord_missed_call_date">Missed call • %1$s</string>
<string name="MessageRecord_s_updated_group">%s updated the group.</string>
<string name="MessageRecord_s_called_you">%s called you</string>
<string name="MessageRecord_s_called_you_date">%1$s called you • %2$s</string>
<string name="MessageRecord_called_s">Called %s</string>
<string name="MessageRecord_missed_call_from">Missed call from %s</string>
<string name="MessageRecord_s_joined_signal">%s is on Signal!</string>
<string name="MessageRecord_you_disabled_disappearing_messages">You disabled disappearing messages.</string>
<string name="MessageRecord_s_disabled_disappearing_messages">%1$s disabled disappearing messages.</string>

View file

@ -29,28 +29,28 @@ public final class UpdateDescriptionTest {
@Test
public void staticDescription_byGetStaticString() {
UpdateDescription description = UpdateDescription.staticDescription("update");
UpdateDescription description = UpdateDescription.staticDescription("update", 0, 0);
assertEquals("update", description.getStaticString());
}
@Test
public void staticDescription_has_empty_mentions() {
UpdateDescription description = UpdateDescription.staticDescription("update");
UpdateDescription description = UpdateDescription.staticDescription("update", 0, 0);
assertTrue(description.getMentioned().isEmpty());
}
@Test
public void staticDescription_byString() {
UpdateDescription description = UpdateDescription.staticDescription("update");
UpdateDescription description = UpdateDescription.staticDescription("update", 0, 0);
assertEquals("update", description.getString());
}
@Test(expected = AssertionError.class)
public void stringFactory_cannot_run_on_main_thread() {
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), () -> "update");
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), () -> "update", 0, 0);
setMainThread(true);
@ -59,7 +59,7 @@ public final class UpdateDescriptionTest {
@Test(expected = UnsupportedOperationException.class)
public void stringFactory_cannot_call_static_string() {
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), () -> "update");
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), () -> "update", 0, 0);
description.getStaticString();
}
@ -73,7 +73,7 @@ public final class UpdateDescriptionTest {
return "update";
};
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory);
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory, 0 , 0);
assertEquals(0, factoryCalls.get());
@ -89,7 +89,7 @@ public final class UpdateDescriptionTest {
public void stringFactory_reevaluated_on_every_call() {
AtomicInteger factoryCalls = new AtomicInteger();
UpdateDescription.StringFactory stringFactory = () -> "call" + factoryCalls.incrementAndGet();
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory);
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory, 0, 0);
setMainThread(false);
@ -100,8 +100,8 @@ public final class UpdateDescriptionTest {
@Test
public void concat_static_lines() {
UpdateDescription description1 = UpdateDescription.staticDescription("update1");
UpdateDescription description2 = UpdateDescription.staticDescription("update2");
UpdateDescription description1 = UpdateDescription.staticDescription("update1", 0, 0);
UpdateDescription description2 = UpdateDescription.staticDescription("update2", 0 , 0);
UpdateDescription description = UpdateDescription.concatWithNewLines(Arrays.asList(description1, description2));
@ -112,7 +112,7 @@ public final class UpdateDescriptionTest {
@Test
public void concat_single_does_not_make_new_object() {
UpdateDescription description = UpdateDescription.staticDescription("update1");
UpdateDescription description = UpdateDescription.staticDescription("update1", 0 , 0);
UpdateDescription concat = UpdateDescription.concatWithNewLines(Collections.singletonList(description));
@ -125,8 +125,8 @@ public final class UpdateDescriptionTest {
AtomicInteger factoryCalls2 = new AtomicInteger();
UpdateDescription.StringFactory stringFactory1 = () -> "update." + factoryCalls1.incrementAndGet();
UpdateDescription.StringFactory stringFactory2 = () -> "update." + factoryCalls2.incrementAndGet();
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory1);
UpdateDescription description2 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory2);
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory1, 0, 0);
UpdateDescription description2 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory2, 0, 0);
factoryCalls1.set(10);
factoryCalls2.set(20);
@ -148,9 +148,9 @@ public final class UpdateDescriptionTest {
AtomicInteger factoryCalls2 = new AtomicInteger();
UpdateDescription.StringFactory stringFactory1 = () -> "update." + factoryCalls1.incrementAndGet();
UpdateDescription.StringFactory stringFactory2 = () -> "update." + factoryCalls2.incrementAndGet();
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory1);
UpdateDescription description2 = UpdateDescription.staticDescription("static");
UpdateDescription description3 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory2);
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory1, 0, 0);
UpdateDescription description2 = UpdateDescription.staticDescription("static", 0, 0);
UpdateDescription description3 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory2, 0, 0);
factoryCalls1.set(100);
factoryCalls2.set(200);