Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ buildscript {
versions.navigationFragment = '2.5.1'
versions.firebaseBom = '26.1.0'
versions.okhttp3LoggingInterceptor = '4.12.0'
// P2P embedded server (Netty + TLS). Keep all io.ktor:* on this version (3.x: Netty enableHttp2/enableH2c, HTTP/1.1 for TLS P2P).
versions.ktor = '3.3.0'
versions.squareupTape = '1.2.3'
versions.cacheword = '0.1.1'
versions.glide = '4.15.0'
versions.burgstallerOkhttpDigest = '3.1.1'
versions.javarosa = '2.6.0'
versions.javarosa = '4.4.0'
versions.commonsIo = '2.6'
versions.rxandroid = '2.1.1'
versions.rxrelay = '2.1.1'
Expand Down Expand Up @@ -92,6 +94,7 @@ buildscript {
google()
mavenCentral()
maven { url 'https://jitpack.io' } // required for Nextcloud

}

def isFdroid = project.hasProperty('fdroid')
Expand Down
6 changes: 6 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/237.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- Implemented Nearby Sharing: Nearby Sharing lets users securely share files in physical proximity. Nearby Sharing is fully offline, available across platforms and devices, and assures end-to-end encryption. https://tella-app.org/nearby-sharing/
- Implemented security fixes detected by our most recent security audit (to be published soon!).
- New languages support: Ukrainian.
- Bug fixes and minor improvements.

Full release notes: https://tella-app.org/releases
6 changes: 6 additions & 0 deletions fastlane/metadata/android/es/changelogs/237.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- Nueva funcionalidad Nearby Sharing: Permite compartir archivos de forma segura con personas que se encuentran físicamente cerca. Funciona sin conexión (offline), multi-plataforma (Android, iOS y Desktop) y garantiza cifrado de extremo a extremo: https://tella-app.org/nearby-sharing/
- Correcciones de seguridad detectadas en nuestra última auditoría de seguridad.
- Nuevo idioma: Ucraniano.
- Corrección de bugs y pequeñas mejoras.

Notas de la versión completas: https://tella-app.org/releases
36 changes: 29 additions & 7 deletions mobile/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
// Must match root build.gradle ext.versions.kotlin — Gradle plugin portal requires an explicit version here
id 'org.jetbrains.kotlin.plugin.serialization' version '2.2.0'
id 'kotlin-kapt'
id 'com.google.dagger.hilt.android'
}
Expand All @@ -24,6 +26,10 @@ configurations.all {
force "com.android.tools:desugar_jdk_libs:2.1.3"
force "com.google.android.gms:play-services-base:$versions.playServicesBase"
force "com.google.android.gms:play-services-basement:$versions.playServicesBase"
// Ktor (root versions.ktor) targets coroutines 1.7.x; 1.9+ drops internal APIs → NoSuchMethodError (LockFreeLinkedListHead.addLast)
force "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"
force "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
force "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.7.3"
}
}

