mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-04-28 22:16:22 +00:00
Finished trust/distrust icons & border color
This commit is contained in:
parent
a2433956fe
commit
95e8ef9fc4
10 changed files with 108 additions and 18 deletions
|
|
@ -36,6 +36,7 @@ import org.linphone.core.AlertListenerStub
|
||||||
import org.linphone.core.AudioDevice
|
import org.linphone.core.AudioDevice
|
||||||
import org.linphone.core.Call
|
import org.linphone.core.Call
|
||||||
import org.linphone.core.CallListenerStub
|
import org.linphone.core.CallListenerStub
|
||||||
|
import org.linphone.core.ChatRoom.SecurityLevel
|
||||||
import org.linphone.core.Core
|
import org.linphone.core.Core
|
||||||
import org.linphone.core.CoreListenerStub
|
import org.linphone.core.CoreListenerStub
|
||||||
import org.linphone.core.MediaDirection
|
import org.linphone.core.MediaDirection
|
||||||
|
|
@ -556,19 +557,20 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
||||||
when (currentCall.currentParams.mediaEncryption) {
|
when (currentCall.currentParams.mediaEncryption) {
|
||||||
MediaEncryption.ZRTP -> {
|
MediaEncryption.ZRTP -> {
|
||||||
val authToken = currentCall.authenticationToken
|
val authToken = currentCall.authenticationToken
|
||||||
val deviceIsTrusted = currentCall.authenticationTokenVerified && authToken != null
|
val isDeviceTrusted = currentCall.authenticationTokenVerified && authToken != null
|
||||||
Log.i(
|
Log.i(
|
||||||
"$TAG Current call media encryption is ZRTP, auth token is ${if (deviceIsTrusted) "trusted" else "not trusted yet"}"
|
"$TAG Current call media encryption is ZRTP, auth token is ${if (isDeviceTrusted) "trusted" else "not trusted yet"}"
|
||||||
)
|
)
|
||||||
isRemoteDeviceTrusted.postValue(deviceIsTrusted)
|
isRemoteDeviceTrusted.postValue(isDeviceTrusted)
|
||||||
contact.value?.showTrust?.postValue(deviceIsTrusted)
|
val securityLevel = if (isDeviceTrusted) SecurityLevel.Encrypted else SecurityLevel.Safe
|
||||||
|
contact.value?.trust?.postValue(securityLevel)
|
||||||
|
|
||||||
if (!deviceIsTrusted && authToken.orEmpty().isNotEmpty()) {
|
if (!isDeviceTrusted && authToken.orEmpty().isNotEmpty()) {
|
||||||
Log.i("$TAG Showing ZRTP SAS confirmation dialog")
|
Log.i("$TAG Showing ZRTP SAS confirmation dialog")
|
||||||
showZrtpSasDialog(authToken!!.uppercase(Locale.getDefault()))
|
showZrtpSasDialog(authToken!!.uppercase(Locale.getDefault()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return deviceIsTrusted
|
return isDeviceTrusted
|
||||||
}
|
}
|
||||||
MediaEncryption.SRTP, MediaEncryption.DTLS -> {
|
MediaEncryption.SRTP, MediaEncryption.DTLS -> {
|
||||||
}
|
}
|
||||||
|
|
@ -614,18 +616,19 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
||||||
displayedAddress.postValue(address.asStringUriOnly())
|
displayedAddress.postValue(address.asStringUriOnly())
|
||||||
|
|
||||||
val isDeviceTrusted = updateEncryption()
|
val isDeviceTrusted = updateEncryption()
|
||||||
|
val securityLevel = if (isDeviceTrusted) SecurityLevel.Encrypted else SecurityLevel.Safe
|
||||||
val friend = coreContext.contactsManager.findContactByAddress(address)
|
val friend = coreContext.contactsManager.findContactByAddress(address)
|
||||||
if (friend != null) {
|
if (friend != null) {
|
||||||
displayedName.postValue(friend.name)
|
displayedName.postValue(friend.name)
|
||||||
val model = ContactAvatarModel(friend)
|
val model = ContactAvatarModel(friend)
|
||||||
model.showTrust.postValue(isDeviceTrusted)
|
model.trust.postValue(securityLevel)
|
||||||
contact.postValue(model)
|
contact.postValue(model)
|
||||||
} else {
|
} else {
|
||||||
val fakeFriend = coreContext.core.createFriend()
|
val fakeFriend = coreContext.core.createFriend()
|
||||||
fakeFriend.name = LinphoneUtils.getDisplayName(address)
|
fakeFriend.name = LinphoneUtils.getDisplayName(address)
|
||||||
fakeFriend.addAddress(address)
|
fakeFriend.addAddress(address)
|
||||||
val model = ContactAvatarModel(fakeFriend)
|
val model = ContactAvatarModel(fakeFriend)
|
||||||
model.showTrust.postValue(isDeviceTrusted)
|
model.trust.postValue(securityLevel)
|
||||||
contact.postValue(model)
|
contact.postValue(model)
|
||||||
displayedName.postValue(fakeFriend.name)
|
displayedName.postValue(fakeFriend.name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import android.provider.ContactsContract
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
|
import org.linphone.core.ChatRoom.SecurityLevel
|
||||||
import org.linphone.core.ConsolidatedPresence
|
import org.linphone.core.ConsolidatedPresence
|
||||||
import org.linphone.core.Friend
|
import org.linphone.core.Friend
|
||||||
import org.linphone.core.FriendListenerStub
|
import org.linphone.core.FriendListenerStub
|
||||||
|
|
@ -55,7 +56,7 @@ class ContactAvatarModel @WorkerThread constructor(val friend: Friend) {
|
||||||
|
|
||||||
val firstContactStartingByThatLetter = MutableLiveData<Boolean>()
|
val firstContactStartingByThatLetter = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val showTrust = MutableLiveData<Boolean>()
|
val trust = MutableLiveData<SecurityLevel>()
|
||||||
|
|
||||||
private val friendListener = object : FriendListenerStub() {
|
private val friendListener = object : FriendListenerStub() {
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
|
|
@ -70,6 +71,8 @@ class ContactAvatarModel @WorkerThread constructor(val friend: Friend) {
|
||||||
init {
|
init {
|
||||||
friend.addListener(friendListener)
|
friend.addListener(friendListener)
|
||||||
|
|
||||||
|
trust.postValue(SecurityLevel.Safe) // TODO FIXME: use API
|
||||||
|
|
||||||
name.postValue(friend.name)
|
name.postValue(friend.name)
|
||||||
computePresence()
|
computePresence()
|
||||||
avatar.postValue(getAvatarUri())
|
avatar.postValue(getAvatarUri())
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ import io.getstream.avatarview.AvatarView
|
||||||
import io.getstream.avatarview.coil.loadImage
|
import io.getstream.avatarview.coil.loadImage
|
||||||
import org.linphone.BR
|
import org.linphone.BR
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
|
import org.linphone.core.ChatRoom
|
||||||
import org.linphone.core.ConsolidatedPresence
|
import org.linphone.core.ConsolidatedPresence
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||||
|
|
@ -306,13 +307,22 @@ fun AvatarView.loadContactAvatar(contact: ContactAvatarModel?) {
|
||||||
avatarInitials = initials
|
avatarInitials = initials
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contact.showTrust.value == true) {
|
when (contact.trust.value) {
|
||||||
avatarBorderColor =
|
ChatRoom.SecurityLevel.Unsafe -> {
|
||||||
resources.getColor(R.color.blue_info_500, context.theme)
|
avatarBorderColor =
|
||||||
avatarBorderWidth =
|
resources.getColor(R.color.red_danger_500, context.theme)
|
||||||
AppUtils.getDimension(R.dimen.avatar_trust_border_width).toInt()
|
avatarBorderWidth =
|
||||||
} else {
|
AppUtils.getDimension(R.dimen.avatar_trust_border_width).toInt()
|
||||||
avatarBorderWidth = AppUtils.getDimension(R.dimen.zero).toInt()
|
}
|
||||||
|
ChatRoom.SecurityLevel.Encrypted -> {
|
||||||
|
avatarBorderColor =
|
||||||
|
resources.getColor(R.color.blue_info_500, context.theme)
|
||||||
|
avatarBorderWidth =
|
||||||
|
AppUtils.getDimension(R.dimen.avatar_trust_border_width).toInt()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
avatarBorderWidth = AppUtils.getDimension(R.dimen.zero).toInt()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSuccess = { _, _ ->
|
onSuccess = { _, _ ->
|
||||||
|
|
|
||||||
23
app/src/main/res/drawable/not_trusted.xml
Normal file
23
app/src/main/res/drawable/not_trusted.xml
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="11dp"
|
||||||
|
android:height="10dp"
|
||||||
|
android:viewportWidth="11"
|
||||||
|
android:viewportHeight="10">
|
||||||
|
<path
|
||||||
|
android:pathData="M1.019,5a4.231,4.231 0,1 0,8.462 0a4.231,4.231 0,1 0,-8.462 0z"
|
||||||
|
android:fillColor="#DD5F5F"/>
|
||||||
|
<group>
|
||||||
|
<clip-path
|
||||||
|
android:pathData="M0.25,0h10v10h-10z"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M5.25,2.917C5.48,2.917 5.667,3.103 5.667,3.333V5C5.667,5.23 5.48,5.417 5.25,5.417C5.02,5.417 4.833,5.23 4.833,5V3.333C4.833,3.103 5.02,2.917 5.25,2.917Z"
|
||||||
|
android:fillColor="#364860"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M5.25,6.25C5.02,6.25 4.833,6.437 4.833,6.667C4.833,6.897 5.02,7.083 5.25,7.083H5.254C5.484,7.083 5.671,6.897 5.671,6.667C5.671,6.437 5.484,6.25 5.254,6.25H5.25Z"
|
||||||
|
android:fillColor="#364860"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M3.23,0.539C3.308,0.461 3.414,0.417 3.525,0.417H6.975C7.085,0.417 7.191,0.461 7.27,0.539L9.711,2.98C9.789,3.059 9.833,3.164 9.833,3.275V6.725C9.833,6.835 9.789,6.941 9.711,7.02L7.27,9.461C7.191,9.539 7.085,9.583 6.975,9.583H3.525C3.414,9.583 3.308,9.539 3.23,9.461L0.789,7.02C0.711,6.941 0.667,6.835 0.667,6.725V3.275C0.667,3.164 0.711,3.059 0.789,2.98L3.23,0.539ZM3.698,1.25L1.5,3.448V6.552L3.698,8.75H6.802L9,6.552V3.448L6.802,1.25H3.698Z"
|
||||||
|
android:fillColor="#364860"
|
||||||
|
android:fillType="evenOdd"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
|
<import type="org.linphone.core.ChatRoom.SecurityLevel" />
|
||||||
<variable
|
<variable
|
||||||
name="transferClickListener"
|
name="transferClickListener"
|
||||||
type="View.OnClickListener" />
|
type="View.OnClickListener" />
|
||||||
|
|
@ -90,8 +91,8 @@
|
||||||
android:id="@+id/trust_badge"
|
android:id="@+id/trust_badge"
|
||||||
android:layout_width="@dimen/avatar_presence_badge_in_call_size"
|
android:layout_width="@dimen/avatar_presence_badge_in_call_size"
|
||||||
android:layout_height="@dimen/avatar_presence_badge_in_call_size"
|
android:layout_height="@dimen/avatar_presence_badge_in_call_size"
|
||||||
android:src="@drawable/trusted"
|
android:src="@{viewModel.contact.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
|
||||||
android:visibility="@{viewModel.contact.showTrust ? View.VISIBLE : View.GONE}"
|
android:visibility="@{viewModel.contact.trust == SecurityLevel.Encrypted || viewModel.contact.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||||
app:layout_constraintStart_toStartOf="@id/avatar"
|
app:layout_constraintStart_toStartOf="@id/avatar"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
<import type="org.linphone.core.ConsolidatedPresence" />
|
<import type="org.linphone.core.ConsolidatedPresence" />
|
||||||
|
<import type="org.linphone.core.ChatRoom.SecurityLevel" />
|
||||||
<variable
|
<variable
|
||||||
name="model"
|
name="model"
|
||||||
type="org.linphone.ui.main.contacts.model.ContactAvatarModel" />
|
type="org.linphone.ui.main.contacts.model.ContactAvatarModel" />
|
||||||
|
|
@ -55,6 +56,15 @@
|
||||||
app:layout_constraintEnd_toEndOf="@id/avatar"
|
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/trust_badge"
|
||||||
|
android:layout_width="@dimen/avatar_presence_badge_size"
|
||||||
|
android:layout_height="@dimen/avatar_presence_badge_size"
|
||||||
|
android:src="@{model.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
|
||||||
|
android:visibility="@{model.trust == SecurityLevel.Encrypted || model.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
style="@style/default_text_style"
|
style="@style/default_text_style"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
<import type="org.linphone.core.ConsolidatedPresence" />
|
<import type="org.linphone.core.ConsolidatedPresence" />
|
||||||
|
<import type="org.linphone.core.ChatRoom.SecurityLevel" />
|
||||||
<variable
|
<variable
|
||||||
name="backClickListener"
|
name="backClickListener"
|
||||||
type="View.OnClickListener" />
|
type="View.OnClickListener" />
|
||||||
|
|
@ -125,6 +126,15 @@
|
||||||
app:layout_constraintEnd_toEndOf="@id/avatar"
|
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/trust_badge"
|
||||||
|
android:layout_width="@dimen/avatar_presence_badge_in_call_size"
|
||||||
|
android:layout_height="@dimen/avatar_presence_badge_in_call_size"
|
||||||
|
android:src="@{viewModel.contact.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
|
||||||
|
android:visibility="@{viewModel.contact.trust == SecurityLevel.Encrypted || viewModel.contact.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
style="@style/default_text_style"
|
style="@style/default_text_style"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
<import type="android.graphics.Typeface" />
|
<import type="android.graphics.Typeface" />
|
||||||
<import type="org.linphone.core.ConsolidatedPresence" />
|
<import type="org.linphone.core.ConsolidatedPresence" />
|
||||||
|
<import type="org.linphone.core.ChatRoom.SecurityLevel" />
|
||||||
<variable
|
<variable
|
||||||
name="model"
|
name="model"
|
||||||
type="org.linphone.ui.main.contacts.model.ContactAvatarModel" />
|
type="org.linphone.ui.main.contacts.model.ContactAvatarModel" />
|
||||||
|
|
@ -84,6 +85,15 @@
|
||||||
app:layout_constraintEnd_toEndOf="@id/avatar"
|
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/trust_badge"
|
||||||
|
android:layout_width="@dimen/avatar_presence_badge_size"
|
||||||
|
android:layout_height="@dimen/avatar_presence_badge_size"
|
||||||
|
android:src="@{model.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
|
||||||
|
android:visibility="@{model.trust == SecurityLevel.Encrypted || model.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
style="@style/default_text_style"
|
style="@style/default_text_style"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
<import type="org.linphone.core.ConsolidatedPresence" />
|
<import type="org.linphone.core.ConsolidatedPresence" />
|
||||||
|
<import type="org.linphone.core.ChatRoom.SecurityLevel" />
|
||||||
<variable
|
<variable
|
||||||
name="backClickListener"
|
name="backClickListener"
|
||||||
type="View.OnClickListener" />
|
type="View.OnClickListener" />
|
||||||
|
|
@ -99,6 +100,15 @@
|
||||||
app:layout_constraintEnd_toEndOf="@id/avatar"
|
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/trust_badge"
|
||||||
|
android:layout_width="@dimen/avatar_presence_badge_in_call_size"
|
||||||
|
android:layout_height="@dimen/avatar_presence_badge_in_call_size"
|
||||||
|
android:src="@{viewModel.callLogModel.avatarModel.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
|
||||||
|
android:visibility="@{viewModel.callLogModel.avatarModel.trust == SecurityLevel.Encrypted || viewModel.callLogModel.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
style="@style/default_text_style"
|
style="@style/default_text_style"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
<import type="android.graphics.Typeface" />
|
<import type="android.graphics.Typeface" />
|
||||||
<import type="org.linphone.core.ConsolidatedPresence" />
|
<import type="org.linphone.core.ConsolidatedPresence" />
|
||||||
|
<import type="org.linphone.core.ChatRoom.SecurityLevel" />
|
||||||
<variable
|
<variable
|
||||||
name="model"
|
name="model"
|
||||||
type="org.linphone.ui.main.history.model.CallLogModel" />
|
type="org.linphone.ui.main.history.model.CallLogModel" />
|
||||||
|
|
@ -61,6 +62,15 @@
|
||||||
app:layout_constraintEnd_toEndOf="@id/avatar"
|
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/trust_badge"
|
||||||
|
android:layout_width="@dimen/avatar_presence_badge_size"
|
||||||
|
android:layout_height="@dimen/avatar_presence_badge_size"
|
||||||
|
android:src="@{model.avatarModel.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
|
||||||
|
android:visibility="@{model.avatarModel.trust == SecurityLevel.Encrypted || model.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
style="@style/default_text_style"
|
style="@style/default_text_style"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue