Packages and offers fixes, HMG Internet work in progress,

merge-requests/582/head
Zohaib Iqbal Kambrani 4 years ago
parent 0ae4a13c02
commit ab8b62bc3a

@ -1,22 +1,23 @@
package com.ejada.hmg.hmgwifi
import android.annotation.SuppressLint
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.net.wifi.WifiConfiguration
import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
import android.net.wifi.WifiNetworkSpecifier
import android.os.Build
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import com.ejada.hmg.MainActivity
import com.ejada.hmg.utils.FlutterText
import com.ejada.hmg.utils.HMGUtils
class HMG_Guest(context: MainActivity) {
class HMG_Guest(private var context: MainActivity) {
private var wifiManager: WifiManager? = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager?
private var connectivityManager: ConnectivityManager? = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
private var context = context
private val TAG = "HMG_Guest"
private val TEST = false
@ -40,114 +41,69 @@ class HMG_Guest(context: MainActivity) {
wm.isWifiEnabled = true
HMGUtils.popFlutterText(context,"enablingWifi");
HMGUtils.timer(2000,false){
connect()
connectWifi()
}
}else{
connect()
connectWifi()
}
}
}
private fun errorConnecting(){
completionOnUiThread(false, "errorConnectingHmgNetwork")
}
private fun connect(){
val security = "OPEN"
val networkPass = ""
Log.d(TAG, "Connecting to SSID \"$SSID\" with password \"$networkPass\" and with security \"$security\" ...")
// You need to create WifiConfiguration instance like this:
val conf = WifiConfiguration()
conf.SSID = SSID
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
conf.networkId = ssidToNetworkId(SSID)
val wm = wifiManager!!
if (conf.networkId == -1) {
wm.addNetwork(conf)
} else {
Log.v(TAG, "WiFi found - updating it.\n")
wm.updateNetwork(conf)
fun connectWifi(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
wifiManager?.let { connectApiGreaterThen28(it) }
}else {
connectApiLessThen29()
}
}
conf.networkId = ssidToNetworkId(SSID)
Log.d(TAG, "Network ID: ${conf.networkId}")
val networkIdToConnect = conf.networkId
if (networkIdToConnect >= 0) {
Log.v(TAG, "Start connecting to $SSID Wifi...")
// We disable the network before connecting, because if this was the last connection before
// a disconnect(), this will not reconnect.
wm.disableNetwork(networkIdToConnect)
val result = wm.enableNetwork(networkIdToConnect, true)
if(result){
HMGUtils.timer(8000,false){
if(wm.getConnectionInfo().getSSID() == SSID){
completionOnUiThread(true, "successConnectingHmgNetwork")
}else{
errorConnecting()
}
}
// I }else{f CompileSDK is greater and equals to APILevel 29
@RequiresApi(Build.VERSION_CODES.Q)
private fun connectApiGreaterThen28(wm:WifiManager){
Log.e(TAG, "connection wifi with Android Q+")
val wifiNetworkSpecifier: WifiNetworkSpecifier = WifiNetworkSpecifier.Builder()
// .setWpa2Passphrase(password)
.build()
val networkRequest: NetworkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(wifiNetworkSpecifier)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) //removeCapability added for hotspots without internet
.build()
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
connectivityManager.bindProcessToNetwork(network)
Log.e(TAG, "onAvailable")
}
}else{
errorConnecting()
override fun onLosing(network: Network, maxMsToLive: Int) {
super.onLosing(network, maxMsToLive)
Log.e(TAG, "onLosing")
}
override fun onLost(network: Network) {
super.onLost(network)
Log.e(TAG, "onLosing")
Log.e(TAG, "losing active connection")
}
override fun onUnavailable() {
super.onUnavailable()
Log.e(TAG, "onUnavailable")
}
}else{
Log.v(TAG, "Cannot connect to $SSID network")
errorConnecting()
}
}
private fun errorConnecting(){
completionOnUiThread(false, "errorConnectingHmgNetwork")
}
// If CompileSDK is greater and equals to APILevel 29
private fun connectNewer(wm:WifiManager){
// Log.e(TAG, "connection wifi Q")
//
// val wifiNetworkSpecifier: WifiNetworkSpecifier = WifiNetworkSpecifier.Builder()
// .setSsid(ssid)
// .setWpa2Passphrase(password)
// .build()
//
// val networkRequest: NetworkRequest = NetworkRequest.Builder()
// .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
// .setNetworkSpecifier(wifiNetworkSpecifier)
// .build()
//
// var connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
// var networkCallback = object : ConnectivityManager.NetworkCallback() {
// override fun onAvailable(network: Network) {
// super.onAvailable(network)
// connectivityManager.bindProcessToNetwork(network)
// Log.e(TAG, "onAvailable")
// }
//
// override fun onLosing(network: Network, maxMsToLive: Int) {
// super.onLosing(network, maxMsToLive)
// Log.e(TAG, "onLosing")
// }
//
// override fun onLost(network: Network) {
// super.onLost(network)
// Log.e(TAG, "onLosing")
// Log.e(TAG, "losing active connection")
// }
//
// override fun onUnavailable() {
// super.onUnavailable()
// Log.e(TAG, "onUnavailable")
// }
// }
// connectivityManager.requestNetwork(networkRequest, networkCallback)
//timeout add because "No devices found" wasn't handled correct and doesn't throw Unavailable
connectivityManager.requestNetwork(networkRequest, networkCallback, 30000)
}
@ -156,6 +112,7 @@ class HMG_Guest(context: MainActivity) {
* networks, and returns the networkId for the network if the SSID matches. If not,
* it returns -1.
*/
@SuppressLint("MissingPermission")
private fun ssidToNetworkId(ssid: String): Int {
val currentNetworks = wifiManager!!.configuredNetworks
var networkId = -1
@ -169,4 +126,130 @@ class HMG_Guest(context: MainActivity) {
}
return networkId
}
}
fun connectApiLessThen29(){
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q){
// Initialize the WifiConfiguration object
val security = "OPEN"
val networkPass = ""
Log.d(TAG, "Connecting to SSID \"$SSID\" with password \"$networkPass\" and with security \"$security\" ...")
// You need to create WifiConfiguration instance like this:
val conf = WifiConfiguration()
conf.SSID = SSID
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
conf.networkId = ssidToNetworkId(SSID)
val wm = wifiManager!!
if (conf.networkId == -1) {
wm.addNetwork(conf)
} else {
Log.v(TAG, "WiFi found - updating it.\n")
wm.updateNetwork(conf)
}
conf.networkId = ssidToNetworkId(SSID)
Log.d(TAG, "Network ID: ${conf.networkId}")
val networkIdToConnect = conf.networkId
if (networkIdToConnect >= 0) {
Log.v(TAG, "Start connecting to $SSID Wifi...")
// We disable the network before connecting, because if this was the last connection before
// a disconnect(), this will not reconnect.
wm.disableNetwork(networkIdToConnect)
val result = wm.enableNetwork(networkIdToConnect, true)
if(result){
HMGUtils.timer(8000,false){
if(wm.getConnectionInfo().getSSID() == SSID){
completionOnUiThread(true, "successConnectingHmgNetwork")
}else{
errorConnecting()
}
}
}else{
errorConnecting()
}
}else{
Log.v(TAG, "Cannot connect to $SSID network")
errorConnecting()
}
}
/*val wifi = WifiConfiguration();
wifi.hiddenSSID = this.hiddenSSID;
wifi.SSID = newSSID;
wifi.preSharedKey = newPass;
wifi.status = WifiConfiguration.Status.ENABLED;
wifi.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wifi.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
wifi.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wifi.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wifi.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wifi.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wifi.networkId = ssidToNetworkId(newSSID);
// Set network to highest priority (deprecated in API >= 26)
if(Build.VERSION.SDK_INT < 26) {
wifi.priority = getMaxWifiPriority(wifiManager) + 1;
}
// After processing authentication types, add or update network
if(wifi.networkId == -1) { // -1 means SSID configuration does not exist yet
int newNetId = wifiManager.addNetwork(wifi);
if( newNetId > -1 ){
callbackContext.success( newNetId );
} else {
callbackContext.error( "ERROR_ADDING_NETWORK" );
}
} else {
int updatedNetID = wifiManager.updateNetwork(wifi);
if(updatedNetID == -1)
updatedNetID = wifiManager.addNetwork(wifi);
if(updatedNetID > -1) {
callbackContext.success( updatedNetID );
} else {
callbackContext.error("ERROR_UPDATING_NETWORK");
}
}
// WifiManager configurations are presistent for API 26+
if(API_VERSION < 26) {
wifiManager.saveConfiguration(); // Call saveConfiguration for older < 26 API
}*/
}
companion object{
/**
* Figure out what the highest priority network in the network list is and return that priority
*/
@RequiresApi(Build.VERSION_CODES.S)
fun getMaxWifiPriority(wifiManager:WifiManager) : Int {
val configurations = wifiManager.callerConfiguredNetworks
var maxPriority = 0
configurations.forEach {
if (it.priority > maxPriority) {
maxPriority = it.priority;
}
}
return maxPriority;
}
}
}

