SmartSnackbars
This commit is contained in:
@@ -9,8 +9,6 @@ import android.net.wifi.WifiManager
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.StringRes
|
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import be.mygod.vpnhotspot.util.DeviceStorageApp
|
import be.mygod.vpnhotspot.util.DeviceStorageApp
|
||||||
import be.mygod.vpnhotspot.util.Event0
|
import be.mygod.vpnhotspot.util.Event0
|
||||||
@@ -55,6 +53,4 @@ class App : Application() {
|
|||||||
val masquerade: Boolean get() = pref.getBoolean(KEY_MASQUERADE, true)
|
val masquerade: Boolean get() = pref.getBoolean(KEY_MASQUERADE, true)
|
||||||
|
|
||||||
val cleanRoutings = Event0()
|
val cleanRoutings = Event0()
|
||||||
|
|
||||||
fun toast(@StringRes resId: Int) = handler.post { Toast.makeText(this, resId, Toast.LENGTH_SHORT).show() }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package be.mygod.vpnhotspot
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import be.mygod.vpnhotspot.App.Companion.app
|
import be.mygod.vpnhotspot.App.Companion.app
|
||||||
import be.mygod.vpnhotspot.manage.LocalOnlyHotspotManager
|
import be.mygod.vpnhotspot.manage.LocalOnlyHotspotManager
|
||||||
@@ -11,6 +10,7 @@ import be.mygod.vpnhotspot.net.IpNeighbourMonitor
|
|||||||
import be.mygod.vpnhotspot.net.TetheringManager
|
import be.mygod.vpnhotspot.net.TetheringManager
|
||||||
import be.mygod.vpnhotspot.util.broadcastReceiver
|
import be.mygod.vpnhotspot.util.broadcastReceiver
|
||||||
import be.mygod.vpnhotspot.util.debugLog
|
import be.mygod.vpnhotspot.util.debugLog
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
|
|
||||||
@RequiresApi(26)
|
@RequiresApi(26)
|
||||||
@@ -89,7 +89,7 @@ class LocalOnlyHotspotService : IpNeighbourMonitoringService() {
|
|||||||
getString(R.string.tethering_temp_hotspot_failure_tethering_disallowed)
|
getString(R.string.tethering_temp_hotspot_failure_tethering_disallowed)
|
||||||
else -> getString(R.string.failure_reason_unknown, reason)
|
else -> getString(R.string.failure_reason_unknown, reason)
|
||||||
})
|
})
|
||||||
Toast.makeText(this@LocalOnlyHotspotService, message, Toast.LENGTH_SHORT).show()
|
SmartSnackbar.make(message).show()
|
||||||
startFailure(if (reason == WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE) null else
|
startFailure(if (reason == WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE) null else
|
||||||
StartFailure(message))
|
StartFailure(message))
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ class LocalOnlyHotspotService : IpNeighbourMonitoringService() {
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
startFailure(e)
|
startFailure(e)
|
||||||
} catch (e: SecurityException) {
|
} catch (e: SecurityException) {
|
||||||
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
|
SmartSnackbar.make(e.localizedMessage).show()
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
startFailure(e)
|
startFailure(e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package be.mygod.vpnhotspot
|
package be.mygod.vpnhotspot
|
||||||
|
|
||||||
import android.widget.Toast
|
|
||||||
import be.mygod.vpnhotspot.App.Companion.app
|
import be.mygod.vpnhotspot.App.Companion.app
|
||||||
import be.mygod.vpnhotspot.net.Routing
|
import be.mygod.vpnhotspot.net.Routing
|
||||||
import be.mygod.vpnhotspot.net.UpstreamMonitor
|
import be.mygod.vpnhotspot.net.UpstreamMonitor
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.net.InterfaceAddress
|
import java.net.InterfaceAddress
|
||||||
@@ -48,9 +48,9 @@ class LocalOnlyInterfaceManager(val downstream: String) : UpstreamMonitor.Callba
|
|||||||
routing.ipForward() // local only interfaces need not enable ip_forward
|
routing.ipForward() // local only interfaces need not enable ip_forward
|
||||||
.rule().forward(strict)
|
.rule().forward(strict)
|
||||||
if (app.masquerade) routing.masquerade(strict)
|
if (app.masquerade) routing.masquerade(strict)
|
||||||
if (!routing.dnsRedirect(dns).start()) app.toast(R.string.noisy_su_failure)
|
if (!routing.dnsRedirect(dns).start()) SmartSnackbar.make(R.string.noisy_su_failure).show()
|
||||||
} catch (e: SocketException) {
|
} catch (e: SocketException) {
|
||||||
Toast.makeText(app, e.message, Toast.LENGTH_SHORT).show()
|
SmartSnackbar.make(e.localizedMessage).show()
|
||||||
Crashlytics.logException(e)
|
Crashlytics.logException(e)
|
||||||
routing = null
|
routing = null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,17 @@ import be.mygod.vpnhotspot.client.ClientsFragment
|
|||||||
import be.mygod.vpnhotspot.databinding.ActivityMainBinding
|
import be.mygod.vpnhotspot.databinding.ActivityMainBinding
|
||||||
import be.mygod.vpnhotspot.manage.TetheringFragment
|
import be.mygod.vpnhotspot.manage.TetheringFragment
|
||||||
import be.mygod.vpnhotspot.util.ServiceForegroundConnector
|
import be.mygod.vpnhotspot.util.ServiceForegroundConnector
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationMenuView
|
import com.google.android.material.bottomnavigation.BottomNavigationMenuView
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import q.rorbin.badgeview.QBadgeView
|
import q.rorbin.badgeview.QBadgeView
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener, ServiceConnection {
|
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener, ServiceConnection {
|
||||||
|
companion object {
|
||||||
|
var current: MainActivity? = null
|
||||||
|
}
|
||||||
|
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
private lateinit var badge: QBadgeView
|
private lateinit var badge: QBadgeView
|
||||||
private var clients: ClientMonitorService.Binder? = null
|
private var clients: ClientMonitorService.Binder? = null
|
||||||
@@ -33,7 +38,6 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
fun launchUrl(url: Uri) = customTabsIntent.launchUrl(this, url)
|
fun launchUrl(url: Uri) = customTabsIntent.launchUrl(this, url)
|
||||||
fun snackbar(text: CharSequence = "") = Snackbar.make(binding.fragmentHolder, text, Snackbar.LENGTH_LONG)
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -47,6 +51,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
|
|||||||
badge.badgeGravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
|
badge.badgeGravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
|
||||||
badge.setGravityOffset(16f, 0f, true)
|
badge.setGravityOffset(16f, 0f, true)
|
||||||
ServiceForegroundConnector(this, this, ClientMonitorService::class)
|
ServiceForegroundConnector(this, this, ClientMonitorService::class)
|
||||||
|
SmartSnackbar.Register(binding.fragmentHolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNavigationItemSelected(item: MenuItem) = when (item.itemId) {
|
override fun onNavigationItemSelected(item: MenuItem) = when (item.itemId) {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import android.net.wifi.p2p.WifiP2pInfo
|
|||||||
import android.net.wifi.p2p.WifiP2pManager
|
import android.net.wifi.p2p.WifiP2pManager
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import be.mygod.vpnhotspot.App.Companion.app
|
import be.mygod.vpnhotspot.App.Companion.app
|
||||||
@@ -22,6 +21,7 @@ import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.requestPersistentGroupI
|
|||||||
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.setWifiP2pChannels
|
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.setWifiP2pChannels
|
||||||
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.startWps
|
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.startWps
|
||||||
import be.mygod.vpnhotspot.util.*
|
import be.mygod.vpnhotspot.util.*
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
|
|
||||||
@@ -50,11 +50,11 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
WpsInfo.KEYPAD
|
WpsInfo.KEYPAD
|
||||||
}
|
}
|
||||||
}, object : WifiP2pManager.ActionListener {
|
}, object : WifiP2pManager.ActionListener {
|
||||||
override fun onSuccess() = Toast.makeText(this@RepeaterService,
|
override fun onSuccess() = SmartSnackbar.make(
|
||||||
if (pin == null) R.string.repeater_wps_success_pbc else R.string.repeater_wps_success_keypad,
|
if (pin == null) R.string.repeater_wps_success_pbc else R.string.repeater_wps_success_keypad)
|
||||||
Toast.LENGTH_SHORT).show()
|
.shortToast().show()
|
||||||
override fun onFailure(reason: Int) = Toast.makeText(this@RepeaterService,
|
override fun onFailure(reason: Int) = SmartSnackbar.make(
|
||||||
formatReason(R.string.repeater_wps_failure, reason), Toast.LENGTH_SHORT).show()
|
formatReason(R.string.repeater_wps_failure, reason)).show()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,10 +64,10 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
|
|
||||||
fun resetCredentials() = (groups + group).filterNotNull().forEach {
|
fun resetCredentials() = (groups + group).filterNotNull().forEach {
|
||||||
p2pManager.deletePersistentGroup(channel, it.netId, object : WifiP2pManager.ActionListener {
|
p2pManager.deletePersistentGroup(channel, it.netId, object : WifiP2pManager.ActionListener {
|
||||||
override fun onSuccess() = Toast.makeText(this@RepeaterService,
|
override fun onSuccess() = SmartSnackbar.make(R.string.repeater_reset_credentials_success)
|
||||||
R.string.repeater_reset_credentials_success, Toast.LENGTH_SHORT).show()
|
.shortToast().show()
|
||||||
override fun onFailure(reason: Int) = Toast.makeText(this@RepeaterService,
|
override fun onFailure(reason: Int) = SmartSnackbar.make(
|
||||||
formatReason(R.string.repeater_reset_credentials_failure, reason), Toast.LENGTH_SHORT).show()
|
formatReason(R.string.repeater_reset_credentials_failure, reason)).show()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
} catch (e: ReflectiveOperationException) {
|
} catch (e: ReflectiveOperationException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Crashlytics.logException(e)
|
Crashlytics.logException(e)
|
||||||
Toast.makeText(this@RepeaterService, e.message, Toast.LENGTH_LONG).show()
|
SmartSnackbar.make(e.localizedMessage).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
binder.statusChanged()
|
binder.statusChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatReason(@StringRes resId: Int, reason: Int): String? {
|
private fun formatReason(@StringRes resId: Int, reason: Int): String {
|
||||||
val result = getString(resId, when (reason) {
|
val result = getString(resId, when (reason) {
|
||||||
WifiP2pManager.ERROR -> getString(R.string.repeater_failure_reason_error)
|
WifiP2pManager.ERROR -> getString(R.string.repeater_failure_reason_error)
|
||||||
WifiP2pManager.P2P_UNSUPPORTED -> getString(R.string.repeater_failure_reason_p2p_unsupported)
|
WifiP2pManager.P2P_UNSUPPORTED -> getString(R.string.repeater_failure_reason_p2p_unsupported)
|
||||||
@@ -147,14 +147,13 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
p2pManager.setWifiP2pChannels(channel, 0, oc, object : WifiP2pManager.ActionListener {
|
p2pManager.setWifiP2pChannels(channel, 0, oc, object : WifiP2pManager.ActionListener {
|
||||||
override fun onSuccess() { }
|
override fun onSuccess() { }
|
||||||
override fun onFailure(reason: Int) {
|
override fun onFailure(reason: Int) {
|
||||||
Toast.makeText(this@RepeaterService, formatReason(R.string.repeater_set_oc_failure, reason),
|
SmartSnackbar.make(formatReason(R.string.repeater_set_oc_failure, reason)).show()
|
||||||
Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} catch (e: InvocationTargetException) {
|
} catch (e: InvocationTargetException) {
|
||||||
if (oc != 0) {
|
if (oc != 0) {
|
||||||
val message = getString(R.string.repeater_set_oc_failure, e.message)
|
val message = getString(R.string.repeater_set_oc_failure, e.message)
|
||||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
|
SmartSnackbar.make(message).show()
|
||||||
Crashlytics.logException(Failure(message))
|
Crashlytics.logException(Failure(message))
|
||||||
}
|
}
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
@@ -195,9 +194,8 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
p2pManager.removeGroup(channel, object : WifiP2pManager.ActionListener {
|
p2pManager.removeGroup(channel, object : WifiP2pManager.ActionListener {
|
||||||
override fun onSuccess() = doStart()
|
override fun onSuccess() = doStart()
|
||||||
override fun onFailure(reason: Int) {
|
override fun onFailure(reason: Int) {
|
||||||
Toast.makeText(this@RepeaterService,
|
SmartSnackbar.make(formatReason(R.string.repeater_remove_old_group_failure, reason))
|
||||||
formatReason(R.string.repeater_remove_old_group_failure, reason),
|
.show()
|
||||||
Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -237,8 +235,8 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
status = Status.ACTIVE
|
status = Status.ACTIVE
|
||||||
showNotification(group)
|
showNotification(group)
|
||||||
}
|
}
|
||||||
private fun startFailure(msg: CharSequence?, group: WifiP2pGroup? = null) {
|
private fun startFailure(msg: CharSequence, group: WifiP2pGroup? = null) {
|
||||||
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
|
SmartSnackbar.make(msg).show()
|
||||||
showNotification()
|
showNotification()
|
||||||
if (group != null) removeGroup() else clean()
|
if (group != null) removeGroup() else clean()
|
||||||
}
|
}
|
||||||
@@ -251,8 +249,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
override fun onSuccess() = clean()
|
override fun onSuccess() = clean()
|
||||||
override fun onFailure(reason: Int) {
|
override fun onFailure(reason: Int) {
|
||||||
if (reason == WifiP2pManager.BUSY) clean() else { // assuming it's already gone
|
if (reason == WifiP2pManager.BUSY) clean() else { // assuming it's already gone
|
||||||
Toast.makeText(this@RepeaterService,
|
SmartSnackbar.make(formatReason(R.string.repeater_remove_group_failure, reason)).show()
|
||||||
formatReason(R.string.repeater_remove_group_failure, reason), Toast.LENGTH_SHORT).show()
|
|
||||||
status = Status.ACTIVE
|
status = Status.ACTIVE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import be.mygod.vpnhotspot.net.UpstreamMonitor
|
|||||||
import be.mygod.vpnhotspot.preference.AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat
|
import be.mygod.vpnhotspot.preference.AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat
|
||||||
import be.mygod.vpnhotspot.preference.SharedPreferenceDataStore
|
import be.mygod.vpnhotspot.preference.SharedPreferenceDataStore
|
||||||
import be.mygod.vpnhotspot.util.loggerSuStream
|
import be.mygod.vpnhotspot.util.loggerSuStream
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import com.takisoft.preferencex.PreferenceFragmentCompat
|
import com.takisoft.preferencex.PreferenceFragmentCompat
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -27,7 +28,6 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
|||||||
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
preferenceManager.preferenceDataStore = SharedPreferenceDataStore(app.pref)
|
preferenceManager.preferenceDataStore = SharedPreferenceDataStore(app.pref)
|
||||||
addPreferencesFromResource(R.xml.pref_settings)
|
addPreferencesFromResource(R.xml.pref_settings)
|
||||||
val mainActivity = activity as MainActivity
|
|
||||||
val boot = findPreference("service.repeater.startOnBoot") as SwitchPreference
|
val boot = findPreference("service.repeater.startOnBoot") as SwitchPreference
|
||||||
boot.setOnPreferenceChangeListener { _, value ->
|
boot.setOnPreferenceChangeListener { _, value ->
|
||||||
BootReceiver.enabled = value as Boolean
|
BootReceiver.enabled = value as Boolean
|
||||||
@@ -35,7 +35,7 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
boot.isChecked = BootReceiver.enabled
|
boot.isChecked = BootReceiver.enabled
|
||||||
findPreference("service.clean").setOnPreferenceClickListener {
|
findPreference("service.clean").setOnPreferenceClickListener {
|
||||||
if (Routing.clean() == null) mainActivity.snackbar().setText(R.string.root_unavailable).show()
|
if (Routing.clean() == null) SmartSnackbar.make(R.string.root_unavailable).show()
|
||||||
else app.cleanRoutings()
|
else app.cleanRoutings()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
findPreference("misc.source").setOnPreferenceClickListener {
|
findPreference("misc.source").setOnPreferenceClickListener {
|
||||||
mainActivity.launchUrl("https://github.com/Mygod/VPNHotspot".toUri())
|
(activity as MainActivity).launchUrl("https://github.com/Mygod/VPNHotspot".toUri())
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
findPreference("misc.donate").setOnPreferenceClickListener {
|
findPreference("misc.donate").setOnPreferenceClickListener {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import be.mygod.vpnhotspot.net.Routing
|
|||||||
import be.mygod.vpnhotspot.net.TetheringManager
|
import be.mygod.vpnhotspot.net.TetheringManager
|
||||||
import be.mygod.vpnhotspot.net.UpstreamMonitor
|
import be.mygod.vpnhotspot.net.UpstreamMonitor
|
||||||
import be.mygod.vpnhotspot.util.broadcastReceiver
|
import be.mygod.vpnhotspot.util.broadcastReceiver
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.net.SocketException
|
import java.net.SocketException
|
||||||
@@ -32,7 +33,7 @@ class TetheringService : IpNeighbourMonitoringService(), UpstreamMonitor.Callbac
|
|||||||
private var receiverRegistered = false
|
private var receiverRegistered = false
|
||||||
private val receiver = broadcastReceiver { _, intent ->
|
private val receiver = broadcastReceiver { _, intent ->
|
||||||
synchronized(routings) {
|
synchronized(routings) {
|
||||||
for (iface in routings.keys - TetheringManager.getTetheredIfaces(intent.extras))
|
for (iface in routings.keys - TetheringManager.getTetheredIfaces(intent.extras!!))
|
||||||
routings.remove(iface)?.stop()
|
routings.remove(iface)?.stop()
|
||||||
updateRoutingsLocked()
|
updateRoutingsLocked()
|
||||||
}
|
}
|
||||||
@@ -60,7 +61,7 @@ class TetheringService : IpNeighbourMonitoringService(), UpstreamMonitor.Callbac
|
|||||||
routings.remove(downstream)
|
routings.remove(downstream)
|
||||||
failed = true
|
failed = true
|
||||||
}
|
}
|
||||||
if (failed) app.toast(R.string.noisy_su_failure)
|
if (failed) SmartSnackbar.make(R.string.noisy_su_failure).show()
|
||||||
} else if (!receiverRegistered) {
|
} else if (!receiverRegistered) {
|
||||||
registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED))
|
registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED))
|
||||||
app.cleanRoutings[this] = {
|
app.cleanRoutings[this] = {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import be.mygod.vpnhotspot.net.wifi.P2pSupplicantConfiguration
|
|||||||
import be.mygod.vpnhotspot.net.wifi.WifiP2pDialogFragment
|
import be.mygod.vpnhotspot.net.wifi.WifiP2pDialogFragment
|
||||||
import be.mygod.vpnhotspot.util.ServiceForegroundConnector
|
import be.mygod.vpnhotspot.util.ServiceForegroundConnector
|
||||||
import be.mygod.vpnhotspot.util.formatAddresses
|
import be.mygod.vpnhotspot.util.formatAddresses
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import java.net.NetworkInterface
|
import java.net.NetworkInterface
|
||||||
import java.net.SocketException
|
import java.net.SocketException
|
||||||
@@ -100,14 +101,13 @@ class RepeaterManager(private val parent: TetheringFragment) : Manager(), Servic
|
|||||||
val binder = binder
|
val binder = binder
|
||||||
val group = binder?.service?.group
|
val group = binder?.service?.group
|
||||||
val ssid = group?.networkName
|
val ssid = group?.networkName
|
||||||
val mainActivity = parent.activity as MainActivity
|
|
||||||
if (ssid != null) {
|
if (ssid != null) {
|
||||||
val wifi = WifiConfiguration()
|
val wifi = WifiConfiguration()
|
||||||
val conf = P2pSupplicantConfiguration()
|
val conf = P2pSupplicantConfiguration()
|
||||||
wifi.SSID = ssid
|
wifi.SSID = ssid
|
||||||
wifi.preSharedKey = group.passphrase
|
wifi.preSharedKey = group.passphrase
|
||||||
if (wifi.preSharedKey == null) {
|
if (wifi.preSharedKey == null) {
|
||||||
wifi.preSharedKey = conf.readPsk { mainActivity.snackbar(it.message.toString()).show() }
|
wifi.preSharedKey = conf.readPsk { SmartSnackbar.make(it.message.toString()).show() }
|
||||||
}
|
}
|
||||||
if (wifi.preSharedKey != null) {
|
if (wifi.preSharedKey != null) {
|
||||||
WifiP2pDialogFragment().apply {
|
WifiP2pDialogFragment().apply {
|
||||||
@@ -118,7 +118,7 @@ class RepeaterManager(private val parent: TetheringFragment) : Manager(), Servic
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mainActivity.snackbar().setText(R.string.repeater_configure_failure).show()
|
SmartSnackbar.make(R.string.repeater_configure_failure).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import be.mygod.vpnhotspot.databinding.ListitemInterfaceBinding
|
|||||||
import be.mygod.vpnhotspot.net.TetherType
|
import be.mygod.vpnhotspot.net.TetherType
|
||||||
import be.mygod.vpnhotspot.net.TetheringManager
|
import be.mygod.vpnhotspot.net.TetheringManager
|
||||||
import be.mygod.vpnhotspot.net.wifi.WifiApManager
|
import be.mygod.vpnhotspot.net.wifi.WifiApManager
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
|
|
||||||
@@ -92,7 +93,7 @@ sealed class TetherManager(protected val parent: TetheringFragment) : Manager(),
|
|||||||
|
|
||||||
override fun onTetheringStarted() = data.notifyChange()
|
override fun onTetheringStarted() = data.notifyChange()
|
||||||
override fun onTetheringFailed() =
|
override fun onTetheringFailed() =
|
||||||
(parent.activity as MainActivity).snackbar().setText(R.string.tethering_manage_failed).show()
|
SmartSnackbar.make(R.string.tethering_manage_failed).show()
|
||||||
|
|
||||||
override fun bindTo(viewHolder: RecyclerView.ViewHolder) {
|
override fun bindTo(viewHolder: RecyclerView.ViewHolder) {
|
||||||
(viewHolder as ViewHolder).manager = this
|
(viewHolder as ViewHolder).manager = this
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.util.Log
|
|||||||
import be.mygod.vpnhotspot.App.Companion.app
|
import be.mygod.vpnhotspot.App.Companion.app
|
||||||
import be.mygod.vpnhotspot.R
|
import be.mygod.vpnhotspot.R
|
||||||
import be.mygod.vpnhotspot.util.thread
|
import be.mygod.vpnhotspot.util.thread
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InterruptedIOException
|
import java.io.InterruptedIOException
|
||||||
@@ -67,7 +68,7 @@ abstract class IpMonitor : Runnable {
|
|||||||
if (err.isNotBlank()) {
|
if (err.isNotBlank()) {
|
||||||
Crashlytics.log(Log.ERROR, javaClass.simpleName, err)
|
Crashlytics.log(Log.ERROR, javaClass.simpleName, err)
|
||||||
Crashlytics.logException(FlushFailure())
|
Crashlytics.logException(FlushFailure())
|
||||||
app.toast(R.string.noisy_su_failure)
|
SmartSnackbar.make(R.string.noisy_su_failure).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
process.inputStream.bufferedReader().useLines(this::processLines)
|
process.inputStream.bufferedReader().useLines(this::processLines)
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import android.widget.TextView
|
|||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import be.mygod.vpnhotspot.App.Companion.app
|
import be.mygod.vpnhotspot.App.Companion.app
|
||||||
import be.mygod.vpnhotspot.MainActivity
|
|
||||||
import be.mygod.vpnhotspot.R
|
import be.mygod.vpnhotspot.R
|
||||||
import be.mygod.vpnhotspot.manage.TetheringFragment
|
import be.mygod.vpnhotspot.manage.TetheringFragment
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
@@ -90,8 +90,8 @@ class WifiP2pDialogFragment : DialogFragment(), TextWatcher, DialogInterface.OnC
|
|||||||
app.handler.postDelayed((targetFragment as TetheringFragment).adapter.repeaterManager
|
app.handler.postDelayed((targetFragment as TetheringFragment).adapter.repeaterManager
|
||||||
.binder!!::requestGroupUpdate, 1000)
|
.binder!!::requestGroupUpdate, 1000)
|
||||||
}
|
}
|
||||||
false -> (activity as MainActivity).snackbar().setText(R.string.noisy_su_failure).show()
|
false -> SmartSnackbar.make(R.string.noisy_su_failure).show()
|
||||||
null -> (activity as MainActivity).snackbar().setText(R.string.root_unavailable).show()
|
null -> SmartSnackbar.make(R.string.root_unavailable).show()
|
||||||
}
|
}
|
||||||
DialogInterface.BUTTON_NEUTRAL ->
|
DialogInterface.BUTTON_NEUTRAL ->
|
||||||
(targetFragment as TetheringFragment).adapter.repeaterManager.binder!!.resetCredentials()
|
(targetFragment as TetheringFragment).adapter.repeaterManager.binder!!.resetCredentials()
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import androidx.databinding.BindingAdapter
|
|||||||
import be.mygod.vpnhotspot.App.Companion.app
|
import be.mygod.vpnhotspot.App.Companion.app
|
||||||
import be.mygod.vpnhotspot.BuildConfig
|
import be.mygod.vpnhotspot.BuildConfig
|
||||||
import be.mygod.vpnhotspot.R
|
import be.mygod.vpnhotspot.R
|
||||||
|
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import java.net.NetworkInterface
|
import java.net.NetworkInterface
|
||||||
import java.net.SocketException
|
import java.net.SocketException
|
||||||
@@ -57,7 +58,7 @@ fun thread(name: String? = null, start: Boolean = true, isDaemon: Boolean = fals
|
|||||||
contextClassLoader: ClassLoader? = null, priority: Int = -1, block: () -> Unit): Thread {
|
contextClassLoader: ClassLoader? = null, priority: Int = -1, block: () -> Unit): Thread {
|
||||||
val thread = kotlin.concurrent.thread(false, isDaemon, contextClassLoader, name, priority, block)
|
val thread = kotlin.concurrent.thread(false, isDaemon, contextClassLoader, name, priority, block)
|
||||||
thread.setUncaughtExceptionHandler { _, e ->
|
thread.setUncaughtExceptionHandler { _, e ->
|
||||||
app.toast(R.string.noisy_su_failure)
|
SmartSnackbar.make(R.string.noisy_su_failure).show()
|
||||||
Crashlytics.logException(e)
|
Crashlytics.logException(e)
|
||||||
}
|
}
|
||||||
if (start) thread.start()
|
if (start) thread.start()
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package be.mygod.vpnhotspot.widget
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleObserver
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
|
import be.mygod.vpnhotspot.App.Companion.app
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
|
||||||
|
sealed class SmartSnackbar {
|
||||||
|
companion object {
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
|
private var holder: View? = null
|
||||||
|
|
||||||
|
fun make(@StringRes text: Int): SmartSnackbar = make(app.getText(text))
|
||||||
|
fun make(text: CharSequence = ""): SmartSnackbar {
|
||||||
|
val holder = holder
|
||||||
|
return if (holder == null) ToastWrapper(Toast.makeText(app, text, Toast.LENGTH_LONG)) else
|
||||||
|
SnackbarWrapper(Snackbar.make(holder, text, Snackbar.LENGTH_LONG))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Register(private val view: View) : LifecycleObserver {
|
||||||
|
init {
|
||||||
|
(view.context as LifecycleOwner).lifecycle.addObserver(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||||
|
fun onResume() {
|
||||||
|
holder = view
|
||||||
|
}
|
||||||
|
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
||||||
|
fun onPause() {
|
||||||
|
if (holder === view) holder = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun show()
|
||||||
|
open fun shortToast() = this
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SnackbarWrapper(private val snackbar: Snackbar) : SmartSnackbar() {
|
||||||
|
override fun show() = snackbar.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ToastWrapper(private val toast: Toast) : SmartSnackbar() {
|
||||||
|
override fun show() {
|
||||||
|
app.handler.post(toast::show)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shortToast() = apply { toast.duration = Toast.LENGTH_SHORT }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user