Compare commits

..

16 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] c60c8a7937 Apply maxWidth to content views instead of container to properly limit bubble width
Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-01-02 18:03:47 +00:00
copilot-swe-agent[bot] 07d6d8e81d Wrap body_bubble in FrameLayout to make maxWidth work with RelativeLayout constraints
Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-01-02 17:46:03 +00:00
copilot-swe-agent[bot] 9bcc241445 Update comments to explain software layer and bubble width constraint relationship
Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-01-02 16:38:46 +00:00
copilot-swe-agent[bot] 6b42987c9a Limit message bubble width on large screens to prevent software layer overflow
Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-01-02 16:36:45 +00:00
copilot-swe-agent[bot] 6d4f5bc2ca Extract magic number to named constant for better code quality
Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-01-02 16:05:08 +00:00
copilot-swe-agent[bot] 9c678db7cb Add conditional software layer based on screen size with proper documentation
Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-01-02 16:03:44 +00:00
copilot-swe-agent[bot] 84bea44f2c Fix: Remove software layer from RecyclerView to prevent memory overflow on foldables
Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-01-01 12:13:37 +00:00
copilot-swe-agent[bot] d5e994d8d3 Initial plan 2026-01-01 12:09:20 +00:00
adbenitez 8d6147761b add comment 2025-12-23 20:11:03 +01:00
adbenitez 9d6abfd979 avoid wrongly showing emoji icon while recording audio and event arrives 2025-12-23 20:08:57 +01:00
adbenitez 46f4324478 upload mappings to release 2025-12-22 20:03:44 +01:00
adbenitez bfeab57744 update screenshots 2025-12-22 19:36:26 +01:00
adbenitez 2e99926e82 Fix file_provider_paths.xml to support SD card 2025-12-22 19:21:22 +01:00
adb 76e4c59119 Merge pull request #87 from ArcaneChat/copilot/add-email-subject-field
Add subject field for mailing list chats
2025-12-16 20:31:45 +01:00
adbenitez 33b69b9f3a update scripts 2025-12-16 20:30:50 +01:00
adbenitez b4f5e2d124 allow to set subject in email threads 2025-12-16 20:25:05 +01:00
17 changed files with 116 additions and 24 deletions
+5 -1
View File
@@ -59,6 +59,8 @@ jobs:
rm build/outputs/apk/foss/release/*universal*
./gradlew assembleGplayRelease
mv build/outputs/apk/gplay/release/*universal* build/outputs/apk/foss/release/ArcaneChat-gplay.apk
mv build/outputs/mapping/fossRelease/mapping.txt build/outputs/mapping/fossRelease/mapping-foss.txt
mv build/outputs/mapping/gplayRelease/mapping.txt build/outputs/mapping/fossRelease/mapping-gplay.txt
- name: Release on GitHub
uses: softprops/action-gh-release@v1
@@ -67,7 +69,9 @@ jobs:
body: '[<img src="store/get-it-on-gplay.png" alt="Get it on Google Play" height="48">](https://play.google.com/store/apps/details?id=com.github.arcanechat) [<img src="store/get-it-on-fdroid.png" alt="Get it on F-Droid" height="48">](https://f-droid.org/packages/chat.delta.lite) [<img src="store/get-it-on-github.png" alt="Get it on GitHub" height="48">](https://github.com/ArcaneChat/android/releases/latest/download/ArcaneChat-gplay.apk)'
prerelease: ${{ contains(github.event.ref, '-beta') }}
fail_on_unmatched_files: true
files: build/outputs/apk/foss/release/*.apk
files: |
build/outputs/apk/foss/release/*.apk
build/outputs/mapping/fossRelease/mapping-*.txt
- name: Release on ZapStore
run: |
Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 KiB

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 447 KiB

After

Width:  |  Height:  |  Size: 446 KiB

+1
View File
@@ -6,3 +6,4 @@ find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/Delta Chat
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/get.delta.chat/github.com\/ArcaneChat/g'
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/delta.chat\/donate/arcanechat.me\/#contribute/g'
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/Delta Chat/ArcaneChat/g'
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/❤️/💜/g'
+1
View File
@@ -6,6 +6,7 @@ find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/ArcaneChat
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/github.com\/ArcaneChat/get.delta.chat/g'
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/arcanechat.me\/#contribute/delta.chat\/donate/g'
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/ArcaneChat/Delta Chat/g'
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/💜/❤️/g'
# don't revert the app name
sed -i 's/>Delta Chat</>ArcaneChat</g' ./src/main/res/values/strings.xml
@@ -786,6 +786,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
return future;
}
inputPanel.setSubject(draft.getSubject());
final String text = TextUtils.isEmpty(sharedText)? draft.getText() : sharedText;
if(!text.isEmpty()) {
composeText.setText(text);
@@ -977,10 +979,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (dcChat.canSend()) {
composePanel.setVisibility(View.VISIBLE);
attachmentManager.setHidden(false);
inputPanel.setSubjectVisible(!dcChat.isEncrypted());
} else {
composePanel.setVisibility(View.GONE);
attachmentManager.setHidden(true);
hideSoftKeyboard();
inputPanel.setSubjectVisible(false);
}
}
@@ -1063,12 +1067,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
Optional<QuoteModel> quote = inputPanel.getQuote();
boolean editing = isEditing;
final String subject = inputPanel.getSubject();
// for a quick ui feedback, we clear the related controls immediately on sending messages.
// for drafts, however, we do not change the controls, the activity may be resumed.
if (action==ACTION_SEND_OUT) {
composeText.setText("");
inputPanel.clearQuote();
inputPanel.clearSubject();
}
Util.runOnAnyBackgroundThread(() -> {
@@ -1133,6 +1139,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
msg.setQuote(quote.get().getQuotedMsg());
}
if (!subject.isEmpty() && msg != null) {
msg.setSubject(subject);
}
if (action==ACTION_SEND_OUT) {
// for WEBXDC, drafts are just sent out as is.
@@ -152,6 +152,8 @@ public class ConversationFragment extends MessageSelectorFragment
// setLayerType() is needed to allow larger items (long texts in our case)
// with hardware layers, drawing may result in errors as "OpenGLRenderer: Path too large to be rendered into a texture"
// On foldable devices with large screens, software layer can exceed memory limits (~11MB).
// To prevent this, message bubble width is constrained via maxWidth in layout files.
list.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
return view;
@@ -411,8 +411,11 @@ public class ConversationItem extends BaseConversationItem
bodyText.setClickable(false);
bodyText.setFocusable(false);
String subject = messageRecord.getSubject();
String text = messageRecord.getText();
if (!subject.isEmpty() && messageRecord.isOutgoing() && !messageRecord.isSecure()) text = subject + "\n\n" + text;
if (messageRecord.getType() == DcMsg.DC_MSG_CALL || text.isEmpty()) {
bodyText.setVisibility(View.GONE);
}
@@ -56,6 +56,7 @@ public class InputPanel extends ConstraintLayout
private QuoteView quoteView;
private EmojiToggle emojiToggle;
private ComposeText composeText;
private android.widget.EditText subjectText;
private View quickCameraToggle;
private View quickAudioToggle;
private View buttonToggle;
@@ -91,6 +92,7 @@ public class InputPanel extends ConstraintLayout
this.quoteView = findViewById(R.id.quote_view);
this.emojiToggle = findViewById(R.id.emoji_toggle);
this.composeText = findViewById(R.id.embedded_text_editor);
this.subjectText = findViewById(R.id.subject_text);
this.quickCameraToggle = findViewById(R.id.quick_camera_toggle);
this.quickAudioToggle = findViewById(R.id.quick_audio_toggle);
this.buttonToggle = findViewById(R.id.button_toggle);
@@ -198,6 +200,31 @@ public class InputPanel extends ConstraintLayout
composeText.performClick();
}
public void setSubjectVisible(boolean visible) {
subjectText.setVisibility(visible ? View.VISIBLE : View.GONE);
// don't make it visible if visible is false to avoid showing it while recording audio and an event triggers setSubjectVisible(false)
if (visible) emojiToggle.setVisibility(View.GONE);
}
public String getSubject() {
if (subjectText != null && subjectText.getVisibility() == View.VISIBLE) {
return subjectText.getText().toString().trim();
}
return "";
}
public void clearSubject() {
if (subjectText != null) {
subjectText.setText("");
}
}
public void setSubject(String subject) {
if (subjectText != null && subject != null) {
subjectText.setText(subject);
}
}
public void setMediaKeyboard(@NonNull MediaKeyboard mediaKeyboard) {
mediaKeyboard.setKeyboardListener(this);
}
@@ -25,11 +25,28 @@
app:message_type="preview"
tools:visibility="visible" />
<EditText
android:id="@+id/subject_text"
style="@style/ComposeEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="6dp"
android:hint="@string/subject"
android:inputType="text"
android:maxLines="1"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/quote_view"
tools:visibility="visible" />
<FrameLayout
android:id="@+id/input_field_frame_layout"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/button_toggle"
app:layout_constraintTop_toBottomOf="@id/quote_view"
app:layout_constraintTop_toBottomOf="@id/subject_text"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -38,13 +38,13 @@
android:id="@+id/reply_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignStart="@id/body_bubble"
android:layout_alignTop="@id/body_bubble"
android:layout_alignBottom="@id/body_bubble"
android:layout_alignStart="@id/body_bubble_wrapper"
android:layout_alignTop="@id/body_bubble_wrapper"
android:layout_alignBottom="@id/body_bubble_wrapper"
android:alpha="0"
app:srcCompat="?menu_reply_icon"
android:tint="?icon_tint"
android:layout_alignLeft="@id/body_bubble" />
android:layout_alignLeft="@id/body_bubble_wrapper" />
<FrameLayout
android:id="@+id/contact_photo_container"
@@ -52,7 +52,7 @@
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignBottom="@id/body_bubble">
android:layout_alignBottom="@id/body_bubble_wrapper">
<org.thoughtcrime.securesms.components.AvatarImageView
android:id="@+id/contact_photo"
@@ -65,8 +65,8 @@
</FrameLayout>
<LinearLayout
android:id="@+id/body_bubble"
<FrameLayout
android:id="@+id/body_bubble_wrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/message_bubble_edge_margin"
@@ -74,7 +74,12 @@
android:layout_marginLeft="6dp"
android:layout_marginStart="6dp"
android:layout_toRightOf="@id/contact_photo_container"
android:layout_toEndOf="@id/contact_photo_container"
android:layout_toEndOf="@id/contact_photo_container">
<LinearLayout
android:id="@+id/body_bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:clipToPadding="false"
android:clipChildren="false"
@@ -112,6 +117,7 @@
android:id="@+id/quote_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="@dimen/message_bubble_max_width"
android:layout_marginTop="@dimen/message_bubble_top_padding"
android:layout_marginStart="6dp"
android:layout_marginEnd="6dp"
@@ -186,6 +192,7 @@
android:id="@+id/conversation_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="@dimen/message_bubble_max_width"
android:layout_marginBottom="@dimen/message_bubble_collapsed_footer_padding"
android:layout_marginLeft="@dimen/message_bubble_horizontal_padding"
android:layout_marginRight="@dimen/message_bubble_horizontal_padding"
@@ -247,12 +254,14 @@
</LinearLayout>
</FrameLayout>
<org.thoughtcrime.securesms.reactions.ReactionsConversationView
android:id="@+id/reactions_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/body_bubble"
android:layout_alignStart="@id/body_bubble"
android:layout_below="@id/body_bubble_wrapper"
android:layout_alignStart="@id/body_bubble_wrapper"
android:layout_marginTop="-4dp"
android:orientation="horizontal"
app:message_type="incoming" />
+20 -11
View File
@@ -40,24 +40,29 @@
android:id="@+id/reply_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignStart="@id/body_bubble"
android:layout_alignTop="@id/body_bubble"
android:layout_alignBottom="@id/body_bubble"
android:layout_alignStart="@id/body_bubble_wrapper"
android:layout_alignTop="@id/body_bubble_wrapper"
android:layout_alignBottom="@id/body_bubble_wrapper"
android:alpha="0"
app:srcCompat="?menu_reply_icon"
android:tint="?icon_tint"
android:layout_alignLeft="@id/body_bubble" />
android:layout_alignLeft="@id/body_bubble_wrapper" />
<FrameLayout
android:id="@+id/body_bubble_wrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/indicators_parent"
android:layout_toStartOf="@+id/indicators_parent"
android:layout_alignWithParentIfMissing="true"
android:layout_marginLeft="@dimen/message_bubble_edge_margin"
android:layout_marginStart="@dimen/message_bubble_edge_margin">
<LinearLayout
android:id="@+id/body_bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_toLeftOf="@+id/indicators_parent"
android:layout_toStartOf="@+id/indicators_parent"
android:layout_alignWithParentIfMissing="true"
android:layout_marginLeft="@dimen/message_bubble_edge_margin"
android:layout_marginStart="@dimen/message_bubble_edge_margin"
android:clipToPadding="false"
android:clipChildren="false"
android:background="@color/white"
@@ -94,6 +99,7 @@
android:id="@+id/quote_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="@dimen/message_bubble_max_width"
android:layout_marginTop="@dimen/message_bubble_top_padding"
android:layout_marginStart="6dp"
android:layout_marginEnd="6dp"
@@ -168,6 +174,7 @@
android:id="@+id/conversation_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="@dimen/message_bubble_max_width"
android:layout_marginLeft="@dimen/message_bubble_horizontal_padding"
android:layout_marginRight="@dimen/message_bubble_horizontal_padding"
android:layout_marginBottom="@dimen/message_bubble_collapsed_footer_padding"
@@ -228,12 +235,14 @@
</LinearLayout>
</FrameLayout>
<org.thoughtcrime.securesms.reactions.ReactionsConversationView
android:id="@+id/reactions_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/body_bubble"
android:layout_alignEnd="@id/body_bubble"
android:layout_below="@id/body_bubble_wrapper"
android:layout_alignEnd="@id/body_bubble_wrapper"
android:layout_marginTop="-4dp"
android:orientation="horizontal"
app:message_type="outgoing" />
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Limit bubble width on large screens (tablets/foldable devices) to prevent software layer overflow -->
<dimen name="message_bubble_max_width">600dp</dimen>
</resources>
+1
View File
@@ -23,6 +23,7 @@
<dimen name="message_bubble_edge_margin">32dp</dimen>
<dimen name="message_bubble_bottom_padding">6dp</dimen>
<dimen name="message_bubble_showmore_padding">8dp</dimen>
<dimen name="message_bubble_max_width">512dp</dimen>
<dimen name="transparent_footer_padding">2dp</dimen>
<dimen name="media_bubble_remove_button_size">24dp</dimen>
<dimen name="media_bubble_edit_button_size">24dp</dimen>
+4 -1
View File
@@ -3,8 +3,11 @@
<external-cache-path name="external_cache" path="." />
<external-files-path name="external_files" path="." />
<!-- this is needed for access to the cache dir in SD card -->
<root-path name="external_root" path="/storage/" />
<external-path name="external_pictures" path="Pictures"/>
<external-path name="external_video" path="Movies"/>
<external-path name="external_audio" path="Music"/>
<external-path name="external_download" path="Download"/>
</paths>
</paths>