Merge branch 'main' into wch423/audio-background-play

This commit is contained in:
adb
2026-01-29 22:17:24 +01:00
committed by GitHub
10 changed files with 134 additions and 48 deletions
@@ -2,8 +2,8 @@ package com.b44t.messenger;
public class DcAccounts {
public DcAccounts(String dir) {
accountsCPtr = createAccountsCPtr(dir);
public DcAccounts(String dir, DcEventChannel channel) {
accountsCPtr = createAccountsCPtr(dir, channel);
if (accountsCPtr == 0) throw new RuntimeException("createAccountsCPtr() returned null pointer");
}
@@ -38,7 +38,7 @@ public class DcAccounts {
// working with raw c-data
private long accountsCPtr; // CAVE: the name is referenced in the JNI
private native long createAccountsCPtr (String dir);
private native long createAccountsCPtr (String dir, DcEventChannel channel);
private native void unrefAccountsCPtr ();
private native long getEventEmitterCPtr ();
private native long getJsonrpcInstanceCPtr ();
@@ -0,0 +1,27 @@
package com.b44t.messenger;
public class DcEventChannel {
public DcEventChannel() {
eventChannelCPtr = createEventChannelCPtr();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
if (eventChannelCPtr != 0) {
unrefEventChannelCPtr();
eventChannelCPtr = 0;
}
}
public DcEventEmitter getEventEmitter() {
return new DcEventEmitter(getEventEmitterCPtr());
}
// working with raw c-data
private long eventChannelCPtr; // CAVE: the name is referenced in the JNI
private native long createEventChannelCPtr ();
private native void unrefEventChannelCPtr ();
private native long getEventEmitterCPtr ();
}
@@ -23,6 +23,7 @@ import androidx.work.WorkManager;
import com.b44t.messenger.DcAccounts;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEvent;
import com.b44t.messenger.DcEventChannel;
import com.b44t.messenger.DcEventEmitter;
import com.b44t.messenger.FFITransport;
@@ -173,7 +174,29 @@ public class ApplicationContext extends MultiDexApplication {
Util.runOnBackground(() -> {
synchronized (initLock) {
try {
dcAccounts = new DcAccounts(new File(getFilesDir(), "accounts").getAbsolutePath());
DcEventChannel eventChannel = new DcEventChannel();
DcEventEmitter emitter = eventChannel.getEventEmitter();
eventCenter = new DcEventCenter(this);
new Thread(() -> {
Log.i(TAG, "Starting event loop");
while (true) {
DcEvent event = emitter.getNextEvent();
if (event == null) {
break;
}
if (isInitialized) {
eventCenter.handleEvent(event);
} else {
// not fully initialized, only handle logging events,
// ex. account migrations during DcAccounts initialization
eventCenter.handleLogging(event);
}
}
Log.i("DeltaChat", "shutting down event handler");
}, "eventThread").start();
dcAccounts = new DcAccounts(new File(getFilesDir(), "accounts").getAbsolutePath(), eventChannel);
Log.i(TAG, "DcAccounts created");
rpc = new Rpc(new FFITransport(dcAccounts.getJsonrpcInstance()));
Log.i(TAG, "Rpc created");
@@ -213,28 +236,12 @@ public class ApplicationContext extends MultiDexApplication {
}
dcContext = dcAccounts.getSelectedAccount();
notificationCenter = new NotificationCenter(this);
eventCenter = new DcEventCenter(this);
dcLocationManager = new DcLocationManager(this, dcContext);
// Mark as initialized before starting threads that depend on it
isInitialized = true;
initLock.notifyAll();
Log.i(TAG, "DcAccounts initialization complete");
new Thread(() -> {
Log.i(TAG, "Starting event loop");
DcEventEmitter emitter = dcAccounts.getEventEmitter();
Log.i(TAG, "DcEventEmitter obtained");
while (true) {
DcEvent event = emitter.getNextEvent();
if (event==null) {
break;
}
eventCenter.handleEvent(event);
}
Log.i("DeltaChat", "shutting down event handler");
}, "eventThread").start();
// set translations before starting I/O to avoid sending untranslated MDNs (issue #2288)
DcHelper.setStockTranslations(this);
@@ -875,7 +875,7 @@ public class ConversationFragment extends MessageSelectorFragment
@Override
public void onReactionClicked(DcMsg messageRecord) {
ReactionsDetailsFragment dialog = new ReactionsDetailsFragment(messageRecord.getId());
ReactionsDetailsFragment dialog = ReactionsDetailsFragment.newInstance(messageRecord.getId());
dialog.show(getActivity().getSupportFragmentManager(), null);
}
}
@@ -47,20 +47,23 @@ import chat.delta.rpc.RpcException;
public class AccountSelectionListFragment extends DialogFragment implements DcEventCenter.DcEventDelegate
{
private static final String TAG = AccountSelectionListFragment.class.getSimpleName();
private final ConversationListActivity activity;
private static final String ARG_SELECT_ONLY = "select_only";
private RecyclerView recyclerView;
private AccountSelectionListAdapter adapter;
private final boolean selectOnly;
private boolean selectOnly;
public AccountSelectionListFragment(ConversationListActivity activity, boolean selectOnly) {
super();
this.activity = activity;
this.selectOnly = selectOnly;
public static AccountSelectionListFragment newInstance(boolean selectOnly) {
AccountSelectionListFragment fragment = new AccountSelectionListFragment();
Bundle args = new Bundle();
args.putBoolean(ARG_SELECT_ONLY, selectOnly);
fragment.setArguments(args);
return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
selectOnly = getArguments() != null && getArguments().getBoolean(ARG_SELECT_ONLY, false);
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity())
.setTitle(R.string.switch_account)
.setNegativeButton(R.string.cancel, null);
@@ -179,6 +182,7 @@ public class AccountSelectionListFragment extends DialogFragment implements DcEv
}
private void onSetTag(int accountId) {
ConversationListActivity activity = (ConversationListActivity)requireActivity();
AccountSelectionListFragment.this.dismiss();
DcContext dcContext = DcHelper.getAccounts(activity).getAccount(accountId);
@@ -202,6 +206,7 @@ public class AccountSelectionListFragment extends DialogFragment implements DcEv
private void onDeleteProfile(int accountId) {
AccountSelectionListFragment.this.dismiss();
ConversationListActivity activity = (ConversationListActivity)requireActivity();
DcAccounts accounts = DcHelper.getAccounts(activity);
Rpc rpc = DcHelper.getRpc(activity);
@@ -254,6 +259,7 @@ public class AccountSelectionListFragment extends DialogFragment implements DcEv
@Override
public void onItemClick(AccountSelectionListItem contact) {
AccountSelectionListFragment.this.dismiss();
ConversationListActivity activity = (ConversationListActivity)requireActivity();
int accountId = contact.getAccountId();
if (accountId == DC_CONTACT_ID_ADD_ACCOUNT) {
AccountManager.getInstance().switchAccountAndStartActivity(activity, 0);
@@ -138,7 +138,7 @@ public class AccountManager {
// ui
public void showSwitchAccountMenu(ConversationListActivity activity, boolean selectOnly) {
AccountSelectionListFragment dialog = new AccountSelectionListFragment(activity, selectOnly);
AccountSelectionListFragment dialog = AccountSelectionListFragment.newInstance(selectOnly);
dialog.show(((FragmentActivity) activity).getSupportFragmentManager(), null);
}
@@ -164,6 +164,23 @@ public class DcEventCenter {
});
}
public void handleLogging(@NonNull DcEvent event) {
final String logPrefix = "[accId="+event.getAccountId()+ "] ";
switch (event.getId()) {
case DcContext.DC_EVENT_INFO:
Log.i("DeltaChat", logPrefix + event.getData2Str());
break;
case DcContext.DC_EVENT_WARNING:
Log.w("DeltaChat", logPrefix + event.getData2Str());
break;
case DcContext.DC_EVENT_ERROR:
Log.e("DeltaChat", logPrefix + event.getData2Str());
break;
}
}
public long handleEvent(@NonNull DcEvent event) {
int accountId = event.getAccountId();
int id = event.getId();
@@ -205,20 +222,7 @@ public class DcEventCenter {
return 0;
}
final String logPrefix = "[accId="+accountId + "] ";
switch (id) {
case DcContext.DC_EVENT_INFO:
Log.i("DeltaChat", logPrefix + event.getData2Str());
break;
case DcContext.DC_EVENT_WARNING:
Log.w("DeltaChat", logPrefix + event.getData2Str());
break;
case DcContext.DC_EVENT_ERROR:
Log.e("DeltaChat", logPrefix + event.getData2Str());
break;
}
handleLogging(event);
if (accountId != context.getDcContext().getAccountId()) {
return 0;
@@ -36,19 +36,24 @@ import chat.delta.rpc.types.Reactions;
public class ReactionsDetailsFragment extends DialogFragment implements DcEventCenter.DcEventDelegate {
private static final String TAG = ReactionsDetailsFragment.class.getSimpleName();
private static final String ARG_MSG_ID = "msg_id";
private RecyclerView recyclerView;
private ReactionRecipientsAdapter adapter;
private final int msgId;
private int msgId;
public ReactionsDetailsFragment(int msgId) {
super();
this.msgId = msgId;
public static ReactionsDetailsFragment newInstance(int msgId) {
ReactionsDetailsFragment fragment = new ReactionsDetailsFragment();
Bundle args = new Bundle();
args.putInt(ARG_MSG_ID, msgId);
fragment.setArguments(args);
return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
msgId = getArguments() != null? getArguments().getInt(ARG_MSG_ID, 0) : 0;
adapter = new ReactionRecipientsAdapter(requireActivity(), GlideApp.with(requireActivity()), new ListClickListener());
LayoutInflater inflater = requireActivity().getLayoutInflater();