@ -3,7 +3,6 @@ package com.ejada.hmg.hmgwifi
import android.annotation.SuppressLint
import com.ejada.hmg.utils.API
import com.ejada.hmg.MainActivity
import com.ejada.hmg.utils.FlutterText
import com.github.kittinunf.fuel.core.extensions.jsonBody
import com.github.kittinunf.fuel.httpGet
import com.github.kittinunf.fuel.httpPost
@ -14,7 +13,7 @@ import java.util.*
@SuppressLint("MissingPermission")
class HMG_Internet(flutterMainActivity: MainActivity) {
private val TAG = "HMG_Wifi"
private val TEST = false
private val TEST = true
private var context = flutterMainActivity;
@ -41,7 +40,7 @@ class HMG_Internet(flutterMainActivity: MainActivity) {
fun connectToHMGGuestNetwork(patientId: String, completion: (status: Boolean, message: String) -> Unit): HMG_Internet {
completionListener = completion
getWifiCredentials(patientId) {
WPA(context,SSID).connect(USER_NAME,PASSWORD) { status, message ->
WpaEnterprise(context,SSID).connect(USER_NAME,PASSWORD) { status, message ->
completionOnUiThread(status,message)
}
}

@ -0,0 +1,160 @@
package com.ejada.hmg.hmgwifi
import android.annotation.SuppressLint
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.net.wifi.*
import android.net.wifi.SupplicantState.ASSOCIATED
import android.net.wifi.SupplicantState.COMPLETED
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.ejada.hmg.MainActivity
import com.ejada.hmg.utils.HMGUtils
class WpaEnterprise(private val mainActivity: MainActivity, private var SSID: String) {
private var TAG = "WpaEnterprise"
private lateinit var identity:String
private lateinit var password:String
private lateinit var completion:((status: Boolean, message: String) -> Unit)
fun connect(identity:String, password:String, completion: (status: Boolean, message: String) -> Unit) {
this.password = password
this.identity = identity
this.completion = completion
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
apiGreaterThen28()
}else if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q){
apiLessThen29()
}
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
fun apiLessThen29(){
val wifiManager = mainActivity.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifi = WifiConfiguration()
wifi.SSID = """"$SSID""""
wifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP)
wifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X)
wifi.enterpriseConfig = enterpriseConfig()
wifi.networkId = ssidToNetworkId(wifi.SSID, wifiManager)
if (wifi.networkId == -1) {
wifiManager.addNetwork(wifi)
} else {
Log.v(TAG, "WiFi found - updating it.\n")
wifiManager.updateNetwork(wifi)
}
Log.v(TAG, "saving config.\n")
wifiManager.saveConfiguration()
wifi.networkId = ssidToNetworkId(wifi.SSID, wifiManager)
Log.v(TAG, "wifi ID in device = " + wifi.networkId)
var supState: SupplicantState
val networkIdToConnect = wifi.networkId
if (networkIdToConnect >= 0) {
Log.v(TAG, "Start connecting...\n")
// We disable the network before connecting, because if this was the last connection before
// a disconnect(), this will not reconnect.
wifiManager.disableNetwork(networkIdToConnect)
wifiManager.enableNetwork(networkIdToConnect, true)
val wifiInfo: WifiInfo = wifiManager.connectionInfo
HMGUtils.timer(5000,false){
supState = wifiInfo.supplicantState
Log.i(TAG, "Done connect to network : status = $supState")
val successStates = listOf(COMPLETED, ASSOCIATED)
if (successStates.contains(supState))
completion(true,"Connected to internet Wifi")
else
completion(false,"errorConnectingHmgNetwork")
}
} else {
Log.v(TAG, "WifiWizard: cannot connect to network")
completion(false,"errorConnectingHmgNetwork")
}
}
/**
* This method takes a given String, searches the current list of configured WiFi
* networks, and returns the networkId for the network if the SSID matches. If not,
* it returns -1.
*/
@SuppressLint("MissingPermission")
private fun ssidToNetworkId(ssid: String, wifiManager: WifiManager): Int {
val currentNetworks = wifiManager.configuredNetworks
var networkId = -1
// For each network in the list, compare the SSID with the given one
for (test in currentNetworks) {
if (test.SSID == ssid) {
networkId = test.networkId
break
}
}
return networkId
}
@RequiresApi(Build.VERSION_CODES.Q)
fun apiGreaterThen28(){
val connectivityManager = mainActivity.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
Log.e(TAG, "connection wifi with Android Q+")
val wifiNetworkSpecifier: WifiNetworkSpecifier = WifiNetworkSpecifier.Builder()
.setWpa2EnterpriseConfig(enterpriseConfig())
.build()
val networkRequest: NetworkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(wifiNetworkSpecifier)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) //removeCapability added for hotspots without internet
.build()
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
connectivityManager.bindProcessToNetwork(network)
Log.e(TAG, "onAvailable")
}
override fun onLosing(network: Network, maxMsToLive: Int) {
super.onLosing(network, maxMsToLive)
Log.e(TAG, "onLosing")
}
override fun onLost(network: Network) {
super.onLost(network)
Log.e(TAG, "onLosing")
Log.e(TAG, "losing active connection")
}
override fun onUnavailable() {
super.onUnavailable()
Log.e(TAG, "onUnavailable")
}
}
//timeout add because "No devices found" wasn't handled correct and doesn't throw Unavailable
connectivityManager.requestNetwork(networkRequest, networkCallback, 30000)
}
fun enterpriseConfig() : WifiEnterpriseConfig{
// Initialize the WifiConfiguration object
val enterpriseConfig = WifiEnterpriseConfig()
enterpriseConfig.eapMethod = WifiEnterpriseConfig.Eap.PEAP
enterpriseConfig.identity = identity
enterpriseConfig.password = password
return enterpriseConfig;
}
}

