mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 385f516d63 | |||
| 6c89845cf9 | |||
| ee73ccf6ef | |||
| c9b6bb15e6 | |||
| e810f27ac2 | |||
| eeee1637c3 | |||
| 521adebda2 | |||
| b759203e93 |
@@ -360,6 +360,7 @@
|
||||
<activity android:name=".WebxdcActivity"
|
||||
android:label=""
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:windowSoftInputMode="adjustPan"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize|uiMode">
|
||||
</activity>
|
||||
|
||||
|
||||
@@ -569,11 +569,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
} else if (itemId == R.id.menu_show_map) {
|
||||
WebxdcActivity.openMaps(this, chatId);
|
||||
return true;
|
||||
} else if (itemId == R.id.menu_audio_call) {
|
||||
CallUtil.startCall(this, chatId, true);
|
||||
return true;
|
||||
} else if (itemId == R.id.menu_video_call) {
|
||||
CallUtil.startCall(this, chatId, false);
|
||||
} else if (itemId == R.id.menu_start_call) {
|
||||
CallUtil.startCall(this, chatId);
|
||||
return true;
|
||||
} else if (itemId == R.id.menu_all_media) {
|
||||
handleAllMedia();
|
||||
|
||||
@@ -77,7 +77,8 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity
|
||||
findViewById(R.id.status_bar_background).setBackgroundResource(R.drawable.search_toolbar_shadow);
|
||||
} else {
|
||||
// add padding to avoid content hidden behind system bars
|
||||
ViewUtil.applyWindowInsets(findViewById(R.id.content_container));
|
||||
// Use applyWindowInsetsExcludingIme to respect navigation bars but not keyboard
|
||||
ViewUtil.applyWindowInsetsExcludingIme(findViewById(R.id.content_container));
|
||||
}
|
||||
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
|
||||
@@ -19,40 +19,23 @@ public class CallUtil {
|
||||
private static final String TAG = CallUtil.class.getSimpleName();
|
||||
|
||||
public static void startCall(Activity activity, int chatId) {
|
||||
startCall(activity, chatId, false);
|
||||
}
|
||||
|
||||
public static void startCall(Activity activity, int chatId, boolean audioOnly) {
|
||||
String[] permissions = audioOnly
|
||||
? new String[] { Manifest.permission.RECORD_AUDIO }
|
||||
: new String[] { Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO };
|
||||
|
||||
String permissionExplanation = audioOnly
|
||||
? activity.getString(R.string.perm_explain_access_to_mic_for_calls_denied)
|
||||
: activity.getString(R.string.perm_explain_access_to_camera_and_mic_denied);
|
||||
|
||||
Permissions.with(activity)
|
||||
.request(permissions)
|
||||
.request(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
|
||||
.ifNecessary()
|
||||
.withPermanentDenialDialog(permissionExplanation)
|
||||
.withPermanentDenialDialog(activity.getString(R.string.perm_explain_access_to_camera_denied))
|
||||
.onAllGranted(() -> {
|
||||
int accId = DcHelper.getContext(activity).getAccountId();
|
||||
startCall(activity, accId, chatId, audioOnly);
|
||||
startCall(activity, accId, chatId);
|
||||
})
|
||||
.execute();
|
||||
}
|
||||
|
||||
public static void startCall(Context context, int accId, int chatId) {
|
||||
startCall(context, accId, chatId, false);
|
||||
}
|
||||
|
||||
public static void startCall(Context context, int accId, int chatId, boolean audioOnly) {
|
||||
Intent intent = new Intent(context, CallActivity.class);
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.putExtra(CallActivity.EXTRA_ACCOUNT_ID, accId);
|
||||
intent.putExtra(CallActivity.EXTRA_CHAT_ID, chatId);
|
||||
String hash = audioOnly ? "?disableVideoCompletely#startCall" : "#startCall";
|
||||
intent.putExtra(CallActivity.EXTRA_HASH, hash);
|
||||
intent.putExtra(CallActivity.EXTRA_HASH, "#startCall");
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
@@ -316,6 +316,23 @@ public class ViewUtil {
|
||||
return Insets.max(systemBars, displayCutout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get combined insets from status bar, navigation bar and display cutout areas,
|
||||
* excluding the IME (soft keyboard).
|
||||
*
|
||||
* @param windowInsets The window insets to extract from
|
||||
* @return Combined insets excluding IME
|
||||
*/
|
||||
private static Insets getCombinedInsetsExcludingIme(@NonNull WindowInsetsCompat windowInsets) {
|
||||
Insets systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
Insets displayCutout = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout());
|
||||
|
||||
// Combine systemBars (which excludes IME) with displayCutout using max to handle notches/cutouts
|
||||
Insets combined = Insets.max(systemBars, displayCutout);
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply window insets to a view by adding margin to avoid drawing it behind system bars.
|
||||
* Convenience method that applies insets to all sides.
|
||||
@@ -451,6 +468,67 @@ public class ViewUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply window insets to a view by adding padding to avoid drawing elements behind system bars,
|
||||
* excluding IME (soft keyboard) insets. This is useful for views that should respect navigation
|
||||
* bars but handle keyboard resizing through the window's soft input mode.
|
||||
*
|
||||
* This method stores the original padding values in view tags to ensure that
|
||||
* padding doesn't accumulate on multiple inset applications.
|
||||
*
|
||||
* Note: This feature is only enabled on API 30+ (Android 11+) where WindowInsets APIs
|
||||
* work correctly. On older API levels, the method returns early and the view will use
|
||||
* default system bar handling (content may be drawn behind system bars).
|
||||
*
|
||||
* @param view The view to apply insets to
|
||||
*/
|
||||
public static void applyWindowInsetsExcludingIme(@NonNull View view) {
|
||||
// Only enable on API 30+ where WindowInsets APIs work correctly
|
||||
if (!isEdgeToEdgeSupported()) return;
|
||||
|
||||
// Store the original padding as a tag only if not already stored
|
||||
// This prevents losing the true original padding on subsequent calls
|
||||
if (view.getTag(R.id.tag_window_insets_padding_left) == null) {
|
||||
view.setTag(R.id.tag_window_insets_padding_left, view.getPaddingLeft());
|
||||
view.setTag(R.id.tag_window_insets_padding_top, view.getPaddingTop());
|
||||
view.setTag(R.id.tag_window_insets_padding_right, view.getPaddingRight());
|
||||
view.setTag(R.id.tag_window_insets_padding_bottom, view.getPaddingBottom());
|
||||
}
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
|
||||
Insets insets = getCombinedInsetsExcludingIme(windowInsets);
|
||||
|
||||
// Retrieve the original padding values from tags with null checks
|
||||
Integer leftTag = (Integer) v.getTag(R.id.tag_window_insets_padding_left);
|
||||
Integer topTag = (Integer) v.getTag(R.id.tag_window_insets_padding_top);
|
||||
Integer rightTag = (Integer) v.getTag(R.id.tag_window_insets_padding_right);
|
||||
Integer bottomTag = (Integer) v.getTag(R.id.tag_window_insets_padding_bottom);
|
||||
int basePaddingLeft = leftTag != null ? leftTag : 0;
|
||||
int basePaddingTop = topTag != null ? topTag : 0;
|
||||
int basePaddingRight = rightTag != null ? rightTag : 0;
|
||||
int basePaddingBottom = bottomTag != null ? bottomTag : 0;
|
||||
|
||||
v.setPadding(
|
||||
basePaddingLeft + insets.left,
|
||||
basePaddingTop + insets.top,
|
||||
basePaddingRight + insets.right,
|
||||
basePaddingBottom + insets.bottom
|
||||
);
|
||||
|
||||
// Consume IME insets to prevent them from affecting child views (like WebView)
|
||||
// This stops the double-padding issue where both window resize and inset padding occur
|
||||
WindowInsetsCompat withoutIme = new WindowInsetsCompat.Builder(windowInsets)
|
||||
.setInsets(WindowInsetsCompat.Type.ime(), Insets.NONE)
|
||||
.build();
|
||||
return withoutIme;
|
||||
});
|
||||
|
||||
// Request the initial insets to be dispatched if the view is attached
|
||||
if (view.isAttachedToWindow()) {
|
||||
ViewCompat.requestApplyInsets(view);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the top status bar inset as the height of a view.
|
||||
*/
|
||||
|
||||
@@ -28,14 +28,7 @@
|
||||
<item android:id="@+id/menu_start_call"
|
||||
android:title="@string/start_call"
|
||||
android:icon="@drawable/ic_videocam_white_24dp"
|
||||
app:showAsAction="always">
|
||||
<menu>
|
||||
<item android:id="@+id/menu_audio_call"
|
||||
android:title="@string/start_audio_call" />
|
||||
<item android:id="@+id/menu_video_call"
|
||||
android:title="@string/start_video_call" />
|
||||
</menu>
|
||||
</item>
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item android:id="@+id/menu_all_media"
|
||||
android:title="@string/apps_and_media"
|
||||
|
||||
@@ -380,8 +380,6 @@
|
||||
|
||||
<!-- the action "to call someone", used as a tooltip for the "phone" icon. not: "the call" -->
|
||||
<string name="start_call">Call</string>
|
||||
<string name="start_audio_call">Audio Call</string>
|
||||
<string name="start_video_call">Video Call</string>
|
||||
<!-- the action "to answer" or to "accept" or to "pick up" a call. not: "the answer" -->
|
||||
<string name="answer_call">Answer</string>
|
||||
<!-- the action "to decline" a call, not: "the decline" -->
|
||||
@@ -1039,8 +1037,6 @@
|
||||
<string name="perm_explain_access_to_camera_denied">To take photos or capture videos, go to the app settings, select \"Permissions\", and enable \"Camera\".</string>
|
||||
<!-- give the user an idea where to find the "Microphone" option. the hint is only shown if access was initially denied by the user. pick up wordings really used on the systems, but do not be overly precise: things shift around often and there are too many system we support to track every detail and click path -->
|
||||
<string name="perm_explain_access_to_mic_denied">To send audio messages, go to system or app settings, select "Permissions" or "Privacy & Security", and enable \"Microphone\".</string>
|
||||
<string name="perm_explain_access_to_camera_and_mic_denied">To make video calls, go to the app settings, select \"Permissions\", and enable \"Camera\" and \"Microphone\".</string>
|
||||
<string name="perm_explain_access_to_mic_for_calls_denied">To make audio calls, go to system or app settings, select "Permissions" or "Privacy & Security", and enable \"Microphone\".</string>
|
||||
<string name="perm_explain_access_to_storage_denied">To receive or send files, go to the app settings, select \"Permissions\", and enable \"Storage\".</string>
|
||||
<string name="perm_explain_access_to_location_denied">To attach a location, go to the app settings, select \"Permissions\", and enable \"Location\".</string>
|
||||
<string name="perm_explain_access_to_notifications_denied">To receive notifications, go to \"System Settings / Apps / Delta Chat\" and enable \"Notifications\".</string>
|
||||
|
||||
Reference in New Issue
Block a user