Expand All @@ -50,7 +56,10 @@ android {
// Make sure SimpleXML configuration files are included
pickFirsts += [
"META-INF/services/org.simpleframework.xml.*",
"META-INF/versions/9/OSGI-INF/MANIFEST.MF"
"META-INF/versions/9/OSGI-INF/MANIFEST.MF",
// Netty (transitive): identical metadata in every module JAR
"META-INF/io.netty.versions.properties",
"META-INF/INDEX.LIST",
]
}
}
Expand All @@ -60,9 +69,8 @@ android {
minSdk versions.minSdk
targetSdk versions.targetSdk
// F-Droid fastlane changelog: fastlane/metadata/android/en-US/changelogs/<versionCode>.txt
versionCode 233

versionName "2.20.2"
versionCode 237
versionName "3.0.0"
multiDexEnabled true

ndk { abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64" }
Expand Down Expand Up @@ -322,8 +330,8 @@ dependencies {
playstoreImplementation "com.dropbox.core:dropbox-core-sdk:$versions.dropboxVersion"
playstoreImplementation "com.dropbox.core:dropbox-android-sdk:$versions.dropboxVersion"
implementation 'commons-httpclient:commons-httpclient:3.1'
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.10.2")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.7.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")


implementation 'commons-codec:commons-codec:1.15'
Expand All @@ -337,9 +345,23 @@ dependencies {
implementation "com.github.nextcloud-deps.hwsecurity:hwsecurity-fido:$versions.fidoVersion"
implementation "com.github.nextcloud-deps.hwsecurity:hwsecurity-fido2:$versions.fidoVersion"

//QR CODE SCAN/GENERATE LIBRARY
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'

// ktor: Netty required for HTTPS (CIO engine has no TLS in 2.3.x). Keep io.netty in proguard-rules.pro.
implementation("io.ktor:ktor-serialization-kotlinx-json:${versions.ktor}")
implementation("io.ktor:ktor-server-core:${versions.ktor}")
implementation("io.ktor:ktor-server-netty:${versions.ktor}")
implementation("io.ktor:ktor-server-content-negotiation:${versions.ktor}")
implementation "io.ktor:ktor-server-call-logging:${versions.ktor}"


implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3' // Use the latest version


// Add exclusions to prevent other libraries from pulling in xmlpull
// JavaRosa - allow it to use xpp3
implementation ("org.opendatakit:opendatakit-javarosa:$versions.javarosa") {
implementation ("org.getodk:javarosa:$versions.javarosa") {
exclude group: "xmlpull", module: "xmlpull"
// NO xpp3 exclusion - JavaRosa needs it
}
Expand Down
41 changes: 41 additions & 0 deletions mobile/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,38 @@
-dontwarn org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer
# ========== END MISSING CLASSES ==========

# ========== Netty/Ktor on Android - JVM-only classes not present on Android ==========
# R8 shrinks Netty channel classes; ReflectiveChannelFactory needs public no-arg ctors (NioServerSocketChannel)
-keep class io.netty.** { *; }
# Netty tcnative (OpenSSL native bindings - Android uses Conscrypt/JDK SSL)
-dontwarn io.netty.internal.tcnative.**
# java.lang.management (not on Android - used by Ktor debug detector)
-dontwarn java.lang.management.**
# Log4j2 (optional Netty logging backend)
-dontwarn org.apache.logging.log4j.**
# Jetty NPN (deprecated ALPN predecessor, not on Android)
-dontwarn org.eclipse.jetty.npn.**
# Reactor BlockHound (reactive blocking detection, not on Android)
-dontwarn reactor.blockhound.**
# Optional Netty codec / platform deps (referenced from netty-codec but not bundled; Ktor HTTPS does not need them)
-dontwarn com.aayushatharva.brotli4j.**
-dontwarn com.github.luben.zstd.**
-dontwarn com.jcraft.jzlib.**
-dontwarn com.ning.compress.**
-dontwarn com.oracle.svm.core.**
-dontwarn lzma.sdk.**
-dontwarn net.jpountz.**
-dontwarn org.jboss.marshalling.**
# OpenJDK-only cert APIs (Netty OpenJdkSelfSignedCertGenerator); Android uses Conscrypt / app-provided certs
-dontwarn sun.security.x509.**
# Netty 4.2+ optional pkitesting / CertificateBuilder (SelfSignedCertificate path, not on Android)
-dontwarn io.netty.pkitesting.**
# JFR (jdk.jfr.*) — not part of the Android Java API; optional Netty tracing hooks
-dontwarn jdk.jfr.**
# OSGi bundle metadata annotations (JCTools / shaded deps) — not used on Android
-dontwarn org.osgi.annotation.**
# ========== END Netty/Ktor ==========

# Keep the interfaces + concrete impls
-keep class org.xmlpull.v1.XmlPullParser { *; }
-keep class org.xmlpull.v1.XmlSerializer { *; }
Expand Down Expand Up @@ -170,6 +202,11 @@
# Hilt
-keep class * extends java.lang.annotation.Annotation { *; }
-keep @javax.inject.Inject class * { *; }
# AndroidEntryPoint: keep generated Hilt_* bases (R8 minify — avoids Missing class Hilt_*)
-keep class org.horizontal.tella.mobile.**.Hilt_* { *; }
-keep interface org.horizontal.tella.mobile.**.*_GeneratedInjector { *; }
# Explicit: flavor-only fragments must not be stripped before Hilt aggregating task sees them
-keep class org.horizontal.tella.mobile.views.dialog.Hilt_CollectServerDialogFragment { *; }

# Keep Gson adapters and creators
-keep class * extends com.google.gson.TypeAdapter { *; }
Expand Down Expand Up @@ -423,3 +460,7 @@
-keep class com.hzontal.tella_vault.Vault { *; }
-keep class org.horizontal.tella.mobile.data.KeyRxVault { *; }
# ========== END SIMPLE XML RULES ==========


-keep class org.bouncycastle.** { *; }
-dontwarn org.bouncycastle.**
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.hardware.SensorManager
import android.media.AudioManager
import android.os.Build
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.OrientationEventListener
import android.view.Surface
import android.view.View
import android.view.WindowManager
import android.widget.ImageView
import android.widget.SeekBar
import android.widget.TextView
Expand Down Expand Up @@ -129,23 +131,32 @@ class CameraActivity : MetadataActivity(), IMetadataAttachPresenterContract.IVie

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
window.attributes = window.attributes.apply {
layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
}
binding = ActivityCameraBinding.inflate(layoutInflater)
setContentView(binding.root)
// SurfaceView (default performance mode) can paint above sibling views on API 31+ / some devices.
binding.viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE
ViewCompat.setOnApplyWindowInsetsListener(binding.topBar) { view, insets ->
val statusBars = insets.getInsets(WindowInsetsCompat.Type.statusBars())
val cutout = insets.getInsets(WindowInsetsCompat.Type.displayCutout())
// Never fall back to ViewUtil.getStatusBarHeight() here: with enableEdgeToEdge(), the system
// often reports statusBars.top == 0 while the fallback still adds a full status-bar inset,
// which shows as an empty black strip above the toolbar (Pixel / Android 12+).
val top = maxOf(statusBars.top, cutout.top)
view.updatePadding(top = top)
insets
}
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, insets ->
val statusBars = insets.getInsets(WindowInsetsCompat.Type.statusBars())
val navBars = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
view.updatePadding(bottom = navBars.bottom)
val cutout = insets.getInsets(WindowInsetsCompat.Type.displayCutout())
val mandatory = insets.getInsets(WindowInsetsCompat.Type.mandatorySystemGestures())
var top = maxOf(statusBars.top, cutout.top, mandatory.top)
if (top == 0) {
val ignoring = insets.getInsetsIgnoringVisibility(
WindowInsetsCompat.Type.statusBars() or WindowInsetsCompat.Type.displayCutout()
)
top = maxOf(top, ignoring.top)
}
val bottom = maxOf(navBars.bottom, mandatory.bottom)
val left = maxOf(statusBars.left, navBars.left, cutout.left, mandatory.left)
val right = maxOf(statusBars.right, navBars.right, cutout.right, mandatory.right)
view.setPadding(left, top, right, bottom)
insets
}
ViewCompat.requestApplyInsets(binding.root)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package org.horizontal.tella.mobile.views.dialog

import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.text.TextUtils
Expand Down Expand Up @@ -57,8 +56,6 @@ class CollectServerDialogFragment : AppCompatDialogFragment() {
lateinit var advancedToggle: PanelToggleButton
lateinit var advancedPanel: ViewGroup

private var context: Context? = null

private var validated = true

interface CollectServerDialogHandler {
Expand Down Expand Up @@ -98,7 +95,6 @@ class CollectServerDialogFragment : AppCompatDialogFragment() {
val server = arguments?.getSerializable(OBJECT_KEY) as? CollectServer

binding = DialogCollectServerBinding.inflate(inflater, container, false)
context = requireContext()

initView()
observeLiveData()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,6 @@ class TellaUploadServerDialogFragment : AppCompatDialogFragment(), ICheckTUSServ
private var presenter: CheckTUSServerPresenter? = null
private var serverId: Long = 0


interface TellaUploadServerDialogHandler {
fun onTellaUploadServerDialogCreate(server: TellaReportServer?)
fun onTellaUploadServerDialogUpdate(server: TellaReportServer?)
fun onDialogDismiss()
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand Down
23 changes: 20 additions & 3 deletions mobile/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="35" />
android:targetSdkVersion="36" />

<uses-feature
android:name="android.hardware.camera"
Expand All @@ -19,6 +19,8 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<uses-permission
Expand All @@ -31,6 +33,14 @@
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
</intent>
<intent>
<action android:name="android.intent.action.OPEN_DOCUMENT" />
<data android:mimeType="*/*" />
</intent>
<intent>
<action android:name="android.intent.action.GET_CONTENT" />
<data android:mimeType="*/*" />
</intent>
</queries>

<application
Expand All @@ -44,9 +54,9 @@
android:roundIcon="@mipmap/tella_icon_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
android:usesCleartextTraffic="false"
tools:ignore="GoogleAppIndexingWarning"
tools:replace="android:allowBackup">
tools:replace="android:allowBackup,android:usesCleartextTraffic">

<meta-data
android:name="firebase_analytics_collection_deactivated"
Expand Down Expand Up @@ -470,6 +480,7 @@

<activity
android:name=".views.activity.MainActivity"
android:launchMode="singleTop"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
android:theme="@style/AppTheme.NoActionBar" />
<activity
Expand Down Expand Up @@ -650,6 +661,12 @@
</intent-filter>
</activity>

<activity
android:name=".views.fragment.peertopeer.activity.PeerToPeerActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="adjustResize" />

</application>

</manifest>
1 change: 1 addition & 0 deletions mobile/src/main/assets/testDemo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is a test yo
Loading