@ -1,3 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="61.183" height="61.227" viewBox="0 0 61.183 61.227">
<path id="Path_4645" data-name="Path 4645" d="M240.521,51.17s2.141-.016,3.648-.016l11.428.056c1.364,0,2.5-1.45,2.564-3.545l.013-9.549c0-2.036.91-3.629,2.321-3.72L264,34.368c1.413.087,2.383,1.7,2.383,3.723l-.009,9.6c.062,2.094,1.014,3.461,2.385,3.461l15.384.042.028-11.8c0-2.03-.976-3.607-2.4-3.7l-6.18-.031c-1.367,0-2.442-1.443-2.5-3.54l-.024-3.192c.068-2.094,1.149-3.534,2.519-3.534l6.214.018c1.412-.091,2.332-1.758,2.332-3.785L284.147,6.9a6.275,6.275,0,0,1-4.76,2.976l-10.45-.009c-1.361,0-2.5,1.484-2.564,3.578v9.459c-.064,2.09-1.133,3.569-2.5,3.569l-3.162-.024c-1.371,0-2.467-1.431-2.529-3.515l.008-9.563c-.062-2.095-1.148-3.5-2.516-3.5l-15.165.007,0,11.764c0,2.032.949,3.659,2.365,3.753l6.214-.026c1.405.092,2.4,1.768,2.4,3.789l-.019,2.723c0,2.031-.96,3.656-2.372,3.748l-6.224-.015c-1.416.1-2.365,1.7-2.365,3.731Zm52.241-45.1v49.2a6.256,6.256,0,0,1-6.325,5.951H237.873a6.231,6.231,0,0,1-6.294-5.958l0-49.295A6.253,6.253,0,0,1,237.883,0L286.4.021a6.371,6.371,0,0,1,6.36,6.053" transform="translate(-231.579)" fill="#ec1c2b"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -14,7 +14,6 @@
306FE6CB271D8B73002D6EFC /* OpenTok.swift in Sources */ = {isa = PBXBuildFile; fileRef = 306FE6CA271D8B73002D6EFC /* OpenTok.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
813F9CBA7DD5ED63B28B8BB6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 767C165F7ABF3BF1F829B9BF /* Pods_Runner.framework */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@ -36,6 +35,7 @@
E9C8C136256BACDA00EFFB62 /* HMG_Guest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C8C135256BACDA00EFFB62 /* HMG_Guest.swift */; };
E9E27168256E3A4000F49B69 /* LocalizedFromFlutter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E27167256E3A4000F49B69 /* LocalizedFromFlutter.swift */; };
E9F7623B25922BCE00FB5CCF /* FlutterConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9F7623A25922BCE00FB5CCF /* FlutterConstants.swift */; };
FA0839686861F9C0546E6F45 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C703B0BB1CDBBCA30693DBD3 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -58,13 +58,12 @@
301C79AF27200DED0016307B /* OpenTokLocalVideoFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTokLocalVideoFactory.swift; sourceTree = "<group>"; };
306FE6C7271D790C002D6EFC /* OpenTokPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTokPlatformBridge.swift; sourceTree = "<group>"; };
306FE6CA271D8B73002D6EFC /* OpenTok.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTok.swift; sourceTree = "<group>"; };
308FEC658188F7D588BE7580 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
44DB2098C8C4B08C2F3B1329 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
767C165F7ABF3BF1F829B9BF /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
969F0CEC868FD7C196987A3E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
84A70B284E0DDF62ECE83D3B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -72,7 +71,8 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
DCFFD369041FFFFA94CF7B26 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
9C2760F1A81999922ACAA9E6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
C703B0BB1CDBBCA30693DBD3 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E91B538D256AAA6500E96549 /* GlobalHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlobalHelper.swift; sourceTree = "<group>"; };
E91B538E256AAA6500E96549 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
E91B538F256AAA6500E96549 /* API.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = API.swift; sourceTree = "<group>"; };
@ -99,8 +99,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
813F9CBA7DD5ED63B28B8BB6 /* Pods_Runner.framework in Frameworks */,
E9620805255C2ED100D3A35D /* NetworkExtension.framework in Frameworks */,
FA0839686861F9C0546E6F45 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -121,7 +121,7 @@
isa = PBXGroup;
children = (
E9620804255C2ED100D3A35D /* NetworkExtension.framework */,
767C165F7ABF3BF1F829B9BF /* Pods_Runner.framework */,
C703B0BB1CDBBCA30693DBD3 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -129,9 +129,9 @@
605039E5DDF72C245F9765FE /* Pods */ = {
isa = PBXGroup;
children = (
DCFFD369041FFFFA94CF7B26 /* Pods-Runner.debug.xcconfig */,
969F0CEC868FD7C196987A3E /* Pods-Runner.release.xcconfig */,
308FEC658188F7D588BE7580 /* Pods-Runner.profile.xcconfig */,
44DB2098C8C4B08C2F3B1329 /* Pods-Runner.debug.xcconfig */,
9C2760F1A81999922ACAA9E6 /* Pods-Runner.release.xcconfig */,
84A70B284E0DDF62ECE83D3B /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@ -232,15 +232,15 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
299B8FE131E5BAE7FA7E2FC9 /* [CP] Check Pods Manifest.lock */,
D74B98D9E413413D50043E1B /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
EFDAD5E1235DCA1DB6187148 /* [CP] Embed Pods Frameworks */,
29B24CD65FDFD6111DD04897 /* [CP] Copy Pods Resources */,
796644D4DF82E4D5FBECBF3B /* [CP] Embed Pods Frameworks */,
0EF99525B5E50490BA0DF0A4 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -257,7 +257,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@ -304,29 +304,7 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
299B8FE131E5BAE7FA7E2FC9 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
29B24CD65FDFD6111DD04897 /* [CP] Copy Pods Resources */ = {
0EF99525B5E50490BA0DF0A4 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -357,6 +335,23 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
796644D4DF82E4D5FBECBF3B /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -371,21 +366,26 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
EFDAD5E1235DCA1DB6187148 /* [CP] Embed Pods Frameworks */ = {
D74B98D9E413413D50043E1B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
@ -520,6 +520,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -659,6 +660,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -692,6 +694,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

@ -20,6 +20,12 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>comgooglemaps</string>
<string>baidumap</string>
<string>iosamap</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MinimumOSVersion</key>
@ -94,13 +100,5 @@
<false/>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>comgooglemaps</string>
<string>baidumap</string>
<string>iosamap</string>
</array>
</dict>
</plist>

@ -14,6 +14,7 @@ const PACKAGES_PRODUCTS = '/api/products';
const PACKAGES_CUSTOMER = '/api/customers';
const PACKAGES_SHOPPING_CART = '/api/shopping_cart_items';
const PACKAGES_ORDERS = '/api/orders';
const PACKAGES_ORDER_HISTORY = '/api/orders/items';
const PACKAGES_TAMARA_OPT = '/api/orders/paymentoptions/tamara';
const BASE_URL = 'https://uat.hmgwebservices.com/';
// const BASE_URL = 'https://hmgwebservices.com/';

@ -517,7 +517,8 @@ class BaseAppClient {
}
simpleGet(String fullUrl,
{Function(dynamic response, int statusCode) onSuccess, Function(String error, int statusCode) onFailure, Map<String, String> queryParams, Map<String, String> headers}) async {
{Function(dynamic response, int statusCode) onSuccess, Function(String error, int statusCode) onFailure, Map<String, dynamic> queryParams, Map<String, String> headers}) async {
headers = headers ?? {};
String url = fullUrl;
var haveParams = (queryParams != null);

@ -24,14 +24,15 @@ Map<String, String> packagesAuthHeader = {};
class OffersAndPackagesServices extends BaseService {
AuthenticatedUser patientUser;
List<PackagesCategoriesResponseModel> categoryList = List();
List<PackagesResponseModel> productList = List();
List<PackagesResponseModel> latestOffersList = List();
List<TamaraPaymentOption> tamaraPaymentOptions = List();
List<PackagesResponseModel> bestSellerList = List();
List<PackagesResponseModel> bannersList = List();
List<PackagesCartItemsResponseModel> cartItemList = List();
List<HospitalsModel> _hospitals = List();
List<PackagesCategoriesResponseModel> categoryList = [];
List<PackagesResponseModel> productList = [];
List<PackagesResponseModel> latestOffersList = [];
List<TamaraPaymentOption> tamaraPaymentOptions = [];
List<PackagesResponseModel> bestSellerList = [];
List<PackagesResponseModel> bannersList = [];
List<PackagesResponseModel> ordersHistory = [];
List<PackagesCartItemsResponseModel> cartItemList = [];
List<HospitalsModel> _hospitals = [];
List<HospitalsModel> get hospitals => _hospitals;
String cartItemCount = "";
@ -58,7 +59,7 @@ class OffersAndPackagesServices extends BaseService {
request.sinceId = (productList.isNotEmpty) ? productList.last.id : 0;
productList = List();
productList = [];
var url = EXA_CART_API_BASE_URL + PACKAGES_PRODUCTS;
await baseAppClient.simpleGet(url, headers: packagesAuthHeader, onSuccess: (dynamic stringResponse, int statusCode) {
if (statusCode == 200) {
@ -349,6 +350,40 @@ class OffersAndPackagesServices extends BaseService {
return errorThrow ?? order_id;
}
// --------------------
// Order History
// --------------------
Future<List<PackagesResponseModel>> orderHistory({@required BuildContext context, bool showLoading = true}) async {
// if(ordersHistory.isNotEmpty)
// return ordersHistory;
Future errorThrow;
// https://mdlaboratories.com/offersdiscounts/api/orders/items/0535256053?fields=id,product,utilize_by_vida,valid_until_date_utc,order_id&page=1&limit=100
Map<String, dynamic> queryParams ={};
queryParams['fields'] = 'id,product,utilize_by_vida,valid_until_date_utc,order_id';
queryParams['page'] = "1";
queryParams['limit'] = "100";
print(queryParams);
_showLoading(context, showLoading);
var url = EXA_CART_API_BASE_URL + PACKAGES_ORDER_HISTORY + "/${user.mobileNumber}";
await baseAppClient.simpleGet(url, headers: packagesAuthHeader, queryParams: queryParams, onSuccess: (dynamic stringResponse, int statusCode) {
_hideLoading(context, showLoading);
var jsonResponse = json.decode(stringResponse);
final order_items = jsonResponse["order_items"] as List;
ordersHistory = order_items.map((e) => PackagesResponseModel().fromJson(e['product'])).toList();
print(ordersHistory);
}, onFailure: (String error, int statusCode) {
_hideLoading(context, showLoading);
log(error);
errorThrow = Future.error(error);
});
return errorThrow ?? ordersHistory;
}
Future<ResponseModel<PackagesOrderResponseModel>> getOrderById(int id, {@required BuildContext context, bool showLoading = true}) async {
Future errorThrow;
ResponseModel<PackagesOrderResponseModel> response;

@ -16,6 +16,7 @@ import 'package:diplomaticquarterapp/pages/landing/widgets/services_view.dart';
import 'package:diplomaticquarterapp/pages/landing/widgets/slider_view.dart';
import 'package:diplomaticquarterapp/pages/medical/medical_profile_page_new.dart';
import 'package:diplomaticquarterapp/pages/packages_offers/OfferAndPackagesPage.dart';
import 'package:diplomaticquarterapp/pages/packages_offers/packages_offers_tab_pager.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
@ -284,7 +285,7 @@ class _HomePageFragment2State extends State<HomePageFragment2> {
child: InkWell(
onTap: () {
AuthenticatedUser user = projectViewModel.user;
Navigator.of(context).push(MaterialPageRoute(builder: (context) => PackagesHomePage(user)));
Navigator.of(context).push(MaterialPageRoute(builder: (context) => PackagesOfferTabPage(user)));
},
child: Container(
width: double.infinity,

@ -13,6 +13,7 @@ import 'package:diplomaticquarterapp/pages/ErService/ErOptions.dart';
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
import 'package:diplomaticquarterapp/pages/livecare/livecare_home.dart';
import 'package:diplomaticquarterapp/pages/packages_offers/OfferAndPackagesPage.dart';
import 'package:diplomaticquarterapp/pages/packages_offers/packages_offers_tab_pager.dart';
import 'package:diplomaticquarterapp/pages/paymentService/payment_service.dart';
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
@ -420,7 +421,7 @@ class _HomePageState extends State<HomePage> {
padding: const EdgeInsets.only(bottom: 15, right: 15, left: 15),
child: InkWell(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => PackagesHomePage(projectViewModel.user)));
Navigator.of(context).push(MaterialPageRoute(builder: (context) => PackagesOfferTabPage(projectViewModel.user)));
},
child: Container(
decoration: BoxDecoration(

@ -21,7 +21,9 @@ import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'
import 'package:diplomaticquarterapp/services/family_files/family_files_provider.dart' as family;
import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/HMGNetworkConnectivity.dart';
import 'package:diplomaticquarterapp/uitl/LocalNotification.dart';
import 'package:diplomaticquarterapp/uitl/PlatformBridge.dart';
import 'package:diplomaticquarterapp/uitl/SignalRUtil.dart';
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
@ -232,10 +234,10 @@ class _LandingPageState extends State<LandingPage> with WidgetsBindingObserver {
});
// HMG (Guest/Internet) Wifi Access [Zohaib Kambrani]
//for now commented to reduce this call will enable it when needed
// HMGNetworkConnectivity(context, () {
// GifLoaderDialogUtils.showMyDialog(context);
// PlatformBridge().connectHMGGuestWifi().then((value) => {GifLoaderDialogUtils.hideDialog(context)});
// }).checkAndConnectIfNoInternet();
HMGNetworkConnectivity(context, () {
GifLoaderDialogUtils.showMyDialog(context);
PlatformBridge.shared().connectHMGGuestWifi().then((value) => {GifLoaderDialogUtils.hideDialog(context)});
}).checkAndConnectIfNoInternet();
requestPermissions().then((results) {
locationUtils.getCurrentLocation();

@ -15,8 +15,9 @@ import 'package:rating_bar/rating_bar.dart';
class OfferAndPackagesDetail extends StatefulWidget {
final PackagesResponseModel itemModel;
final Function(PackagesResponseModel product) onCartClick;
bool showAddToCartFooter = true;
const OfferAndPackagesDetail({@required this.itemModel, @required this.onCartClick, Key key}) : super(key: key);
OfferAndPackagesDetail({@required this.itemModel, @required this.onCartClick, Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => OfferAndPackagesDetailState();
@ -30,6 +31,11 @@ class OfferAndPackagesDetailState extends State<OfferAndPackagesDetail> {
@override
Widget build(BuildContext context) {
final images = widget.itemModel.images ?? [];
String image = "";
if(images.isNotEmpty)
image = widget.itemModel.images.first.src ?? "";
return BaseView<PackagesViewModel>(
onModelReady: (model) {
viewModel = model;
@ -58,7 +64,11 @@ class OfferAndPackagesDetailState extends State<OfferAndPackagesDetail> {
aspectRatio: 333 / 333,
child: ClipRRect(
borderRadius: BorderRadius.circular(15.0),
child: Image.network("https://mdlaboratories.com/offersdiscounts/images/thumbs/0000162_dermatology-testing.jpeg", fit: BoxFit.fill),
child: Image.network(
image,
fit: BoxFit.fill,
errorBuilder: (a1,a2,a3) => Container(color: Colors.grey.withOpacity(0.25),),
),
),
),
),
@ -181,7 +191,8 @@ class OfferAndPackagesDetailState extends State<OfferAndPackagesDetail> {
],
),
),
Row(
if(widget.showAddToCartFooter && widget.onCartClick != null)
Row(
children: [
Expanded(
child: Column(

@ -14,9 +14,11 @@ import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/h2o/h20_setting
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
import 'package:diplomaticquarterapp/pages/packages_offers/ClinicOfferAndPackagesPage.dart';
import 'package:diplomaticquarterapp/pages/packages_offers/OfferAndPackagesCartPage.dart';
import 'package:diplomaticquarterapp/pages/packages_offers/packages_orders_history.dart';
import 'package:diplomaticquarterapp/routes.dart';
import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart' as auth;
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:diplomaticquarterapp/uitl/navigation_service.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart' as utils;
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
@ -84,7 +86,6 @@ class _PackagesHomePageState extends State<PackagesHomePage> {
}
}
AppScaffold appScaffold;
PackagesCategoriesResponseModel selectedClinic;
@override
@ -94,87 +95,74 @@ class _PackagesHomePageState extends State<PackagesHomePage> {
allowAny: true,
onModelReady: (model) => viewModel = model,
builder: (_, model, wi) {
return appScaffold = AppScaffold(
description: TranslationBase.of(context).offerAndPackagesDetails,
imagesInfo: [ImagesInfo(imageAr: 'https://hmgwebservices.com/Images/MobileApp/CMC/ar/0.png', imageEn: 'https://hmgwebservices.com/Images/MobileApp/CMC/en/0.png')],
appBarTitle: TranslationBase.of(context).offerAndPackages,
isShowAppBar: true,
isPharmacy: false,
backgroundColor: Color(0xfff7f7f7),
showPharmacyCart: false,
isOfferPackages: true,
showOfferPackagesCart: false,
isShowDecPage: false,
showNewAppBar: true,
showNewAppBarTitle: true,
body: Column(
children: [
Expanded(
child: ListView(
padding: EdgeInsets.only(top: 21, bottom: 21),
physics: BouncingScrollPhysics(),
children: [
inputWidget(TranslationBase.of(context).search, "", _searchTextController, isInputTypeNum: false),
SizedBox(height: 12),
Padding(
padding: const EdgeInsets.only(left: 21, right: 21),
child: CommonDropDownView(TranslationBase.of(context).browseOffers, selectedClinic?.name ?? TranslationBase.of(context).selectClinic, () => showClinicSelectionList())
.withBorderedContainer,
),
SizedBox(height: 12),
Container(
width: double.infinity,
height: MediaQuery.of(context).size.width * 0.8,
child: ListView.separated(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: BouncingScrollPhysics(),
padding: EdgeInsets.only(left: 21, right: 21),
itemCount: viewModel.bestSellerList.length,
separatorBuilder: (context, index) {
return mWidth(9.0);
},
itemBuilder: (BuildContext context, int index) {
return PackagesItemCard(
itemModel: viewModel.bestSellerList[index],
onCartClick: onProductCartClick,
);
},
),
return Column(
children: [
Expanded(
child: ListView(
padding: EdgeInsets.only(top: 21, bottom: 21),
physics: BouncingScrollPhysics(),
children: [
inputWidget(TranslationBase.of(context).search, "", _searchTextController, isInputTypeNum: false),
SizedBox(height: 12),
Padding(
padding: const EdgeInsets.only(left: 21, right: 21),
child: CommonDropDownView(TranslationBase.of(context).browseOffers, selectedClinic?.name ?? TranslationBase.of(context).selectClinic, () => showClinicSelectionList())
.withBorderedContainer,
),
SizedBox(height: 12),
Container(
width: double.infinity,
height: MediaQuery.of(context).size.width * 0.8,
child: ListView.separated(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: BouncingScrollPhysics(),
padding: EdgeInsets.only(left: 21, right: 21),
itemCount: viewModel.bestSellerList.length,
separatorBuilder: (context, index) {
return mWidth(9.0);
},
itemBuilder: (BuildContext context, int index) {
return PackagesItemCard(
itemModel: viewModel.bestSellerList[index],
onCartClick: onProductCartClick,
);
},
),
SizedBox(height: 12),
Container(
width: double.infinity,
height: MediaQuery.of(context).size.width * 0.8,
child: ListView.separated(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: BouncingScrollPhysics(),
padding: EdgeInsets.only(left: 21, right: 21),
itemCount: viewModel.latestOffersList.length,
separatorBuilder: (context, index) {
return mWidth(9.0);
},
itemBuilder: (BuildContext context, int index) {
return PackagesItemCard(
itemModel: viewModel.latestOffersList[index],
onCartClick: onProductCartClick,
);
},
),
),
SizedBox(height: 12),
Container(
width: double.infinity,
height: MediaQuery.of(context).size.width * 0.8,
child: ListView.separated(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: BouncingScrollPhysics(),
padding: EdgeInsets.only(left: 21, right: 21),
itemCount: viewModel.latestOffersList.length,
separatorBuilder: (context, index) {
return mWidth(9.0);
},
itemBuilder: (BuildContext context, int index) {
return PackagesItemCard(
itemModel: viewModel.latestOffersList[index],
onCartClick: onProductCartClick,
);
},
),
],
),
),
],
),
DefaultButton(
TranslationBase.of(context).myCart,
onCartClick,
svgIcon: "assets/images/new/cart.svg",
isTextExpanded: false,
count: viewModel?.service?.customer?.shoppingCartItems?.length ?? 0,
).insideContainer
],
),
),
DefaultButton(
TranslationBase.of(context).myCart,
onCartClick,
svgIcon: "assets/images/new/cart.svg",
isTextExpanded: false,
count: viewModel?.service?.customer?.shoppingCartItems?.length ?? 0,
).insideContainer
],
);
},
);

@ -0,0 +1,86 @@
import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart';
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
import 'package:diplomaticquarterapp/pages/packages_offers/OfferAndPackagesPage.dart';
import 'package:diplomaticquarterapp/pages/packages_offers/packages_orders_history.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class PackagesOfferTabPage extends StatefulWidget{
AuthenticatedUser user;
PackagesOfferTabPage(this.user);
@override
State<StatefulWidget> createState() => PackagesOfferTabPageState();
}
class PackagesOfferTabPageState extends State<PackagesOfferTabPage> with SingleTickerProviderStateMixin{
TabController _tabController;
ProjectViewModel _projectViewModel;
@override
void initState() {
_tabController = TabController(length: 2, vsync: this);
super.initState();
}
@override
Widget build(BuildContext context) {
_projectViewModel = Provider.of(context);
return AppScaffold(
description: TranslationBase.of(context).offerAndPackagesDetails,
imagesInfo: [ImagesInfo(imageAr: 'https://hmgwebservices.com/Images/MobileApp/CMC/ar/0.png', imageEn: 'https://hmgwebservices.com/Images/MobileApp/CMC/en/0.png')],
appBarTitle: TranslationBase.of(context).offerAndPackages,
isShowAppBar: true,
isPharmacy: false,
backgroundColor: Color(0xfff7f7f7),
showPharmacyCart: false,
isOfferPackages: true,
showOfferPackagesCart: false,
isShowDecPage: false,
showNewAppBar: true,
showNewAppBarTitle: true,
body: Column(
children: <Widget>[
TabBar(
controller: _tabController,
indicatorWeight: 3.0,
indicatorSize: TabBarIndicatorSize.tab,
labelColor: Color(0xff2B353E),
unselectedLabelColor: Color(0xff575757),
labelPadding: EdgeInsets.only(top: 15, bottom: 13, left: 20, right: 20),
labelStyle: TextStyle(
fontFamily: _projectViewModel.isArabic ? 'Cairo' : 'Poppins',
fontSize: 16,
fontWeight: FontWeight.w600,
letterSpacing: -0.48,
),
unselectedLabelStyle: TextStyle(
fontFamily: _projectViewModel.isArabic ? 'Cairo' : 'Poppins',
fontSize: 16,
fontWeight: FontWeight.w600,
letterSpacing: -0.48,
),
tabs: [Text(TranslationBase.of(context).offerAndPackages), Text(TranslationBase.of(context).orderLog)],
),
Expanded(
child: TabBarView(
physics: BouncingScrollPhysics(),
controller: _tabController,
children: <Widget>[
PackagesHomePage(widget.user),
PackagesOrdersHistory()
],
),
)
],
),
);
}
}

@ -0,0 +1,98 @@
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesCartItemsResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesResponseModel.dart';
import 'package:diplomaticquarterapp/core/viewModels/packages_offers/PackagesOffersViewModel.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/Loader/gif_loader_container.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/ConfirmWithMessageDialog.dart';
import 'package:diplomaticquarterapp/widgets/offers_packages/PackagesOrderHistoryItemCard.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'OfferAndPackageDetailPage.dart';
class PackagesOrdersHistory extends StatefulWidget{
@override
State<StatefulWidget> createState() => PackagesOrdersHistorySatate();
}
class PackagesOrdersHistorySatate extends State<PackagesOrdersHistory>{
ProjectViewModel projectViewModel;
PackagesViewModel packagesViewModel;
List<PackagesResponseModel> orders;
@override
void initState() {
Future.delayed(Duration(milliseconds: 200)).then((value) async{
final orders_ = await packagesViewModel.service.orderHistory(context: context);
setState(() => orders = orders_ ?? []);
});
}
@override
Widget build(BuildContext context) {
projectViewModel = Provider.of(context);
return BaseView<PackagesViewModel>(
allowAny: true,
onModelReady: (model) => packagesViewModel = model,
builder: (_, model, wi) {
return content(context);
}
);
}
Widget content(BuildContext context){
if(orders == null){
return SizedBox();
}else if(orders.isEmpty){
return getNoDataWidget(context);
}else {
return ListView.separated(
padding: EdgeInsets.all(20),
itemCount: orders.length,
itemBuilder: (ctx, idx) => item(ctx, order: orders[idx]),
separatorBuilder: (ctx, idx) => SizedBox(height: 10),
);
}
}
Widget item(BuildContext context, {@required PackagesResponseModel order}){
return InkWell(
child: PackagesOrderHistoryItemCard(itemModel: order, viewModel: packagesViewModel),
onTap: (){
final detailPage = OfferAndPackagesDetail(itemModel: order, onCartClick: null)..showAddToCartFooter = false;
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => detailPage));
},
);
}
void showConfirmMessage(BuildContext context, {@required PackagesResponseModel order}){
showDialog(
context: context,
builder: (cxt) => ConfirmWithMessageDialog(
message: TranslationBase.of(context).cancelOrderMsg,
onTap: () {
},
),
);
return;
}
Color color(int status){
if (status == 1) { //pending
return Color(0xffCC9B14);
} else if (status == 2) { //processing
return Color(0xff2E303A);
} else if (status == 3) { //completed
return Color(0xff359846);
} else if (status == 4 || status == 6 || status == 7) { //cancel // Rejected
return Color(0xffD02127);
}
return Colors.transparent;
}
}

@ -70,7 +70,7 @@ class _RateAppointmentClinicState extends State<RateAppointmentClinic> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
model.appointmentDetails.projectName,
model.appointmentDetails.projectName ?? '',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64, height: 25 / 16),
),
Text(

@ -6,7 +6,7 @@ class AppSharedPreferences {
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
/// Save String [key] the key for save value [value] the value we need to save it
setString(String key, String value) async {
Future setString(String key, String value) async {
final SharedPreferences prefs = await _prefs;
return prefs.setString(key, value);
}
@ -42,7 +42,7 @@ class AppSharedPreferences {
}
/// Get String [key] the key was saved
getString(String key) async {
Future getString(String key) async {
final SharedPreferences prefs = await _prefs;
return prefs.getString(key);
}

@ -1,6 +1,8 @@
import 'package:diplomaticquarterapp/locator.dart';
import 'package:flutter/material.dart';
MaterialPageRoute _pageRoute(Widget page) => MaterialPageRoute(builder: (BuildContext context) => page);
class NavigationService {
final GlobalKey<NavigatorState> navigatorKey =
new GlobalKey<NavigatorState>();
@ -18,4 +20,11 @@ class NavigationService {
}
}
class Navigate{
static to({@required Widget page}){
final context = locator<NavigationService>().navigatorKey.currentContext;
Navigator.of(context).push(_pageRoute(page));
}
}
BuildContext get currentContext => locator<NavigationService>().navigatorKey.currentContext;

@ -1472,6 +1472,7 @@ class TranslationBase {
String get enablingWifi => localizedValues['enablingWifi'][locale.languageCode];
String get offerAndPackages => localizedValues['offerAndPackages'][locale.languageCode];
String get orderHistory => localizedValues['orderHistory'][locale.languageCode];
String get offerAndPackagesDetails => localizedValues['offerAndPackagesDetails'][locale.languageCode];

@ -546,7 +546,7 @@ class Utils {
medical.add(InkWell(
onTap: () {
userData().then((userData_) {
if (projectViewModel.isLogin && userData_ != null) {
if (projectViewModel.isLogin && userData_ != null || true) {
String patientID = userData_.patientID.toString();
GifLoaderDialogUtils.showMyDialog(context);
projectViewModel

@ -3,6 +3,7 @@ import 'package:flutter_svg/svg.dart';
extension WithContainer on Widget {
Widget get insideContainer => Container(color: Colors.white, padding: EdgeInsets.only(top: 16, bottom: 16, right: 21, left: 21), child: this);
Widget get expand => Expanded(child: this);
}
class DefaultButton extends StatelessWidget {

@ -99,18 +99,19 @@ class MyInAppBrowser extends InAppBrowser {
if (onExitCallback != null) onExitCallback(appo, isPaymentDone);
}
// @override
// Future<ShouldOverrideUrlLoadingAction> shouldOverrideUrlLoading(ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) async {
// var url = shouldOverrideUrlLoadingRequest.url;
// debugPrint("redirecting/overriding to: $url");
//
// if (paymentType == _PAYMENT_TYPE.PACKAGES && [PACKAGES_PAYMENT_SUCCESS_URL, PACKAGES_PAYMENT_FAIL_URL].contains(url)) {
// isPaymentDone = (url == PACKAGES_PAYMENT_SUCCESS_URL);
// close();
// }
//
// return ShouldOverrideUrlLoadingAction.ALLOW;
// }
@override
Future<NavigationActionPolicy> shouldOverrideUrlLoading(NavigationAction navigationAction) {
var url = navigationAction.request.url.toString();
debugPrint("redirecting/overriding to: $url");
if (paymentType == _PAYMENT_TYPE.PACKAGES && [PACKAGES_PAYMENT_SUCCESS_URL, PACKAGES_PAYMENT_FAIL_URL].contains(url)) {
isPaymentDone = (url == PACKAGES_PAYMENT_SUCCESS_URL);
close();
}
return Future.value(NavigationActionPolicy.ALLOW);
}
getLanguageID() async {
return await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
@ -135,7 +136,7 @@ class MyInAppBrowser extends InAppBrowser {
openPackagesPaymentBrowser({@required int customer_id, @required int order_id}) {
paymentType = _PAYMENT_TYPE.PACKAGES;
var full_url = '$PACKAGES_REQUEST_PAYMENT_URL?customer_id=$customer_id&order_id=$order_id';
this.browser.openUrlRequest(urlRequest: URLRequest(url: Uri.parse(full_url)), options: _InAppBrowserOptions);
this.openUrlRequest(urlRequest: URLRequest(url: Uri.parse(full_url)), options: _InAppBrowserOptions);
}
openPaymentBrowser(double amount, String orderDesc, String transactionID, String projId, String emailId, String paymentMethod, dynamic patientType, String patientName, dynamic patientID,
@ -367,6 +368,8 @@ class MyChromeSafariBrowser extends ChromeSafariBrowser {
onLoadStartCallback("ApplePay");
}
@override
void onClosed() {
print("ChromeSafari browser closed");

@ -0,0 +1,124 @@
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesCartItemsResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesResponseModel.dart';
import 'package:diplomaticquarterapp/core/viewModels/packages_offers/PackagesOffersViewModel.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/CounterView.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
bool wide = true;
class PackagesOrderHistoryItemCard extends StatefulWidget {
final PackagesResponseModel itemModel;
final PackagesViewModel viewModel;
final Function getCartItems;
const PackagesOrderHistoryItemCard({@required this.itemModel, @required this.viewModel, this.getCartItems, Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => PackagesOrderHistoryItemCardState();
}
class PackagesOrderHistoryItemCardState extends State<PackagesOrderHistoryItemCard> {
@override
Widget build(BuildContext context) {
wide = !wide;
return Container(
decoration: cardRadius(15.0),
height: 95,
padding: EdgeInsets.all(9),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
_image(widget.itemModel),
SizedBox(width: 7),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_itemName(widget.itemModel.name),
Expanded(child: _itemDescription(widget.itemModel.shortDescription)),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_itemPrice(widget.itemModel.price, context: context),
_cancelButton(context, itemModel: widget.itemModel)
],
),
],
),
)
],
),
);
}
}
Widget _cancelButton(BuildContext context, {@required PackagesResponseModel itemModel, VoidCallback onClick}) => InkWell(
onTap:onClick,
child: Padding(
padding: const EdgeInsets.only(right: 3, bottom: 3),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// Text(
// TranslationBase.of(context).removeMember,
// style: TextStyle(
// fontSize: 10,
// color: CustomColors.accentColor,
// fontWeight: FontWeight.w600,
// letterSpacing: -0.36,
// ),
// ),
// SizedBox(width: 2),
// SvgPicture.asset("assets/images/new-design/delete.svg", color: CustomColors.accentColor),
],
),
),
);
Widget _image(PackagesResponseModel model) => AspectRatio(
aspectRatio: 1 / 1,
child: ClipRRect(
borderRadius: BorderRadius.circular(15), child: ((model.images ?? []).isNotEmpty) ? Utils.loadNetworkImage(url: model.images.first.src, fitting: BoxFit.fill) : Container(color: Colors.grey[200])),
);
Widget _itemName(String name) => Text(
name,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Color(0xff2B353E),
letterSpacing: -0.56,
),
);
Widget _itemDescription(String desc) => Text(
desc,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w500,
color: Color(0xff535353),
letterSpacing: -0.4,
),
);
Widget _itemPrice(double price, {@required BuildContext context}) {
final prc = (price ?? 0.0).toStringAsFixed(2);
return Text(
'$prc ${TranslationBase.of(context).sar}',
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w600,
color: Color(0xff5D5D5D),
letterSpacing: -0.44,
),
);
}
Loading…
Cancel
Save