use of org.thoughtcrime.securesms.groups.GroupId in project Signal-Android by WhisperSystems.
the class TypingSendJob method onRun.
@Override
public void onRun() throws Exception {
if (!Recipient.self().isRegistered()) {
throw new NotPushRegisteredException();
}
if (!TextSecurePreferences.isTypingIndicatorsEnabled(context)) {
return;
}
Log.d(TAG, "Sending typing " + (typing ? "started" : "stopped") + " for thread " + threadId);
Recipient recipient = SignalDatabase.threads().getRecipientForThreadId(threadId);
if (recipient == null) {
Log.w(TAG, "Tried to send a typing indicator to a non-existent thread.");
return;
}
if (recipient.isBlocked()) {
Log.w(TAG, "Not sending typing indicators to blocked recipients.");
return;
}
if (recipient.isSelf()) {
Log.w(TAG, "Not sending typing indicators to self.");
return;
}
if (recipient.isPushV1Group() || recipient.isMmsGroup()) {
Log.w(TAG, "Not sending typing indicators to unsupported groups.");
return;
}
if (!recipient.isRegistered() || recipient.isForceSmsSelection()) {
Log.w(TAG, "Not sending typing indicators to non-Signal recipients.");
return;
}
List<Recipient> recipients = Collections.singletonList(recipient);
Optional<byte[]> groupId = Optional.absent();
if (recipient.isGroup()) {
recipients = SignalDatabase.groups().getGroupMembers(recipient.requireGroupId(), GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);
groupId = Optional.of(recipient.requireGroupId().getDecodedId());
}
recipients = RecipientUtil.getEligibleForSending(Stream.of(recipients).map(Recipient::resolve).filter(r -> !r.isBlocked()).toList());
SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis(), groupId);
try {
GroupSendUtil.sendTypingMessage(context, recipient.getGroupId().transform(GroupId::requireV2).orNull(), recipients, typingMessage, this::isCanceled);
} catch (CancelationException e) {
Log.w(TAG, "Canceled during send!");
}
}
use of org.thoughtcrime.securesms.groups.GroupId in project Signal-Android by WhisperSystems.
the class EditProfileFragment method initializeResources.
private void initializeResources(@NonNull View view, @Nullable GroupId groupId) {
Bundle arguments = requireArguments();
boolean isEditingGroup = groupId != null;
this.toolbar = view.findViewById(R.id.toolbar);
this.title = view.findViewById(R.id.title);
this.avatar = view.findViewById(R.id.avatar);
this.givenName = view.findViewById(R.id.given_name);
this.familyName = view.findViewById(R.id.family_name);
this.finishButton = view.findViewById(R.id.finish_button);
this.reveal = view.findViewById(R.id.reveal);
this.preview = view.findViewById(R.id.name_preview);
this.avatarPreviewBackground = view.findViewById(R.id.avatar_background);
this.avatarPreview = view.findViewById(R.id.avatar_placeholder);
this.nextIntent = arguments.getParcelable(NEXT_INTENT);
this.avatar.setOnClickListener(v -> startAvatarSelection());
view.findViewById(R.id.mms_group_hint).setVisibility(isEditingGroup && groupId.isMms() ? View.VISIBLE : View.GONE);
if (isEditingGroup) {
EditTextUtil.addGraphemeClusterLimitFilter(givenName, FeatureFlags.getMaxGroupNameGraphemeLength());
givenName.addTextChangedListener(new AfterTextChanged(s -> viewModel.setGivenName(s.toString())));
givenName.setHint(R.string.EditProfileFragment__group_name);
givenName.requestFocus();
toolbar.setTitle(R.string.EditProfileFragment__edit_group);
preview.setVisibility(View.GONE);
if (groupId.isV2()) {
EditTextUtil.addGraphemeClusterLimitFilter(familyName, MAX_DESCRIPTION_GLYPHS);
familyName.addTextChangedListener(new AfterTextChanged(s -> {
EditProfileNameFragment.trimFieldToMaxByteLength(s, MAX_DESCRIPTION_BYTES);
viewModel.setFamilyName(s.toString());
}));
familyName.setHint(R.string.EditProfileFragment__group_description);
familyName.setSingleLine(false);
familyName.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
LearnMoreTextView descriptionText = view.findViewById(R.id.description_text);
descriptionText.setLearnMoreVisible(false);
descriptionText.setText(R.string.CreateProfileActivity_group_descriptions_will_be_visible_to_members_of_this_group_and_people_who_have_been_invited);
} else {
familyName.setVisibility(View.GONE);
familyName.setEnabled(false);
view.findViewById(R.id.description_text).setVisibility(View.GONE);
}
view.<ImageView>findViewById(R.id.avatar_placeholder).setImageResource(R.drawable.ic_group_outline_40);
} else {
EditTextUtil.addGraphemeClusterLimitFilter(givenName, EditProfileNameFragment.NAME_MAX_GLYPHS);
EditTextUtil.addGraphemeClusterLimitFilter(familyName, EditProfileNameFragment.NAME_MAX_GLYPHS);
this.givenName.addTextChangedListener(new AfterTextChanged(s -> {
EditProfileNameFragment.trimFieldToMaxByteLength(s);
viewModel.setGivenName(s.toString());
}));
this.familyName.addTextChangedListener(new AfterTextChanged(s -> {
EditProfileNameFragment.trimFieldToMaxByteLength(s);
viewModel.setFamilyName(s.toString());
}));
LearnMoreTextView descriptionText = view.findViewById(R.id.description_text);
descriptionText.setLearnMoreVisible(true);
descriptionText.setOnLinkClickListener(v -> CommunicationActions.openBrowserLink(requireContext(), getString(R.string.EditProfileFragment__support_link)));
}
this.finishButton.setOnClickListener(v -> {
this.finishButton.setIndeterminateProgressMode(true);
this.finishButton.setProgress(50);
handleUpload();
});
this.finishButton.setText(arguments.getInt(NEXT_BUTTON_TEXT, R.string.CreateProfileActivity_next));
if (arguments.getBoolean(SHOW_TOOLBAR, true)) {
this.toolbar.setVisibility(View.VISIBLE);
this.toolbar.setNavigationOnClickListener(v -> requireActivity().finish());
this.title.setVisibility(View.GONE);
}
}
use of org.thoughtcrime.securesms.groups.GroupId in project Signal-Android by WhisperSystems.
the class EditProfileFragment method onViewCreated.
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
GroupId groupId = GroupId.parseNullableOrThrow(requireArguments().getString(GROUP_ID, null));
initializeViewModel(requireArguments().getBoolean(EXCLUDE_SYSTEM, false), groupId, savedInstanceState != null);
initializeResources(view, groupId);
initializeProfileAvatar();
initializeProfileName();
getParentFragmentManager().setFragmentResultListener(AvatarPickerFragment.REQUEST_KEY_SELECT_AVATAR, getViewLifecycleOwner(), (key, bundle) -> {
if (bundle.getBoolean(AvatarPickerFragment.SELECT_AVATAR_CLEAR)) {
viewModel.setAvatarMedia(null);
viewModel.setAvatar(null);
avatar.setImageDrawable(null);
} else {
Media media = bundle.getParcelable(AvatarPickerFragment.SELECT_AVATAR_MEDIA);
handleMediaFromResult(media);
}
});
}
use of org.thoughtcrime.securesms.groups.GroupId in project Signal-Android by WhisperSystems.
the class GroupDatabase method fixMissingMasterKey.
/**
* There was a point in time where we weren't properly responding to group creates on linked devices. This would result in us having a Recipient entry for the
* group, but we'd either be missing the group entry, or that entry would be missing a master key. This method fixes this scenario.
*/
public void fixMissingMasterKey(@NonNull GroupMasterKey groupMasterKey) {
GroupId.V2 groupId = GroupId.v2(groupMasterKey);
if (getGroupV1ByExpectedV2(groupId).isPresent()) {
Log.w(TAG, "There already exists a V1 group that should be migrated into this group. But if the recipient already exists, there's not much we can do here.");
}
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
db.beginTransaction();
try {
String query = GROUP_ID + " = ?";
String[] args = SqlUtil.buildArgs(groupId);
ContentValues values = new ContentValues();
values.put(V2_MASTER_KEY, groupMasterKey.serialize());
int updated = db.update(TABLE_NAME, values, query, args);
if (updated < 1) {
Log.w(TAG, "No group entry. Creating restore placeholder for " + groupId);
create(groupMasterKey, DecryptedGroup.newBuilder().setRevision(GroupsV2StateProcessor.RESTORE_PLACEHOLDER_REVISION).build(), true);
} else {
Log.w(TAG, "Had a group entry, but it was missing a master key. Updated.");
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
Log.w(TAG, "Scheduling request for latest group info for " + groupId);
ApplicationDependencies.getJobManager().add(new RequestGroupV2InfoJob(groupId));
}
use of org.thoughtcrime.securesms.groups.GroupId in project Signal-Android by WhisperSystems.
the class PushProcessMessageQueueJobMigration method migratePushProcessMessageJob.
@NonNull
private static JobData migratePushProcessMessageJob(@NonNull Context context, @NonNull JobData jobData) throws IOException {
Data data = jobData.getData();
String suffix = "";
if (data.getInt("message_state") == 0) {
SignalServiceContent content = SignalServiceContent.deserialize(Base64.decode(data.getString("message_content")));
if (content != null && content.getDataMessage().isPresent() && content.getDataMessage().get().getGroupContext().isPresent()) {
Log.i(TAG, "Migrating a group message.");
try {
GroupId groupId = GroupUtil.idFromGroupContext(content.getDataMessage().get().getGroupContext().get());
Recipient recipient = Recipient.externalGroupExact(context, groupId);
suffix = recipient.getId().toQueueKey();
} catch (BadGroupIdException e) {
Log.w(TAG, "Bad groupId! Using default queue.");
}
} else if (content != null) {
Log.i(TAG, "Migrating an individual message.");
suffix = RecipientId.from(content.getSender()).toQueueKey();
}
} else {
Log.i(TAG, "Migrating an exception message.");
String exceptionSender = data.getString("exception_sender");
GroupId exceptionGroup = GroupId.parseNullableOrThrow(data.getStringOrDefault("exception_groupId", null));
if (exceptionGroup != null) {
suffix = Recipient.externalGroupExact(context, exceptionGroup).getId().toQueueKey();
} else if (exceptionSender != null) {
suffix = Recipient.external(context, exceptionSender).getId().toQueueKey();
}
}
return jobData.withQueueKey("__PUSH_PROCESS_JOB__" + suffix);
}
Aggregations