Skip to content

Commit

Permalink
Warn the user when the wifi is off and option to enable (fixes #21)
Browse files Browse the repository at this point in the history
  • Loading branch information
asos-savvasdalkitsis committed Nov 12, 2017
1 parent bfac7fb commit 4abfd5b
Show file tree
Hide file tree
Showing 18 changed files with 147 additions and 18 deletions.
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18"/>

Expand Down
1 change: 1 addition & 0 deletions app/src/main/assets/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ body {
* Moved to Firebase from fabric
* Navigating to ip setup if missing when uploading to Game Frame
* Changing the navigation bar color to the same color as the status bar on lollipop and later devices
* Warn the user when the wifi is off and option to enable

#### v1.1.2
##### 04 Nov 2017
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ import com.savvasdalkitsis.gameframe.feature.ip.repository.IpRepository
import com.savvasdalkitsis.gameframe.feature.navigation.Navigator
import com.savvasdalkitsis.gameframe.infra.rx.RxTransformers
import com.savvasdalkitsis.gameframe.base.BasePresenter
import com.savvasdalkitsis.gameframe.feature.wifi.model.WifiNotEnabledException
import com.savvasdalkitsis.gameframe.feature.wifi.usecase.WifiUseCase
import io.reactivex.Completable

class ControlPresenter(private val gameFrameUseCase: GameFrameUseCase,
private val ipRepository: IpRepository,
private val navigator: Navigator): BasePresenter<ControlView>() {
private val navigator: Navigator,
private val wifiUseCase: WifiUseCase): BasePresenter<ControlView>() {

fun loadIpAddress() = stream {
ipRepository.ipAddress
Expand Down Expand Up @@ -59,10 +62,19 @@ class ControlPresenter(private val gameFrameUseCase: GameFrameUseCase,
.compose(RxTransformers.schedulers())

private fun runCommandAndNotifyView(command: Completable) = stream {
runCommand(command).subscribe({ view?.operationSuccess() }, { e -> view?.operationFailure(e) })
runCommand(command).subscribe({ view?.operationSuccess() }, { e ->
when (e) {
is WifiNotEnabledException -> view?.wifiNotEnabledError(e)
else -> view?.operationFailure(e)
}
})
}

private fun runCommandAndIgnoreResult(command: Completable) = stream {
runCommand(command).subscribe({ }, { })
}

fun enableWifi() {
wifiUseCase.enableWifi()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class ControlFragment : BaseFragment<ControlView, ControlPresenter>(), ControlVi
override val presenter = PresenterInjector.controlPresenter()
override val view = this
private lateinit var fab: FloatingActionButton
private val coordinator: View get() = activity!!.findViewById(R.id.view_coordinator)

override val layoutId: Int
get() = R.layout.fragment_control
Expand Down Expand Up @@ -120,11 +121,18 @@ class ControlFragment : BaseFragment<ControlView, ControlPresenter>(), ControlVi
presenter.changeClockFace(ClockFace.from(position))
}

override fun operationSuccess() = Snackbars.success(activity!!.findViewById(R.id.view_coordinator), R.string.success)
override fun operationSuccess() = Snackbars.success(coordinator, R.string.success)

override fun operationFailure(e: Throwable) {
Log.e(ControlFragment::class.java.name, "Operation failure", e)
Snackbars.error(activity!!.findViewById(R.id.view_coordinator), R.string.operation_failed)
Snackbars.error(coordinator, R.string.operation_failed)
}

override fun wifiNotEnabledError(e: Throwable) {
Log.e(ControlFragment::class.java.name, "Operation failure", e)
Snackbars.actionError(coordinator, R.string.wifi_not_enabled, R.string.enable) {
presenter.enableWifi()
}
}

override fun ipAddressLoaded(ipAddress: IpAddress) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ interface ControlView: BaseView {
fun ipAddressLoaded(ipAddress: IpAddress)

fun ipCouldNotBeFound(throwable: Throwable)

fun wifiNotEnabledError(e: Throwable)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*
* 'Game Frame' is a registered trademark of LEDSEQ
*/
package com.savvasdalkitsis.gameframe.feature.gameframe.usecase
package com.savvasdalkitsis.gameframe.feature.gameframe.model

import com.savvasdalkitsis.gameframe.feature.gameframe.api.CommandResponse

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ import com.savvasdalkitsis.gameframe.feature.ip.model.IpAddress
import com.savvasdalkitsis.gameframe.feature.ip.model.IpNotFoundException
import com.savvasdalkitsis.gameframe.feature.ip.usecase.IpDiscoveryUseCase
import com.savvasdalkitsis.gameframe.feature.bmp.usecase.BmpUseCase
import com.savvasdalkitsis.gameframe.feature.gameframe.model.GameFrameCommandError
import com.savvasdalkitsis.gameframe.feature.ip.repository.IpRepository
import com.savvasdalkitsis.gameframe.feature.saves.usecase.FileUseCase
import com.savvasdalkitsis.gameframe.feature.wifi.model.WifiNotEnabledException
import com.savvasdalkitsis.gameframe.feature.wifi.usecase.WifiUseCase
import com.savvasdalkitsis.gameframe.feature.workspace.element.grid.model.Grid
import com.savvasdalkitsis.gameframe.injector.feature.ip.repository.IpRepositoryInjector
import io.reactivex.Completable
import io.reactivex.Flowable
import io.reactivex.Maybe
Expand All @@ -47,7 +49,8 @@ class GameFrameUseCase(private val okHttpClient: OkHttpClient,
private val ipDiscoveryUseCase: IpDiscoveryUseCase,
private val fileUseCase: FileUseCase,
private val bmpUseCase: BmpUseCase,
private val ipRepository: IpRepository) {
private val ipRepository: IpRepository,
private val wifiUseCase: WifiUseCase) {

fun togglePower() = issueCommand("power")

Expand Down Expand Up @@ -104,7 +107,13 @@ class GameFrameUseCase(private val okHttpClient: OkHttpClient,
private fun uploadFile(file: File): Completable {
val requestFile = RequestBody.create(MediaType.parse("image/bmp"), file)
val filePart = MultipartBody.Part.createFormData("my_file[]", "0.bmp", requestFile)
return gameFrameApi.upload(filePart).to(mapResponse())
return gameFrameApi.upload(filePart)
.to(mapResponse())
.onErrorResumeNext { error -> wifiUseCase.isWifiEnabled()
.flatMapCompletable { enabled ->
if (!enabled) Completable.error(WifiNotEnabledException())
else Completable.error(error)
} }
}

private fun play(name: String) = issueCommand("play", name)
Expand Down Expand Up @@ -141,11 +150,19 @@ class GameFrameUseCase(private val okHttpClient: OkHttpClient,
private fun issueCommand(key: String, value: String = ""): Completable =
ipRepository.ipAddress
.flatMapCompletable { gameFrameApi.command(param(key, value)).to(mapResponse()) }
.onErrorResumeNext(changeErrorToWifiIfNotEnabled())

private fun changeErrorToWifiIfNotEnabled(): (Throwable) -> Completable = { error ->
wifiUseCase.isWifiEnabled().flatMapCompletable { enabled ->
if (!enabled) Completable.error(WifiNotEnabledException())
else Completable.error(error)
}
}

private fun setParam(key: String): Completable = gameFrameApi.set(param(key))

private fun wrap(response: CommandResponse) =
GameFrameCommandError("Command was not successful. response: $response", response)

private fun isSuccess(response: CommandResponse?) = "success" == response?.status
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,21 @@ import com.savvasdalkitsis.gameframe.feature.ip.model.IpAddress
import com.savvasdalkitsis.gameframe.feature.ip.repository.IpRepository
import com.savvasdalkitsis.gameframe.feature.ip.usecase.IpDiscoveryUseCase
import com.savvasdalkitsis.gameframe.feature.ip.view.IpSetupView
import com.savvasdalkitsis.gameframe.feature.wifi.usecase.WifiUseCase
import com.savvasdalkitsis.gameframe.infra.rx.RxTransformers
import io.reactivex.disposables.CompositeDisposable

class IpSetupPresenter(private val gameFrameUseCase: GameFrameUseCase,
private val ipRepository: IpRepository,
private val ipDiscoveryUseCase: IpDiscoveryUseCase): BasePresenter<IpSetupView>() {
private val ipDiscoveryUseCase: IpDiscoveryUseCase,
private val wifiUseCase: WifiUseCase): BasePresenter<IpSetupView>() {

fun start() {
loadStoredIp()
stream {
wifiUseCase.isWifiEnabled()
.filter { !it }
.subscribe( { view?.displayWifiNotEnabled() } )
}
}

fun setup(ipAddress: IpAddress) {
Expand Down Expand Up @@ -74,4 +80,8 @@ class IpSetupPresenter(private val gameFrameUseCase: GameFrameUseCase,
)
}
}

fun enableWifi() {
wifiUseCase.enableWifi()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ class IpSetupActivity : BaseActivity<IpSetupView, IpSetupPresenter>(), IpSetupVi
presenter.start()
}

override fun displayWifiNotEnabled() {
Snackbars.actionError(findViewById(R.id.view_setup_content), R.string.wifi_not_enabled, R.string.enable) {
presenter.enableWifi()
}
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ interface IpSetupView: BaseView {
fun tryingAddress(ipAddress: IpAddress)

fun displayIdleView()

fun displayWifiNotEnabled()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright 2017 Savvas Dalkitsis
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 'Game Frame' is a registered trademark of LEDSEQ
*/
package com.savvasdalkitsis.gameframe.feature.wifi.model

class WifiNotEnabledException: Exception()
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright 2017 Savvas Dalkitsis
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 'Game Frame' is a registered trademark of LEDSEQ
*/
package com.savvasdalkitsis.gameframe.feature.wifi.usecase

import android.content.Context
import android.net.wifi.WifiManager
import io.reactivex.Single

class WifiUseCase(val context: Context) {

private val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager

fun isWifiEnabled(): Single<Boolean> = Single.just(wifiManager.isWifiEnabled)

fun enableWifi() = wifiManager.setWifiEnabled(true)
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ import com.savvasdalkitsis.gameframe.feature.gameframe.usecase.GameFrameUseCase
import com.savvasdalkitsis.gameframe.feature.history.model.MomentList
import com.savvasdalkitsis.gameframe.feature.history.usecase.HistoryUseCase
import com.savvasdalkitsis.gameframe.feature.ip.model.IpBaseHostMissingException
import com.savvasdalkitsis.gameframe.feature.ip.model.IpNotFoundException
import com.savvasdalkitsis.gameframe.feature.message.MessageDisplay
import com.savvasdalkitsis.gameframe.feature.navigation.Navigator
import com.savvasdalkitsis.gameframe.feature.wifi.model.WifiNotEnabledException
import com.savvasdalkitsis.gameframe.feature.wifi.usecase.WifiUseCase
import com.savvasdalkitsis.gameframe.feature.workspace.element.grid.model.Grid
import com.savvasdalkitsis.gameframe.feature.workspace.element.grid.model.GridDisplay
import com.savvasdalkitsis.gameframe.feature.workspace.element.grid.view.GridTouchedListener
Expand All @@ -52,7 +53,8 @@ class WorkspacePresenter<Options, in BitmapSource>(private val gameFrameUseCase:
private val stringUseCase: StringUseCase,
private val messageDisplay: MessageDisplay,
private val navigator: Navigator,
private val bitmapFileUseCase: BitmapFileUseCase<BitmapSource>) : GridTouchedListener, BasePresenter<WorkspaceView<Options>>() {
private val bitmapFileUseCase: BitmapFileUseCase<BitmapSource>,
private val wifiUseCase: WifiUseCase) : GridTouchedListener, BasePresenter<WorkspaceView<Options>>() {

private lateinit var gridDisplay: GridDisplay
private var tempName: String? = null
Expand Down Expand Up @@ -300,6 +302,7 @@ class WorkspacePresenter<Options, in BitmapSource>(private val gameFrameUseCase:
view?.operationFailed(e)
navigator.navigateToIpSetup()
}
is WifiNotEnabledException -> view?.wifiNotEnabledError(e)
else -> view?.operationFailed(e)
} })
}
Expand Down Expand Up @@ -339,4 +342,8 @@ class WorkspacePresenter<Options, in BitmapSource>(private val gameFrameUseCase:
view?.displaySelectedPalette(stringUseCase.getString(R.string.palette_name, present.selectedPalette.title))
view?.rendered()
}

fun enableWifi() {
wifiUseCase.enableWifi()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ class WorkspaceFragment : BaseFragment<WorkspaceView<Menu>, WorkspacePresenter<M
presenter.bindGrid(view_draw_led_grid_view)
}

override fun wifiNotEnabledError(e: Throwable) {
Snackbars.actionError(coordinator(), R.string.wifi_not_enabled, R.string.enable) {
presenter.enableWifi()
}
}

override fun onResume() {
super.onResume()
setFabState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ interface WorkspaceView<in O>: BaseView {
fun displaySelectedLayerName(layerName: String)
fun displaySelectedPalette(paletteName: String)
fun displayUnsupportedVersion()
fun wifiNotEnabledError(e: Throwable)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,22 @@ import com.savvasdalkitsis.gameframe.injector.usecase.UseCaseInjector.changeLogU
import com.savvasdalkitsis.gameframe.injector.usecase.UseCaseInjector.gameFrameUseCase
import com.savvasdalkitsis.gameframe.injector.usecase.UseCaseInjector.ipDiscoveryUseCase
import com.savvasdalkitsis.gameframe.injector.usecase.UseCaseInjector.stringUseCase
import com.savvasdalkitsis.gameframe.injector.usecase.UseCaseInjector.wifiUseCase
import com.savvasdalkitsis.gameframe.injector.usecase.UseCaseInjector.workspaceUseCase

object PresenterInjector {

fun ipSetupPresenter() =
IpSetupPresenter(gameFrameUseCase(), ipRepository(), ipDiscoveryUseCase())
IpSetupPresenter(gameFrameUseCase(), ipRepository(), ipDiscoveryUseCase(), wifiUseCase())

fun controlPresenter() = ControlPresenter(gameFrameUseCase(), ipRepository(), navigator())
fun controlPresenter() = ControlPresenter(gameFrameUseCase(), ipRepository(), navigator(), wifiUseCase())

fun widgetPresenter() =
WidgetPresenter(gameFrameUseCase(), ipRepository(), navigator())

fun workspacePresenter() = WorkspacePresenter<Menu, View>(gameFrameUseCase(),
blendUseCase(), workspaceUseCase(), stringUseCase(), messageDisplay(), navigator(), bitmapFileUseCase())
blendUseCase(), workspaceUseCase(), stringUseCase(), messageDisplay(), navigator(),
bitmapFileUseCase(), wifiUseCase())

fun homePresenter() = HomePresenter(changeLogUseCase())
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ import com.savvasdalkitsis.gameframe.feature.ip.usecase.IpDiscoveryUseCase
import com.savvasdalkitsis.gameframe.feature.bmp.usecase.BmpUseCase
import com.savvasdalkitsis.gameframe.feature.changelog.usecase.ChangeLogUseCase
import com.savvasdalkitsis.gameframe.feature.saves.usecase.FileUseCase
import com.savvasdalkitsis.gameframe.feature.wifi.usecase.WifiUseCase
import com.savvasdalkitsis.gameframe.feature.workspace.usecase.WorkspaceUseCase
import com.savvasdalkitsis.gameframe.infra.android.StringUseCase
import com.savvasdalkitsis.gameframe.injector.ApplicationInjector.application
import com.savvasdalkitsis.gameframe.injector.feature.gameframe.api.GameFrameApiInjector.gameFrameApi
import com.savvasdalkitsis.gameframe.injector.feature.ip.repository.IpRepositoryInjector
import com.savvasdalkitsis.gameframe.injector.feature.ip.repository.IpRepositoryInjector.ipRepository
import com.savvasdalkitsis.gameframe.injector.infra.android.AndroidInjector.wifiManager
import com.savvasdalkitsis.gameframe.injector.infra.network.OkHttpClientInjector.okHttpClient
Expand All @@ -45,7 +45,8 @@ object UseCaseInjector {
ipDiscoveryUseCase(),
fileUseCase(),
bmpUseCase(),
ipRepository()
ipRepository(),
wifiUseCase()
)

fun ipDiscoveryUseCase() = IP_DISCOVERY_USE_CASE
Expand All @@ -63,4 +64,6 @@ object UseCaseInjector {
fun bitmapFileUseCase() = AndroidViewBitmapFileUseCase(application())

fun changeLogUseCase() = ChangeLogUseCase(rxSharedPreferences())

fun wifiUseCase() = WifiUseCase(application())
}
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,6 @@
<string name="cancel">Cancel</string>
<string name="export_image">Export image</string>
<string name="changelog">Changelog</string>
<string name="wifi_not_enabled">Wifi is not enabled</string>
<string name="enable">Enable</string>
</resources>

0 comments on commit 4abfd5b

Please sign in to comment.