added push notification

This commit is contained in:
Komek Hayytnazarov 2023-03-28 11:36:10 +05:00
parent 024e6ad920
commit 1a2b2c3553
25 changed files with 1893 additions and 274 deletions

View File

@ -0,0 +1,6 @@
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgg/ZGtTj5/039UqzA
ue++alEsAiEMA2vLoEURmJHsjkegCgYIKoZIzj0DAQehRANCAARXKcRr5aZ/o8ZA
pQbq4ZM40sTfruafKY08hnD/wEerNbKnl1tX3PWtNnLfi3+pL+0mLr/rF62Trdzq
p5J9y2v8
-----END PRIVATE KEY-----

View File

@ -22,6 +22,9 @@ if (flutterVersionName == null) {
}
apply plugin: 'com.android.application'
// START: FlutterFire Configuration
apply plugin: 'com.google.gms.google-services'
// END: FlutterFire Configuration
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
@ -32,7 +35,7 @@ if (keystorePropertiesFile.exists()) {
}
android {
compileSdkVersion 31
compileSdkVersion 33
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
@ -50,7 +53,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.elektronika.tm"
minSdkVersion 20 //TODO: Change to 16 in production
minSdkVersion 21 //TODO: Change to 16 in production
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName

View File

@ -0,0 +1,39 @@
{
"project_info": {
"project_number": "186538881179",
"project_id": "elektronika-app",
"storage_bucket": "elektronika-app.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:186538881179:android:96a2f9ce98f8bbf00f563e",
"android_client_info": {
"package_name": "com.elektronika.tm"
}
},
"oauth_client": [
{
"client_id": "186538881179-j5f608hapm9p4cmdo01fe6r8atca6ep8.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyD9JBvYuGMFymroLwL9rYxkqB6u7EIaee0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "186538881179-j5f608hapm9p4cmdo01fe6r8atca6ep8.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}

View File

@ -4,6 +4,16 @@
<application
android:label="Elektronika"
android:icon="@mipmap/launcher_icon">
<!-- NOTE: the below 2 lines is for notification -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_launcher" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />
<activity
android:name=".MainActivity"
android:exported="true"

View File

@ -0,0 +1,411 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="526"
android:viewportHeight="526"
android:width="526dp"
android:height="526dp">
<path
android:pathData="M0 0L526 0L526 526L0 526L0 0ZM229 88L229 221L231 222L296 222L297 221L297 88L229 88ZM211 147Q183 158 163 176Q144 193 131 216Q123 230 118 248L113 275L113 302L114 303L114 311L118 329L123 344Q134 369 151 389Q168 407 191 420Q205 428 223 433L250 438L277 438L278 437L286 437L304 433L319 428Q344 417 364 400Q382 383 395 361Q403 346 408 329L413 302L413 275L412 274L412 266L408 248L403 233Q392 207 375 188Q352 161 316 147L313 148L313 202L331 214Q347 229 356 251L361 267L362 280L363 281L362 305L356 326Q349 343 337 356Q322 372 301 381L285 386L272 387L271 388L247 387L226 381Q208 374 196 362Q179 347 170 326L165 310L164 297L163 296L164 272L170 251Q177 233 189 221Q199 209 213 202L213 148L211 147Z"
android:fillColor="#C3000E"
android:strokeColor="#C3000E"
android:strokeWidth="1" />
<path
android:pathData="M229.5 88L230 221L296 221L296 88.5L297 88.5L297 220.5L295.5 222L230.5 222L229 220.5L229.5 88Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M190.5 156L189.5 158L190.5 156Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M185.5 159L184.5 161L185.5 159Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M345.5 162L346.5 164L345.5 162Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M176.5 165L175.5 167L176.5 165Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M173.5 167L172.5 169L173.5 167Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M352.5 167L353.5 169L352.5 167Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M168.5 171L166.5 174L168.5 171Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M357.5 171L358.5 173L357.5 171Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M162.5 176L151.5 188L162.5 176Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M363.5 176L374.5 188L363.5 176Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M377.5 191L379.5 194L377.5 191Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M147.5 192L146.5 194L147.5 192Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M143.5 197L142.5 199L143.5 197Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M382.5 197L383.5 199L382.5 197Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M384.5 200L385.5 202L384.5 200Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M138.5 204L137.5 206L138.5 204Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M207.5 204L206.5 206L207.5 204Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M203.5 207L202.5 209L203.5 207Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M322.5 207L323.5 209L322.5 207Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M390.5 209L391.5 211L390.5 209Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M199.5 210L196.5 214L199.5 210Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M326.5 210L329.5 214L326.5 210Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M188.5 221L185.5 225L188.5 221Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M337.5 221L340.5 225L337.5 221Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M183.5 227L182.5 229L183.5 227Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M342.5 227L343.5 229L342.5 227Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M345.5 231L346.5 233L345.5 231Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M115.5 260L116 262.5L115 262.5L115.5 260Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M411.5 265L412 268.5L411 268.5L411.5 265Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M114.5 266L115 268.5L114 268.5L114.5 266Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M361.5 269L362 271.5L361 271.5L361.5 269Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M113.5 274L114 280.5L113 280.5L113.5 274Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M412.5 274L413 279.5L412 279.5L412.5 274Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M163.5 275L164 279.5L163 279.5L163.5 275Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M362.5 275L363 279.5L362 279.5L362.5 275Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M412.5 295L413 301.5L412 301.5L412.5 295Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M113.5 296L114 301.5L113 301.5L113.5 296Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M163.5 296L164 300.5L163 300.5L163.5 296Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M362.5 296L363 300.5L362 300.5L362.5 296Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M164.5 304L165 306.5L164 306.5L164.5 304Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M114.5 307L115 310.5L114 310.5L114.5 307Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M411.5 307L412 309.5L411 309.5L411.5 307Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M410.5 313L411 315.5L410 315.5L410.5 313Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M179.5 343L180.5 345L179.5 343Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M182.5 347L183.5 349L182.5 347Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M343.5 347L342.5 349L343.5 347Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M185.5 351L188.5 355L185.5 351Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M340.5 351L337.5 355L340.5 351Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M196.5 362L199.5 366L196.5 362Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M329.5 362L326.5 366L329.5 362Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M134.5 365L135.5 367L134.5 365Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M202.5 367L203.5 369L202.5 367Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M323.5 367L322.5 369L323.5 367Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M319.5 370L318.5 372L319.5 370Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M388.5 370L387.5 372L388.5 370Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M140.5 374L141.5 376L140.5 374Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M142.5 377L143.5 379L142.5 377Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M383.5 377L382.5 379L383.5 377Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M146.5 382L148.5 385L146.5 382Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M379.5 382L378.5 384L379.5 382Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M279.5 386L282 386.5L279.5 387L279.5 386Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M250.5 387L255 387.5L250.5 388L250.5 387Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M271.5 387L276 387.5L271.5 388L271.5 387Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M151.5 388L162.5 400L151.5 388Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M374.5 388L363.5 400L374.5 388Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M359.5 402L357.5 405L359.5 402Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M167.5 403L168.5 405L167.5 403Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M172.5 407L173.5 409L172.5 407Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M353.5 407L352.5 409L353.5 407Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M350.5 409L349.5 411L350.5 409Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M179.5 412L180.5 414L179.5 412Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M341.5 415L340.5 417L341.5 415Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M235.5 435L238 435.5L235.5 436L235.5 435Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M241.5 436L244 436.5L241.5 437L241.5 436Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M282.5 436L286 436.5L282.5 437L282.5 436Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M249.5 437L256 437.5L249.5 438L249.5 437Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M271.5 437L277 437.5L271.5 438L271.5 437Z"
android:fillColor="#EFBABE"
android:strokeColor="#EFBABE"
android:strokeWidth="1" />
<path
android:pathData="M230 88L296 88L296 221L230 221L230 88Z"
android:fillColor="#FFFFFF"
android:strokeColor="#FFFFFF"
android:strokeWidth="1" />
<path
android:pathData="M211.5 147L213 147.5L213 200.5Q196.7 210.2 185 224.5Q172.6 239.6 166 260.5L163 275.5L163 300.5Q170.8 343.8 199.5 366Q214.6 378.4 235.5 385L250.5 388L275.5 388Q318.8 380.3 341 351.5Q353.4 336.4 360 315.5L363 300.5L363 275.5Q355.3 232.3 326.5 210L313 200.5L313 147.5L314.5 147Q352.9 161.6 377 190.5Q394.1 209.9 404 236.5L411 262.5L412 279.5L413 280.5L413 294.5L412 295.5L412 306.5L411 307.5L410 318.5L400 349.5Q385.5 381 360.5 402Q341.1 419.1 314.5 429L288.5 436L271.5 437L270.5 438L256.5 438L255.5 437L244.5 437L243.5 436L232.5 435L201.5 425Q170 410.5 149 385.5Q131.9 366.1 122 339.5L115 313.5L114 296.5L113 295.5L113 281.5L114 280.5L114 269.5L115 268.5L116 257.5L126 226.5Q140.5 195 165.5 174Q184.9 156.9 211.5 147Z"
android:fillColor="#FFFFFF"
android:strokeColor="#FFFFFF"
android:strokeWidth="1" />
</vector>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="default_notification_channel_id">default_channel_id</string>
</resources>

View File

@ -7,6 +7,9 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
// START: FlutterFire Configuration
classpath 'com.google.gms:google-services:4.3.10'
// END: FlutterFire Configuration
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

View File

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.0'
platform :ios, '11.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

View File

@ -1,14 +1,77 @@
PODS:
- device_info_plus (0.0.1):
- Flutter
- Firebase/CoreOnly (10.6.0):
- FirebaseCore (= 10.6.0)
- Firebase/Messaging (10.6.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 10.6.0)
- firebase_core (2.8.0):
- Firebase/CoreOnly (= 10.6.0)
- Flutter
- firebase_messaging (14.3.0):
- Firebase/Messaging (= 10.6.0)
- firebase_core
- Flutter
- FirebaseCore (10.6.0):
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Logger (~> 7.8)
- FirebaseCoreInternal (10.7.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseInstallations (10.7.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- PromisesObjC (~> 2.1)
- FirebaseMessaging (10.6.0):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleDataTransport (~> 9.2)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Reachability (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- nanopb (< 2.30910.0, >= 2.30908.0)
- Flutter (1.0.0)
- flutter_local_notifications (0.0.1):
- Flutter
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- path_provider_ios (0.0.1):
- GoogleDataTransport (9.2.1):
- GoogleUtilities/Environment (~> 7.7)
- nanopb (< 2.30910.0, >= 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/AppDelegateSwizzler (7.11.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (7.11.0):
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/Logger (7.11.0):
- GoogleUtilities/Environment
- GoogleUtilities/Network (7.11.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (7.11.0)"
- GoogleUtilities/Reachability (7.11.0):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (7.11.0):
- GoogleUtilities/Logger
- nanopb (2.30909.0):
- nanopb/decode (= 2.30909.0)
- nanopb/encode (= 2.30909.0)
- nanopb/decode (2.30909.0)
- nanopb/encode (2.30909.0)
- path_provider_foundation (0.0.1):
- Flutter
- shared_preferences_ios (0.0.1):
- FlutterMacOS
- PromisesObjC (2.2.0)
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite (0.0.2):
- Flutter
- FMDB (>= 2.7.5)
@ -23,9 +86,12 @@ PODS:
DEPENDENCIES:
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
- Flutter (from `Flutter`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
@ -34,17 +100,32 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- Firebase
- FirebaseCore
- FirebaseCoreInternal
- FirebaseInstallations
- FirebaseMessaging
- FMDB
- GoogleDataTransport
- GoogleUtilities
- nanopb
- PromisesObjC
EXTERNAL SOURCES:
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
firebase_core:
:path: ".symlinks/plugins/firebase_core/ios"
firebase_messaging:
:path: ".symlinks/plugins/firebase_messaging/ios"
Flutter:
:path: Flutter
path_provider_ios:
:path: ".symlinks/plugins/path_provider_ios/ios"
shared_preferences_ios:
:path: ".symlinks/plugins/shared_preferences_ios/ios"
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher_ios:
@ -58,16 +139,28 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
Firebase: f13680471b021937f2230ea8503c7809d8c29806
firebase_core: 58542d7399889ebdbb034baa72d081e54c5c814d
firebase_messaging: 01a8db2962f81ea190d08db767aba2e7e805e647
FirebaseCore: fa80ad16a62d52f67274b5b88304c3a318bbf9a4
FirebaseCoreInternal: 8845798510aae74703467480f71ac613788d0696
FirebaseInstallations: 59c0e4c7a816a0f76710d83f77e5369b3e45eb96
FirebaseMessaging: fd93783258c53ae5cdb9b41bf0c51606a677f2d5
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
GoogleDataTransport: ea169759df570f4e37bdee1623ec32a7e64e67c4
GoogleUtilities: c2bdc4cf2ce786c4d2e6b3bcfd599a25ca78f06f
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
webview_flutter_wkwebview: 005fbd90c888a42c5690919a1527ecc6649e1162
webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d
COCOAPODS: 1.11.3

View File

@ -3,13 +3,14 @@
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
254BA050D82AF8FEF3809DD7 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15A85E9D6A4DFD56FDD682FD /* Pods_Runner.framework */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
4AC4E22798DB4759A40D4DBB /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 51E96759B37E93004BE91A8C /* GoogleService-Info.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
@ -35,6 +36,7 @@
15A85E9D6A4DFD56FDD682FD /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3F18407BE8A79EE2307E2EB9 /* 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>"; };
51E96759B37E93004BE91A8C /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
52306709286D664D009453DF /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; 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>"; };
@ -99,6 +101,7 @@
97C146EF1CF9000F007C117D /* Products */,
44FDD469DA3537A51D276323 /* Pods */,
4E26FCEF2DD2C69FEDF54D54 /* Frameworks */,
51E96759B37E93004BE91A8C /* GoogleService-Info.plist */,
);
sourceTree = "<group>";
};
@ -193,6 +196,7 @@
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
4AC4E22798DB4759A40D4DBB /* GoogleService-Info.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -218,6 +222,7 @@
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -254,6 +259,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -361,6 +367,7 @@
DEVELOPMENT_TEAM = QQPXL8D953;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.shopping";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -492,6 +499,7 @@
DEVELOPMENT_TEAM = QQPXL8D953;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.shopping";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -518,6 +526,7 @@
DEVELOPMENT_TEAM = QQPXL8D953;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.shopping";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>186538881179-d39r6qso5iv98m8m60vev91gtsh8fs9o.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.186538881179-d39r6qso5iv98m8m60vev91gtsh8fs9o</string>
<key>API_KEY</key>
<string>AIzaSyCS07pxfuN62pBYCauLVRAWttTx0GSNDH0</string>
<key>GCM_SENDER_ID</key>
<string>186538881179</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.elektronika.tm</string>
<key>PROJECT_ID</key>
<string>elektronika-app</string>
<key>STORAGE_BUCKET</key>
<string>elektronika-app.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:186538881179:ios:fb651acd4ce97d5d0f563e</string>
</dict>
</plist>

View File

@ -26,6 +26,13 @@
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>

View File

@ -0,0 +1,7 @@
{
"file_generated_by": "FlutterFire CLI",
"purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory",
"GOOGLE_APP_ID": "1:186538881179:ios:fb651acd4ce97d5d0f563e",
"FIREBASE_PROJECT_ID": "elektronika-app",
"GCM_SENDER_ID": "186538881179"
}

View File

@ -0,0 +1,26 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
Future<String> downloadFile(String url, String filename) async {
var dio = Dio();
final directory = await getApplicationDocumentsDirectory();
final filePath = '${directory.path}/$filename';
// final response = await
Response response = await dio.get(url,
options: Options(
responseType: ResponseType.bytes,
followRedirects: false,
receiveTimeout: 5000000,
));
final file = File(filePath);
var raf = file.openSync(mode: FileMode.write);
// response.data is List<int> type
raf.writeFromSync(response.data);
await raf.close();
return filePath;
}

View File

@ -0,0 +1,266 @@
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get/get.dart';
import '../../../firebase_options.dart';
import '../../app.dart';
import 'download_file.dart';
class FCMFunctions {
static final FCMFunctions _singleton = new FCMFunctions._internal();
FCMFunctions._internal();
factory FCMFunctions() {
return _singleton;
}
late FirebaseMessaging messaging;
late FlutterLocalNotificationsPlugin flip;
late InitializationSettings initSettings;
//************************************************************************************************************ */
/// Create a [AndroidNotificationChannel] for heads up notifications
late AndroidNotificationChannel channel;
/// Initialize the [FlutterLocalNotificationsPlugin] package.
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
//************************************************************************************************************ */
Future initApp() async {
debugPrint('init firebase');
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
messaging = FirebaseMessaging.instance;
if (!kIsWeb) {
channel = const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
importance: Importance.high,
);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
/// Create an Android Notification Channel.
///
/// We use this channel in the `AndroidManifest.xml` file to override the
/// default FCM channel to enable heads up notifications.
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
//for IOS Foreground Notification
await messaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
flip = FlutterLocalNotificationsPlugin();
var initializationSettingsAndroid = const AndroidInitializationSettings('@drawable/ic_launcher');
var initializationSettingsIOs = const DarwinInitializationSettings();
initSettings = InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsIOs);
}
}
Future subscribeToTopics(String topic) async {
await messaging.subscribeToTopic(topic);
}
///Expire : https://firebase.google.com/docs/cloud-messaging/manage-tokens
Future<String?> getFCMToken() async {
final fcmToken = await messaging.getToken();
debugPrint('Get FCM Token ------->: $fcmToken');
return fcmToken;
}
void tokenListener() {
debugPrint('tokenListener');
messaging.onTokenRefresh.listen((fcmToken) {
debugPrint('Listen FCM Token ------->: $fcmToken');
// If necessary send token to application server.
}).onError((err) {
debugPrint('tokenListener err $err');
});
}
/// IOS
Future iosWebPermission() async {
if (Platform.isIOS || kIsWeb) {
/* NotificationSettings settings = */ await messaging.requestPermission();
}
}
///Foreground messages
///
///To handle messages while your application is in the foreground, listen to the onMessage stream.
void foreGroundMessageListener() {
FirebaseMessaging.onMessage.listen(_onMessageHandler);
FirebaseMessaging.onMessageOpenedApp.listen(_onMessageOpenedApp);
}
// foreground
Future<void> _onMessageHandler(RemoteMessage message) async {
debugPrint('onMessageHandler');
_showNotificationViaFBConsole(message);
}
// FLUTTER_NOTIFICATION_CLICK
// background (app minimized)
Future<void> _onMessageOpenedApp(RemoteMessage message) async => _performClickAction(message);
Future<void> _showNotification(RemoteMessage message) async {
final String imgUrl = message.data['imageUrl'] ?? '';
debugPrint('imgUrl $imgUrl');
final RemoteNotification? notification = message.notification;
final largeIconPath = await downloadFile(imgUrl, 'largeIcon');
final bigPicturePath = await downloadFile(imgUrl, 'bigPicture');
final BigPictureStyleInformation styleInformation = new BigPictureStyleInformation(
FilePathAndroidBitmap(bigPicturePath),
largeIcon: FilePathAndroidBitmap(largeIconPath),
);
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
channel.id,
channel.name,
icon: '@drawable/ic_launcher',
channelDescription: channel.description,
// importance: Importance.max,
// priority: Priority.high,
color: ThemeColor.mainColor,
styleInformation: styleInformation,
);
var iOSPlatformChannelSpecifics = DarwinNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics,
);
FlutterLocalNotificationsPlugin flip = FlutterLocalNotificationsPlugin();
await flip.show(0, notification?.title, notification?.body, platformChannelSpecifics, payload: 'Default_Sound');
}
Future<void> _showNotificationViaFBConsole(RemoteMessage message) async {
final RemoteNotification? notification = message.notification;
if (notification == null) return;
final String? imgUrl = _getImageUrl(notification);
debugPrint('==> imgUrl: $imgUrl ');
BigPictureStyleInformation? styleInformation;
if (imgUrl != null) {
final largeIconPath = await downloadFile(imgUrl, 'largeIcon');
final bigPicturePath = await downloadFile(imgUrl, 'bigPicture');
styleInformation = new BigPictureStyleInformation(
FilePathAndroidBitmap(bigPicturePath),
largeIcon: FilePathAndroidBitmap(largeIconPath),
);
}
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
channel.id,
channel.name,
icon: '@drawable/ic_launcher',
channelDescription: channel.description,
// importance: Importance.max,
priority: Priority.high,
color: ThemeColor.mainColor,
styleInformation: styleInformation,
);
var iOSPlatformChannelSpecifics = DarwinNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics,
);
flip.initialize(
initSettings,
// onDidReceiveBackgroundNotificationResponse: (details) {
// debugPrint('==> ${details.payload}');
// },
onDidReceiveNotificationResponse: (details) {
debugPrint('onDidReceiveNotificationResponse');
_performClickAction(message);
},
);
await flip.show(0, notification.title, notification.body, platformChannelSpecifics, payload: 'Default_Sound');
}
Future<void> _performClickAction(RemoteMessage message) async {
// if (message.data['type'] == 'product') {
// final int productId = int.parse(message.data['id']);
// final ProductModel? model = await ProductApi.getProductById(productId);
// if (model != null) Get.to(() => ProductDetailsPage(model: model));
// } else if (message.data['type'] == 'filter') {
// message.data.remove('type');
// navigateToProductListScreen(message.data, false);
// } else {
// open dialog
// if (message.notification == null) return;
// Get.to(
// () => NotificationPage(title: message.notification!.title ?? '', data: message.notification!.body ?? ''),
// );
// }
}
String? _getImageUrl(RemoteNotification notification) {
if (Platform.isIOS && notification.apple != null) return notification.apple?.imageUrl;
if (Platform.isAndroid && notification.android != null) return notification.android?.imageUrl;
return null;
}
}
final fcmFunctions = FCMFunctions();
// backgroundHandler must be on top and separated
Future<void> onBackgroundHandler(RemoteMessage message) async {
// fcmFunctions._showNotification(message);
fcmFunctions._showNotificationViaFBConsole(message);
}
Future<void> initFCMFunctions() async {
await fcmFunctions.initApp();
await fcmFunctions.iosWebPermission();
FirebaseMessaging.onBackgroundMessage(onBackgroundHandler);
await fcmFunctions.getFCMToken();
fcmFunctions.tokenListener();
fcmFunctions.foreGroundMessageListener();
await fcmFunctions.subscribeToTopics('notifications');
}
/* final http.Response response = await http.get(Uri.parse(URL));
BigPictureStyleInformation bigPictureStyleInformation =
BigPictureStyleInformation(
ByteArrayAndroidBitmap.fromBase64String(base64Encode(image)),
largeIcon: ByteArrayAndroidBitmap.fromBase64String(base64Encode(image)),
);
flutterLocalNotificationsPlugin.show(
Random().nextInt(1000),
title,
description,
NotificationDetails(
android: AndroidNotificationDetails(channel.id, channel.name,
channelDescription: channel.description,
importance: Importance.high,
styleInformation: bigPictureStyleInformation),
),
); */

View File

@ -143,4 +143,12 @@ class FilterApi {
return [];
}
}
static Future<List<FilterOption>> getOptions(int page, int itemsPerPage, FilterModel model, String searchKey) async {
debugPrint('page:$page, model:${model.code}' ', id:${model.id}');
List<FilterOption> options = [];
return options;
}
}

