diff --git a/mobile/build.gradle b/mobile/build.gradle
index 6199898f..a40daad4 100644
--- a/mobile/build.gradle
+++ b/mobile/build.gradle
@@ -64,16 +64,17 @@ dependencies {
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycleVersion"
kapt "androidx.room:room-compiler:$roomVersion"
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation "androidx.browser:browser:1.0.0"
+ implementation 'androidx.browser:browser:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
- implementation "androidx.core:core-ktx:1.0.1"
+ implementation 'androidx.core:core-ktx:1.0.1'
+ implementation 'androidx.emoji:emoji:1.0.0'
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"
- implementation "androidx.preference:preference:1.1.0-alpha02"
+ implementation 'androidx.preference:preference:1.1.0-alpha02'
implementation "androidx.room:room-coroutines:$roomVersion"
implementation 'com.github.luongvo:BadgeView:1.1.5'
implementation 'com.github.topjohnwu.libsu:core:2.2.0'
- implementation "com.google.android.material:material:1.0.0"
+ implementation 'com.google.android.material:material:1.0.0'
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'com.linkedin.dexmaker:dexmaker:2.21.0'
implementation 'com.takisoft.preferencex:preferencex-simplemenu:1.0.0'
@@ -87,7 +88,7 @@ dependencies {
androidTestImplementation "androidx.room:room-testing:$roomVersion"
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
- androidTestImplementation "androidx.test.ext:junit-ktx:1.1.0"
+ androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.0'
}
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Base"))
diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/App.kt b/mobile/src/main/java/be/mygod/vpnhotspot/App.kt
index 6edb99c2..8507be73 100644
--- a/mobile/src/main/java/be/mygod/vpnhotspot/App.kt
+++ b/mobile/src/main/java/be/mygod/vpnhotspot/App.kt
@@ -11,10 +11,14 @@ import android.preference.PreferenceManager
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
+import androidx.core.provider.FontRequest
+import androidx.emoji.text.EmojiCompat
+import androidx.emoji.text.FontRequestEmojiCompatConfig
import be.mygod.vpnhotspot.room.AppDatabase
import be.mygod.vpnhotspot.util.DeviceStorageApp
import be.mygod.vpnhotspot.util.Event0
import be.mygod.vpnhotspot.util.RootSession
+import timber.log.Timber
import java.util.*
class App : Application() {
@@ -35,6 +39,16 @@ class App : Application() {
} else deviceStorage = this
DebugHelper.init()
ServiceNotification.updateNotificationChannels()
+ EmojiCompat.init(FontRequestEmojiCompatConfig(deviceStorage, FontRequest(
+ "com.google.android.gms.fonts",
+ "com.google.android.gms",
+ "Noto Color Emoji Compat",
+ R.array.com_google_android_gms_fonts_certs)).apply {
+ setEmojiSpanIndicatorEnabled(BuildConfig.DEBUG)
+ registerInitCallback(object : EmojiCompat.InitCallback() {
+ override fun onFailed(throwable: Throwable?) = Timber.d(throwable)
+ })
+ })
}
override fun onConfigurationChanged(newConfig: Configuration?) {
diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/client/Client.kt b/mobile/src/main/java/be/mygod/vpnhotspot/client/Client.kt
index f1fa1301..783682dc 100644
--- a/mobile/src/main/java/be/mygod/vpnhotspot/client/Client.kt
+++ b/mobile/src/main/java/be/mygod/vpnhotspot/client/Client.kt
@@ -15,7 +15,6 @@ import be.mygod.vpnhotspot.room.ClientRecord
import be.mygod.vpnhotspot.room.macToString
import be.mygod.vpnhotspot.util.makeIpSpan
import be.mygod.vpnhotspot.util.makeMacSpan
-import be.mygod.vpnhotspot.util.onEmpty
import java.net.InetAddress
import java.util.*
@@ -43,8 +42,10 @@ open class Client(val mac: Long, val iface: String) {
* we hijack the get title process to check if we need to perform MacLookup,
* as record might not be initialized in other more appropriate places
*/
- if (record?.nickname.isNullOrEmpty() && record?.macLookupPending != false) MacLookup.perform(mac)
- SpannableStringBuilder(record?.nickname.onEmpty(macIface)).apply {
+ SpannableStringBuilder(if (record?.nickname.isNullOrEmpty()) {
+ if (record?.macLookupPending != false) MacLookup.perform(mac)
+ macIface
+ } else emojize(record?.nickname)).apply {
if (record?.blocked == true) {
setSpan(StrikethroughSpan(), 0, length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
}
diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt
index 58005512..11e1bc99 100644
--- a/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt
+++ b/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt
@@ -55,7 +55,7 @@ class ClientsFragment : Fragment(), MainScope by MainScope.Supervisor() {
setTitle(getString(R.string.clients_nickname_title, arg.mac.macToString()))
setPositiveButton(android.R.string.ok, listener)
setNegativeButton(android.R.string.cancel, null)
- setNeutralButton(R.string.clients_nickname_set_to_vendor, listener)
+ setNeutralButton(emojize(getText(R.string.clients_nickname_set_to_vendor)), listener)
}
override fun onCreateDialog(savedInstanceState: Bundle?) = super.onCreateDialog(savedInstanceState).apply {
diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/client/Emojize.kt b/mobile/src/main/java/be/mygod/vpnhotspot/client/Emojize.kt
new file mode 100644
index 00000000..159dcdc6
--- /dev/null
+++ b/mobile/src/main/java/be/mygod/vpnhotspot/client/Emojize.kt
@@ -0,0 +1,10 @@
+package be.mygod.vpnhotspot.client
+
+import androidx.emoji.text.EmojiCompat
+import java.lang.IllegalStateException
+
+fun emojize(text: CharSequence?): CharSequence? = if (text == null) null else try {
+ EmojiCompat.get().process(text)
+} catch (_: IllegalStateException) {
+ text
+}
diff --git a/mobile/src/main/res/layout/dialog_nickname.xml b/mobile/src/main/res/layout/dialog_nickname.xml
index b0677114..2d136aa2 100644
--- a/mobile/src/main/res/layout/dialog_nickname.xml
+++ b/mobile/src/main/res/layout/dialog_nickname.xml
@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
-
-
+
diff --git a/mobile/src/main/res/values/font_certs.xml b/mobile/src/main/res/values/font_certs.xml
new file mode 100644
index 00000000..d63462fc
--- /dev/null
+++ b/mobile/src/main/res/values/font_certs.xml
@@ -0,0 +1,32 @@
+
+
+
+
+ - @array/com_google_android_gms_fonts_certs_dev
+ - @array/com_google_android_gms_fonts_certs_prod
+
+
+ -
+ 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
+
+
+