mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c8e91328d | |||
| 5c30e9e16a | |||
| dcaa19b29d | |||
| 11845da65f | |||
| 82262cb166 | |||
| e85ae5247a | |||
| 40cdeee47a | |||
| 5040fb4634 | |||
| 4313e8824b | |||
| 102c3fd82a | |||
| dc31eee4bc | |||
| 875f0e5c86 | |||
| 2b36e2dc26 | |||
| 6a9c3ab8ca | |||
| 2ab544b18e | |||
| 2630e22421 | |||
| 1b7e32ab44 | |||
| 8436909977 | |||
| 9dd44c24b3 | |||
| 5d0e85b30d | |||
| 5193dfa412 | |||
| 96490e23f8 | |||
| 7959b07d45 | |||
| c4ae7927ad | |||
| ba0515ebc5 | |||
| 349bab9510 | |||
| e26f803d1f | |||
| 60ab7f2826 | |||
| 67d2c89bcc | |||
| e511237e5e | |||
| f249fd6174 | |||
| 6db45c1911 | |||
| 06a1114744 | |||
| 3afff5625b | |||
| cef8ddeedb | |||
| 2f0ac973c0 | |||
| 9465776715 | |||
| 39685a575d | |||
| 8601736387 | |||
| 98d8572baf | |||
| 917e764b6f | |||
| 52263150c8 | |||
| c2aba94b34 | |||
| 1278dfd395 | |||
| 44a688470f | |||
| e9a09d9c72 | |||
| abc49a3b95 | |||
| cdd4e5eccd | |||
| fa8ed2b881 | |||
| 0731fe9447 | |||
| d3567d9f0c | |||
| 66ab1f8051 | |||
| 872fd17f5e | |||
| af49018911 |
@@ -4,14 +4,20 @@ on:
|
||||
workflows: ["Upload Preview APK"]
|
||||
types: [completed]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
artifacts-url-comments:
|
||||
name: add artifact links to pull request
|
||||
permissions:
|
||||
pull-requests: write
|
||||
actions: read
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- name: add artifact links to pull request
|
||||
uses: tonyhallett/artifacts-url-comments@v1.1.0
|
||||
uses: tonyhallett/artifacts-url-comments@0965ff1a7ae03c5c1644d3c30f956effea4e05ef # v1.1.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
|
||||
@@ -10,6 +10,8 @@ on:
|
||||
- 'jni/dc_wrapper.c'
|
||||
- 'scripts/ndk-make.sh'
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -17,14 +19,15 @@ jobs:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
persist-credentials: false
|
||||
|
||||
- uses: android-actions/setup-android@v3
|
||||
- uses: nttld/setup-ndk@v1
|
||||
- uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
||||
- uses: nttld/setup-ndk@ed92fe6cadad69be94a966a7ee3271275e62f779 # v1.6.0
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r27
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
with:
|
||||
workspaces: jni/deltachat-core-rust
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ on:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
@@ -17,6 +19,8 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: 17
|
||||
@@ -30,6 +34,6 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/actions/wrapper-validation@v4
|
||||
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
|
||||
- name: Check formatting
|
||||
run: ./gradlew spotlessCheck
|
||||
|
||||
@@ -6,6 +6,8 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Upload Preview APK
|
||||
@@ -14,6 +16,7 @@ jobs:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
persist-credentials: false
|
||||
|
||||
- name: Validate Fastlane Metadata
|
||||
uses: ashutoshgngwr/validate-fastlane-supply-metadata@v2
|
||||
@@ -33,15 +36,15 @@ jobs:
|
||||
${{ runner.os }}-gradle-
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/actions/wrapper-validation@v4
|
||||
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
|
||||
|
||||
- uses: android-actions/setup-android@v3
|
||||
- uses: nttld/setup-ndk@v1
|
||||
- uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
||||
- uses: nttld/setup-ndk@ed92fe6cadad69be94a966a7ee3271275e62f779 # v1.6.0
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r27
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
with:
|
||||
workspaces: jni/deltachat-core-rust
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
name: GitHub Actions Security Analysis with zizmor
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
zizmor:
|
||||
name: Run zizmor
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files.
|
||||
contents: read
|
||||
actions: read
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Run zizmor
|
||||
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
|
||||
@@ -0,0 +1,6 @@
|
||||
rules:
|
||||
unpinned-uses:
|
||||
config:
|
||||
policies:
|
||||
actions/*: ref-pin
|
||||
dependabot/*: ref-pin
|
||||
+2
-1
@@ -244,7 +244,8 @@ $ANDROID_NDK_ROOT/ndk-stack --sym obj/local/armeabi-v7a --dump crash.txt > decod
|
||||
|
||||
Replace `armeabi-v7a` by the correct architecture the logs come from (can be guessed by trial and error)
|
||||
|
||||
### Deobfuscating Java/Kotlin Stack Traces
|
||||
|
||||
### Deobfuscating Java Stack Traces
|
||||
|
||||
Because the app uses code minification (ProGuard/R8), Java stack traces in crash reports are obfuscated.
|
||||
To decode them, use `retrace` with the `mapping.txt` file that is included in the symbols zip:
|
||||
|
||||
@@ -4,9 +4,18 @@
|
||||
|
||||
* Better incoming call system integration
|
||||
* Calls are not experimental anymore and don't need to be manually enabled
|
||||
* Channels are no longer experimental and are available by default
|
||||
* Display a permanent notification when doing location streaming and get rid of dangerous "Access Location in Background" permission
|
||||
* Autoplay all voice messages in a chat
|
||||
* Allow to share location for 24 hours
|
||||
* Allow mini-apps to play audio without user interaction
|
||||
* Mark chats as unread (long tap a chat and select the corresponding option from the three-dot-menu)
|
||||
* Add "Mark all as read" option to profile menu in the profile switcher
|
||||
* Fix process of upgrading from a very old version of the app
|
||||
* Show more recent added stickers at the top of the sticker picker
|
||||
* Allow to open links in messages via actions in TalkBack menu
|
||||
* Allow to open map if user clicks "Location streaming enabled" system message
|
||||
* Fix: do not accidentally set draft in chats that don't allow sending messages
|
||||
|
||||
## v2.49.0
|
||||
2026-04
|
||||
|
||||
@@ -39,7 +39,7 @@ public class EnterChatsBenchmark {
|
||||
// PLEASE BACKUP YOUR ACCOUNT BEFORE RUNNING THIS!
|
||||
// ==============================================================================================
|
||||
|
||||
private static final String TAG = EnterChatsBenchmark.class.getSimpleName();
|
||||
private static final String TAG = "EnterChatsBenchmark";
|
||||
|
||||
@Rule
|
||||
public ActivityScenarioRule<ConversationListActivity> activityRule =
|
||||
|
||||
@@ -6,7 +6,7 @@ import android.util.Log;
|
||||
/** Non-GMS, always uses the platform LocationManager. */
|
||||
public final class LocationSourceFactory {
|
||||
|
||||
private static final String TAG = LocationSourceFactory.class.getSimpleName();
|
||||
private static final String TAG = "LocationSourceFactory";
|
||||
|
||||
private LocationSourceFactory() {}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import com.google.android.gms.location.Priority;
|
||||
|
||||
public class GmsLocationSource implements LocationSource {
|
||||
|
||||
private static final String TAG = GmsLocationSource.class.getSimpleName();
|
||||
private static final String TAG = "GmsLocationSource";
|
||||
private static final long UPDATE_INTERVAL_MS = 3_000;
|
||||
private static final long FASTEST_INTERVAL_MS = 1_000;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import com.google.android.gms.common.GoogleApiAvailability;
|
||||
*/
|
||||
public final class LocationSourceFactory {
|
||||
|
||||
private static final String TAG = LocationSourceFactory.class.getSimpleName();
|
||||
private static final String TAG = "LocationSourceFactory";
|
||||
|
||||
private LocationSourceFactory() {}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.service.FetchForegroundService;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class FcmReceiveService extends FirebaseMessagingService {
|
||||
private static final String TAG = FcmReceiveService.class.getSimpleName();
|
||||
private static final String TAG = "FcmReceiveService";
|
||||
private static final Object INIT_LOCK = new Object();
|
||||
private static boolean initialized;
|
||||
private static volatile boolean triedRegistering;
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
|
||||
|
||||
@@ -490,7 +491,7 @@
|
||||
android:name=".calls.CallService"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="camera|microphone" />
|
||||
android:foregroundServiceType="camera|microphone|phoneCall" />
|
||||
|
||||
<receiver
|
||||
android:name=".notifications.MarkReadReceiver"
|
||||
|
||||
@@ -59,8 +59,6 @@ public class DcMsg {
|
||||
public static final int DC_VIDEOCHATTYPE_UNKNOWN = 0;
|
||||
public static final int DC_VIDEOCHATTYPE_BASICWEBRTC = 1;
|
||||
|
||||
private static final String TAG = DcMsg.class.getSimpleName();
|
||||
|
||||
public DcMsg(DcContext context, int viewtype) {
|
||||
msgCPtr = context.createMsgCPtr(viewtype);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import java.util.ArrayList;
|
||||
import org.thoughtcrime.securesms.components.audioplay.AudioPlaybackViewModel;
|
||||
import org.thoughtcrime.securesms.components.audioplay.ChatAudioQueueProvider;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.service.AudioPlaybackService;
|
||||
@@ -35,7 +36,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class AllMediaActivity extends PassphraseRequiredActionBarActivity
|
||||
implements DcEventCenter.DcEventDelegate {
|
||||
private static final String TAG = AllMediaActivity.class.getSimpleName();
|
||||
private static final String TAG = "AllMediaActivity";
|
||||
|
||||
public static final String CHAT_ID_EXTRA = "chat_id";
|
||||
public static final String CONTACT_ID_EXTRA = "contact_id";
|
||||
@@ -107,7 +108,9 @@ public class AllMediaActivity extends PassphraseRequiredActionBarActivity
|
||||
eventCenter.addObserver(DcContext.DC_EVENT_CHAT_MODIFIED, this);
|
||||
eventCenter.addObserver(DcContext.DC_EVENT_CONTACTS_CHANGED, this);
|
||||
|
||||
int accountId = DcHelper.getAccounts(this).getSelectedAccount().getAccountId();
|
||||
playbackViewModel = new ViewModelProvider(this).get(AudioPlaybackViewModel.class);
|
||||
playbackViewModel.setQueueProvider(new ChatAudioQueueProvider(this, chatId, accountId));
|
||||
initializeMediaController();
|
||||
}
|
||||
|
||||
@@ -119,6 +122,7 @@ public class AllMediaActivity extends PassphraseRequiredActionBarActivity
|
||||
mediaController = null;
|
||||
playbackViewModel.setMediaController(null);
|
||||
}
|
||||
playbackViewModel.setQueueProvider(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.webxdc.WebxdcGarbageCollectionWorker;
|
||||
|
||||
public class ApplicationContext extends MultiDexApplication {
|
||||
private static final String TAG = ApplicationContext.class.getSimpleName();
|
||||
private static final String TAG = "ApplicationContext";
|
||||
private static final Object initLock = new Object();
|
||||
private static volatile boolean isInitialized = false;
|
||||
|
||||
@@ -218,7 +218,7 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
Log.i(TAG, "DcAccounts created");
|
||||
rpc = new Rpc(new FFITransport(dcAccounts.getJsonrpcInstance()));
|
||||
Log.i(TAG, "Rpc created");
|
||||
AccountManager.getInstance().migrateToDcAccounts(this);
|
||||
AccountManager.getInstance().migrateToDcAccounts(this, dcAccounts);
|
||||
|
||||
int[] allAccounts = dcAccounts.getAll();
|
||||
Log.i(TAG, "Number of profiles: " + allAccounts.length);
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public abstract class BaseActionBarActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = BaseActionBarActivity.class.getSimpleName();
|
||||
private static final String TAG = "BaseActionBarActivity";
|
||||
protected DynamicTheme dynamicTheme = new DynamicTheme();
|
||||
|
||||
protected void onPreCreate() {
|
||||
|
||||
@@ -47,7 +47,7 @@ import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask;
|
||||
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
|
||||
public abstract class BaseConversationListFragment extends Fragment implements ActionMode.Callback {
|
||||
private static final String TAG = BaseConversationListFragment.class.getSimpleName();
|
||||
private static final String TAG = "BaseConversationListFragment";
|
||||
protected ActionMode actionMode;
|
||||
protected PulsingFloatingActionButton fab;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
*/
|
||||
public abstract class ContactSelectionActivity extends PassphraseRequiredActionBarActivity
|
||||
implements ContactSelectionListFragment.OnContactSelectedListener {
|
||||
private static final String TAG = ContactSelectionActivity.class.getSimpleName();
|
||||
private static final String TAG = "ContactSelectionActivity";
|
||||
|
||||
protected ContactSelectionListFragment contactsFragment;
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
*/
|
||||
public class ContactSelectionListFragment extends Fragment
|
||||
implements LoaderManager.LoaderCallbacks<DcContactsLoader.Ret>, DcEventCenter.DcEventDelegate {
|
||||
private static final String TAG = ContactSelectionListFragment.class.getSimpleName();
|
||||
private static final String TAG = "ContactSelectionListFragment";
|
||||
|
||||
public static final String MULTI_SELECT = "multi_select";
|
||||
public static final String SELECT_UNENCRYPTED_EXTRA = "select_unencrypted_extra";
|
||||
|
||||
@@ -101,6 +101,7 @@ import org.thoughtcrime.securesms.components.ScaleStableImageView;
|
||||
import org.thoughtcrime.securesms.components.SendButton;
|
||||
import org.thoughtcrime.securesms.components.audioplay.AudioPlaybackViewModel;
|
||||
import org.thoughtcrime.securesms.components.audioplay.AudioView;
|
||||
import org.thoughtcrime.securesms.components.audioplay.ChatAudioQueueProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
@@ -148,7 +149,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
InputPanel.Listener,
|
||||
InputPanel.MediaListener,
|
||||
AudioView.OnActionListener {
|
||||
private static final String TAG = ConversationActivity.class.getSimpleName();
|
||||
private static final String TAG = "ConversationActivity";
|
||||
|
||||
public static final String ACCOUNT_ID_EXTRA = "account_id";
|
||||
public static final String CHAT_ID_EXTRA = "chat_id";
|
||||
@@ -223,7 +224,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
initializeViews();
|
||||
initializeResources();
|
||||
|
||||
int accountId = DcHelper.getAccounts(this).getSelectedAccount().getAccountId();
|
||||
playbackViewModel = new ViewModelProvider(this).get(AudioPlaybackViewModel.class);
|
||||
playbackViewModel.setQueueProvider(new ChatAudioQueueProvider(this, chatId, accountId));
|
||||
initializeMediaController();
|
||||
|
||||
initializeSecurity(false, isDefaultSms)
|
||||
@@ -413,6 +416,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
mediaController = null;
|
||||
playbackViewModel.setMediaController(null);
|
||||
}
|
||||
playbackViewModel.setQueueProvider(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@@ -672,8 +676,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
public void setDraftText(String txt) {
|
||||
composeText.setText(txt);
|
||||
composeText.setSelection(composeText.getText().length());
|
||||
try {
|
||||
if (rpc.canSend(rpc.getSelectedAccountId(), chatId)) {
|
||||
composeText.setText(txt);
|
||||
composeText.setSelection(composeText.getText().length());
|
||||
}
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Rpc error", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void hideSoftKeyboard() {
|
||||
@@ -1119,6 +1129,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
if (chatId == DcChat.DC_CHAT_NO_CHAT)
|
||||
throw new IllegalStateException("can't display a conversation for no chat.");
|
||||
dcChat = DcHelper.getContext(context).getChat(chatId);
|
||||
attachmentTypeSelector = null;
|
||||
recipient = new Recipient(this, dcChat);
|
||||
glideRequests = GlideApp.with(this);
|
||||
|
||||
@@ -1267,6 +1278,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
DcContext dcContext = DcHelper.getContext(context);
|
||||
final int currentChatId = dcChat.getId();
|
||||
final boolean canSend = dcChat.canSend();
|
||||
Util.runOnAnyBackgroundThread(
|
||||
() -> {
|
||||
DcMsg msg = null;
|
||||
@@ -1389,7 +1401,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dcContext.setDraft(currentChatId, msg);
|
||||
// set or clear draft if user can't send in chat since they can't delete it otherwise
|
||||
dcContext.setDraft(currentChatId, canSend ? msg : null);
|
||||
}
|
||||
future.set(currentChatId);
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@ import org.thoughtcrime.securesms.util.views.ConversationAdaptiveActionsToolbar;
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public class ConversationFragment extends MessageSelectorFragment {
|
||||
private static final String TAG = ConversationFragment.class.getSimpleName();
|
||||
private static final String TAG = "ConversationFragment";
|
||||
|
||||
private static final int SCROLL_ANIMATION_THRESHOLD = 50;
|
||||
|
||||
@@ -944,6 +944,8 @@ public class ConversationFragment extends MessageSelectorFragment {
|
||||
WebxdcActivity.openWebxdcActivity(
|
||||
getContext(), messageRecord.getParent(), messageRecord.getWebxdcHref());
|
||||
}
|
||||
} else if (messageRecord.getInfoType() == DcMsg.DC_INFO_LOCATIONSTREAMING_ENABLED) {
|
||||
WebxdcActivity.openMaps(getContext(), (int) chatId);
|
||||
} else if (messageRecord.getInfoType() == DcMsg.DC_INFO_CHAT_DESCRIPTION_CHANGED) {
|
||||
Intent intent = new Intent(getContext(), ProfileActivity.class);
|
||||
intent.putExtra(ProfileActivity.CHAT_ID_EXTRA, (int) chatId);
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
@@ -36,6 +37,7 @@ import androidx.annotation.DimenRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import chat.delta.rpc.RpcException;
|
||||
import chat.delta.rpc.types.CallInfo;
|
||||
import chat.delta.rpc.types.CallState;
|
||||
@@ -44,6 +46,7 @@ import chat.delta.rpc.types.VcardContact;
|
||||
import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.thoughtcrime.securesms.calls.CallCoordinator;
|
||||
@@ -72,6 +75,7 @@ import org.thoughtcrime.securesms.mms.VcardSlide;
|
||||
import org.thoughtcrime.securesms.reactions.ReactionsConversationView;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Linkifier;
|
||||
import org.thoughtcrime.securesms.util.LongClickCopySpan;
|
||||
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
|
||||
import org.thoughtcrime.securesms.util.MarkdownUtil;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
@@ -86,7 +90,7 @@ import org.thoughtcrime.securesms.util.views.Stub;
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
public class ConversationItem extends BaseConversationItem {
|
||||
private static final String TAG = ConversationItem.class.getSimpleName();
|
||||
private static final String TAG = "ConversationItem";
|
||||
|
||||
private static final Rect SWIPE_RECT = new Rect();
|
||||
|
||||
@@ -120,6 +124,9 @@ public class ConversationItem extends BaseConversationItem {
|
||||
private Stub<CallItemView> callViewStub;
|
||||
private @Nullable EventListener eventListener;
|
||||
|
||||
// IDs of accessibility actions registered via ViewCompat.addAccessibilityAction
|
||||
private final List<Integer> linkActionIds = new ArrayList<>();
|
||||
|
||||
private int measureCalls;
|
||||
|
||||
private int incomingBubbleColor;
|
||||
@@ -424,6 +431,12 @@ public class ConversationItem extends BaseConversationItem {
|
||||
bodyText.setClickable(false);
|
||||
bodyText.setFocusable(false);
|
||||
|
||||
// Remove any link actions registered for the previous message binding
|
||||
for (int id : linkActionIds) {
|
||||
ViewCompat.removeAccessibilityAction(this, id);
|
||||
}
|
||||
linkActionIds.clear();
|
||||
|
||||
String subject = messageRecord.getSubject();
|
||||
String text = messageRecord.getText();
|
||||
|
||||
@@ -433,12 +446,33 @@ public class ConversationItem extends BaseConversationItem {
|
||||
if (messageRecord.getType() == DcMsg.DC_MSG_CALL || text.isEmpty()) {
|
||||
bodyText.setVisibility(View.GONE);
|
||||
} else {
|
||||
Spannable spannable = (Spannable) MarkdownUtil.toMarkdown(context, text);
|
||||
Spannable spannable = MarkdownUtil.toMarkdown(context, text);
|
||||
if (batchSelected.isEmpty()) {
|
||||
spannable = Linkifier.linkify(spannable);
|
||||
Linkifier.linkify(spannable);
|
||||
}
|
||||
bodyText.setText(spannable);
|
||||
bodyText.setVisibility(View.VISIBLE);
|
||||
|
||||
// Register a TalkBack "Actions" entry for each link in the message
|
||||
Spanned spanned = (Spanned) spannable;
|
||||
final TextView tv = bodyText;
|
||||
for (LongClickCopySpan span :
|
||||
spanned.getSpans(0, spanned.length(), LongClickCopySpan.class)) {
|
||||
int start = spanned.getSpanStart(span);
|
||||
int end = spanned.getSpanEnd(span);
|
||||
if (start >= 0 && end > start && end <= spanned.length()) {
|
||||
String linkText = spanned.subSequence(start, end).toString();
|
||||
String label = context.getString(R.string.accessibility_link_action, linkText);
|
||||
linkActionIds.add(
|
||||
ViewCompat.addAccessibilityAction(
|
||||
this,
|
||||
label,
|
||||
(v, args) -> {
|
||||
span.onClick(tv);
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int downloadState = messageRecord.getDownloadState();
|
||||
|
||||
@@ -91,7 +91,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class ConversationListActivity extends PassphraseRequiredActionBarActivity
|
||||
implements ConversationListFragment.ConversationSelectedListener {
|
||||
private static final String TAG = ConversationListActivity.class.getSimpleName();
|
||||
private static final String TAG = "ConversationListActivity";
|
||||
private static final String OPENPGP4FPR = "openpgp4fpr";
|
||||
private static final String NDK_ARCH_WARNED = "ndk_arch_warned";
|
||||
public static final String CLEAR_NOTIFICATIONS = "clear_notifications";
|
||||
|
||||
@@ -56,7 +56,7 @@ public class ConversationListFragment extends BaseConversationListFragment
|
||||
public static final String ARCHIVE = "archive";
|
||||
public static final String RELOAD_LIST = "reload_list";
|
||||
|
||||
private static final String TAG = ConversationListFragment.class.getSimpleName();
|
||||
private static final String TAG = "ConversationListFragment";
|
||||
|
||||
private RecyclerView list;
|
||||
private View emptyState;
|
||||
|
||||
@@ -42,7 +42,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public class CreateProfileActivity extends BaseActionBarActivity {
|
||||
|
||||
private static final String TAG = CreateProfileActivity.class.getSimpleName();
|
||||
private static final String TAG = "CreateProfileActivity";
|
||||
|
||||
private static final int REQUEST_CODE_AVATAR = 1;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class EphemeralMessagesDialog {
|
||||
|
||||
private static final String TAG = EphemeralMessagesDialog.class.getSimpleName();
|
||||
private static final String TAG = "EphemeralMessagesDialog";
|
||||
|
||||
public static void show(
|
||||
final Context context,
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
implements ItemClickListener {
|
||||
|
||||
private static final String TAG = GroupCreateActivity.class.getSimpleName();
|
||||
private static final String TAG = "GroupCreateActivity";
|
||||
public static final String EDIT_GROUP_CHAT_ID = "edit_group_chat_id";
|
||||
public static final String CREATE_BROADCAST = "create_broadcast";
|
||||
public static final String UNENCRYPTED = "unencrypted";
|
||||
@@ -307,8 +307,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
private boolean showGroupNameEmptyToast(String groupName) {
|
||||
if (groupName == null) {
|
||||
Toast.makeText(this, getString(R.string.group_please_enter_group_name), Toast.LENGTH_LONG)
|
||||
.show();
|
||||
Toast.makeText(this, getString(R.string.please_enter_chat_name), Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -65,7 +65,7 @@ import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
public class InstantOnboardingActivity extends BaseActionBarActivity
|
||||
implements DcEventCenter.DcEventDelegate {
|
||||
|
||||
private static final String TAG = InstantOnboardingActivity.class.getSimpleName();
|
||||
private static final String TAG = "InstantOnboardingActivity";
|
||||
private static final String DCACCOUNT = "dcaccount";
|
||||
private static final String DCLOGIN = "dclogin";
|
||||
private static final String INSTANCES_URL = "https://chatmail.at/relays";
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.thoughtcrime.securesms.util.FileProviderUtil;
|
||||
|
||||
public class LogViewActivity extends BaseActionBarActivity {
|
||||
|
||||
private static final String TAG = LogViewActivity.class.getSimpleName();
|
||||
private static final String TAG = "LogViewActivity";
|
||||
|
||||
LogViewFragment logViewFragment;
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
implements RecipientModifiedListener, LoaderManager.LoaderCallbacks<DcMediaGalleryElement> {
|
||||
|
||||
private static final String TAG = MediaPreviewActivity.class.getSimpleName();
|
||||
private static final String TAG = "MediaPreviewActivity";
|
||||
|
||||
public static final String ACTIVITY_TITLE_EXTRA = "activity_title";
|
||||
public static final String EDIT_AVATAR_CHAT_ID = "avatar_for_chat_id";
|
||||
|
||||
@@ -41,7 +41,7 @@ import org.thoughtcrime.securesms.qr.QrCodeHandler;
|
||||
*/
|
||||
public class NewConversationActivity extends ContactSelectionActivity {
|
||||
|
||||
private static final String TAG = NewConversationActivity.class.getSimpleName();
|
||||
private static final String TAG = "NewConversationActivity";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle, boolean ready) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.service.GenericForegroundService;
|
||||
|
||||
public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarActivity {
|
||||
private static final String TAG = PassphraseRequiredActionBarActivity.class.getSimpleName();
|
||||
private static final String TAG = "PassphraseRequiredActionBarActivity";
|
||||
|
||||
@Override
|
||||
protected final void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class ProfileAdapter extends RecyclerView.Adapter {
|
||||
private static final String TAG = ProfileAdapter.class.getSimpleName();
|
||||
private static final String TAG = "ProfileAdapter";
|
||||
|
||||
public static final int ITEM_AVATAR = 10;
|
||||
public static final int ITEM_DIVIDER = 20;
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
public class ProfileFragment extends Fragment
|
||||
implements ProfileAdapter.ItemClickListener, DcEventCenter.DcEventDelegate {
|
||||
|
||||
private static final String TAG = ProfileFragment.class.getSimpleName();
|
||||
private static final String TAG = "ProfileFragment";
|
||||
public static final String CHAT_ID_EXTRA = "chat_id";
|
||||
public static final String CONTACT_ID_EXTRA = "contact_id";
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
|
||||
|
||||
public class ResolveMediaTask extends AsyncTask<Uri, Void, Uri> {
|
||||
|
||||
private static final String TAG = ResolveMediaTask.class.getSimpleName();
|
||||
private static final String TAG = "ResolveMediaTask";
|
||||
|
||||
interface OnMediaResolvedListener {
|
||||
void onMediaResolved(Uri uri);
|
||||
|
||||
@@ -47,7 +47,7 @@ import org.thoughtcrime.securesms.util.ShareUtil;
|
||||
*/
|
||||
public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
implements ResolveMediaTask.OnMediaResolvedListener {
|
||||
private static final String TAG = ShareActivity.class.getSimpleName();
|
||||
private static final String TAG = "ShareActivity";
|
||||
|
||||
public static final String EXTRA_ACC_ID = "acc_id";
|
||||
public static final String EXTRA_CHAT_ID = "chat_id";
|
||||
|
||||
@@ -18,21 +18,18 @@ public class ShareLocationDialog {
|
||||
switch (which) {
|
||||
default:
|
||||
case 0:
|
||||
shareLocationUnit = 5 * 60;
|
||||
break;
|
||||
case 1:
|
||||
shareLocationUnit = 30 * 60;
|
||||
break;
|
||||
case 2:
|
||||
case 1:
|
||||
shareLocationUnit = 60 * 60;
|
||||
break;
|
||||
case 3:
|
||||
case 2:
|
||||
shareLocationUnit = 2 * 60 * 60;
|
||||
break;
|
||||
case 4:
|
||||
case 3:
|
||||
shareLocationUnit = 6 * 60 * 60;
|
||||
break;
|
||||
case 5:
|
||||
case 4:
|
||||
shareLocationUnit = 24 * 60 * 60;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class WebViewActivity extends PassphraseRequiredActionBarActivity
|
||||
implements SearchView.OnQueryTextListener, WebView.FindListener {
|
||||
private static final String TAG = WebViewActivity.class.getSimpleName();
|
||||
private static final String TAG = "WebViewActivity";
|
||||
// Regex to extract the host from a URL for IDN conversion.
|
||||
private static final Pattern URL_PATTERN =
|
||||
Pattern.compile("^((?:[a-zA-Z0-9]+://)?)([^/?#]+)(.*)$");
|
||||
|
||||
@@ -59,7 +59,7 @@ import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcEventDelegate {
|
||||
private static final String TAG = WebxdcActivity.class.getSimpleName();
|
||||
private static final String TAG = "WebxdcActivity";
|
||||
private static final String EXTRA_ACCOUNT_ID = "accountId";
|
||||
private static final String EXTRA_APP_MSG_ID = "appMessageId";
|
||||
private static final String EXTRA_HIDE_ACTION_BAR = "hideActionBar";
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class WebxdcStoreActivity extends PassphraseRequiredActionBarActivity {
|
||||
private static final String TAG = WebxdcStoreActivity.class.getSimpleName();
|
||||
private static final String TAG = "WebxdcStoreActivity";
|
||||
|
||||
private DcContext dcContext;
|
||||
private Rpc rpc;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class WelcomeActivity extends BaseActionBarActivity
|
||||
implements DcEventCenter.DcEventDelegate {
|
||||
public static final String BACKUP_QR_EXTRA = "backup_qr_extra";
|
||||
public static final int PICK_BACKUP = 20574;
|
||||
private static final String TAG = WelcomeActivity.class.getSimpleName();
|
||||
private static final String TAG = "WelcomeActivity";
|
||||
public static final String TMP_BACKUP_FILE = "tmp-backup-file";
|
||||
|
||||
private ProgressDialog progressDialog = null;
|
||||
|
||||
@@ -41,7 +41,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class AccountSelectionListFragment extends DialogFragment
|
||||
implements DcEventCenter.DcEventDelegate {
|
||||
private static final String TAG = AccountSelectionListFragment.class.getSimpleName();
|
||||
private static final String TAG = "AccountSelectionListFragment";
|
||||
private static final String ARG_SELECT_ONLY = "select_only";
|
||||
private RecyclerView recyclerView;
|
||||
private AccountSelectionListAdapter adapter;
|
||||
@@ -157,6 +157,12 @@ public class AccountSelectionListFragment extends DialogFragment
|
||||
onSetTag(accountId);
|
||||
} else if (itemId == R.id.menu_move_to_top) {
|
||||
onMoveToTop(accountId);
|
||||
} else if (itemId == R.id.menu_mark_all_as_read) {
|
||||
try {
|
||||
DcHelper.getRpc(requireActivity()).marknoticedAllChats(accountId);
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Error calling rpc.marknoticedAllChats()", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.util.Prefs;
|
||||
|
||||
public class AudioCodec {
|
||||
|
||||
private static final String TAG = AudioCodec.class.getSimpleName();
|
||||
private static final String TAG = "AudioCodec";
|
||||
|
||||
private static final int SAMPLE_RATE_BALANCED = 44100;
|
||||
private static final int BIT_RATE_BALANCED = 32000;
|
||||
@@ -196,7 +196,7 @@ public class AudioCodec {
|
||||
setFinished();
|
||||
}
|
||||
},
|
||||
AudioCodec.class.getSimpleName())
|
||||
"AudioCodec")
|
||||
.start();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class AudioRecorder {
|
||||
|
||||
private static final String TAG = AudioRecorder.class.getSimpleName();
|
||||
private static final String TAG = "AudioRecorder";
|
||||
|
||||
private static final ExecutorService executor = ThreadUtil.newDynamicSingleThreadedExecutor();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.thoughtcrime.securesms.R;
|
||||
/** Bottom sheet dialog for selecting audio output device */
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
public class AudioDevicePickerDialog extends BottomSheetDialog {
|
||||
private static final String TAG = AudioDevicePickerDialog.class.getSimpleName();
|
||||
private static final String TAG = "AudioDevicePickerDialog";
|
||||
|
||||
public interface OnDeviceSelectedListener {
|
||||
void onDeviceSelected(CallEndpointCompat endpoint);
|
||||
|
||||
@@ -51,7 +51,7 @@ import org.webrtc.VideoTrack;
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public class CallActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = CallActivity.class.getSimpleName();
|
||||
private static final String TAG = "CallActivity";
|
||||
private static final int MIC_PERMISSION_REQUEST_CODE = 1001;
|
||||
private static final int CAMERA_PERMISSION_REQUEST_CODE = 1002;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ import org.webrtc.VideoTrack;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public class CallCoordinator implements DcEventCenter.DcEventDelegate {
|
||||
private static final String TAG = CallCoordinator.class.getSimpleName();
|
||||
private static final String TAG = "CallCoordinator";
|
||||
|
||||
// Notification channels
|
||||
private static final String CHANNEL_ID_INCOMING = "voip_incoming_calls";
|
||||
@@ -215,7 +215,8 @@ public class CallCoordinator implements DcEventCenter.DcEventDelegate {
|
||||
calleeName = "Unknown";
|
||||
}
|
||||
|
||||
showOrUpdateOngoingNotification("Calling " + calleeName + "...");
|
||||
showOrUpdateOngoingNotification(
|
||||
appContext.getString(R.string.calling_person, calleeName));
|
||||
}
|
||||
|
||||
// Initialize call
|
||||
@@ -402,6 +403,15 @@ public class CallCoordinator implements DcEventCenter.DcEventDelegate {
|
||||
callService.stopRingtone();
|
||||
}
|
||||
|
||||
// Promote the service to foreground immediately. Waiting until onIncomingCallAccepted
|
||||
// on executor pool thread is too late on stricter OEM.
|
||||
//
|
||||
// Do not cancel() but use showOrUpdateOngoingNotification to replace incoming
|
||||
// notification without a gap.
|
||||
String callerName = displayName.getValue();
|
||||
if (callerName == null) callerName = "Unknown";
|
||||
showOrUpdateOngoingNotification(appContext.getString(R.string.call_with, callerName));
|
||||
|
||||
// Notify Android system with CallControlScope
|
||||
CallControlScope scope = activeCallControlScope;
|
||||
if (scope != null) {
|
||||
@@ -425,8 +435,6 @@ public class CallCoordinator implements DcEventCenter.DcEventDelegate {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
notificationManager.cancel(NOTIFICATION_ID_CALL);
|
||||
}
|
||||
|
||||
public void answerWebRTC() {
|
||||
@@ -921,7 +929,7 @@ public class CallCoordinator implements DcEventCenter.DcEventDelegate {
|
||||
callerName = "Unknown";
|
||||
}
|
||||
|
||||
showOrUpdateOngoingNotification("Call with " + callerName);
|
||||
showOrUpdateOngoingNotification(appContext.getString(R.string.call_with, callerName));
|
||||
}
|
||||
|
||||
private synchronized void onCallAnsweredOnOtherDevice() {
|
||||
@@ -1008,7 +1016,7 @@ public class CallCoordinator implements DcEventCenter.DcEventDelegate {
|
||||
if (calleeName == null) {
|
||||
calleeName = "Unknown";
|
||||
}
|
||||
showOrUpdateOngoingNotification("Call with " + calleeName);
|
||||
showOrUpdateOngoingNotification(appContext.getString(R.string.call_with, calleeName));
|
||||
}
|
||||
|
||||
private synchronized void onCallEnded(int accId, int callId) {
|
||||
@@ -1101,6 +1109,14 @@ public class CallCoordinator implements DcEventCenter.DcEventDelegate {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callService != null) {
|
||||
try {
|
||||
callService.stopForegroundAndDismiss();
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "stopForegroundAndDismiss failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear state
|
||||
this.activeAccId = null;
|
||||
this.activeCallId = null;
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.app.Notification;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioFocusRequest;
|
||||
import android.media.AudioManager;
|
||||
@@ -13,7 +14,9 @@ import android.media.ToneGenerator;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
@@ -33,7 +36,7 @@ import org.webrtc.VideoTrack;
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public class CallService extends Service implements WebRTCClient.Callbacks {
|
||||
|
||||
private static final String TAG = CallService.class.getSimpleName();
|
||||
private static final String TAG = "CallService";
|
||||
|
||||
private final IBinder binder = new LocalBinder();
|
||||
|
||||
@@ -432,6 +435,12 @@ public class CallService extends Service implements WebRTCClient.Callbacks {
|
||||
|
||||
disposeWebRTC();
|
||||
|
||||
try {
|
||||
stopForeground(STOP_FOREGROUND_REMOVE);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "stopForeground failed", e);
|
||||
}
|
||||
|
||||
stopService();
|
||||
}
|
||||
|
||||
@@ -494,13 +503,44 @@ public class CallService extends Service implements WebRTCClient.Callbacks {
|
||||
// Foreground Notification
|
||||
|
||||
public void startForegroundWithNotification(int id, Notification notification) {
|
||||
Log.d(TAG, "Starting foreground with notification id: " + id);
|
||||
startForeground(id, notification);
|
||||
// Always run on main thread
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
new Handler(Looper.getMainLooper())
|
||||
.post(() -> startForegroundWithNotification(id, notification));
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "Starting call FGS with notification id: " + id);
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
startForeground(id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL);
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
int types =
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE
|
||||
| ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
|
||||
startForeground(id, notification, types);
|
||||
} else {
|
||||
startForeground(id, notification);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "startForeground failed", e);
|
||||
if (callCoordinator != null) {
|
||||
callCoordinator.reportError("Failed to activate call FGS: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stopForegroundAndDismiss() {
|
||||
Log.d(TAG, "Stopping foreground and dismissing notification");
|
||||
stopForeground(STOP_FOREGROUND_REMOVE);
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
new Handler(Looper.getMainLooper()).post(this::stopForegroundAndDismiss);
|
||||
return;
|
||||
}
|
||||
Log.d(TAG, "Stopping call FGS and dismissing notification");
|
||||
try {
|
||||
stopForeground(STOP_FOREGROUND_REMOVE);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "stopForeground failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
|
||||
public class CallUtil {
|
||||
private static final String TAG = CallUtil.class.getSimpleName();
|
||||
private static final String TAG = "CallUtil";
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public static void startAudioCall(Context context, int chatId) {
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.webrtc.VideoTrack;
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public class CallViewModel extends AndroidViewModel {
|
||||
|
||||
private static final String TAG = CallViewModel.class.getSimpleName();
|
||||
private static final String TAG = "CallViewModel";
|
||||
|
||||
private final CallCoordinator callCoordinator;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.webrtc.VideoTrack;
|
||||
|
||||
public class MediaStreamManager {
|
||||
|
||||
private static final String TAG = MediaStreamManager.class.getSimpleName();
|
||||
private static final String TAG = "MediaStreamManager";
|
||||
private static final String STREAM_ID = "local_stream";
|
||||
private static final String AUDIO_TRACK_ID = "audio_track";
|
||||
private static final String VIDEO_TRACK_ID = "video_track";
|
||||
|
||||
@@ -92,6 +92,10 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
ViewUtil.findById(layout, R.id.location_linear_layout).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (DcHelper.getContext(context).getChat(chatId).isOutBroadcast()) {
|
||||
ViewUtil.findById(layout, R.id.webxdc_linear_layout).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
setLocationButtonImage(context);
|
||||
|
||||
setContentView(layout);
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
|
||||
public class CallItemView extends FrameLayout {
|
||||
private static final String TAG = CallItemView.class.getSimpleName();
|
||||
private static final String TAG = "CallItemView";
|
||||
|
||||
private final @NonNull ImageView icon;
|
||||
private final @NonNull TextView title;
|
||||
|
||||
@@ -43,7 +43,7 @@ public class InputPanel extends ConstraintLayout
|
||||
KeyboardAwareLinearLayout.OnKeyboardShownListener,
|
||||
MediaKeyboard.MediaKeyboardListener {
|
||||
|
||||
private static final String TAG = InputPanel.class.getSimpleName();
|
||||
private static final String TAG = "InputPanel";
|
||||
|
||||
private static final int FADE_TIME = 150;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
* been opened and what its height would be.
|
||||
*/
|
||||
public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
|
||||
private static final String TAG = KeyboardAwareLinearLayout.class.getSimpleName();
|
||||
private static final String TAG = "KeyboardAwareLinearLayout";
|
||||
|
||||
private static final long KEYBOARD_DEBOUNCE = 150;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
|
||||
private static final String TAG = QuoteView.class.getSimpleName();
|
||||
private static final String TAG = "QuoteView";
|
||||
|
||||
private static final int MESSAGE_TYPE_PREVIEW = 0;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public class ScaleStableImageView extends AppCompatImageView
|
||||
implements KeyboardAwareLinearLayout.OnKeyboardShownListener,
|
||||
KeyboardAwareLinearLayout.OnKeyboardHiddenListener {
|
||||
|
||||
private static final String TAG = ScaleStableImageView.class.getSimpleName();
|
||||
private static final String TAG = "ScaleStableImageView";
|
||||
|
||||
private Drawable defaultDrawable;
|
||||
private Drawable currentDrawable;
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
|
||||
public class SearchToolbar extends LinearLayout {
|
||||
|
||||
private static final String TAG = SearchToolbar.class.getSimpleName();
|
||||
private static final String TAG = "SearchToolbar";
|
||||
private float x, y;
|
||||
private MenuItem searchItem;
|
||||
private EditText searchText;
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class ThumbnailView extends FrameLayout {
|
||||
|
||||
private static final String TAG = ThumbnailView.class.getSimpleName();
|
||||
private static final String TAG = "ThumbnailView";
|
||||
private static final int WIDTH = 0;
|
||||
private static final int HEIGHT = 1;
|
||||
private static final int MIN_WIDTH = 0;
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.mms.VcardSlide;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
public class VcardView extends FrameLayout {
|
||||
private static final String TAG = VcardView.class.getSimpleName();
|
||||
private static final String TAG = "VcardView";
|
||||
|
||||
private final @NonNull AvatarView avatar;
|
||||
private final @NonNull TextView name;
|
||||
|
||||
+110
-37
@@ -6,22 +6,26 @@ import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.PlaybackException;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.session.MediaController;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class AudioPlaybackViewModel extends ViewModel {
|
||||
private static final String TAG = AudioPlaybackViewModel.class.getSimpleName();
|
||||
private static final String TAG = "AudioPlaybackViewModel";
|
||||
|
||||
private static final int NON_MESSAGE_AUDIO_MSG_ID =
|
||||
0; // Audios not attached to a message doesn't have message id.
|
||||
@@ -34,6 +38,8 @@ public class AudioPlaybackViewModel extends ViewModel {
|
||||
private final ExecutorService extractionExecutor = Executors.newFixedThreadPool(2);
|
||||
|
||||
private @Nullable MediaController mediaController;
|
||||
private @Nullable ChatAudioQueueProvider queueProvider;
|
||||
private @Nullable Player.Listener playerListener;
|
||||
private final Handler handler;
|
||||
private boolean isUserSeeking = false;
|
||||
|
||||
@@ -47,6 +53,11 @@ public class AudioPlaybackViewModel extends ViewModel {
|
||||
}
|
||||
|
||||
public void setMediaController(@Nullable MediaController controller) {
|
||||
if (this.mediaController != null && playerListener != null) {
|
||||
this.mediaController.removeListener(playerListener);
|
||||
}
|
||||
playerListener = null;
|
||||
|
||||
this.mediaController = controller;
|
||||
if (mediaController != null && mediaController.isPlaying()) {
|
||||
startUpdateProgress();
|
||||
@@ -59,30 +70,41 @@ public class AudioPlaybackViewModel extends ViewModel {
|
||||
public void loadAudioAndPlay(int msgId, Uri audioUri) {
|
||||
if (mediaController == null) return;
|
||||
|
||||
// Set media item if we have a different audio.
|
||||
if (isDifferentAudio(msgId, audioUri)) {
|
||||
updateState(msgId, audioUri, AudioPlaybackState.PlaybackStatus.LOADING, 0, 0);
|
||||
String mediaId = String.valueOf(msgId);
|
||||
|
||||
MediaItem mediaItem =
|
||||
new MediaItem.Builder().setMediaId(String.valueOf(msgId)).setUri(audioUri).build();
|
||||
mediaController.setMediaItem(mediaItem);
|
||||
mediaController.prepare();
|
||||
MediaItem current = mediaController.getCurrentMediaItem();
|
||||
if (current != null && mediaId.equals(current.mediaId)) {
|
||||
mediaController.play();
|
||||
return;
|
||||
}
|
||||
|
||||
play(msgId, audioUri);
|
||||
updateState(msgId, audioUri, AudioPlaybackState.PlaybackStatus.LOADING, 0, 0);
|
||||
|
||||
List<MediaItem> items = null;
|
||||
int startIndex = -1;
|
||||
|
||||
if (queueProvider != null) {
|
||||
items = queueProvider.buildAudioQueue();
|
||||
startIndex = indexOfMediaId(items, mediaId);
|
||||
}
|
||||
|
||||
if (startIndex < 0) {
|
||||
items =
|
||||
Collections.singletonList(
|
||||
new MediaItem.Builder().setMediaId(mediaId).setUri(audioUri).build());
|
||||
startIndex = 0;
|
||||
}
|
||||
|
||||
mediaController.setMediaItems(items, startIndex, 0);
|
||||
mediaController.prepare();
|
||||
mediaController.play();
|
||||
}
|
||||
|
||||
private boolean isSameAudio(int msgId, Uri audioUri) {
|
||||
return !isDifferentAudio(msgId, audioUri);
|
||||
}
|
||||
|
||||
private boolean isDifferentAudio(int msgId, Uri audioUri) {
|
||||
AudioPlaybackState currentState = playbackState.getValue();
|
||||
|
||||
return currentState != null
|
||||
&& (msgId != currentState.getMsgId()
|
||||
|| currentState.getAudioUri() == null
|
||||
|| currentState.getAudioUri() != null && !currentState.getAudioUri().equals(audioUri));
|
||||
private static int indexOfMediaId(List<MediaItem> items, String mediaId) {
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
if (mediaId.equals(items.get(i).mediaId)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public LiveData<Map<Integer, Long>> getDurations() {
|
||||
@@ -138,46 +160,72 @@ public class AudioPlaybackViewModel extends ViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
public void pause(int msgId, Uri audioUri) {
|
||||
if (mediaController != null && isSameAudio(msgId, audioUri)) {
|
||||
public void pause(int msgId) {
|
||||
if (isCurrentItem(msgId)) {
|
||||
mediaController.pause();
|
||||
}
|
||||
}
|
||||
|
||||
public void play(int msgId, Uri audioUri) {
|
||||
if (mediaController != null && isSameAudio(msgId, audioUri)) {
|
||||
public void play(int msgId) {
|
||||
if (isCurrentItem(msgId)) {
|
||||
mediaController.play();
|
||||
}
|
||||
}
|
||||
|
||||
public void seekTo(long position, int msgId, Uri audioUri) {
|
||||
if (mediaController != null && isSameAudio(msgId, audioUri)) {
|
||||
public void seekTo(long position, int msgId) {
|
||||
if (isCurrentItem(msgId)) {
|
||||
mediaController.seekTo(position);
|
||||
}
|
||||
}
|
||||
|
||||
public void stop(int msgId, Uri audioUri) {
|
||||
if (mediaController != null && isSameAudio(msgId, audioUri)) {
|
||||
public void stop(int msgId) {
|
||||
if (isCurrentItem(msgId)) {
|
||||
mediaController.stop();
|
||||
mediaController.clearMediaItems();
|
||||
stopUpdateProgress();
|
||||
playbackState.setValue(AudioPlaybackState.idle());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCurrentItem(int msgId) {
|
||||
if (mediaController == null) return false;
|
||||
MediaItem current = mediaController.getCurrentMediaItem();
|
||||
return current != null && String.valueOf(msgId).equals(current.mediaId);
|
||||
}
|
||||
|
||||
public void stopNonMessageAudioPlayback() {
|
||||
stopByIds(NON_MESSAGE_AUDIO_MSG_ID);
|
||||
}
|
||||
|
||||
// A special method for deleting message, where we only use message Ids
|
||||
public void stopByIds(int... msgIds) {
|
||||
AudioPlaybackState currentState = playbackState.getValue();
|
||||
if (mediaController == null) return;
|
||||
|
||||
if (mediaController != null && currentState != null) {
|
||||
AudioPlaybackState currentState = playbackState.getValue();
|
||||
boolean stoppedCurrent = false;
|
||||
|
||||
if (currentState != null) {
|
||||
for (int msgId : msgIds) {
|
||||
if (msgId == currentState.getMsgId()) {
|
||||
mediaController.stop();
|
||||
mediaController.clearMediaItems();
|
||||
stopUpdateProgress();
|
||||
playbackState.setValue(AudioPlaybackState.idle());
|
||||
stoppedCurrent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!stoppedCurrent) {
|
||||
Set<String> deletedMediaIds = new HashSet<>();
|
||||
for (int msgId : msgIds) {
|
||||
deletedMediaIds.add(String.valueOf(msgId));
|
||||
}
|
||||
for (int i = mediaController.getMediaItemCount() - 1; i >= 0; i--) {
|
||||
MediaItem item = mediaController.getMediaItemAt(i);
|
||||
if (deletedMediaIds.contains(item.mediaId)) {
|
||||
mediaController.removeMediaItem(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,10 +239,10 @@ public class AudioPlaybackViewModel extends ViewModel {
|
||||
private void setupPlayerListener() {
|
||||
if (mediaController == null) return;
|
||||
|
||||
mediaController.addListener(
|
||||
playerListener =
|
||||
new Player.Listener() {
|
||||
@Override
|
||||
public void onEvents(Player player, Player.Events events) {
|
||||
public void onEvents(@NonNull Player player, @NonNull Player.Events events) {
|
||||
if (events.containsAny(Player.EVENT_IS_PLAYING_CHANGED)) {
|
||||
if (player.isPlaying()) {
|
||||
startUpdateProgress();
|
||||
@@ -203,20 +251,40 @@ public class AudioPlaybackViewModel extends ViewModel {
|
||||
}
|
||||
updateCurrentState(false);
|
||||
}
|
||||
if (events.containsAny(Player.EVENT_MEDIA_ITEM_TRANSITION)) {
|
||||
updateCurrentState(true);
|
||||
}
|
||||
if (events.containsAny(Player.EVENT_PLAYBACK_STATE_CHANGED)) {
|
||||
if (player.getPlaybackState() == Player.STATE_READY) {
|
||||
updateCurrentState(false);
|
||||
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
|
||||
// This is to prevent automatically playing after the audio
|
||||
// has been play to the end once, then user dragged the seek bar again
|
||||
} else if (player.getPlaybackState() == Player.STATE_ENDED
|
||||
&& !player.hasNextMediaItem()) {
|
||||
mediaController.setPlayWhenReady(false);
|
||||
}
|
||||
}
|
||||
if (events.containsAny(Player.EVENT_PLAYER_ERROR)) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerError(@NonNull PlaybackException error) {
|
||||
Log.w(
|
||||
TAG,
|
||||
"Playback error on msgId="
|
||||
+ (mediaController.getCurrentMediaItem() != null
|
||||
? mediaController.getCurrentMediaItem().mediaId
|
||||
: "null"),
|
||||
error);
|
||||
|
||||
if (mediaController.hasNextMediaItem()) {
|
||||
mediaController.seekToNextMediaItem();
|
||||
mediaController.prepare();
|
||||
mediaController.play();
|
||||
} else {
|
||||
updateCurrentAudioState(AudioPlaybackState.PlaybackStatus.ERROR, 0, 0);
|
||||
mediaController.clearMediaItems();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
mediaController.addListener(playerListener);
|
||||
}
|
||||
|
||||
private void updateCurrentState(boolean queryPlaying) {
|
||||
@@ -285,6 +353,11 @@ public class AudioPlaybackViewModel extends ViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
// Playing Queue
|
||||
public void setQueueProvider(@Nullable ChatAudioQueueProvider provider) {
|
||||
this.queueProvider = provider;
|
||||
}
|
||||
|
||||
// Progress tracking
|
||||
private final Runnable progressRunnable =
|
||||
new Runnable() {
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.thoughtcrime.securesms.util.DateUtils;
|
||||
|
||||
public class AudioView extends FrameLayout {
|
||||
|
||||
private static final String TAG = AudioView.class.getSimpleName();
|
||||
private static final String TAG = "AudioView";
|
||||
|
||||
private final @NonNull ImageView playPauseButton;
|
||||
private final AnimatedVectorDrawableCompat playToPauseDrawable;
|
||||
@@ -109,12 +109,12 @@ public class AudioView extends FrameLayout {
|
||||
|
||||
AudioPlaybackState state = viewModel.getPlaybackState().getValue();
|
||||
|
||||
if (state != null && msgId == state.getMsgId() && audioUri.equals(state.getAudioUri())) {
|
||||
if (state != null && msgId == state.getMsgId()) {
|
||||
// Same audio
|
||||
if (state.getStatus() == AudioPlaybackState.PlaybackStatus.PLAYING) {
|
||||
viewModel.pause(msgId, audioUri);
|
||||
viewModel.pause(msgId);
|
||||
} else {
|
||||
viewModel.play(msgId, audioUri);
|
||||
viewModel.play(msgId);
|
||||
}
|
||||
} else {
|
||||
// Different audio
|
||||
@@ -145,7 +145,7 @@ public class AudioView extends FrameLayout {
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
viewModel.setUserSeeking(false);
|
||||
viewModel.seekTo(seekBar.getProgress(), msgId, audioUri);
|
||||
viewModel.seekTo(seekBar.getProgress(), msgId);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -305,7 +305,7 @@ public class AudioView extends FrameLayout {
|
||||
if (audioUri == null || state == null) return;
|
||||
|
||||
// Check if this state is about this message
|
||||
boolean isThisMessage = msgId == state.getMsgId() && audioUri.equals(state.getAudioUri());
|
||||
boolean isThisMessage = msgId == state.getMsgId();
|
||||
|
||||
if (isThisMessage) {
|
||||
updateUIForPlaybackState(state);
|
||||
@@ -340,13 +340,9 @@ public class AudioView extends FrameLayout {
|
||||
private void onDurationsChanged(Map<Integer, Long> durations) {
|
||||
AudioPlaybackState state = viewModel.getPlaybackState().getValue();
|
||||
|
||||
// When there is no playback happening, msgId can be -1 and audioUri is null
|
||||
if (state != null
|
||||
&& msgId >= 0
|
||||
&& msgId == state.getMsgId()
|
||||
&& audioUri != null
|
||||
&& audioUri.equals(state.getAudioUri())) {
|
||||
return; // Is playing this message
|
||||
// When there is no playback happening, msgId can be -1
|
||||
if (state != null && msgId >= 0 && msgId == state.getMsgId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Long duration = durations.get(msgId);
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package org.thoughtcrime.securesms.components.audioplay;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
|
||||
public class ChatAudioQueueProvider {
|
||||
|
||||
private final Context context;
|
||||
private final int chatId;
|
||||
private final int accountId;
|
||||
|
||||
public ChatAudioQueueProvider(@NonNull Context context, int chatId, int accountId) {
|
||||
this.context = context.getApplicationContext();
|
||||
this.chatId = chatId;
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<MediaItem> buildAudioQueue() {
|
||||
DcContext dcContext = DcHelper.getContext(context);
|
||||
int[] msgIds = dcContext.getChatMedia(chatId, DcMsg.DC_MSG_AUDIO, DcMsg.DC_MSG_VOICE, 0);
|
||||
|
||||
List<MediaItem> items = new ArrayList<>(msgIds.length);
|
||||
for (int msgId : msgIds) {
|
||||
String id = String.valueOf(msgId);
|
||||
items.add(
|
||||
new MediaItem.Builder()
|
||||
.setMediaId(id)
|
||||
.setUri(Uri.parse("dcmsg://" + accountId + "/" + id))
|
||||
.build());
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.util.ResUtil;
|
||||
public class MediaKeyboard extends LinearLayout
|
||||
implements InputView, Consumer<EmojiViewItem>, StickerPickerView.StickerPickerListener {
|
||||
|
||||
private static final String TAG = MediaKeyboard.class.getSimpleName();
|
||||
private static final String TAG = "MediaKeyboard";
|
||||
|
||||
@Nullable private MediaKeyboardListener keyboardListener;
|
||||
private EmojiPickerView emojiPicker;
|
||||
|
||||
@@ -71,7 +71,7 @@ public class StickerPickerView extends RecyclerView {
|
||||
}
|
||||
|
||||
// Sort stickers just to provide consistent order
|
||||
Collections.sort(stickerFiles, (f1, f2) -> f1.getName().compareToIgnoreCase(f2.getName()));
|
||||
Collections.sort(stickerFiles, (f1, f2) -> f2.getName().compareToIgnoreCase(f1.getName()));
|
||||
|
||||
return stickerFiles;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.thoughtcrime.securesms.util.Prefs;
|
||||
|
||||
@SuppressLint("BatteryLife")
|
||||
public class DozeReminder {
|
||||
private static final String TAG = DozeReminder.class.getSimpleName();
|
||||
private static final String TAG = "DozeReminder";
|
||||
|
||||
public static boolean isEligible(Context context) {
|
||||
if (context == null) {
|
||||
|
||||
@@ -19,7 +19,7 @@ import androidx.viewpager.widget.ViewPager;
|
||||
*/
|
||||
public class HackyViewPager extends ViewPager {
|
||||
|
||||
private static final String TAG = HackyViewPager.class.getSimpleName();
|
||||
private static final String TAG = "HackyViewPager";
|
||||
|
||||
public HackyViewPager(Context context) {
|
||||
super(context);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package org.thoughtcrime.securesms.components.viewpager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Matrix;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
public class RtlSafeViewPager extends HackyViewPager {
|
||||
private final Matrix mirrorMatrix = new Matrix();
|
||||
private boolean rtl;
|
||||
|
||||
public RtlSafeViewPager(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public RtlSafeViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
updateLayoutDirection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRtlPropertiesChanged(int layoutDirection) {
|
||||
super.onRtlPropertiesChanged(layoutDirection);
|
||||
updateLayoutDirection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (!isRtl()) {
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
}
|
||||
|
||||
MotionEvent mirrored = getMirroredMotionEvent(ev);
|
||||
try {
|
||||
return super.onInterceptTouchEvent(mirrored);
|
||||
} finally {
|
||||
mirrored.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
if (!isRtl()) {
|
||||
return super.onTouchEvent(ev);
|
||||
}
|
||||
|
||||
MotionEvent mirrored = getMirroredMotionEvent(ev);
|
||||
try {
|
||||
return super.onTouchEvent(mirrored);
|
||||
} finally {
|
||||
mirrored.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRtl() {
|
||||
return rtl;
|
||||
}
|
||||
|
||||
private MotionEvent getMirroredMotionEvent(@NonNull MotionEvent ev) {
|
||||
MotionEvent mirrored = MotionEvent.obtain(ev);
|
||||
mirrorMatrix.reset();
|
||||
mirrorMatrix.setScale(-1f, 1f, getWidth() / 2f, 0f);
|
||||
mirrored.transform(mirrorMatrix);
|
||||
return mirrored;
|
||||
}
|
||||
|
||||
private void updateLayoutDirection() {
|
||||
rtl = ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL;
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ import org.thoughtcrime.securesms.accounts.AccountSelectionListFragment;
|
||||
|
||||
public class AccountManager {
|
||||
|
||||
private static final String TAG = AccountManager.class.getSimpleName();
|
||||
private static final String TAG = "AccountManager";
|
||||
private static final String LAST_ACCOUNT_ID = "last_account_id";
|
||||
private static AccountManager self;
|
||||
|
||||
@@ -38,7 +38,7 @@ public class AccountManager {
|
||||
return self;
|
||||
}
|
||||
|
||||
public void migrateToDcAccounts(ApplicationContext context) {
|
||||
public void migrateToDcAccounts(Context context, DcAccounts dcAccounts) {
|
||||
try {
|
||||
int selectAccountId = 0;
|
||||
|
||||
@@ -49,8 +49,7 @@ public class AccountManager {
|
||||
if (!file.isDirectory()
|
||||
&& file.getName().startsWith("messenger")
|
||||
&& file.getName().endsWith(".db")) {
|
||||
int accountId =
|
||||
ApplicationContext.getDcAccounts().migrateAccount(file.getAbsolutePath());
|
||||
int accountId = dcAccounts.migrateAccount(file.getAbsolutePath());
|
||||
if (accountId != 0) {
|
||||
String selName =
|
||||
PreferenceManager.getDefaultSharedPreferences(context)
|
||||
@@ -67,7 +66,7 @@ public class AccountManager {
|
||||
}
|
||||
|
||||
if (selectAccountId != 0) {
|
||||
ApplicationContext.getDcAccounts().selectAccount(selectAccountId);
|
||||
dcAccounts.selectAccount(selectAccountId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error in migrateToDcAccounts()", e);
|
||||
|
||||
@@ -5,7 +5,6 @@ import androidx.annotation.NonNull;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import org.thoughtcrime.securesms.util.AsyncLoader;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class DcContactsLoader extends AsyncLoader<DcContactsLoader.Ret> {
|
||||
@@ -53,10 +52,7 @@ public class DcContactsLoader extends AsyncLoader<DcContactsLoader.Ret> {
|
||||
}
|
||||
if (query == null && addCreateGroupLinks) {
|
||||
additional_items = Util.appendInt(additional_items, DcContact.DC_CONTACT_ID_NEW_GROUP);
|
||||
|
||||
final boolean broadcastsEnabled = Prefs.isNewBroadcastAvailable(getContext());
|
||||
if (broadcastsEnabled)
|
||||
additional_items = Util.appendInt(additional_items, DcContact.DC_CONTACT_ID_NEW_BROADCAST);
|
||||
additional_items = Util.appendInt(additional_items, DcContact.DC_CONTACT_ID_NEW_BROADCAST);
|
||||
|
||||
if (!dcContext.isChatmail()) {
|
||||
additional_items =
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.thoughtcrime.securesms.service.FetchForegroundService;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class DcEventCenter {
|
||||
private static final String TAG = DcEventCenter.class.getSimpleName();
|
||||
private static final String TAG = "DcEventCenter";
|
||||
private @NonNull final Hashtable<Integer, ArrayList<DcEventDelegate>> currentAccountObservers =
|
||||
new Hashtable<>();
|
||||
private @NonNull final Hashtable<Integer, ArrayList<DcEventDelegate>> multiAccountObservers =
|
||||
|
||||
@@ -42,7 +42,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class DcHelper {
|
||||
|
||||
private static final String TAG = DcHelper.class.getSimpleName();
|
||||
private static final String TAG = "DcHelper";
|
||||
|
||||
public static final String CONFIG_CONFIGURED_ADDRESS = "configured_addr";
|
||||
public static final String CONFIG_DISPLAY_NAME = "displayname";
|
||||
@@ -225,6 +225,8 @@ public class DcHelper {
|
||||
dcContext.setStockTranslation(201, context.getString(R.string.qrshow_join_channel_hint));
|
||||
dcContext.setStockTranslation(202, context.getString(R.string.you_joined_the_channel));
|
||||
dcContext.setStockTranslation(203, context.getString(R.string.secure_join_channel_started));
|
||||
dcContext.setStockTranslation(204, context.getString(R.string.channel_name_changed));
|
||||
dcContext.setStockTranslation(205, context.getString(R.string.channel_image_changed));
|
||||
dcContext.setStockTranslation(210, context.getString(R.string.stats_msg_body));
|
||||
dcContext.setStockTranslation(220, context.getString(R.string.proxy_enabled));
|
||||
dcContext.setStockTranslation(221, context.getString(R.string.proxy_enabled_hint));
|
||||
|
||||
@@ -40,7 +40,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
*/
|
||||
public class DirectShareUtil {
|
||||
|
||||
private static final String TAG = DirectShareUtil.class.getSimpleName();
|
||||
private static final String TAG = "DirectShareUtil";
|
||||
private static final String SHORTCUT_CATEGORY = "android.shortcut.conversation";
|
||||
|
||||
public static void clearShortcut(@NonNull Context context, int chatId) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.thoughtcrime.securesms.util.Prefs;
|
||||
|
||||
public class KeepAliveService extends Service {
|
||||
|
||||
private static final String TAG = KeepAliveService.class.getSimpleName();
|
||||
private static final String TAG = "KeepAliveService";
|
||||
|
||||
static KeepAliveService s_this = null;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import android.util.Log;
|
||||
|
||||
public class NetworkStateReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = NetworkStateReceiver.class.getSimpleName();
|
||||
private static final String TAG = "NetworkStateReceiver";
|
||||
private int debugConnectedCount;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.thoughtcrime.securesms.ContactSelectionListFragment;
|
||||
import org.thoughtcrime.securesms.util.Hash;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
|
||||
@@ -37,7 +36,7 @@ import org.thoughtcrime.securesms.util.Prefs;
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
public class ContactAccessor {
|
||||
private static final String TAG = ContactSelectionListFragment.class.getSimpleName();
|
||||
private static final String TAG = "ContactAccessor";
|
||||
|
||||
private static final int CONTACT_CURSOR_NAME = 0;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.util.AsyncLoader;
|
||||
|
||||
public class PagingMediaLoader extends AsyncLoader<DcMediaGalleryElement> {
|
||||
|
||||
private static final String TAG = PagingMediaLoader.class.getSimpleName();
|
||||
private static final String TAG = "PagingMediaLoader";
|
||||
|
||||
private final DcMsg msg;
|
||||
private final boolean leftIsRecent;
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
|
||||
public class LocationStreamingService extends Service {
|
||||
|
||||
private static final String TAG = LocationStreamingService.class.getSimpleName();
|
||||
private static final String TAG = "LocationStreamingService";
|
||||
private static final String ACTION_STOP = "org.thoughtcrime.securesms.geolocation.STOP_STREAMING";
|
||||
private static final int NOTIFICATION_ID = 8801;
|
||||
private static final String CHANNEL_ID = "location_streaming";
|
||||
|
||||
@@ -15,7 +15,7 @@ import java.util.concurrent.Executor;
|
||||
|
||||
public class PlatformLocationSource implements LocationSource {
|
||||
|
||||
private static final String TAG = PlatformLocationSource.class.getSimpleName();
|
||||
private static final String TAG = "PlatformLocationSource";
|
||||
private static final long UPDATE_INTERVAL_MS = 0;
|
||||
|
||||
private LocationManager locationManager;
|
||||
@@ -36,7 +36,7 @@ public class PlatformLocationSource implements LocationSource {
|
||||
registered = requestProvider(context, LocationManager.FUSED_PROVIDER, callback);
|
||||
}
|
||||
|
||||
// Fall back (or complement) with individual providers
|
||||
// Fall back with individual providers
|
||||
if (!registered) {
|
||||
requestProvider(context, LocationManager.GPS_PROVIDER, callback);
|
||||
requestProvider(context, LocationManager.NETWORK_PROVIDER, callback);
|
||||
|
||||
@@ -19,7 +19,7 @@ import androidx.annotation.NonNull;
|
||||
|
||||
class JobConsumer extends Thread {
|
||||
|
||||
private static final String TAG = JobConsumer.class.getSimpleName();
|
||||
private static final String TAG = "JobConsumer";
|
||||
|
||||
enum JobResult {
|
||||
SUCCESS,
|
||||
|
||||
@@ -75,7 +75,7 @@ import org.thoughtcrime.securesms.util.views.Stub;
|
||||
|
||||
public class AttachmentManager {
|
||||
|
||||
private static final String TAG = AttachmentManager.class.getSimpleName();
|
||||
private static final String TAG = "AttachmentManager";
|
||||
|
||||
private final @NonNull Context context;
|
||||
private final @NonNull Stub<View> attachmentViewStub;
|
||||
@@ -283,7 +283,7 @@ public class AttachmentManager {
|
||||
removableMediaView.display(audioView, false);
|
||||
removableMediaView.addRemoveClickListener(
|
||||
v -> {
|
||||
playbackViewModel.stop(audioView.getMsgId(), audioView.getAudioUri());
|
||||
playbackViewModel.stop(audioView.getMsgId());
|
||||
});
|
||||
result.set(true);
|
||||
} else if (slide.isVcard()) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.io.InputStream;
|
||||
|
||||
class DecryptableStreamLocalUriFetcher extends StreamLocalUriFetcher {
|
||||
|
||||
private static final String TAG = DecryptableStreamLocalUriFetcher.class.getSimpleName();
|
||||
private static final String TAG = "DecryptableStreamLocalUriFetcher";
|
||||
|
||||
private final Context context;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import android.util.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
public class InChatSounds {
|
||||
private static final String TAG = InChatSounds.class.getSimpleName();
|
||||
private static final String TAG = "InChatSounds";
|
||||
private static volatile InChatSounds instance;
|
||||
|
||||
private SoundPool soundPool = null;
|
||||
|
||||
@@ -54,7 +54,7 @@ import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class NotificationCenter {
|
||||
private static final String TAG = NotificationCenter.class.getSimpleName();
|
||||
private static final String TAG = "NotificationCenter";
|
||||
@NonNull private final ApplicationContext context;
|
||||
private volatile ChatData visibleChat = null;
|
||||
private volatile Pair<Integer, Integer> visibleWebxdc = null;
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
/** Get the response text from the Wearable Device and sends an message as a reply */
|
||||
public class RemoteReplyReceiver extends BroadcastReceiver {
|
||||
|
||||
public static final String TAG = RemoteReplyReceiver.class.getSimpleName();
|
||||
public static final String TAG = "RemoteReplyReceiver";
|
||||
public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY";
|
||||
public static final String ACCOUNT_ID_EXTRA = "account_id";
|
||||
public static final String CHAT_ID_EXTRA = "chat_id";
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
|
||||
implements DcEventCenter.DcEventDelegate {
|
||||
private static final String TAG = AdvancedPreferenceFragment.class.getSimpleName();
|
||||
private static final String TAG = "AdvancedPreferenceFragment";
|
||||
|
||||
private ListPreference showEmails;
|
||||
CheckBoxPreference selfReportingCheckbox;
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ import org.thoughtcrime.securesms.util.Prefs;
|
||||
public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragment
|
||||
implements Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = NotificationsPreferenceFragment.class.getSimpleName();
|
||||
private static final String TAG = "NotificationsPreferenceFragment";
|
||||
|
||||
private CheckBoxPreference ignoreBattery;
|
||||
private CheckBoxPreference notificationsEnabled;
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class PersistentBlobProvider {
|
||||
|
||||
private static final String TAG = PersistentBlobProvider.class.getSimpleName();
|
||||
private static final String TAG = "PersistentBlobProvider";
|
||||
|
||||
private static final String URI_STRING = "content://org.thoughtcrime.securesms/capture-new";
|
||||
public static final Uri CONTENT_URI = Uri.parse(URI_STRING);
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class BackupProviderFragment extends Fragment implements DcEventCenter.DcEventDelegate {
|
||||
|
||||
private static final String TAG = BackupProviderFragment.class.getSimpleName();
|
||||
private static final String TAG = "BackupProviderFragment";
|
||||
|
||||
private DcContext dcContext;
|
||||
private DcBackupProvider dcBackupProvider;
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class BackupReceiverFragment extends Fragment implements DcEventCenter.DcEventDelegate {
|
||||
|
||||
private static final String TAG = BackupProviderFragment.class.getSimpleName();
|
||||
private static final String TAG = "BackupProviderFragment";
|
||||
|
||||
private DcContext dcContext;
|
||||
private TextView statusLine;
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class BackupTransferActivity extends BaseActionBarActivity {
|
||||
|
||||
private static final String TAG = BackupTransferActivity.class.getSimpleName();
|
||||
private static final String TAG = "BackupTransferActivity";
|
||||
|
||||
public enum TransferMode {
|
||||
INVALID(0),
|
||||
|
||||
@@ -40,7 +40,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class QrActivity extends BaseActionBarActivity implements View.OnClickListener {
|
||||
|
||||
private static final String TAG = QrActivity.class.getSimpleName();
|
||||
private static final String TAG = "QrActivity";
|
||||
public static final String EXTRA_SCAN_RELAY = "scan_relay";
|
||||
|
||||
private static final int REQUEST_CODE_IMAGE = 46243;
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
|
||||
public class QrCodeHandler {
|
||||
private static final String TAG = QrCodeHandler.class.getSimpleName();
|
||||
private static final String TAG = "QrCodeHandler";
|
||||
|
||||
public static int SECUREJOIN_SOURCE_EXTERNAL_LINK = 1;
|
||||
public static int SECUREJOIN_SOURCE_INTERNAL_LINK = 2;
|
||||
@@ -363,20 +363,24 @@ public class QrCodeHandler {
|
||||
SecurejoinSource source,
|
||||
SecurejoinUiPath uipath) {
|
||||
String msg;
|
||||
int positiveButton;
|
||||
switch (qrParsed.getState()) {
|
||||
case DcContext.DC_QR_ASK_VERIFYGROUP:
|
||||
msg = activity.getString(R.string.qrscan_ask_join_group, qrParsed.getText1());
|
||||
positiveButton = R.string.join_group;
|
||||
break;
|
||||
case DcContext.DC_QR_ASK_JOIN_BROADCAST:
|
||||
msg = activity.getString(R.string.qrscan_ask_join_channel, qrParsed.getText1());
|
||||
positiveButton = R.string.join_channel;
|
||||
break;
|
||||
default:
|
||||
msg = activity.getString(R.string.ask_start_chat_with, name);
|
||||
positiveButton = R.string.ok;
|
||||
break;
|
||||
}
|
||||
builder.setMessage(msg);
|
||||
builder.setPositiveButton(
|
||||
android.R.string.ok,
|
||||
positiveButton,
|
||||
(dialogInterface, i) -> {
|
||||
secureJoinByQr(qrRawString, source, uipath);
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class QrScanFragment extends Fragment {
|
||||
|
||||
private static final String TAG = QrScanFragment.class.getSimpleName();
|
||||
private static final String TAG = "QrScanFragment";
|
||||
|
||||
private CompoundBarcodeView barcodeScannerView;
|
||||
private MyCaptureManager capture;
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class QrShowFragment extends Fragment implements DcEventCenter.DcEventDelegate {
|
||||
|
||||
private static final String TAG = QrShowFragment.class.getSimpleName();
|
||||
private static final String TAG = "QrShowFragment";
|
||||
public static final int WHITE = 0xFFFFFFFF;
|
||||
private static final int BLACK = 0xFF000000;
|
||||
private static final int WIDTH = 400;
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class ReactionsDetailsFragment extends DialogFragment
|
||||
implements DcEventCenter.DcEventDelegate {
|
||||
private static final String TAG = ReactionsDetailsFragment.class.getSimpleName();
|
||||
private static final String TAG = "ReactionsDetailsFragment";
|
||||
private static final String ARG_MSG_ID = "msg_id";
|
||||
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
@@ -56,7 +56,7 @@ public class EditRelayActivity extends BaseActionBarActivity
|
||||
PORT,
|
||||
}
|
||||
|
||||
private static final String TAG = EditRelayActivity.class.getSimpleName();
|
||||
private static final String TAG = "EditRelayActivity";
|
||||
public static final String EXTRA_ADDR = "extra_addr";
|
||||
|
||||
private TextInputEditText emailInput;
|
||||
|
||||
@@ -37,7 +37,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
public class RelayListActivity extends BaseActionBarActivity
|
||||
implements RelayListAdapter.OnRelayClickListener, DcEventCenter.DcEventDelegate {
|
||||
|
||||
private static final String TAG = RelayListActivity.class.getSimpleName();
|
||||
private static final String TAG = "RelayListActivity";
|
||||
public static final String EXTRA_QR_DATA = "qr_data";
|
||||
|
||||
private RelayListAdapter adapter;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user