mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ecbc3946c9 | |||
| 7c1ee0d90c | |||
| b99426b7c6 | |||
| de1eedc63f | |||
| ec4db3e58f | |||
| 0d2175b641 | |||
| 97620b8a3c | |||
| 24317b38bf | |||
| 6b28ed15e3 | |||
| b8b203e517 | |||
| e5c1e477f0 |
@@ -8,7 +8,7 @@ ArcaneChat is a Delta Chat Android client built on top of the official Delta Cha
|
||||
- **Language:** Java (Java 8 compatibility)
|
||||
- **Build System:** Gradle with Android Gradle Plugin 8.11.1
|
||||
- **Min SDK:** 21 (Android 5.0)
|
||||
- **Target SDK:** 35 (Android 15)
|
||||
- **Target SDK:** 36 (Android 16)
|
||||
- **NDK Version:** 27.0.12077973
|
||||
- **Native Components:** Rust (deltachat-core-rust submodule)
|
||||
- **UI Framework:** Android SDK, Material Design Components
|
||||
@@ -17,13 +17,23 @@ ArcaneChat is a Delta Chat Android client built on top of the official Delta Cha
|
||||
## Repository Structure
|
||||
|
||||
- `src/main/` - Main application source code
|
||||
- `src/main/java/org/thoughtcrime/securesms/` - Main UI components
|
||||
- `src/main/java/com/b44t/messenger/` - Delta Chat core integration
|
||||
- `src/main/java/chat/delta/rpc/` - JSON-RPC bindings (generated, don't edit manually)
|
||||
- `src/main/res/` - Android resources (layouts, strings, drawables)
|
||||
- `src/androidTest/` - Instrumented tests (UI tests, benchmarks)
|
||||
- `src/androidTest/java/com/b44t/messenger/uitests/` - UI tests
|
||||
- `src/androidTest/java/com/b44t/messenger/uibenchmarks/` - Performance benchmarks
|
||||
- `src/gplay/` - Google Play flavor-specific code
|
||||
- `src/foss/` - F-Droid/FOSS flavor-specific code
|
||||
- `jni/deltachat-core-rust/` - Native Rust core library (submodule)
|
||||
- `jni/deltachat-core-rust/` - Native Rust core library (submodule, **don't edit directly**)
|
||||
- `scripts/` - Build and helper scripts
|
||||
- `scripts/ndk-make.sh` - Build native libraries
|
||||
- `scripts/install-toolchains.sh` - Install Rust cross-compilation toolchains
|
||||
- `scripts/generate-rpc-bindings.sh` - Generate JSON-RPC bindings
|
||||
- `docs/` - Documentation
|
||||
- `fastlane/` - App store metadata and screenshots
|
||||
- `.github/workflows/` - CI/CD workflows (GitHub Actions)
|
||||
|
||||
## Build Instructions
|
||||
|
||||
@@ -33,17 +43,36 @@ ArcaneChat is a Delta Chat Android client built on top of the official Delta Cha
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
This MUST be done first before any build attempts.
|
||||
|
||||
2. **Build native libraries:**
|
||||
2. **Set up environment variables:**
|
||||
```bash
|
||||
export ANDROID_NDK_ROOT=/path/to/ndk/27.0.12077973
|
||||
export PATH=${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/:${ANDROID_NDK_ROOT}
|
||||
```
|
||||
Note: Path format varies by OS (linux-x86_64, darwin-x86_64, etc.)
|
||||
|
||||
3. **Install Rust toolchains:**
|
||||
```bash
|
||||
scripts/install-toolchains.sh
|
||||
```
|
||||
Required for building the native Rust components.
|
||||
|
||||
4. **Build native libraries:**
|
||||
```bash
|
||||
scripts/ndk-make.sh
|
||||
```
|
||||
Note: First run may take significant time as it builds for all architectures (armeabi-v7a, arm64-v8a, x86, x86_64)
|
||||
**IMPORTANT:** First run takes 30-60 minutes as it builds for all architectures (armeabi-v7a, arm64-v8a, x86, x86_64).
|
||||
For faster development builds, build for a single architecture:
|
||||
```bash
|
||||
scripts/ndk-make.sh armeabi-v7a
|
||||
```
|
||||
|
||||
3. **Build APK:**
|
||||
5. **Build APK:**
|
||||
```bash
|
||||
./gradlew assembleDebug
|
||||
```
|
||||
Build time: ~2-5 minutes after native libraries are built.
|
||||
|
||||
### Build Flavors
|
||||
|
||||
@@ -55,6 +84,24 @@ ArcaneChat is a Delta Chat Android client built on top of the official Delta Cha
|
||||
- Debug APKs: `build/outputs/apk/gplay/debug/` and `build/outputs/apk/fat/debug/`
|
||||
- Release APKs require signing configuration in `~/.gradle/gradle.properties`
|
||||
|
||||
### Common Build Issues
|
||||
|
||||
1. **Missing NDK or incorrect version:**
|
||||
- Error: `ANDROID_NDK_ROOT not set` or native library missing
|
||||
- Solution: Install NDK 27.0.12077973 and set ANDROID_NDK_ROOT environment variable
|
||||
|
||||
2. **Submodules not initialized:**
|
||||
- Error: Missing deltachat-core-rust files
|
||||
- Solution: Run `git submodule update --init --recursive`
|
||||
|
||||
3. **Gradle wrapper validation:**
|
||||
- Always validate gradle wrapper before building: `./gradlew wrapper --gradle-version=current`
|
||||
- Wrapper is validated in CI via `gradle/actions/wrapper-validation@v4`
|
||||
|
||||
4. **Clean build issues:**
|
||||
- If build fails, try: `./gradlew clean && scripts/ndk-make.sh && ./gradlew assembleDebug`
|
||||
- Remove `build/` directory if clean doesn't work
|
||||
|
||||
## Testing
|
||||
|
||||
### Running Unit Tests
|
||||
@@ -62,16 +109,19 @@ ArcaneChat is a Delta Chat Android client built on top of the official Delta Cha
|
||||
```bash
|
||||
./gradlew test
|
||||
```
|
||||
Expected duration: 1-3 minutes
|
||||
|
||||
### Running Instrumented Tests
|
||||
|
||||
1. **Disable animations** on your device/emulator:
|
||||
- Developer Options → Set "Window animation scale", "Transition animation scale", and "Animator duration scale" to 0x
|
||||
- **CRITICAL:** Tests will fail if animations are enabled
|
||||
|
||||
2. **Run tests:**
|
||||
```bash
|
||||
./gradlew connectedAndroidTest
|
||||
```
|
||||
Expected duration: 10-30 minutes depending on device/emulator
|
||||
|
||||
### Online Tests
|
||||
|
||||
@@ -129,6 +179,14 @@ TEST_MAIL_PW=yourpassword
|
||||
- Java bindings are in `src/main/java/com/b44t/messenger/Dc*.java`
|
||||
- JSON-RPC bindings in `chat.delta.rpc.*` package (generated via dcrpcgen)
|
||||
|
||||
### Generating JSON-RPC Bindings
|
||||
|
||||
To regenerate JSON-RPC bindings after core changes:
|
||||
```bash
|
||||
./scripts/generate-rpc-bindings.sh
|
||||
```
|
||||
**Note:** Requires Rust tooling and [dcrpcgen tool](https://github.com/chatmail/dcrpcgen) installed
|
||||
|
||||
### Working with Translations
|
||||
|
||||
- Translations managed via Transifex (not in repository)
|
||||
@@ -142,6 +200,43 @@ Decode crash symbols:
|
||||
$ANDROID_NDK_ROOT/ndk-stack --sym obj/local/armeabi-v7a --dump crash.txt > decoded.txt
|
||||
```
|
||||
|
||||
## Validation and Quality Checks
|
||||
|
||||
### Pre-commit Checks
|
||||
|
||||
Before committing changes, always run:
|
||||
|
||||
1. **Gradle wrapper validation:**
|
||||
```bash
|
||||
./gradlew wrapper --gradle-version=current
|
||||
```
|
||||
|
||||
2. **Build verification:**
|
||||
```bash
|
||||
./gradlew assembleDebug
|
||||
```
|
||||
|
||||
3. **Unit tests:**
|
||||
```bash
|
||||
./gradlew test
|
||||
```
|
||||
|
||||
4. **Code style:** Match existing code style in modified files (no automatic formatter configured)
|
||||
|
||||
### When to Rebuild Native Libraries
|
||||
|
||||
Rebuild native libraries (`scripts/ndk-make.sh`) when:
|
||||
- Updating deltachat-core-rust submodule
|
||||
- Modifying anything in `jni/` directory
|
||||
- Changing NDK version
|
||||
- After `git clean -fdx` or fresh clone
|
||||
|
||||
**DO NOT** rebuild native libraries for:
|
||||
- Pure Java/Kotlin code changes
|
||||
- Resource file changes
|
||||
- Gradle configuration changes (unless changing native library linking)
|
||||
- Documentation updates
|
||||
|
||||
## WebXDC Support
|
||||
|
||||
ArcaneChat has extended WebXDC support:
|
||||
@@ -152,12 +247,24 @@ ArcaneChat has extended WebXDC support:
|
||||
|
||||
## Important Files
|
||||
|
||||
- `build.gradle` - Main build configuration
|
||||
- `build.gradle` - Main build configuration (Android Gradle Plugin 8.11.1, Java 8 compatibility)
|
||||
- `CONTRIBUTING.md` - Contribution guidelines
|
||||
- `BUILDING.md` - Detailed build setup
|
||||
- `BUILDING.md` - Detailed build setup instructions
|
||||
- `RELEASE.md` - Release process
|
||||
- `proguard-rules.pro` - ProGuard configuration
|
||||
- `google-services.json` - Firebase configuration (gplay flavor)
|
||||
- `proguard-rules.pro` - ProGuard configuration (enabled for both debug and release)
|
||||
- `google-services.json` - Firebase configuration (gplay flavor only)
|
||||
- `settings.gradle` - Gradle settings
|
||||
- `.github/workflows/` - CI/CD configuration
|
||||
|
||||
## Dependencies and Constraints
|
||||
|
||||
- **Java Version:** Java 8 compatibility (do not use Java 9+ features)
|
||||
- **Gradle:** Use wrapper (`./gradlew`) to ensure correct Gradle version
|
||||
- **NDK:** Must use version 27.0.12077973 (specified in build.gradle)
|
||||
- **Min SDK:** 21 (Android 5.0) - code must be compatible
|
||||
- **Target SDK:** 36 (Android 16) - test on this API level when possible
|
||||
- **ProGuard:** Always enabled - ensure ProGuard rules are correct for new dependencies
|
||||
- **Multi-dex:** Enabled - app exceeds 65k method limit
|
||||
|
||||
## Package Structure
|
||||
|
||||
@@ -173,3 +280,35 @@ ArcaneChat has extended WebXDC support:
|
||||
- Native library must be rebuilt after core changes
|
||||
- ProGuard is enabled in both debug and release builds
|
||||
- Multi-dex is enabled due to app size
|
||||
|
||||
## CI/CD Workflows
|
||||
|
||||
### Preview APK Workflow (.github/workflows/preview-apk.yml)
|
||||
|
||||
Runs on every pull request to build and upload a preview APK:
|
||||
|
||||
1. **Setup steps:**
|
||||
- Checks out repository with submodules
|
||||
- Validates Fastlane metadata
|
||||
- Sets up Rust cache (working-directory: jni/deltachat-core-rust)
|
||||
- Sets up Java 17 (Temurin distribution)
|
||||
- Sets up Android SDK
|
||||
- Caches Gradle dependencies
|
||||
- Sets up NDK r27
|
||||
|
||||
2. **Build process:**
|
||||
```bash
|
||||
scripts/install-toolchains.sh && scripts/ndk-make.sh armeabi-v7a
|
||||
./gradlew --no-daemon -PABI_FILTER=armeabi-v7a assembleFossDebug
|
||||
```
|
||||
Note: Builds only armeabi-v7a for faster CI builds
|
||||
|
||||
3. **Output:** Uploads APK artifact to GitHub Actions
|
||||
|
||||
### Important CI Considerations
|
||||
|
||||
- Always validate Gradle wrapper before committing changes
|
||||
- Fastlane metadata must be valid (validated in CI)
|
||||
- Use `--no-daemon` flag for Gradle in CI environments
|
||||
- CI builds use FOSS flavor to avoid Google Services dependencies
|
||||
- Expected CI build time: 15-25 minutes for full workflow
|
||||
|
||||
@@ -36,6 +36,7 @@ public class DcMsg {
|
||||
public final static int DC_INFO_INVALID_UNENCRYPTED_MAIL = 13;
|
||||
public final static int DC_INFO_WEBXDC_INFO_MESSAGE = 32;
|
||||
public final static int DC_INFO_CHAT_E2EE = 50;
|
||||
public final static int DC_INFO_CHAT_DESCRIPTION_CHANGED = 70;
|
||||
|
||||
public final static int DC_STATE_UNDEFINED = 0;
|
||||
public final static int DC_STATE_IN_FRESH = 10;
|
||||
|
||||
@@ -854,6 +854,11 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
WebxdcActivity.openWebxdcActivity(getContext(), messageRecord.getParent(), messageRecord.getWebxdcHref());
|
||||
}
|
||||
}
|
||||
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);
|
||||
startActivity(intent);
|
||||
}
|
||||
else if (!TextUtils.isEmpty(messageRecord.getPOILocation()) && messageRecord.getType() == DcMsg.DC_MSG_TEXT && !messageRecord.hasHtml()) {
|
||||
WebxdcActivity.openMaps(getContext(), getListAdapter().getChat().getId(), "index.html#"+messageRecord.getPOILocation());
|
||||
}
|
||||
|
||||
@@ -18,50 +18,61 @@
|
||||
<org.thoughtcrime.securesms.components.RecentPhotoViewRail
|
||||
android:id="@+id/recent_photos"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:layout_height="160dp"
|
||||
android:padding="4dp"/>
|
||||
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:weightSum="4">
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:scrollbars="horizontal">
|
||||
|
||||
<!-- first row -->
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
android:id="@+id/record_video_button"
|
||||
android:layout_width="53dp"
|
||||
android:layout_height="53dp"
|
||||
android:src="@drawable/attach_record_video"
|
||||
android:scaleType="center"
|
||||
android:contentDescription="@string/video"
|
||||
app:circleColor="#00FFFFFF"/>
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
android:id="@+id/record_video_button"
|
||||
android:layout_width="53dp"
|
||||
android:layout_height="53dp"
|
||||
android:src="@drawable/attach_record_video"
|
||||
android:scaleType="center"
|
||||
android:contentDescription="@string/video"
|
||||
app:circleColor="#00FFFFFF"/>
|
||||
|
||||
<TextView android:layout_marginTop="10dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:text="@string/video"/>
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:text="@string/video"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
android:id="@+id/gallery_button"
|
||||
android:layout_width="53dp"
|
||||
android:layout_height="53dp"
|
||||
@@ -70,133 +81,141 @@
|
||||
android:contentDescription="@string/gallery"
|
||||
app:circleColor="@color/gallery_icon"/>
|
||||
|
||||
<TextView android:layout_marginTop="10dp"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/gallery"/>
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/gallery"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
android:id="@+id/document_button"
|
||||
android:layout_width="53dp"
|
||||
android:layout_height="53dp"
|
||||
android:src="@drawable/ic_insert_drive_file_white_24dp"
|
||||
android:scaleType="center"
|
||||
android:contentDescription="@string/file"
|
||||
app:circleColor="@color/document_icon"/>
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
android:id="@+id/document_button"
|
||||
android:layout_width="53dp"
|
||||
android:layout_height="53dp"
|
||||
android:src="@drawable/ic_insert_drive_file_white_24dp"
|
||||
android:scaleType="center"
|
||||
android:contentDescription="@string/file"
|
||||
app:circleColor="@color/document_icon"/>
|
||||
|
||||
<TextView android:layout_marginTop="10dp"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/file"/>
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/file"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
android:id="@+id/webxdc_button"
|
||||
android:layout_width="53dp"
|
||||
android:layout_height="53dp"
|
||||
android:src="@drawable/ic_apps_24"
|
||||
android:scaleType="center"
|
||||
android:contentDescription="@string/webxdc_app"
|
||||
app:circleColor="@color/apps_icon"
|
||||
/>
|
||||
app:circleColor="@color/apps_icon"/>
|
||||
|
||||
<TextView android:layout_marginTop="10dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:text="@string/webxdc_app"/>
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:text="@string/webxdc_app"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:weightSum="4">
|
||||
|
||||
<!-- second row -->
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:layout_weight="1">
|
||||
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
android:id="@+id/contact_button"
|
||||
android:layout_width="53dp"
|
||||
android:layout_height="53dp"
|
||||
android:src="@drawable/ic_person_white_24dp"
|
||||
android:scaleType="center"
|
||||
android:contentDescription="@string/contact"
|
||||
app:circleColor="@color/contact_icon"/>
|
||||
|
||||
<TextView android:layout_marginTop="10dp"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:text="@string/contact"/>
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
android:id="@+id/contact_button"
|
||||
android:layout_width="53dp"
|
||||
android:layout_height="53dp"
|
||||
android:src="@drawable/ic_person_white_24dp"
|
||||
android:scaleType="center"
|
||||
android:contentDescription="@string/contact"
|
||||
app:circleColor="@color/contact_icon"/>
|
||||
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:text="@string/contact"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/location_linear_layout"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
android:id="@+id/location_button"
|
||||
android:layout_width="53dp"
|
||||
android:layout_height="53dp"
|
||||
android:src="@drawable/ic_location_on_white_24dp"
|
||||
android:scaleType="center"
|
||||
android:visibility="visible"
|
||||
android:contentDescription="@string/location"
|
||||
app:circleColor="@color/location_icon"/>
|
||||
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:id="@+id/location_button_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="visible"
|
||||
android:gravity="center"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:text="@string/location"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout android:id="@+id/location_linear_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.thoughtcrime.securesms.components.CircleColorImageView
|
||||
android:id="@+id/location_button"
|
||||
android:layout_width="53dp"
|
||||
android:layout_height="53dp"
|
||||
android:src="@drawable/ic_location_on_white_24dp"
|
||||
android:scaleType="center"
|
||||
android:visibility="visible"
|
||||
android:contentDescription="@string/location"
|
||||
app:circleColor="@color/location_icon"/>
|
||||
|
||||
<TextView android:layout_marginTop="10dp"
|
||||
android:id="@+id/location_button_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="visible"
|
||||
style="@style/AttachmentTypeLabel"
|
||||
android:text="@string/location"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- fill the gap -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:visibility="invisible">
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user