View File

@ -1,22 +1,22 @@
class CategoryModel {
late int id;
late String name;
late String imageUrl;
// late String imageUrl;
late String iconPath;
late List<CategoryModel> children;
int? parentId;
String? slug;
String? description;
String? categoryIconPath;
CategoryModel({
required this.id,
required this.name,
required this.imageUrl,
// required this.imageUrl,
required this.iconPath,
required this.children,
this.parentId,
this.slug,
this.description,
this.categoryIconPath,
});
CategoryModel.fromJson(Map<String, dynamic> json) {
@ -25,8 +25,8 @@ class CategoryModel {
parentId = json['parent_id'];
slug = json['slug'] ?? '';
description = json['description'] ?? '';
imageUrl = json['image_url'] ?? 'assets/phone.jpg'; //TODO: change
categoryIconPath = json['category_icon_path'] ?? '';
// imageUrl = json['image_url'] ?? 'assets/phone.jpg'; //TODO: change
iconPath = json['category_icon_path'] ?? '';
if (json['children'] != null) {
children = <CategoryModel>[];
json['children'].forEach((v) {

View File

@ -1,4 +1,4 @@
import 'package:badges/badges.dart';
import 'package:badges/badges.dart' as badge;
import 'package:elektronika/app/data/routes/app_routes.dart';
import 'package:elektronika/app/pages/cart/controller.dart';
import 'package:flutter/material.dart';
@ -39,7 +39,8 @@ class CustomAppbarWidget extends StatelessWidget implements PreferredSizeWidget
elevation: this.elevation,
actions: [
GestureDetector(
onTap: () => Get.toNamed(AppRoutes.CONTACTS), //debugPrint('onContactTapped'), //Get.toNamed(AppRoutes.CART),
onTap: () =>
Get.toNamed(AppRoutes.CONTACTS), //debugPrint('onContactTapped'), //Get.toNamed(AppRoutes.CART),
child: Row(
children: [
Icon(Icons.call_outlined, color: Colors.grey, size: 26),
@ -53,9 +54,9 @@ class CustomAppbarWidget extends StatelessWidget implements PreferredSizeWidget
Row(
children: [
controller.state.cartModel.value != null /* && controller.state.cartModel.value?.itemsQty != 0 */
? Badge(
position: BadgePosition.topEnd(top: -14),
animationType: BadgeAnimationType.scale,
? badge.Badge(
position: badge.BadgePosition.topEnd(top: -14),
animationType: badge.BadgeAnimationType.scale,
animationDuration: Duration(milliseconds: 300),
badgeColor: ThemeColor.mainColor.withOpacity(0.70),
badgeContent: Text(

View File

@ -73,14 +73,14 @@ class CategoryItem extends StatelessWidget {
child: root.children.isEmpty
? new ListTile(
// contentPadding: EdgeInsets.symmetric(horizontal: 16.h),
leading: _getTileLeading(root.imageUrl),
leading: _getTileLeading(root.iconPath),
title: _getTileTitle(root.name),
onTap: () => cc.navigateToProducts(root),
)
: new ExpansionTile(
childrenPadding: EdgeInsets.symmetric(horizontal: 12.h),
key: new PageStorageKey<CategoryModel>(root),
leading: _getTileLeading(root.imageUrl),
leading: _getTileLeading(root.iconPath),
title: GestureDetector(
onTap: () => cc.navigateToProducts(root),
child: _getTileTitle(root.name),

69
lib/firebase_options.dart Normal file
View File

@ -0,0 +1,69 @@
// File generated by FlutterFire CLI.
// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for web - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for macos - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.windows:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for windows - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyD9JBvYuGMFymroLwL9rYxkqB6u7EIaee0',
appId: '1:186538881179:android:96a2f9ce98f8bbf00f563e',
messagingSenderId: '186538881179',
projectId: 'elektronika-app',
storageBucket: 'elektronika-app.appspot.com',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyCS07pxfuN62pBYCauLVRAWttTx0GSNDH0',
appId: '1:186538881179:ios:fb651acd4ce97d5d0f563e',
messagingSenderId: '186538881179',
projectId: 'elektronika-app',
storageBucket: 'elektronika-app.appspot.com',
iosClientId: '186538881179-d39r6qso5iv98m8m60vev91gtsh8fs9o.apps.googleusercontent.com',
iosBundleId: 'com.elektronika.tm',
);
}

View File

@ -0,0 +1,143 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../app/app.dart';
import 'multi_select_action.dart';
import 'multi_select_item.dart';
class MultiSelectController extends GetxController
with StateMixin<List<MultiSelectItem<FilterOption>>>, MultiSelectActions<FilterOption>, ScrollMixin {
// List<FilterOption> initialValues;
// String modelCode;
Timer? _debounce;
FilterModel model;
MultiSelectController(this.model);
RxList<FilterOption> selectedValues = <FilterOption>[].obs;
List<MultiSelectItem<FilterOption>> items = [];
RxString searchKey = ''.obs;
int page = 1;
int itemPerPage = 20;
bool getFirstData = false;
RxBool lastPage = false.obs;
@override
void onInit() {
searchKey.value = '';
debugPrint('model.selectedOptions ${model.selectedOptions}');
this.selectedValues.addAll(model.selectedOptions);
update();
getData();
super.onInit();
}
Future<void> getData() async {
await FilterApi.getOptions(page, itemPerPage, model, searchKey.value).then((result) {
final bool emptyRepositories = result.isEmpty;
if (!getFirstData && emptyRepositories) {
change(null, status: RxStatus.empty());
} else if (getFirstData && emptyRepositories) {
lastPage.value = true;
} else {
getFirstData = true;
// convert data
var newItems = result.map((option) => MultiSelectItem<FilterOption>(option, option.adminName)).toList();
debugPrint('newItems ${newItems.length}');
for (var item in newItems) {
item.selected = this.selectedValues.where((element) => element.id == item.value.id).isNotEmpty;
items.add(item);
}
// check is last item
if (items.length < itemPerPage) {
lastPage.value = true;
}
change(items, status: RxStatus.success());
}
update();
}, onError: (err) {
change(null, status: RxStatus.error(err.toString()));
});
}
@override
Future<void> onEndScroll() async {
debugPrint('onEndScroll ${lastPage.value}');
if (!lastPage.value) {
page += 1;
await getData();
}
}
@override
Future<void> onTopScroll() async {
debugPrint('onTopScroll');
}
void clearFilter(BuildContext ctx, void Function(List<FilterOption>)? onClear) {
debugPrint('clearFilter');
for (int i = 0; i < items.length; i++) {
if (selectedValues.contains(items[i].value)) {
items[i].selected = false;
}
}
selectedValues.clear();
this.onClearTap(ctx, selectedValues, onClear);
update();
}
Future<void> onSearchChanged(String val) async {
getFirstData = false;
page = 1;
searchKey.value = val;
if (_debounce?.isActive ?? false) _debounce!.cancel();
_debounce = Timer(const Duration(milliseconds: 600), () {
items.clear();
change(items, status: RxStatus.loading());
getData();
update();
});
}
void onListBoxListTileChanged(
MultiSelectItem<FilterOption> item, void Function(List<FilterOption>)? onSelectionChanged, checked) {
debugPrint('onListBoxListTileChanged');
if (checked) {
item.selected = true;
selectedValues.add(item.value);
} else {
item.selected = false;
selectedValues.removeWhere((e) => e.id == item.value.id);
}
selectedValues.refresh();
if (onSelectionChanged != null) {
onSelectionChanged(selectedValues);
}
update();
}
void onConfirmSelection(BuildContext context, void Function(List<FilterOption>) onConfirm) {
onConfirmTap(context, selectedValues, onConfirm);
update();
}
}

View File

@ -0,0 +1,253 @@
// import 'package:animate_do/animate_do.dart';
// import 'package:flutter/material.dart';
// import 'package:flutter/services.dart';
// import 'package:flutter_screenutil/flutter_screenutil.dart';
// import 'package:flutter_svg/flutter_svg.dart';
// import 'package:get/get.dart';
// import '../../../app/app.dart';
// import 'controller.dart';
// import 'multi_select_item.dart';
// class MultiSelectBottomSheetGetX extends StatelessWidget {
// /// The list of selected values before interaction.
// // final List<FilterOption> initialValue;
// /// The text at the top of the BottomSheet.
// // final String title;
// /// Used to [getData] from api.
// // final String modelCode;
// final FilterModel model;
// /// Fires when the an item is selected / unselected.
// final void Function(List<FilterOption>)? onSelectionChanged;
// /// Fires when confirm is tapped.
// final void Function(List<FilterOption>) onConfirm;
// /// Fires when clear is tapped.
// final void Function(List<FilterOption>) onClear;
// MultiSelectBottomSheetGetX({
// // required this.initialValue,
// // required this.title,
// // required this.modelCode,
// required this.model,
// required this.onConfirm,
// required this.onClear,
// this.onSelectionChanged,
// });
// /// Returns a CheckboxListTile
// Widget _buildListItem(BuildContext context, MultiSelectController msc, MultiSelectItem<FilterOption> item) {
// final theme = Theme.of(context);
// final oldCheckboxTheme = theme.checkboxTheme;
// final newCheckBoxTheme = oldCheckboxTheme.copyWith(
// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(300)),
// );
// return Theme(
// data: theme.copyWith(checkboxTheme: newCheckBoxTheme),
// child: Transform.translate(
// offset: Offset(-24, 0),
// child: Transform.scale(
// scale: 1.h,
// child: CheckboxListTile(
// checkColor: ThemeColor.white,
// value: item.selected,
// activeColor: ThemeColor.mainColor,
// title: model.code != 'color'
// ? Text(item.label)
// : Align(
// alignment: Alignment.centerLeft,
// child: Row(
// children: [
// item.value.swatchValue.isNotEmpty
// ? CircleAvatar(
// backgroundColor: Colors.grey,
// maxRadius: 8.40.w,
// child: CircleAvatar(
// backgroundColor: HexColor(item.value.swatchValue),
// maxRadius: 8.0.w,
// ),
// )
// : SizedBox.shrink(),
// SizedBox(width: 16.w),
// Text(item.label),
// ],
// ),
// ),
// controlAffinity: ListTileControlAffinity.leading,
// onChanged: (checked) => msc.onListBoxListTileChanged(
// item,
// onSelectionChanged,
// checked,
// ),
// ),
// ),
// ),
// );
// }
// @override
// Widget build(BuildContext context) {
// final EdgeInsets mqPadding = MediaQuery.of(context).padding;
// var screenSize = MediaQuery.of(context).size;
// return GetBuilder<MultiSelectController>(
// init: MultiSelectController(model),
// builder: (msc) {
// final bool isLastPage = msc.lastPage.value;
// return Container(
// constraints: BoxConstraints(maxHeight: screenSize.height - mqPadding.top),
// padding: EdgeInsets.only(bottom: mqPadding.bottom + 16, top: 16, left: 16, right: 16),
// decoration: new BoxDecoration(
// color: ThemeColor.white,
// borderRadius: BorderRadius.only(topRight: Radius.circular(16), topLeft: Radius.circular(16)),
// ),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// Container(
// padding: const EdgeInsets.only(top: 8),
// child: Center(child: SvgPicture.asset('assets/icons/drag_line.svg')),
// ),
// SizedBox(height: 8.h),
// // title
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(model.name, style: AppTheme.bottomSheetHeaderStyle),
// SizedBox(height: 16),
// // search box
// Container(
// padding: const EdgeInsets.all(8),
// height: 40.h,
// width: double.infinity,
// decoration: new BoxDecoration(
// color: ThemeColor.colorEFF0F4,
// borderRadius: BorderRadius.circular(8),
// ),
// child: TextFormField(
// cursorColor: Colors.black,
// inputFormatters: [new LengthLimitingTextInputFormatter(30)],
// decoration: InputDecoration(
// border: InputBorder.none,
// prefixIcon: Icon(
// Icons.search,
// size: 24.h,
// color: Colors.grey,
// ),
// ),
// onChanged: (val) => msc.onSearchChanged(val),
// ),
// ),
// SizedBox(height: 20),
// Row(
// children: [
// FadeIn(child: CircleNumberWidget(number: msc.selectedValues.length)),
// SizedBox(width: 8),
// Text(
// 'applied'.tr,
// style: new TextStyle(
// color: ThemeColor.color717278,
// fontSize: 16.sp,
// ),
// ),
// Spacer(),
// msc.selectedValues.isNotEmpty
// ? FadeIn(
// child: TextButton(
// child: Text('clear'.tr),
// style: TextButton.styleFrom(foregroundColor: ThemeColor.mainColor),
// onPressed: () => msc.clearFilter(context, onClear),
// ),
// )
// : SizedBox.shrink(),
// ],
// ),
// ],
// ),
// AppTheme.appDivider,
// // body
// Expanded(
// child: ConstrainedBox(
// constraints: new BoxConstraints(minHeight: 0.3.sh),
// child: msc.obx(
// (state) => state != null
// ? RefreshIndicator(
// onRefresh: msc.getData,
// color: ThemeColor.mainColor,
// child: MediaQuery.removePadding(
// context: context,
// removeTop: true,
// child: ListView.builder(
// shrinkWrap: true,
// controller: msc.scroll,
// itemCount: state.length + 1,
// itemBuilder: (context, index) {
// if (index < state.length) {
// return FadeIn(
// child: _buildListItem(context, msc, state[index]),
// );
// } else if (index == state.length && !isLastPage)
// return Padding(
// padding: const EdgeInsets.only(top: 10, bottom: 40),
// child: Center(
// child: CustomLoader(),
// ),
// );
// else {
// return SizedBox.shrink();
// }
// },
// ),
// ),
// )
// : Center(
// child: Text(
// 'error_occurred'.tr,
// style: TextStyle(fontSize: 18),
// textAlign: TextAlign.center,
// ),
// ),
// onLoading: Center(child: CustomLoader()),
// onEmpty: Align(
// alignment: Alignment.topCenter,
// child: NotFoundWidget(),
// ),
// onError: (error) => Center(
// child: Text(
// 'error_occurred'.tr,
// style: TextStyle(fontSize: 18),
// textAlign: TextAlign.center,
// ),
// ),
// ),
// ),
// ),
// // footer
// msc.selectedValues.isNotEmpty
// ? FadeIn(
// duration: Duration(milliseconds: 900),
// child: ButtonWidthFull(
// title: 'done'.tr,
// btnColor: ThemeColor.mainColor,
// callback: () => msc.onConfirmSelection(
// context,
// onConfirm,
// ),
// ),
// )
// : SizedBox.shrink(),
// ],
// ),
// );
// },
// );
// }
// }

View File

@ -5,11 +5,19 @@ import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'app/app.dart';
import 'app/core/utils/notification_service.dart';
DBHelper dbHelper = DBHelper();
// Firebase initials is separated, app needs to be initialized
// regardless Firebase
Future<void> _initFBInitials() async {
await initFCMFunctions();
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await _initFBInitials();
SharedPreferences prefs = await SharedPreferences.getInstance();

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,9 @@ dependencies:
flutter_staggered_grid_view: ^0.6.1
url_launcher: ^6.1.5
webview_flutter: ^2.8.0
firebase_messaging: ^14.1.1
firebase_core: ^2.3.0
flutter_local_notifications: ^12.0.4
dev_dependencies:
flutter_test: