├── README.md ├── WhatsAppBussiness Clone ├── .github │ └── workflows │ │ └── android.yml ├── assests │ └── images │ │ ├── 16.jpg │ │ ├── 17.jpg │ │ ├── 18.png │ │ ├── 19.jpg │ │ └── 23.jpg ├── buildozer.spec ├── components │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-310.pyc │ │ ├── chatitem.cpython-310.pyc │ │ ├── messagelabel.cpython-310.pyc │ │ ├── screentab.cpython-310.pyc │ │ └── statusitem.cpython-310.pyc │ ├── chatitem.kv │ ├── chatitem.py │ ├── messagelabel.kv │ ├── messagelabel.py │ ├── screentab.py │ ├── statusitem.kv │ └── statusitem.py ├── main.kv ├── main.py └── screens │ ├── __init__.py │ ├── __pycache__ │ ├── __init__.cpython-310.pyc │ ├── chatscreen.cpython-310.pyc │ ├── groupscreen.cpython-310.pyc │ ├── homescreen.cpython-310.pyc │ ├── messagescreen.cpython-310.pyc │ ├── settingscreen.cpython-310.pyc │ ├── statusscreen.cpython-310.pyc │ └── viewstatusscreen.cpython-310.pyc │ ├── chatscreen.kv │ ├── chatscreen.py │ ├── groupscreen.kv │ ├── groupscreen.py │ ├── homescreen.kv │ ├── homescreen.py │ ├── messagescreen.kv │ ├── messagescreen.py │ ├── settingscreen.kv │ ├── settingscreen.py │ ├── statusscreen.kv │ ├── statusscreen.py │ ├── viewstatusscreen.kv │ └── viewstatusscreen.py └── Whatsapp Clone ├── .github └── workflows │ └── android.yml ├── assets └── images │ ├── 1.jpg │ ├── 12.jpg │ ├── 12.png │ ├── 14.jpg │ ├── 15.jpg │ ├── 16.jpg │ ├── 17.jpg │ ├── 18.png │ ├── 19.jpg │ ├── 23.jpg │ ├── 24.jpg │ ├── breezy.jpg │ ├── davido.jpg │ ├── emotion.jpg │ ├── jordan.jpg │ ├── money.jpg │ ├── rihanna.png │ ├── tnt.png │ ├── weeknd.jpg │ └── wizkid.jpg ├── buildozer.spec ├── demo ├── __pycache__ │ ├── demo.cpython-310.pyc │ ├── demo.cpython-36.pyc │ ├── group.cpython-310.pyc │ └── group.cpython-36.pyc ├── demo.py └── group.py ├── kvs ├── pages │ ├── call_screen.kv │ ├── chat_screen.kv │ └── group_screen.kv └── widgets │ ├── avatar.kv │ ├── bottom_navigator.kv │ ├── call_list_item.kv │ ├── chat_list_item.kv │ ├── chatbubble.kv │ ├── group_list_item.kv │ ├── story_layout.kv │ └── text_field.kv ├── main.kv └── main.py /README.md: -------------------------------------------------------------------------------- 1 | # WhatsApp-Redesign 2 | WhatsApp redesign made with Kivy/KivyMD 3 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: [ main ] 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-20.04 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | 13 | # used to cache dependencies with a timeout 14 | - name: Get Date 15 | id: get-date 16 | run: | 17 | echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" 18 | shell: bash 19 | 20 | - name: Cache Buildozer global directory 21 | uses: actions/cache@v2 22 | with: 23 | path: .buildozer_global 24 | key: buildozer-global-${{ hashFiles('buildozer.spec') }} # Replace with your path 25 | 26 | - uses: actions/cache@v2 27 | with: 28 | path: .buildozer 29 | key: ${{ runner.os }}-${{ steps.get-date.outputs.date }}-${{ hashFiles('buildozer.spec') }} 30 | 31 | - name: Build with Buildozer 32 | uses: ArtemSBulgakov/buildozer-action@v1 33 | id: buildozer 34 | with: 35 | command: buildozer android debug 36 | buildozer_version: stable 37 | 38 | - name: Upload artifacts 39 | uses: actions/upload-artifact@v2 40 | with: 41 | name: package 42 | path: ${{ steps.buildozer.outputs.filename }} 43 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/assests/images/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/assests/images/16.jpg -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/assests/images/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/assests/images/17.jpg -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/assests/images/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/assests/images/18.png -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/assests/images/19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/assests/images/19.jpg -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/assests/images/23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/assests/images/23.jpg -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/buildozer.spec: -------------------------------------------------------------------------------- 1 | [app] 2 | 3 | # (str) Title of your application 4 | title = WhatsAppBusiness Clone 5 | 6 | # (str) Package name 7 | package.name = whatsAppBusinessclone 8 | 9 | # (str) Package domain (needed for android/ios packaging) 10 | package.domain = org.whatsappbussiness 11 | 12 | # (str) Source code where the main.py live 13 | source.dir = . 14 | 15 | # (list) Source files to include (let empty to include all the files) 16 | source.include_exts = py,png,jpg,kv,atlas 17 | 18 | # (list) List of inclusions using pattern matching 19 | #source.include_patterns = assets/*,images/*.png 20 | 21 | # (list) Source files to exclude (let empty to not exclude anything) 22 | #source.exclude_exts = spec 23 | 24 | # (list) List of directory to exclude (let empty to not exclude anything) 25 | #source.exclude_dirs = tests, bin, venv 26 | 27 | # (list) List of exclusions using pattern matching 28 | # Do not prefix with './' 29 | #source.exclude_patterns = license,images/*/*.jpg 30 | 31 | # (str) Application versioning (method 1) 32 | version = 0.1 33 | 34 | # (str) Application versioning (method 2) 35 | # version.regex = __version__ = ['"](.*)['"] 36 | # version.filename = %(source.dir)s/main.py 37 | 38 | # (list) Application requirements 39 | # comma separated e.g. requirements = sqlite3,kivy 40 | requirements = python3==3.7.6, hostpython3==3.7.6, kivy==2.2.1, kivymd==1.1.1,pillow, kivy-garden, requests, plyer, android 41 | 42 | # (str) Custom source folders for requirements 43 | # Sets custom source for any requirements with recipes 44 | # requirements.source.kivy = ../../kivy 45 | 46 | # (str) Presplash of the application 47 | #presplash.filename = %(source.dir)s/data/presplash.png 48 | 49 | # (str) Icon of the application 50 | #icon.filename = %(source.dir)s/data/icon.png 51 | 52 | # (list) Supported orientations 53 | # Valid options are: landscape, portrait, portrait-reverse or landscape-reverse 54 | orientation = portrait 55 | 56 | # (list) List of service to declare 57 | #services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY 58 | 59 | # 60 | # OSX Specific 61 | # 62 | 63 | # 64 | # author = © Copyright Info 65 | 66 | # change the major version of python used by the app 67 | osx.python_version = 3.7.6 68 | 69 | # Kivy version to use 70 | osx.kivy_version = 2.2.1 71 | 72 | # 73 | # Android specific 74 | # 75 | 76 | # (bool) Indicate if the application should be fullscreen or not 77 | fullscreen = 0 78 | 79 | # (string) Presplash background color (for android toolchain) 80 | # Supported formats are: #RRGGBB #AARRGGBB or one of the following names: 81 | # red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray, 82 | # darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy, 83 | # olive, purple, silver, teal. 84 | android.presplash_color = fuchsia 85 | 86 | # (string) Presplash animation using Lottie format. 87 | # see https://lottiefiles.com/ for examples and https://airbnb.design/lottie/ 88 | # for general documentation. 89 | # Lottie files can be created using various tools, like Adobe After Effect or Synfig. 90 | #android.presplash_lottie = "path/to/lottie/file.json" 91 | 92 | # (str) Adaptive icon of the application (used if Android API level is 26+ at runtime) 93 | #icon.adaptive_foreground.filename = %(source.dir)s/data/icon_fg.png 94 | #icon.adaptive_background.filename = %(source.dir)s/data/icon_bg.png 95 | 96 | # (list) Permissions 97 | # (See https://python-for-android.readthedocs.io/en/latest/buildoptions/#build-options-1 for all the supported syntaxes and properties) 98 | android.permissions = INTERNET,READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE 99 | 100 | # (list) features (adds uses-feature -tags to manifest) 101 | #android.features = android.hardware.usb.host 102 | 103 | # (int) Target Android API, should be as high as possible. 104 | #android.api = 31 105 | 106 | # (int) Minimum API your APK / AAB will support. 107 | #android.minapi = 21 108 | 109 | # (int) Android SDK version to use 110 | #android.sdk = 20 111 | 112 | # (str) Android NDK version to use 113 | #android.ndk = 23b 114 | 115 | # (int) Android NDK API to use. This is the minimum API your app will support, it should usually match android.minapi. 116 | #android.ndk_api = 21 117 | 118 | # (bool) Use --private data storage (True) or --dir public storage (False) 119 | #android.private_storage = True 120 | 121 | # (str) Android NDK directory (if empty, it will be automatically downloaded.) 122 | #android.ndk_path = 123 | 124 | # (str) Android SDK directory (if empty, it will be automatically downloaded.) 125 | #android.sdk_path = 126 | 127 | # (str) ANT directory (if empty, it will be automatically downloaded.) 128 | #android.ant_path = 129 | 130 | # (bool) If True, then skip trying to update the Android sdk 131 | # This can be useful to avoid excess Internet downloads or save time 132 | # when an update is due and you just want to test/build your package 133 | # android.skip_update = False 134 | 135 | # (bool) If True, then automatically accept SDK license 136 | # agreements. This is intended for automation only. If set to False, 137 | # the default, you will be shown the license when first running 138 | # buildozer. 139 | # android.accept_sdk_license = False 140 | 141 | # (str) Android entry point, default is ok for Kivy-based app 142 | #android.entrypoint = org.kivy.android.PythonActivity 143 | 144 | # (str) Full name including package path of the Java class that implements Android Activity 145 | # use that parameter together with android.entrypoint to set custom Java class instead of PythonActivity 146 | #android.activity_class_name = org.kivy.android.PythonActivity 147 | 148 | # (str) Extra xml to write directly inside the element of AndroidManifest.xml 149 | # use that parameter to provide a filename from where to load your custom XML code 150 | #android.extra_manifest_xml = ./src/android/extra_manifest.xml 151 | 152 | # (str) Extra xml to write directly inside the tag of AndroidManifest.xml 153 | # use that parameter to provide a filename from where to load your custom XML arguments: 154 | #android.extra_manifest_application_arguments = ./src/android/extra_manifest_application_arguments.xml 155 | 156 | # (str) Full name including package path of the Java class that implements Python Service 157 | # use that parameter to set custom Java class which extends PythonService 158 | #android.service_class_name = org.kivy.android.PythonService 159 | 160 | # (str) Android app theme, default is ok for Kivy-based app 161 | # android.apptheme = "@android:style/Theme.NoTitleBar" 162 | 163 | # (list) Pattern to whitelist for the whole project 164 | #android.whitelist = 165 | 166 | # (str) Path to a custom whitelist file 167 | #android.whitelist_src = 168 | 169 | # (str) Path to a custom blacklist file 170 | #android.blacklist_src = 171 | 172 | # (list) List of Java .jar files to add to the libs so that pyjnius can access 173 | # their classes. Don't add jars that you do not need, since extra jars can slow 174 | # down the build process. Allows wildcards matching, for example: 175 | # OUYA-ODK/libs/*.jar 176 | #android.add_jars = foo.jar,bar.jar,path/to/more/*.jar 177 | 178 | # (list) List of Java files to add to the android project (can be java or a 179 | # directory containing the files) 180 | #android.add_src = 181 | 182 | # (list) Android AAR archives to add 183 | #android.add_aars = 184 | 185 | # (list) Put these files or directories in the apk assets directory. 186 | # Either form may be used, and assets need not be in 'source.include_exts'. 187 | # 1) android.add_assets = source_asset_relative_path 188 | # 2) android.add_assets = source_asset_path:destination_asset_relative_path 189 | #android.add_assets = 190 | 191 | # (list) Put these files or directories in the apk res directory. 192 | # The option may be used in three ways, the value may contain one or zero ':' 193 | # Some examples: 194 | # 1) A file to add to resources, legal resource names contain ['a-z','0-9','_'] 195 | # android.add_resources = my_icons/all-inclusive.png:drawable/all_inclusive.png 196 | # 2) A directory, here 'legal_icons' must contain resources of one kind 197 | # android.add_resources = legal_icons:drawable 198 | # 3) A directory, here 'legal_resources' must contain one or more directories, 199 | # each of a resource kind: drawable, xml, etc... 200 | # android.add_resources = legal_resources 201 | #android.add_resources = 202 | 203 | # (list) Gradle dependencies to add 204 | #android.gradle_dependencies = 205 | 206 | # (bool) Enable AndroidX support. Enable when 'android.gradle_dependencies' 207 | # contains an 'androidx' package, or any package from Kotlin source. 208 | # android.enable_androidx requires android.api >= 28 209 | #android.enable_androidx = True 210 | 211 | # (list) add java compile options 212 | # this can for example be necessary when importing certain java libraries using the 'android.gradle_dependencies' option 213 | # see https://developer.android.com/studio/write/java8-support for further information 214 | # android.add_compile_options = "sourceCompatibility = 1.8", "targetCompatibility = 1.8" 215 | 216 | # (list) Gradle repositories to add {can be necessary for some android.gradle_dependencies} 217 | # please enclose in double quotes 218 | # e.g. android.gradle_repositories = "maven { url 'https://kotlin.bintray.com/ktor' }" 219 | #android.add_gradle_repositories = 220 | 221 | # (list) packaging options to add 222 | # see https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html 223 | # can be necessary to solve conflicts in gradle_dependencies 224 | # please enclose in double quotes 225 | # e.g. android.add_packaging_options = "exclude 'META-INF/common.kotlin_module'", "exclude 'META-INF/*.kotlin_module'" 226 | #android.add_packaging_options = 227 | 228 | # (list) Java classes to add as activities to the manifest. 229 | #android.add_activities = com.example.ExampleActivity 230 | 231 | # (str) OUYA Console category. Should be one of GAME or APP 232 | # If you leave this blank, OUYA support will not be enabled 233 | #android.ouya.category = GAME 234 | 235 | # (str) Filename of OUYA Console icon. It must be a 732x412 png image. 236 | #android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png 237 | 238 | # (str) XML file to include as an intent filters in tag 239 | #android.manifest.intent_filters = 240 | 241 | # (list) Copy these files to src/main/res/xml/ (used for example with intent-filters) 242 | #android.res_xml = PATH_TO_FILE, 243 | 244 | # (str) launchMode to set for the main activity 245 | #android.manifest.launch_mode = standard 246 | 247 | # (str) screenOrientation to set for the main activity. 248 | # Valid values can be found at https://developer.android.com/guide/topics/manifest/activity-element 249 | #android.manifest.orientation = fullSensor 250 | 251 | # (list) Android additional libraries to copy into libs/armeabi 252 | #android.add_libs_armeabi = libs/android/*.so 253 | #android.add_libs_armeabi_v7a = libs/android-v7/*.so 254 | #android.add_libs_arm64_v8a = libs/android-v8/*.so 255 | #android.add_libs_x86 = libs/android-x86/*.so 256 | #android.add_libs_mips = libs/android-mips/*.so 257 | 258 | # (bool) Indicate whether the screen should stay on 259 | # Don't forget to add the WAKE_LOCK permission if you set this to True 260 | #android.wakelock = False 261 | 262 | # (list) Android application meta-data to set (key=value format) 263 | #android.meta_data = 264 | 265 | # (list) Android library project to add (will be added in the 266 | # project.properties automatically.) 267 | #android.library_references = 268 | 269 | # (list) Android shared libraries which will be added to AndroidManifest.xml using tag 270 | #android.uses_library = 271 | 272 | # (str) Android logcat filters to use 273 | #android.logcat_filters = *:S python:D 274 | 275 | # (bool) Android logcat only display log for activity's pid 276 | #android.logcat_pid_only = False 277 | 278 | # (str) Android additional adb arguments 279 | #android.adb_args = -H host.docker.internal 280 | 281 | # (bool) Copy library instead of making a libpymodules.so 282 | #android.copy_libs = 1 283 | 284 | # (list) The Android archs to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64 285 | # In past, was `android.arch` as we weren't supporting builds for multiple archs at the same time. 286 | android.archs = arm64-v8a, armeabi-v7a 287 | 288 | # (int) overrides automatic versionCode computation (used in build.gradle) 289 | # this is not the same as app version and should only be edited if you know what you're doing 290 | # android.numeric_version = 1 291 | 292 | # (bool) enables Android auto backup feature (Android API >=23) 293 | android.allow_backup = True 294 | 295 | # (str) XML file for custom backup rules (see official auto backup documentation) 296 | # android.backup_rules = 297 | 298 | # (str) If you need to insert variables into your AndroidManifest.xml file, 299 | # you can do so with the manifestPlaceholders property. 300 | # This property takes a map of key-value pairs. (via a string) 301 | # Usage example : android.manifest_placeholders = [myCustomUrl:\"org.kivy.customurl\"] 302 | # android.manifest_placeholders = [:] 303 | 304 | # (bool) Skip byte compile for .py files 305 | # android.no-byte-compile-python = False 306 | 307 | # (str) The format used to package the app for release mode (aab or apk or aar). 308 | # android.release_artifact = aab 309 | 310 | # (str) The format used to package the app for debug mode (apk or aar). 311 | # android.debug_artifact = apk 312 | 313 | # 314 | # Python for android (p4a) specific 315 | # 316 | 317 | # (str) python-for-android URL to use for checkout 318 | #p4a.url = 319 | 320 | # (str) python-for-android fork to use in case if p4a.url is not specified, defaults to upstream (kivy) 321 | #p4a.fork = kivy 322 | 323 | # (str) python-for-android branch to use, defaults to master 324 | #p4a.branch = master 325 | 326 | # (str) python-for-android specific commit to use, defaults to HEAD, must be within p4a.branch 327 | #p4a.commit = HEAD 328 | 329 | # (str) python-for-android git clone directory (if empty, it will be automatically cloned from github) 330 | #p4a.source_dir = 331 | 332 | # (str) The directory in which python-for-android should look for your own build recipes (if any) 333 | #p4a.local_recipes = 334 | 335 | # (str) Filename to the hook for p4a 336 | #p4a.hook = 337 | 338 | # (str) Bootstrap to use for android builds 339 | # p4a.bootstrap = sdl2 340 | 341 | # (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask) 342 | #p4a.port = 343 | 344 | # Control passing the --use-setup-py vs --ignore-setup-py to p4a 345 | # "in the future" --use-setup-py is going to be the default behaviour in p4a, right now it is not 346 | # Setting this to false will pass --ignore-setup-py, true will pass --use-setup-py 347 | # NOTE: this is general setuptools integration, having pyproject.toml is enough, no need to generate 348 | # setup.py if you're using Poetry, but you need to add "toml" to source.include_exts. 349 | #p4a.setup_py = false 350 | 351 | # (str) extra command line arguments to pass when invoking pythonforandroid.toolchain 352 | #p4a.extra_args = 353 | 354 | 355 | 356 | # 357 | # iOS specific 358 | # 359 | 360 | # (str) Path to a custom kivy-ios folder 361 | #ios.kivy_ios_dir = ../kivy-ios 362 | # Alternately, specify the URL and branch of a git checkout: 363 | ios.kivy_ios_url = https://github.com/kivy/kivy-ios 364 | ios.kivy_ios_branch = master 365 | 366 | # Another platform dependency: ios-deploy 367 | # Uncomment to use a custom checkout 368 | #ios.ios_deploy_dir = ../ios_deploy 369 | # Or specify URL and branch 370 | ios.ios_deploy_url = https://github.com/phonegap/ios-deploy 371 | ios.ios_deploy_branch = 1.10.0 372 | 373 | # (bool) Whether or not to sign the code 374 | ios.codesign.allowed = false 375 | 376 | # (str) Name of the certificate to use for signing the debug version 377 | # Get a list of available identities: buildozer ios list_identities 378 | #ios.codesign.debug = "iPhone Developer: ()" 379 | 380 | # (str) The development team to use for signing the debug version 381 | #ios.codesign.development_team.debug = 382 | 383 | # (str) Name of the certificate to use for signing the release version 384 | #ios.codesign.release = %(ios.codesign.debug)s 385 | 386 | # (str) The development team to use for signing the release version 387 | #ios.codesign.development_team.release = 388 | 389 | # (str) URL pointing to .ipa file to be installed 390 | # This option should be defined along with `display_image_url` and `full_size_image_url` options. 391 | #ios.manifest.app_url = 392 | 393 | # (str) URL pointing to an icon (57x57px) to be displayed during download 394 | # This option should be defined along with `app_url` and `full_size_image_url` options. 395 | #ios.manifest.display_image_url = 396 | 397 | # (str) URL pointing to a large icon (512x512px) to be used by iTunes 398 | # This option should be defined along with `app_url` and `display_image_url` options. 399 | #ios.manifest.full_size_image_url = 400 | 401 | 402 | [buildozer] 403 | 404 | # (int) Log level (0 = error only, 1 = info, 2 = debug (with command output)) 405 | log_level = 2 406 | 407 | # (int) Display warning if buildozer is run as root (0 = False, 1 = True) 408 | warn_on_root = 1 409 | 410 | # (str) Path to build artifact storage, absolute or relative to spec file 411 | # build_dir = ./.buildozer 412 | 413 | # (str) Path to build output (i.e. .apk, .aab, .ipa) storage 414 | # bin_dir = ./bin 415 | 416 | # ----------------------------------------------------------------------------- 417 | # List as sections 418 | # 419 | # You can define all the "list" as [section:key]. 420 | # Each line will be considered as a option to the list. 421 | # Let's take [app] / source.exclude_patterns. 422 | # Instead of doing: 423 | # 424 | #[app] 425 | #source.exclude_patterns = license,data/audio/*.wav,data/images/original/* 426 | # 427 | # This can be translated into: 428 | # 429 | #[app:source.exclude_patterns] 430 | #license 431 | #data/audio/*.wav 432 | #data/images/original/* 433 | # 434 | 435 | 436 | # ----------------------------------------------------------------------------- 437 | # Profiles 438 | # 439 | # You can extend section / key with a profile 440 | # For example, you want to deploy a demo version of your application without 441 | # HD content. You could first change the title to add "(demo)" in the name 442 | # and extend the excluded directories to remove the HD content. 443 | # 444 | #[app@demo] 445 | #title = My Application (demo) 446 | # 447 | #[app:source.exclude_patterns@demo] 448 | #images/hd/* 449 | # 450 | # Then, invoke the command line with the "demo" profile: 451 | # 452 | #buildozer --profile demo android debug 453 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/components/__init__.py -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/components/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/__pycache__/chatitem.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/components/__pycache__/chatitem.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/__pycache__/messagelabel.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/components/__pycache__/messagelabel.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/__pycache__/screentab.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/components/__pycache__/screentab.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/__pycache__/statusitem.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/components/__pycache__/statusitem.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/chatitem.kv: -------------------------------------------------------------------------------- 1 | 2 | : 3 | text:root.username 4 | secondary_text:root.message 5 | ImageLeftWidget: 6 | source:root.source 7 | radius:self.width/2 8 | RightContainer: 9 | size_hint_y:None 10 | height:root.height 11 | size_hint_x:None 12 | width:dp(70) 13 | MDIcon: 14 | icon:root.check_icon 15 | font_size:dp(24) 16 | pos_hint:{'center_x':0.5} 17 | theme_text_color: "Custom" 18 | text_color: "green" 19 | 20 | MDBoxLayout: 21 | orientation:'vertical' 22 | adaptive_height:True 23 | MDLabel: 24 | text:root.time 25 | font_size:'10dp' 26 | MDLabel: 27 | text:root.date 28 | font_size:'10dp' 29 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/chatitem.py: -------------------------------------------------------------------------------- 1 | from kivymd.uix.list import TwoLineAvatarIconListItem, IRightBodyTouch, ILeftBodyTouch 2 | from kivymd.uix.boxlayout import MDBoxLayout 3 | from kivy.properties import StringProperty 4 | from kivy.app import App 5 | from kivy.lang import Builder 6 | import os 7 | 8 | Builder.load_file(os.path.join(os.path.dirname(__file__), 'chatitem.kv')) 9 | 10 | class RightContainer(IRightBodyTouch, MDBoxLayout): 11 | pass 12 | 13 | class LeftContainer(ILeftBodyTouch, MDBoxLayout): 14 | pass 15 | 16 | class ChatItem(TwoLineAvatarIconListItem): 17 | source = StringProperty() 18 | username = StringProperty() 19 | message = StringProperty() 20 | time = StringProperty() 21 | date = StringProperty() 22 | check_icon = StringProperty('numeric-1-circle') 23 | 24 | def on_release(self, *args): 25 | app = App.get_running_app() 26 | screen_manager = app.root.screen_manager 27 | screen_manager.current = 'message' 28 | message_screen = screen_manager.get_screen('message') 29 | self.check_icon = '' 30 | message_screen.load_resource(source=self.source, username=self.username, time=self.time) -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/messagelabel.kv: -------------------------------------------------------------------------------- 1 | : 2 | message_id: -1 3 | bg_color: '#223344' 4 | side: 'left' 5 | text: '' 6 | size_hint_y: None 7 | _size: 0, 0 8 | size: self._size 9 | text_size: None, None 10 | opacity: min(1, self._size[0]) 11 | 12 | MDLabel: 13 | text: root.text 14 | padding: 10, 10 15 | size_hint: None, 1 16 | size: self.texture_size 17 | text_size: root.text_size 18 | 19 | pos_hint: 20 | ( 21 | {'x': 0, 'center_y': .5} 22 | if root.side == 'left' else 23 | {'right': 1, 'center_y': .5} 24 | ) 25 | 26 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/messagelabel.py: -------------------------------------------------------------------------------- 1 | from kivymd.uix.floatlayout import MDFloatLayout 2 | from kivy.properties import StringProperty, ListProperty 3 | from kivy.app import App 4 | from kivy.animation import Animation 5 | 6 | from kivy.lang import Builder 7 | from kivy.metrics import dp 8 | import os 9 | 10 | Builder.load_file(os.path.join(os.path.dirname(__file__), 'messagelabel.kv')) 11 | 12 | class MessageLabel(MDFloatLayout): 13 | messages = ListProperty() 14 | 15 | def update_message_size(self, message_id, texture_size, max_width): 16 | # when the label is updated, we want to make sure the displayed size is 17 | # proper 18 | app = App.get_running_app() 19 | self.messages = app.messages 20 | print(message_id) 21 | if max_width == 0: 22 | return 23 | 24 | one_line = dp(50) # a bit of hack, YMMV 25 | 26 | # if the texture is too big, limit its size 27 | if texture_size[0] >= max_width * 2 / 3: 28 | self.messages[message_id] = { 29 | **self.messages[message_id], 30 | 'text_size': (max_width * 2 / 3, None), 31 | } 32 | 33 | # if it was limited, but is now too small to be limited, raise the limit 34 | elif texture_size[0] < max_width * 2 / 3 and \ 35 | texture_size[1] > one_line: 36 | self.messages[message_id] = { 37 | **self.messages[message_id], 38 | 'text_size': (max_width * 2 / 3, None), 39 | '_size': texture_size, 40 | } 41 | 42 | # just set the size 43 | else: 44 | self.messages[message_id] = { 45 | **self.messages[message_id], 46 | '_size': texture_size, 47 | } -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/screentab.py: -------------------------------------------------------------------------------- 1 | 2 | from kivymd.uix.tab import MDTabsBase 3 | from kivymd.uix.floatlayout import MDFloatLayout 4 | 5 | class ScreenTab(MDTabsBase, MDFloatLayout): 6 | pass 7 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/statusitem.kv: -------------------------------------------------------------------------------- 1 | : 2 | text:root.username 3 | secondary_text:root.date 4 | ImageLeftWidget: 5 | source:root.source 6 | radius:self.width/2 7 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/components/statusitem.py: -------------------------------------------------------------------------------- 1 | from kivymd.uix.list import TwoLineAvatarIconListItem 2 | from kivy.properties import StringProperty 3 | from kivy.lang import Builder 4 | from kivy.app import App 5 | import os 6 | 7 | 8 | Builder.load_file(os.path.join(os.path.dirname(__file__), 'statusitem.kv')) 9 | 10 | class StatusItem(TwoLineAvatarIconListItem): 11 | source = StringProperty('') 12 | username = StringProperty('') 13 | date = StringProperty('') 14 | 15 | 16 | def on_release(self, *args): 17 | app = App.get_running_app() 18 | screen_manager = app.root.screen_manager 19 | screen_manager.current = 'status' 20 | status_screen = screen_manager.get_screen('status') 21 | status_screen.load_resource(source=self.source, status_source=self.source, username=self.username, time=self.date) 22 | 23 | 24 | 25 | #print(screen_manager.current) -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/main.kv: -------------------------------------------------------------------------------- 1 | #:import Window kivy.core.window.Window 2 | 3 | : 4 | screen_manager:screen_manager 5 | MDScreenManager: 6 | id:screen_manager 7 | HomeScreen: 8 | name:'home' 9 | ViewStatusScreen: 10 | name:'status' 11 | MessageScreen: 12 | name:'message' 13 | SettingScreen: 14 | name:'setting' 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/main.py: -------------------------------------------------------------------------------- 1 | from kivymd.app import MDApp 2 | from kivymd.uix.floatlayout import MDFloatLayout 3 | from kivy.properties import ObjectProperty, ListProperty 4 | from kivy.core.window import Window 5 | from kivymd.uix.menu import MDDropdownMenu 6 | from screens.homescreen import HomeScreen 7 | from screens.viewstatusscreen import ViewStatusScreen 8 | from screens.messagescreen import MessageScreen 9 | from screens.settingscreen import SettingScreen 10 | 11 | Window.size = (400, 688) 12 | #Window.top = 0.5 13 | #Window.left = 980 14 | 15 | Window.custom_titlebar = False 16 | class WhatsApp(MDFloatLayout): 17 | screen_manager = ObjectProperty() 18 | 19 | 20 | class MainApp(MDApp): 21 | messages = ListProperty() 22 | def build(self): 23 | self.init_menu() 24 | self.theme_cls.primary_palette = 'Teal' 25 | self.theme_cls.theme_style = 'Dark' 26 | return WhatsApp() 27 | def init_menu(self): 28 | menu_items=[ 29 | { "text":f"Advertise", 30 | "viewclass":"OneLineListItem", 31 | "divider":None, 32 | "on_release":lambda x='Advertise':self.menu_callback(x)}, 33 | {"text":f"Bussiness Tools", 34 | "viewclass":"OneLineListItem", 35 | "divider":None, 36 | "on_release":lambda x='Bussiness Tools':self.menu_callback(x)}, 37 | {"text":f"New Group", 38 | "viewclass":"OneLineListItem", 39 | "divider":None, 40 | "on_release":lambda x='New Group':self.menu_callback(x)}, 41 | 42 | {"text":f"New BroadCast", 43 | "viewclass":"OneLineListItem", 44 | "divider":None, 45 | "on_release":lambda x='New BroadCast':self.menu_callback(x)}, 46 | 47 | {"text":f"Labels", 48 | "viewclass":"OneLineListItem", 49 | "divider":None, 50 | "on_release":lambda x='Labels':self.menu_callback(x)}, 51 | {"text":f"Linked Devices", 52 | "viewclass":"OneLineListItem", 53 | "divider":None, 54 | "on_release":lambda x='Linked Devices':self.menu_callback(x)}, 55 | {"text":f"Starred Message", 56 | "viewclass":"OneLineListItem", 57 | "divider":None, 58 | "on_release":lambda x='Starred Message':self.menu_callback(x)}, 59 | {"text":f"Settings", 60 | "viewclass":"OneLineListItem", 61 | "divider":None, 62 | "on_release":lambda x='Settings':self.settings_callback(x)}, 63 | ] 64 | self.menu = MDDropdownMenu(items=menu_items, 65 | width_mult=4) 66 | def callback(self, instance): 67 | ''' display settings options ''' 68 | self.menu.caller = instance 69 | self.menu.open() 70 | def settings_callback(self, value): 71 | self.menu.dismiss() 72 | self.root.screen_manager.current = 'setting' 73 | 74 | def menu_callback(self, instance): 75 | print(instance) 76 | self.menu.dismiss() 77 | 78 | def change_tabs(self, args): 79 | tab_instance = args[1] 80 | tab_name = args[3] 81 | if tab_name == 'Chats': 82 | tab_instance.children[0].load_chats() 83 | if tab_name == 'Groups': 84 | tab_instance.children[0].load_groups() 85 | #tab_instance.load_groups() 86 | if tab_name == 'Status': 87 | tab_instance.children[0].load_status() 88 | #tab_instance.load_groups() 89 | 90 | if __name__ =='__main__': 91 | MainApp().run() 92 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/screens/__init__.py -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/screens/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/__pycache__/chatscreen.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/screens/__pycache__/chatscreen.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/__pycache__/groupscreen.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/screens/__pycache__/groupscreen.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/__pycache__/homescreen.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/screens/__pycache__/homescreen.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/__pycache__/messagescreen.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/screens/__pycache__/messagescreen.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/__pycache__/settingscreen.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/screens/__pycache__/settingscreen.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/__pycache__/statusscreen.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/screens/__pycache__/statusscreen.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/__pycache__/viewstatusscreen.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/WhatsAppBussiness Clone/screens/__pycache__/viewstatusscreen.cpython-310.pyc -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/chatscreen.kv: -------------------------------------------------------------------------------- 1 | : 2 | chat_container:chat_container 3 | MDBoxLayout: 4 | RecycleView: 5 | id:chat_container 6 | viewclass:'ChatItem' 7 | RecycleBoxLayout: 8 | orientation:'vertical' 9 | default_size_hint:1, None 10 | default_size:None, dp(64) 11 | size_hint_y:None 12 | height:self.minimum_height 13 | 14 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/chatscreen.py: -------------------------------------------------------------------------------- 1 | from kivymd.uix.floatlayout import MDFloatLayout 2 | from kivy.properties import ObjectProperty 3 | from kivy.lang import Builder 4 | import os 5 | 6 | Builder.load_file(os.path.join(os.path.dirname(__file__), 'chatscreen.kv')) 7 | 8 | class ChatScreen(MDFloatLayout): 9 | chat_container = ObjectProperty() 10 | 11 | def load_chats(self): 12 | data = [{'source':'assests/images/17.jpg', 'username':'My Love', 'message':'Good Morning Love', 'date':'Today', 'time':'10:12 AM'} 13 | for i in range(500)] 14 | self.chat_container.data = data 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/groupscreen.kv: -------------------------------------------------------------------------------- 1 | : 2 | group_container:group_container 3 | MDBoxLayout: 4 | MDRecycleView: 5 | id:group_container 6 | viewclass:'ChatItem' 7 | RecycleBoxLayout: 8 | orientation:'vertical' 9 | default_size_hint:1, None 10 | default_size:None, dp(72) 11 | size_hint_y:None 12 | height:self.minimum_height 13 | 14 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/groupscreen.py: -------------------------------------------------------------------------------- 1 | from kivymd.uix.floatlayout import MDFloatLayout 2 | from kivy.properties import ObjectProperty 3 | from kivy.lang import Builder 4 | import os 5 | 6 | Builder.load_file(os.path.join(os.path.dirname(__file__), 'groupscreen.kv')) 7 | 8 | 9 | class GroupScreen(MDFloatLayout): 10 | group_container = ObjectProperty() 11 | def load_groups(self): 12 | data = [{'source':'assests/images/23.jpg', 'username':'Taylor', 'message':'Good Morning Love', 'date':'Today', 'time':'10:12 AM'} 13 | for i in range(300)] 14 | self.group_container.data = data 15 | 16 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/homescreen.kv: -------------------------------------------------------------------------------- 1 | : 2 | MDTopAppBar: 3 | title:'WhatsApp' 4 | pos_hint:{'top':1} 5 | right_action_items:[['camera-outline', lambda x:app.callback(x)],['magnify', lambda x:app.callback(x)],['dots-vertical', lambda x:app.callback(x)],] 6 | size_hint_x:1 7 | MDBoxLayout: 8 | size_hint_y:None 9 | height:root.height*0.9 10 | MDTabs: 11 | tab_hint_x:True 12 | on_tab_switch:app.change_tabs(args) 13 | ScreenTab: 14 | title:'Chats' 15 | ChatScreen: 16 | id:chats 17 | 18 | ScreenTab: 19 | title:'Groups' 20 | GroupScreen: 21 | id:groups 22 | 23 | ScreenTab: 24 | title:'Status' 25 | StatusScreen: 26 | id:status -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/homescreen.py: -------------------------------------------------------------------------------- 1 | from kivymd.uix.screen import MDScreen 2 | from components.screentab import ScreenTab 3 | from components.chatitem import ChatItem 4 | from components.statusitem import StatusItem 5 | from screens.chatscreen import ChatScreen 6 | from screens.groupscreen import GroupScreen 7 | from screens.statusscreen import StatusScreen 8 | from kivy.clock import Clock 9 | from kivy.lang import Builder 10 | import os 11 | 12 | Builder.load_file(os.path.join(os.path.dirname(__file__), 'homescreen.kv')) 13 | 14 | class HomeScreen(MDScreen): 15 | 16 | def on_enter(self, *args): 17 | Clock.schedule_once(self.load,1) 18 | 19 | def load(self, interval): 20 | 21 | self.ids.chats.load_chats() 22 | self.ids.groups.load_groups() 23 | self.ids.status.load_status() 24 | 25 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/messagescreen.kv: -------------------------------------------------------------------------------- 1 | #:import RGBA kivy.utils.rgba 2 | : 3 | 4 | : 5 | MDRelativeLayout: 6 | id:message_bar_layout 7 | size_hint_y:None 8 | height:dp(64) 9 | pos_hint:{'top':1} 10 | md_bg_color:app.theme_cls.primary_color 11 | MDIconButton: 12 | icon:'arrow-left' 13 | pos_hint:{'center_x':0.08, 'center_y':0.5} 14 | on_release:root.back_btn() 15 | FitImage: 16 | size_hint:(None, None) 17 | size:(dp(60),dp(60)) 18 | source:root.source 19 | radius:self.width/2 20 | pos_hint:{'center_x':0.2,'center_y':0.5} 21 | MDBoxLayout: 22 | size_hint_x:None 23 | width:dp(50) 24 | size_hint_y:None 25 | height:message_bar_layout.height 26 | pos_hint:{'center_x':0.35, 'center_y':0.5} 27 | orientation:'vertical' 28 | 29 | MDLabel: 30 | id:lbl_username 31 | text:root.username 32 | font_size:dp(12) 33 | MDLabel: 34 | text:root.time 35 | font_size:dp(8) 36 | MDIconButton: 37 | icon:'dots-vertical' 38 | pos_hint:{'center_x':0.9, 'center_y':0.5} 39 | MDBoxLayout: 40 | size_hint_y:None 41 | height:Window.size[1]*0.9 42 | pos_hint:{'top':0.9} 43 | RecycleView: 44 | id:message_rv 45 | data:app.messages 46 | viewclass:'MessageLabel' 47 | RecycleBoxLayout: 48 | orientation:'vertical' 49 | id:message_box 50 | size_hint_y: None 51 | size: self.minimum_size 52 | default_size_hint: 1, None 53 | # magic value for the default height of the message 54 | default_size: None,50 55 | key_size: '_size' 56 | MDBoxLayout: 57 | pos_hint:{'bottom':0.8} 58 | size_hint_y:None 59 | height: dp(50) 60 | padding:[dp(12),0, dp(12), 0] 61 | MDCard: 62 | radius:[dp(8), dp(8), dp(8), dp(8)] 63 | md_bg_color:app.theme_cls.bg_darkest 64 | MDRelativeLayout: 65 | id:input_layout 66 | MDIconButton: 67 | icon:'emoticon-outline' 68 | pos_hint:{'center_x':0.04, 'center_y':0.5} 69 | FocusTextField: 70 | id:message_input 71 | hint_text:'message' 72 | pos_hint:{'center_x':0.4, 'center_y':0.5} 73 | size_hint_x:None 74 | width:dp(200) 75 | multiline:True 76 | on_focus:root.focus_callback() 77 | unfocus:root.unfocus_callback() 78 | 79 | MDIconButton: 80 | id:language_btn 81 | icon:'translate' 82 | pos_hint:{'center_x':0.7, 'center_y':0.5} 83 | MDIconButton: 84 | id:attachment_btn 85 | icon:'attachment' 86 | pos_hint:{'center_x':0.8, 'center_y':0.5} 87 | 88 | MDIconButton: 89 | id:send_microphone_btn 90 | pos_hint:{'center_x':0.9, 'center_y':0.5} 91 | icon:'microphone' 92 | on_release:root.send_message(message_input) 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/messagescreen.py: -------------------------------------------------------------------------------- 1 | from components.messagelabel import MessageLabel 2 | from kivymd.uix.screen import MDScreen 3 | from kivy.properties import ListProperty, StringProperty, BooleanProperty 4 | from kivymd.uix.button import MDIconButton 5 | from kivy.animation import Animation 6 | from kivy.core.window import Window 7 | from kivy.clock import Clock 8 | from kivy.lang import Builder 9 | from kivy.app import App 10 | import os 11 | 12 | 13 | Builder.load_file(os.path.join(os.path.dirname(__file__), 'messagescreen.kv')) 14 | 15 | 16 | class MessageScreen(MDScreen): 17 | focus_state = BooleanProperty() 18 | 19 | 20 | messages = ListProperty() 21 | time = StringProperty() 22 | username = StringProperty('') 23 | source = StringProperty('') 24 | def __init__(self, **kwargs): 25 | super().__init__(**kwargs) 26 | self.camera_btn = MDIconButton(icon='camera-outline') 27 | Clock.schedule_once(self.custom_init, 1) 28 | 29 | def custom_init(self, *args): 30 | self.app = App.get_running_app() 31 | self.rv = self.ids.message_rv 32 | self.screen_manager = self.app.root.screen_manager 33 | values = [{'message_id': 1, 'text': 'Bernice', 'side': 'right', 'bg_color': '#223344', 'text_size': [None, None]}, {'message_id': 2, 'text': 'do you really think so?', 'side': 'left', 'bg_color': '#332211', 'text_size': [None, None]}] 34 | self.app.messages.extend(values) 35 | def add_message(self, text, side, color): 36 | # create a message for the recycleview 37 | self.messages.append({ 38 | 'message_id': len(self.messages), 39 | 'text': text, 40 | 'side': side, 41 | 'bg_color': color, 42 | 'text_size': [None, None], 43 | }) 44 | self.app.messages.append({ 45 | 'message_id': len(self.messages), 46 | 'text': text, 47 | 'side': side, 48 | 'bg_color': color, 49 | 'text_size': [None, None], 50 | }) 51 | self.rv.data = self.app.messages 52 | 53 | 54 | 55 | @staticmethod 56 | def focus_textinput(textinput): 57 | textinput.focus = False 58 | 59 | def send_message(self, textinput): 60 | print('sending message') 61 | text = textinput.text 62 | textinput.text = '' 63 | self.add_message(text, 'right', '#223344') 64 | self.focus_textinput(textinput) 65 | Clock.schedule_once(lambda *args: self.answer(text), 1) 66 | self.scroll_bottom() 67 | 68 | def answer(self, text, *args): 69 | print('answered message') 70 | self.add_message('do you really think so?', 'left', '#332211') 71 | 72 | def scroll_bottom(self): 73 | rv = self.ids.message_rv 74 | box = self.ids.message_box 75 | if rv.height < box.height: 76 | Animation.cancel_all(rv, 'scroll_y') 77 | Animation(scroll_y=0, t='out_quad', d=.5).start(rv) 78 | def load_resource(self, source='', username='Joe Doe', time='online'): 79 | self.source = source 80 | self.username = username 81 | self.time = time 82 | def back_btn(self): 83 | ''' return to the previous screen''' 84 | self.screen_manager.current = 'home' 85 | def focus_callback(self, *args): 86 | self.focus_state = True 87 | if self.focus_state: 88 | print('focussing') 89 | self.ids.language_btn.pos_hint = {'center_x':0.86, 'center_y':0.5} 90 | self.ids.attachment_btn.pos_hint = {'center_x':0.96, 'center_y':0.5} 91 | self.ids.send_microphone_btn.icon = 'send' 92 | self.ids.input_layout.remove_widget(self.camera_btn) 93 | self.focus_state = False 94 | def on_focus_state(self, instance, value): 95 | if value: 96 | self.unfocus_callback() 97 | 98 | 99 | def unfocus_callback(self, *args): 100 | print('unfocusing') 101 | self.ids.language_btn.pos_hint = {'center_x':0.7, 'center_y':0.5} 102 | self.ids.attachment_btn.pos_hint = {'center_x':0.8, 'center_y':0.5} 103 | if self.camera_btn in self.ids.input_layout.children[:]: 104 | pass 105 | else: 106 | 107 | self.ids.input_layout.add_widget(self.camera_btn) 108 | self.camera_btn.pos_hint = {'center_x':0.9, 'center_y':0.5} 109 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/settingscreen.kv: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | : 5 | theme_text_color:'Custom' 6 | secondary_theme_text_color:'Custom' 7 | text_color:'white' if app.theme_cls.theme_style == 'Dark' else 'black' 8 | secondary_text_color:'gray' 9 | text:root.action 10 | secondary_text:root.description 11 | IconLeftWidget: 12 | icon:root.icon 13 | 14 | : 15 | MDTopAppBar: 16 | title:'Settings' 17 | left_action_items:[['chevron-left', lambda x:root.chevron_back()]] 18 | pos_hint:{'top':1} 19 | MDScrollView: 20 | pos_hint:{'top':0.92} 21 | MDBoxLayout: 22 | orientation:'vertical' 23 | adaptive_height:True 24 | TwoLineAvatarIconListItem: 25 | text:'Liam' 26 | secondary_text:'if life is journey where is the destination' 27 | divider:None 28 | ImageLeftWidget: 29 | source:'assests/images/19.jpg' 30 | radius:self.width/2 31 | TwoLineIconItem: 32 | icon:'briefcase' 33 | action:'Business Tools' 34 | description:'Profile, Catalog, messaging tools' 35 | 36 | TwoLineIconItem: 37 | icon:'account' 38 | action:'Account' 39 | description:'Security, notification, change number' 40 | TwoLineIconItem: 41 | icon:'key-variant' 42 | action:'Privacy ' 43 | description:'Block contact disappearing message' 44 | TwoLineIconItem: 45 | icon:'emoticon-outline' 46 | action:'Avatar' 47 | description:'Create, edit, profile photo' 48 | TwoLineIconItem: 49 | icon:'message-bulleted' 50 | action:'Chats' 51 | description:'Theme wallpaper, chat history' 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/settingscreen.py: -------------------------------------------------------------------------------- 1 | from kivymd.uix.list import TwoLineAvatarIconListItem, TwoLineIconListItem, ILeftBodyTouch 2 | from kivymd.uix.fitimage import FitImage 3 | from kivymd.uix.screen import MDScreen 4 | from kivymd.app import MDApp 5 | from kivy.properties import StringProperty 6 | from kivy.lang import Builder 7 | import os 8 | 9 | Builder.load_file(os.path.join(os.path.dirname(__file__), 'settingscreen.kv')) 10 | 11 | 12 | 13 | class LeftContainer(ILeftBodyTouch, FitImage): 14 | pass 15 | 16 | class TwoLineIconItem(TwoLineAvatarIconListItem): 17 | icon = StringProperty() 18 | action = StringProperty() 19 | description = StringProperty() 20 | 21 | class SettingScreen(MDScreen): 22 | def chevron_back(self): 23 | app = MDApp.get_running_app() 24 | app.root.screen_manager.current = 'home' 25 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/statusscreen.kv: -------------------------------------------------------------------------------- 1 | : 2 | status_container:status_container 3 | MDBoxLayout: 4 | MDRecycleView: 5 | id:status_container 6 | viewclass:'StatusItem' 7 | RecycleBoxLayout: 8 | orientation:'vertical' 9 | default_size_hint:1, None 10 | default_size:None, dp(64) 11 | size_hint_y:None 12 | height:self.minimum_height 13 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/statusscreen.py: -------------------------------------------------------------------------------- 1 | from kivymd.uix.floatlayout import MDFloatLayout 2 | from kivy.properties import ObjectProperty 3 | from kivy.lang import Builder 4 | import os 5 | 6 | Builder.load_file(os.path.join(os.path.dirname(__file__), 'statusscreen.kv')) 7 | 8 | class StatusScreen(MDFloatLayout): 9 | status_container = ObjectProperty() 10 | def load_status(self): 11 | data = [{'source':'assests/images/19.jpg', 'username':'bernice', 'date':'Today'} 12 | for i in range(200)] 13 | self.status_container.data = data -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/viewstatusscreen.kv: -------------------------------------------------------------------------------- 1 | : 2 | progressbar:progressbar 3 | pos_hint:{'top':1} 4 | MDBoxLayout: 5 | orientation:'vertical' 6 | padding:[dp(8), dp(8), dp(8), 0] 7 | MDProgressBar: 8 | id:progressbar 9 | value:0 10 | size_hint_y:None 11 | height:dp(3) 12 | color:[1,1,1,0.5] 13 | MDRelativeLayout: 14 | size_hint_y:None 15 | height:dp(64) 16 | MDIconButton: 17 | icon:'arrow-left' 18 | pos_hint:{'center_x':0.08, 'center_y':0.5} 19 | on_release:root.back_btn() 20 | FitImage: 21 | source:root.source 22 | pos_hint:{'center_x':0.22, 'center_y':0.5} 23 | size_hint:(None, None) 24 | size:(dp(60), dp(60)) 25 | radius:self.width/2 26 | MDBoxLayout: 27 | orientation:'vertical' 28 | pos_hint:{'center_x':0.42, 'center_y':0.5} 29 | size_hint_x:None 30 | width:dp(80) 31 | MDLabel: 32 | text:root.username 33 | font_size:dp(18) 34 | MDLabel: 35 | text:root.time 36 | font_size:dp(12) 37 | MDIconButton: 38 | pos_hint:{'center_x':0.9, 'center_y':0.5} 39 | icon:'dots-vertical' 40 | 41 | MDSmartTile: 42 | source:root.status_source 43 | 44 | 45 | -------------------------------------------------------------------------------- /WhatsAppBussiness Clone/screens/viewstatusscreen.py: -------------------------------------------------------------------------------- 1 | from kivymd.uix.screen import MDScreen 2 | from kivy.animation import Animation 3 | from kivy.properties import StringProperty, ObjectProperty 4 | from kivymd.uix.list import IRightBodyTouch, ILeftBodyTouch 5 | from kivymd.uix.boxlayout import MDBoxLayout 6 | from kivy.lang import Builder 7 | from kivy.clock import Clock 8 | from kivy.app import App 9 | import os 10 | 11 | Builder.load_file(os.path.join(os.path.dirname(__file__), 'viewstatusscreen.kv')) 12 | 13 | class RightContainer(IRightBodyTouch, MDBoxLayout): 14 | pass 15 | ''' 16 | class LeftContainer(ILeftBodyTouch, MDBoxLayout): 17 | pass 18 | 19 | ''' 20 | class ViewStatusScreen(MDScreen): 21 | source = StringProperty() 22 | status_source = StringProperty() 23 | username = StringProperty() 24 | time = StringProperty('00:00') 25 | progressbar = ObjectProperty() 26 | def __init__(self, **kwargs): 27 | super().__init__(**kwargs) 28 | Clock.schedule_once(self.custom_init, 1) 29 | 30 | def custom_init(self, *args): 31 | app = App.get_running_app() 32 | self.screen_manager = app.root.screen_manager 33 | 34 | 35 | def load_resource(self, source='', status_source='', username='', time='00:00'): 36 | ''' load information to the status ''' 37 | self.source = source 38 | self.status_source = status_source 39 | self.username = username 40 | self.time = time 41 | 42 | Clock.schedule_once(self.animate_pregress_bar) 43 | 44 | def animate_pregress_bar(self, args): 45 | ''' animate the progress of the status ''' 46 | self.anim = Animation(duration=5, value=100) 47 | self.anim.bind(on_complete=self.complete) 48 | self.anim.start(self.progressbar) 49 | 50 | def complete(self, *args): 51 | 52 | self.progressbar.value = 0 53 | self.screen_manager.current = self.screen_manager.previous() 54 | 55 | def back_btn(self): 56 | ''' return to the previous screen''' 57 | if self.anim: 58 | self.anim.stop(self.progressbar) 59 | else: 60 | self.screen_manager.current = self.screen_manager.previous() 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Whatsapp Clone/.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: [ main ] 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-20.04 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | 13 | # used to cache dependencies with a timeout 14 | - name: Get Date 15 | id: get-date 16 | run: | 17 | echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" 18 | shell: bash 19 | 20 | - name: Cache Buildozer global directory 21 | uses: actions/cache@v2 22 | with: 23 | path: .buildozer_global 24 | key: buildozer-global-${{ hashFiles('buildozer.spec') }} # Replace with your path 25 | 26 | - uses: actions/cache@v2 27 | with: 28 | path: .buildozer 29 | key: ${{ runner.os }}-${{ steps.get-date.outputs.date }}-${{ hashFiles('buildozer.spec') }} 30 | 31 | - name: Build with Buildozer 32 | uses: ArtemSBulgakov/buildozer-action@v1 33 | id: buildozer 34 | with: 35 | command: buildozer android debug 36 | buildozer_version: stable 37 | 38 | - name: Upload artifacts 39 | uses: actions/upload-artifact@v2 40 | with: 41 | name: package 42 | path: ${{ steps.buildozer.outputs.filename }} 43 | -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/1.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/12.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/12.png -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/14.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/15.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/16.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/17.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/18.png -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/19.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/23.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/24.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/breezy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/breezy.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/davido.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/davido.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/emotion.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/emotion.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/jordan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/jordan.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/money.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/money.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/rihanna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/rihanna.png -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/tnt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/tnt.png -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/weeknd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/weeknd.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/assets/images/wizkid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/assets/images/wizkid.jpg -------------------------------------------------------------------------------- /Whatsapp Clone/buildozer.spec: -------------------------------------------------------------------------------- 1 | [app] 2 | 3 | # (str) Title of your application 4 | title = WhatsAppclone 5 | 6 | # (str) Package name 7 | package.name = whatsappclone 8 | 9 | # (str) Package domain (needed for android/ios packaging) 10 | package.domain = org.whatsappclone 11 | 12 | # (str) Source code where the main.py live 13 | source.dir = . 14 | 15 | # (list) Source files to include (let empty to include all the files) 16 | source.include_exts = py,png,jpg,kv,atlas 17 | 18 | # (list) List of inclusions using pattern matching 19 | #source.include_patterns = assets/*,images/*.png 20 | 21 | # (list) Source files to exclude (let empty to not exclude anything) 22 | #source.exclude_exts = spec 23 | 24 | # (list) List of directory to exclude (let empty to not exclude anything) 25 | #source.exclude_dirs = tests, bin, venv 26 | 27 | # (list) List of exclusions using pattern matching 28 | # Do not prefix with './' 29 | #source.exclude_patterns = license,images/*/*.jpg 30 | 31 | # (str) Application versioning (method 1) 32 | version = 1.1.1 33 | 34 | # (str) Application versioning (method 2) 35 | # version.regex = __version__ = ['"](.*)['"] 36 | # version.filename = %(source.dir)s/main.py 37 | 38 | # (list) Application requirements 39 | # comma separated e.g. requirements = sqlite3,kivy 40 | requirements = python3==3.7.6, hostpython3==3.7.6, kivy==2.2.1, kivymd==1.1.1,pillow, kivy-garden, requests, plyer, android 41 | 42 | # (str) Custom source folders for requirements 43 | # Sets custom source for any requirements with recipes 44 | # requirements.source.kivy = ../../kivy 45 | 46 | # (str) Presplash of the application 47 | #presplash.filename = %(source.dir)s/data/presplash.png 48 | 49 | # (str) Icon of the application 50 | #icon.filename = %(source.dir)s/data/icon.png 51 | 52 | # (list) Supported orientations 53 | # Valid options are: landscape, portrait, portrait-reverse or landscape-reverse 54 | orientation = portrait 55 | 56 | # (list) List of service to declare 57 | #services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY 58 | 59 | # 60 | # OSX Specific 61 | # 62 | 63 | # 64 | # author = © Copyright Info 65 | 66 | # change the major version of python used by the app 67 | osx.python_version = 3.7.6 68 | 69 | # Kivy version to use 70 | osx.kivy_version = 2.2.1 71 | 72 | # 73 | # Android specific 74 | # 75 | 76 | # (bool) Indicate if the application should be fullscreen or not 77 | fullscreen = 0 78 | 79 | # (string) Presplash background color (for android toolchain) 80 | # Supported formats are: #RRGGBB #AARRGGBB or one of the following names: 81 | # red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray, 82 | # darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy, 83 | # olive, purple, silver, teal. 84 | android.presplash_color = fuchsia 85 | 86 | # (string) Presplash animation using Lottie format. 87 | # see https://lottiefiles.com/ for examples and https://airbnb.design/lottie/ 88 | # for general documentation. 89 | # Lottie files can be created using various tools, like Adobe After Effect or Synfig. 90 | #android.presplash_lottie = "path/to/lottie/file.json" 91 | 92 | # (str) Adaptive icon of the application (used if Android API level is 26+ at runtime) 93 | #icon.adaptive_foreground.filename = %(source.dir)s/data/icon_fg.png 94 | #icon.adaptive_background.filename = %(source.dir)s/data/icon_bg.png 95 | 96 | # (list) Permissions 97 | # (See https://python-for-android.readthedocs.io/en/latest/buildoptions/#build-options-1 for all the supported syntaxes and properties) 98 | android.permissions = INTERNET,READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE 99 | 100 | # (list) features (adds uses-feature -tags to manifest) 101 | #android.features = android.hardware.usb.host 102 | 103 | # (int) Target Android API, should be as high as possible. 104 | #android.api = 31 105 | 106 | # (int) Minimum API your APK / AAB will support. 107 | #android.minapi = 21 108 | 109 | # (int) Android SDK version to use 110 | #android.sdk = 20 111 | 112 | # (str) Android NDK version to use 113 | #android.ndk = 23b 114 | 115 | # (int) Android NDK API to use. This is the minimum API your app will support, it should usually match android.minapi. 116 | #android.ndk_api = 21 117 | 118 | # (bool) Use --private data storage (True) or --dir public storage (False) 119 | #android.private_storage = True 120 | 121 | # (str) Android NDK directory (if empty, it will be automatically downloaded.) 122 | #android.ndk_path = 123 | 124 | # (str) Android SDK directory (if empty, it will be automatically downloaded.) 125 | #android.sdk_path = 126 | 127 | # (str) ANT directory (if empty, it will be automatically downloaded.) 128 | #android.ant_path = 129 | 130 | # (bool) If True, then skip trying to update the Android sdk 131 | # This can be useful to avoid excess Internet downloads or save time 132 | # when an update is due and you just want to test/build your package 133 | # android.skip_update = False 134 | 135 | # (bool) If True, then automatically accept SDK license 136 | # agreements. This is intended for automation only. If set to False, 137 | # the default, you will be shown the license when first running 138 | # buildozer. 139 | # android.accept_sdk_license = False 140 | 141 | # (str) Android entry point, default is ok for Kivy-based app 142 | #android.entrypoint = org.kivy.android.PythonActivity 143 | 144 | # (str) Full name including package path of the Java class that implements Android Activity 145 | # use that parameter together with android.entrypoint to set custom Java class instead of PythonActivity 146 | #android.activity_class_name = org.kivy.android.PythonActivity 147 | 148 | # (str) Extra xml to write directly inside the element of AndroidManifest.xml 149 | # use that parameter to provide a filename from where to load your custom XML code 150 | #android.extra_manifest_xml = ./src/android/extra_manifest.xml 151 | 152 | # (str) Extra xml to write directly inside the tag of AndroidManifest.xml 153 | # use that parameter to provide a filename from where to load your custom XML arguments: 154 | #android.extra_manifest_application_arguments = ./src/android/extra_manifest_application_arguments.xml 155 | 156 | # (str) Full name including package path of the Java class that implements Python Service 157 | # use that parameter to set custom Java class which extends PythonService 158 | #android.service_class_name = org.kivy.android.PythonService 159 | 160 | # (str) Android app theme, default is ok for Kivy-based app 161 | # android.apptheme = "@android:style/Theme.NoTitleBar" 162 | 163 | # (list) Pattern to whitelist for the whole project 164 | #android.whitelist = 165 | 166 | # (str) Path to a custom whitelist file 167 | #android.whitelist_src = 168 | 169 | # (str) Path to a custom blacklist file 170 | #android.blacklist_src = 171 | 172 | # (list) List of Java .jar files to add to the libs so that pyjnius can access 173 | # their classes. Don't add jars that you do not need, since extra jars can slow 174 | # down the build process. Allows wildcards matching, for example: 175 | # OUYA-ODK/libs/*.jar 176 | #android.add_jars = foo.jar,bar.jar,path/to/more/*.jar 177 | 178 | # (list) List of Java files to add to the android project (can be java or a 179 | # directory containing the files) 180 | #android.add_src = 181 | 182 | # (list) Android AAR archives to add 183 | #android.add_aars = 184 | 185 | # (list) Put these files or directories in the apk assets directory. 186 | # Either form may be used, and assets need not be in 'source.include_exts'. 187 | # 1) android.add_assets = source_asset_relative_path 188 | # 2) android.add_assets = source_asset_path:destination_asset_relative_path 189 | #android.add_assets = 190 | 191 | # (list) Put these files or directories in the apk res directory. 192 | # The option may be used in three ways, the value may contain one or zero ':' 193 | # Some examples: 194 | # 1) A file to add to resources, legal resource names contain ['a-z','0-9','_'] 195 | # android.add_resources = my_icons/all-inclusive.png:drawable/all_inclusive.png 196 | # 2) A directory, here 'legal_icons' must contain resources of one kind 197 | # android.add_resources = legal_icons:drawable 198 | # 3) A directory, here 'legal_resources' must contain one or more directories, 199 | # each of a resource kind: drawable, xml, etc... 200 | # android.add_resources = legal_resources 201 | #android.add_resources = 202 | 203 | # (list) Gradle dependencies to add 204 | #android.gradle_dependencies = 205 | 206 | # (bool) Enable AndroidX support. Enable when 'android.gradle_dependencies' 207 | # contains an 'androidx' package, or any package from Kotlin source. 208 | # android.enable_androidx requires android.api >= 28 209 | #android.enable_androidx = True 210 | 211 | # (list) add java compile options 212 | # this can for example be necessary when importing certain java libraries using the 'android.gradle_dependencies' option 213 | # see https://developer.android.com/studio/write/java8-support for further information 214 | # android.add_compile_options = "sourceCompatibility = 1.8", "targetCompatibility = 1.8" 215 | 216 | # (list) Gradle repositories to add {can be necessary for some android.gradle_dependencies} 217 | # please enclose in double quotes 218 | # e.g. android.gradle_repositories = "maven { url 'https://kotlin.bintray.com/ktor' }" 219 | #android.add_gradle_repositories = 220 | 221 | # (list) packaging options to add 222 | # see https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html 223 | # can be necessary to solve conflicts in gradle_dependencies 224 | # please enclose in double quotes 225 | # e.g. android.add_packaging_options = "exclude 'META-INF/common.kotlin_module'", "exclude 'META-INF/*.kotlin_module'" 226 | #android.add_packaging_options = 227 | 228 | # (list) Java classes to add as activities to the manifest. 229 | #android.add_activities = com.example.ExampleActivity 230 | 231 | # (str) OUYA Console category. Should be one of GAME or APP 232 | # If you leave this blank, OUYA support will not be enabled 233 | #android.ouya.category = GAME 234 | 235 | # (str) Filename of OUYA Console icon. It must be a 732x412 png image. 236 | #android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png 237 | 238 | # (str) XML file to include as an intent filters in tag 239 | #android.manifest.intent_filters = 240 | 241 | # (list) Copy these files to src/main/res/xml/ (used for example with intent-filters) 242 | #android.res_xml = PATH_TO_FILE, 243 | 244 | # (str) launchMode to set for the main activity 245 | #android.manifest.launch_mode = standard 246 | 247 | # (str) screenOrientation to set for the main activity. 248 | # Valid values can be found at https://developer.android.com/guide/topics/manifest/activity-element 249 | #android.manifest.orientation = fullSensor 250 | 251 | # (list) Android additional libraries to copy into libs/armeabi 252 | #android.add_libs_armeabi = libs/android/*.so 253 | #android.add_libs_armeabi_v7a = libs/android-v7/*.so 254 | #android.add_libs_arm64_v8a = libs/android-v8/*.so 255 | #android.add_libs_x86 = libs/android-x86/*.so 256 | #android.add_libs_mips = libs/android-mips/*.so 257 | 258 | # (bool) Indicate whether the screen should stay on 259 | # Don't forget to add the WAKE_LOCK permission if you set this to True 260 | #android.wakelock = False 261 | 262 | # (list) Android application meta-data to set (key=value format) 263 | #android.meta_data = 264 | 265 | # (list) Android library project to add (will be added in the 266 | # project.properties automatically.) 267 | #android.library_references = 268 | 269 | # (list) Android shared libraries which will be added to AndroidManifest.xml using tag 270 | #android.uses_library = 271 | 272 | # (str) Android logcat filters to use 273 | #android.logcat_filters = *:S python:D 274 | 275 | # (bool) Android logcat only display log for activity's pid 276 | #android.logcat_pid_only = False 277 | 278 | # (str) Android additional adb arguments 279 | #android.adb_args = -H host.docker.internal 280 | 281 | # (bool) Copy library instead of making a libpymodules.so 282 | #android.copy_libs = 1 283 | 284 | # (list) The Android archs to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64 285 | # In past, was `android.arch` as we weren't supporting builds for multiple archs at the same time. 286 | android.archs = arm64-v8a, armeabi-v7a 287 | 288 | # (int) overrides automatic versionCode computation (used in build.gradle) 289 | # this is not the same as app version and should only be edited if you know what you're doing 290 | # android.numeric_version = 1 291 | 292 | # (bool) enables Android auto backup feature (Android API >=23) 293 | android.allow_backup = True 294 | 295 | # (str) XML file for custom backup rules (see official auto backup documentation) 296 | # android.backup_rules = 297 | 298 | # (str) If you need to insert variables into your AndroidManifest.xml file, 299 | # you can do so with the manifestPlaceholders property. 300 | # This property takes a map of key-value pairs. (via a string) 301 | # Usage example : android.manifest_placeholders = [myCustomUrl:\"org.kivy.customurl\"] 302 | # android.manifest_placeholders = [:] 303 | 304 | # (bool) Skip byte compile for .py files 305 | # android.no-byte-compile-python = False 306 | 307 | # (str) The format used to package the app for release mode (aab or apk or aar). 308 | # android.release_artifact = aab 309 | 310 | # (str) The format used to package the app for debug mode (apk or aar). 311 | # android.debug_artifact = apk 312 | 313 | # 314 | # Python for android (p4a) specific 315 | # 316 | 317 | # (str) python-for-android URL to use for checkout 318 | #p4a.url = 319 | 320 | # (str) python-for-android fork to use in case if p4a.url is not specified, defaults to upstream (kivy) 321 | #p4a.fork = kivy 322 | 323 | # (str) python-for-android branch to use, defaults to master 324 | #p4a.branch = master 325 | 326 | # (str) python-for-android specific commit to use, defaults to HEAD, must be within p4a.branch 327 | #p4a.commit = HEAD 328 | 329 | # (str) python-for-android git clone directory (if empty, it will be automatically cloned from github) 330 | #p4a.source_dir = 331 | 332 | # (str) The directory in which python-for-android should look for your own build recipes (if any) 333 | #p4a.local_recipes = 334 | 335 | # (str) Filename to the hook for p4a 336 | #p4a.hook = 337 | 338 | # (str) Bootstrap to use for android builds 339 | # p4a.bootstrap = sdl2 340 | 341 | # (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask) 342 | #p4a.port = 343 | 344 | # Control passing the --use-setup-py vs --ignore-setup-py to p4a 345 | # "in the future" --use-setup-py is going to be the default behaviour in p4a, right now it is not 346 | # Setting this to false will pass --ignore-setup-py, true will pass --use-setup-py 347 | # NOTE: this is general setuptools integration, having pyproject.toml is enough, no need to generate 348 | # setup.py if you're using Poetry, but you need to add "toml" to source.include_exts. 349 | #p4a.setup_py = false 350 | 351 | # (str) extra command line arguments to pass when invoking pythonforandroid.toolchain 352 | #p4a.extra_args = 353 | 354 | 355 | 356 | # 357 | # iOS specific 358 | # 359 | 360 | # (str) Path to a custom kivy-ios folder 361 | #ios.kivy_ios_dir = ../kivy-ios 362 | # Alternately, specify the URL and branch of a git checkout: 363 | ios.kivy_ios_url = https://github.com/kivy/kivy-ios 364 | ios.kivy_ios_branch = master 365 | 366 | # Another platform dependency: ios-deploy 367 | # Uncomment to use a custom checkout 368 | #ios.ios_deploy_dir = ../ios_deploy 369 | # Or specify URL and branch 370 | ios.ios_deploy_url = https://github.com/phonegap/ios-deploy 371 | ios.ios_deploy_branch = 1.10.0 372 | 373 | # (bool) Whether or not to sign the code 374 | ios.codesign.allowed = false 375 | 376 | # (str) Name of the certificate to use for signing the debug version 377 | # Get a list of available identities: buildozer ios list_identities 378 | #ios.codesign.debug = "iPhone Developer: ()" 379 | 380 | # (str) The development team to use for signing the debug version 381 | #ios.codesign.development_team.debug = 382 | 383 | # (str) Name of the certificate to use for signing the release version 384 | #ios.codesign.release = %(ios.codesign.debug)s 385 | 386 | # (str) The development team to use for signing the release version 387 | #ios.codesign.development_team.release = 388 | 389 | # (str) URL pointing to .ipa file to be installed 390 | # This option should be defined along with `display_image_url` and `full_size_image_url` options. 391 | #ios.manifest.app_url = 392 | 393 | # (str) URL pointing to an icon (57x57px) to be displayed during download 394 | # This option should be defined along with `app_url` and `full_size_image_url` options. 395 | #ios.manifest.display_image_url = 396 | 397 | # (str) URL pointing to a large icon (512x512px) to be used by iTunes 398 | # This option should be defined along with `app_url` and `display_image_url` options. 399 | #ios.manifest.full_size_image_url = 400 | 401 | 402 | [buildozer] 403 | 404 | # (int) Log level (0 = error only, 1 = info, 2 = debug (with command output)) 405 | log_level = 2 406 | 407 | # (int) Display warning if buildozer is run as root (0 = False, 1 = True) 408 | warn_on_root = 1 409 | 410 | # (str) Path to build artifact storage, absolute or relative to spec file 411 | # build_dir = ./.buildozer 412 | 413 | # (str) Path to build output (i.e. .apk, .aab, .ipa) storage 414 | # bin_dir = ./bin 415 | 416 | # ----------------------------------------------------------------------------- 417 | # List as sections 418 | # 419 | # You can define all the "list" as [section:key]. 420 | # Each line will be considered as a option to the list. 421 | # Let's take [app] / source.exclude_patterns. 422 | # Instead of doing: 423 | # 424 | #[app] 425 | #source.exclude_patterns = license,data/audio/*.wav,data/images/original/* 426 | # 427 | # This can be translated into: 428 | # 429 | #[app:source.exclude_patterns] 430 | #license 431 | #data/audio/*.wav 432 | #data/images/original/* 433 | # 434 | 435 | 436 | # ----------------------------------------------------------------------------- 437 | # Profiles 438 | # 439 | # You can extend section / key with a profile 440 | # For example, you want to deploy a demo version of your application without 441 | # HD content. You could first change the title to add "(demo)" in the name 442 | # and extend the excluded directories to remove the HD content. 443 | # 444 | #[app@demo] 445 | #title = My Application (demo) 446 | # 447 | #[app:source.exclude_patterns@demo] 448 | #images/hd/* 449 | # 450 | # Then, invoke the command line with the "demo" profile: 451 | # 452 | #buildozer --profile demo android debug 453 | -------------------------------------------------------------------------------- /Whatsapp Clone/demo/__pycache__/demo.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/demo/__pycache__/demo.cpython-310.pyc -------------------------------------------------------------------------------- /Whatsapp Clone/demo/__pycache__/demo.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/demo/__pycache__/demo.cpython-36.pyc -------------------------------------------------------------------------------- /Whatsapp Clone/demo/__pycache__/group.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/demo/__pycache__/group.cpython-310.pyc -------------------------------------------------------------------------------- /Whatsapp Clone/demo/__pycache__/group.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haddiebakrie/WhatsApp-Redesign/9fa90675a1cce5428ffb5a430c1dfb58d25d82f8/Whatsapp Clone/demo/__pycache__/group.cpython-36.pyc -------------------------------------------------------------------------------- /Whatsapp Clone/demo/demo.py: -------------------------------------------------------------------------------- 1 | chats = { 2 | 3 | "anita": ["hey;2:20 PM;read;you", "hi whats up;2:20 PM;read;friend", "how are you doing?;2:20 PM;read;you","doing great you?;2:20 PM;waiting;friend", 4 | "staying alive;2:20 PM;delivered;you"], 5 | "jooyce": ["what's the deal with that guy from earlier;2:20 PM;read;you", "seriously i dont know;2:20 PM;read;friend", "we re not good enough to help move? Lol.;2:20 PM;read;you", "Lol guess we re nt;2:20 PM;read;friend", 6 | "you coming to bariat's;2:20 PM;read;you","yeah what time?;2:50 PM;read;friend", "hope its not late ;2:58 PM;read;friend"], 7 | "weeknd": ["hey;2:20 PM;read;you","hi whats up;2:20 PM;read;friend", "how are you doing?;2:20 PM;read;you","doing great you?;2:20 PM;waiting;friend", 8 | "he really made a fool out of me;2:20 PM;delivered;you"], 9 | "jordan": ["hey;2:20 PM;read;you","hi whats up;2:20 PM;read;friend", "how are you doing?;2:20 PM;read;you","doing great you?;2:20 PM;waiting;friend", 10 | "you keep crying to me;2:20 PM;delivered;you"], 11 | "breezy": ["hey;2:20 PM;read;you","hi whats up;2:20 PM;read;friend", "how are you doing?;2:20 PM;read;you","doing great you?;2:20 PM;waiting;friend", 12 | "staying alive;2:20 PM;delivered;you"], 13 | "wizkid": ["hey;2:20 PM;read;you","hi whats up;2:20 PM;read;friend", "how are you doing?;2:20 PM;read;you","doing great you?;2:20 PM;waiting;friend", 14 | "hopefully something comes up;2:20 PM;delivered;you"], 15 | "davido": ["hey;2:20 PM;read;you","hi whats up;2:20 PM;read;friend", "how are you doing?;2:20 PM;read;you","doing great you?;2:20 PM;waiting;friend", 16 | "i am down here;2:20 PM;delivered;you"], 17 | "zendaya": ["hey;2:20 PM;read;you","hi whats up;2:20 PM;read;friend", "how are you doing?;2:20 PM;read;you","doing great you?;2:20 PM;waiting;friend", 18 | "what tf were you thinking ;2:20 PM;delivered;you"], 19 | "rihanna": ["hey;2:20 PM;read;you","hi whats up;2:20 PM;read;friend", "how are you doing?;2:20 PM;read;you","doing great you?;2:20 PM;waiting;friend", 20 | "i won bro;2:20 PM;delivered;you"], 21 | } 22 | 23 | anita = { 24 | "name": "Anita", 25 | "image": "assets/images/12.png", 26 | "active": True, 27 | "msg": chats["anita"], 28 | } 29 | 30 | jooyce = { 31 | "name": "Jooyce", 32 | "image": "assets/images/16.jpg", 33 | "active": False, 34 | "msg": chats["jooyce"], 35 | } 36 | 37 | weeknd = { 38 | "name": "Weeknd", 39 | "image": "assets/images/weeknd.jpg", 40 | "active": True, 41 | "msg": chats["weeknd"], 42 | } 43 | 44 | jordan = { 45 | "name": "Jordan", 46 | "image": "assets/images/jordan.jpg", 47 | "active": False, 48 | "msg": chats["jordan"], 49 | } 50 | 51 | breezy = { 52 | "name": "Breezy", 53 | "image": "assets/images/breezy.jpg", 54 | "active": True, 55 | "msg": chats["breezy"], 56 | } 57 | 58 | wizkid = { 59 | "name": "Wizkid", 60 | "image": "assets/images/wizkid.jpg", 61 | "active": False, 62 | "msg": chats["wizkid"], 63 | } 64 | 65 | davido = { 66 | "name": "Davido", 67 | "image": "assets/images/davido.jpg", 68 | "active": False, 69 | "msg": chats["davido"], 70 | } 71 | 72 | zendaya = { 73 | "name": "Zendaya", 74 | "image": "assets/images/14.jpg", 75 | "active": False, 76 | "msg": chats["zendaya"], 77 | } 78 | 79 | rihanna = { 80 | "name": "Rihanna", 81 | "image": "assets/images/rihanna.png", 82 | "active": True, 83 | "msg": chats["rihanna"], 84 | } 85 | 86 | profiles = [anita, jooyce, weeknd, jordan, breezy, wizkid, davido, zendaya, rihanna] 87 | 88 | print(profiles[0]["msg"]) 89 | # print(anita.items()) 90 | # chats.items -------------------------------------------------------------------------------- /Whatsapp Clone/demo/group.py: -------------------------------------------------------------------------------- 1 | emo = { 2 | 'name': 'Sad Lyric Videos', 3 | 'image': 'assets/images/emotion.jpg', 4 | 'msg': 'just dropped a mashup click the link below to watch;2:20;read', 5 | } 6 | 7 | money = { 8 | 'name': 'Bag Chasers $$', 9 | 'image': 'assets/images/money.jpg', 10 | 'msg': 'New Airdrop Alert!!!;2:20;read', 11 | } 12 | 13 | tnt = { 14 | 'name': 'Ask Top Notch Tech', 15 | 'image': 'assets/images/tnt.png', 16 | 'msg': 'that was fun tho;2:20;read', 17 | } 18 | 19 | groups = [emo, money, tnt] 20 | -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/pages/call_screen.kv: -------------------------------------------------------------------------------- 1 | : 2 | MDBoxLayout: 3 | orientation: "vertical" 4 | md_bg_color: app.theme_cls.bg_normal 5 | MDTopAppBar: 6 | id: logoToolBar 7 | height: 50 8 | title: "Calls" 9 | right_action_items: [['invert-colors', lambda x: app.show_theme_picker()]] 10 | 11 | 12 | ScrollView: 13 | do_scroll_y: True 14 | bar_width: 0 15 | MDBoxLayout: 16 | adaptive_height: True 17 | # size_hint_y: None 18 | orientation: 'vertical' 19 | md_bg_color: app.theme_cls.bg_normal 20 | CallListItem: 21 | friend_name: 'Lorem Ipsum' 22 | call_date: 'Jan 14, 11:26 PM' 23 | call_type: 'out' 24 | call_mode: 'video' 25 | friend_avatar: 'assets/images/1.jpg' 26 | count: '1' 27 | isMissed: True 28 | 29 | MDBoxLayout: 30 | size_hint_y: None 31 | NavBar: 32 | three: [1, 1, 1, 1] -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/pages/chat_screen.kv: -------------------------------------------------------------------------------- 1 | : 2 | MDBoxLayout: 3 | orientation: "vertical" 4 | md_bg_color: app.theme_cls.bg_normal 5 | MDBoxLayout: 6 | size_hint_y: None 7 | height: 50 8 | spacing: 5 9 | md_bg_color: app.theme_cls.bg_normal 10 | padding: [0, 0, 10, 0] 11 | MDIconButton: 12 | icon: 'arrow-left' 13 | theme_text_color: 'Custom' 14 | text_color: app.theme_cls.opposite_bg_normal 15 | user_font_size: 18 16 | size_hint: (None, None) 17 | pos_hint: {'center_y':.5} 18 | size: 30, 30 19 | padding: 0 20 | pos_hint: {'center_y':.5} 21 | on_press: app.change_screen('message') 22 | MDBoxLayout: 23 | size_hint: None, None 24 | size: 30, 30 25 | orientation: 'vertical' 26 | pos_hint: {'center_y': .5} 27 | Avatar: 28 | source: root.image 29 | size: 30, 30 30 | size_hint: None, None 31 | MDBoxLayout: 32 | orientation: "vertical" 33 | padding: [0, 10, 0, 10] 34 | Label: 35 | text: root.text 36 | size: self.texture_size 37 | size_hint_y: None 38 | size_hint_x: None 39 | font_size: 17 40 | color: app.theme_cls.opposite_bg_normal 41 | bold: True 42 | MDBoxLayout: 43 | size_hint_x: None 44 | spacing: 5 45 | MDIcon: 46 | icon: 'circle' 47 | theme_text_color: 'Custom' 48 | color: [0, 1, 0, 1] if root.active == True else [.5, .5, .5, 1] 49 | font_size: 10 50 | size: 10, 10 51 | size_hint: None, None 52 | Label: 53 | text: 'Active' if root.active == True else 'offline' 54 | size: self.texture_size 55 | size_hint_y: None 56 | size_hint_x: None 57 | font_size: 10 58 | color: app.theme_cls.opposite_bg_normal 59 | 60 | MDBoxLayout: 61 | size_hint_x: None 62 | spacing: 5 63 | MDIconButton: 64 | icon: 'video-outline' 65 | theme_text_color: 'Custom' 66 | text_color: app.theme_cls.primary_color 67 | user_font_size: 16 68 | size_hint: (None, None) 69 | pos_hint: {'center_y':.5} 70 | size: 30, 30 71 | padding: 0 72 | md_bg_color: app.theme_cls.bg_darkest if app.theme_cls.theme_style == 'Light' else app.theme_cls.bg_dark 73 | MDIconButton: 74 | icon: 'phone-outline' 75 | theme_text_color: 'Custom' 76 | text_color: app.theme_cls.primary_color 77 | user_font_size: 16 78 | size_hint: (None, None) 79 | pos_hint: {'center_y':.5} 80 | size: 30, 30 81 | padding: 0 82 | md_bg_color: app.theme_cls.bg_darkest if app.theme_cls.theme_style == 'Light' else app.theme_cls.bg_dark 83 | MDIconButton: 84 | icon: 'dots-vertical' 85 | theme_text_color: 'Custom' 86 | text_color: app.theme_cls.primary_color 87 | user_font_size: 20 88 | size_hint: (None, None) 89 | pos_hint: {'center_y':.5} 90 | size: 30, 30 91 | padding: 0 92 | md_bg_color: app.theme_cls.bg_darkest if app.theme_cls.theme_style == 'Light' else app.theme_cls.bg_dark 93 | 94 | ScrollView: 95 | MDList: 96 | id: msglist 97 | spacing: 5 98 | padding: [0, 10, 0, 10] 99 | 100 | MDBoxLayout: 101 | padding: [10, ] 102 | spacing: 5 103 | size_hint_y:None 104 | height: 40 105 | md_bg_color: app.theme_cls.bg_normal 106 | TextFieldWithTwoIcon: 107 | MDIconButton: 108 | size_hint: (None, None) 109 | icon: 'send' 110 | elevation: 0 111 | user_font_size: 16 112 | theme_text_color: 'Custom' 113 | text_color: [1, 1, 1, 1] 114 | md_bg_color: app.theme_cls.accent_color 115 | canvas.before: 116 | PushMatrix 117 | Rotate: 118 | angle: 45 119 | origin: self.center 120 | canvas.after: 121 | PopMatrix -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/pages/group_screen.kv: -------------------------------------------------------------------------------- 1 | : 2 | MDBoxLayout: 3 | orientation: "vertical" 4 | md_bg_color: app.theme_cls.bg_normal 5 | MDTopAppBar: 6 | id: logoToolBar 7 | height: 50 8 | title: "Groups" 9 | right_action_items: [['invert-colors', lambda x: app.show_theme_picker()]] 10 | 11 | ScrollView: 12 | do_scroll_y: True 13 | bar_width: 0 14 | MDBoxLayout: 15 | adaptive_height: True 16 | # size_hint_y: None 17 | orientation: 'vertical' 18 | md_bg_color: app.theme_cls.bg_normal 19 | id: grouplist 20 | 21 | MDBoxLayout: 22 | size_hint_y: None 23 | NavBar: 24 | two: [1, 1, 1, 1] -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/widgets/avatar.kv: -------------------------------------------------------------------------------- 1 | : 2 | size: (45, 45) 3 | size_hint: (None, None) 4 | source: root.source 5 | MDCard: 6 | size: root.size 7 | size_hint: (None, None) 8 | radius: [30, ] 9 | md_bg_color: app.theme_cls.accent_color 10 | elevation: 0 11 | pos_hint: {'center_x': .5, 'center_y': .5} 12 | 13 | FitImage: 14 | size: root.size[0] - 3, root.size[1]-3 15 | radius: [30, ] 16 | size_hint: (None, None) 17 | source: root.source 18 | pos_hint: {'center_x': .5, 'center_y': .5} -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/widgets/bottom_navigator.kv: -------------------------------------------------------------------------------- 1 | : 2 | orientation: 'vertical' 3 | size_hint_y: None 4 | padding: [0, 0, 0, 10] 5 | one: [1, 1, 1, .5] 6 | two: [1, 1, 1, .5] 7 | three: [1, 1, 1, .5] 8 | four: [1, 1, 1, .5] 9 | MDCard: 10 | id: navBar 11 | radius: [18, ] 12 | md_bg_color: app.theme_cls.primary_color 13 | padding: [10, 0, 10, 0] 14 | size_hint_y: None 15 | size_hint_x: None 16 | width: 220 17 | height: 40 18 | pos_hint: {'center_x': .5} 19 | 20 | NavIcon: 21 | text_color: root.one 22 | on_press: app.change_screen('message') 23 | icon: 'message-minus-outline' 24 | NavIcon: 25 | text_color: root.two 26 | on_press: app.change_screen('group') 27 | icon: 'account-group-outline' 28 | NavIcon: 29 | text_color: root.three 30 | on_press: app.change_screen('call') 31 | icon: 'phone-in-talk-outline' 32 | # NavIcon: 33 | # text_color: root.four 34 | # on_press: app.change_screen('contact') 35 | # icon: 'account-plus-outline' 36 | 37 | 38 | 39 | : 40 | pos_hint: {'center_y': .5} 41 | theme_text_color: 'Custom' 42 | size_hint_x: .1 43 | user_font_size: 20 44 | size: 45, 45 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/widgets/call_list_item.kv: -------------------------------------------------------------------------------- 1 | : 2 | ripple_behavior: True 3 | md_bg_color: 0, 0, 0, 0 4 | elevation: 0 5 | size_hint_y: None 6 | padding: [10, 0, 10, 0] 7 | spacing: 10 8 | height: chatAvatar.height + 10 9 | friend_name: 'Lorem Ipsum' 10 | call_date: 'Jan 14, 11:26 PM' 11 | call_type: 'out' 12 | call_mode: 'video' 13 | friend_avatar: 'assets/images/1.jpg' 14 | count: '1' 15 | isMissed: True 16 | Avatar: 17 | id: chatAvatar 18 | source: root.friend_avatar 19 | pos_hint: {"center_y": .5} 20 | radius: [30, ] 21 | MDBoxLayout: 22 | # md_bg_color: 1, 0, 1, 1 23 | orientation: "vertical" 24 | padding: [0, 0, 0, 10] 25 | spacing: 2 26 | Label: 27 | id: chatUsername 28 | text: root.friend_name 29 | theme_text_color: 'Custom' 30 | size: self.texture_size 31 | size_hint_y: None 32 | size_hint_x: None 33 | font_size: 15 34 | color: app.theme_cls.opposite_bg_normal 35 | bold: True 36 | # 37 | Label: 38 | id: callDate 39 | text: '({}) {}'.format(root.count, root.call_date) 40 | size: self.texture_size 41 | theme_text_color: 'Custom' 42 | size_hint_y: None 43 | size_hint_x: None 44 | bold: True 45 | font_size: 13 46 | color: [.5, .5, .5, 1] 47 | BoxLayout: 48 | height: call_modeid.height + call_typeid.height 49 | size_hint_y: None 50 | orientation: 'vertical' 51 | width: call_typeid.width 52 | size_hint_x: None 53 | pos_hint: {'center_y': .5} 54 | spacing: 2 55 | MDIcon: 56 | id: call_modeid 57 | theme_style: 'Custom' 58 | icon: root.call_mode 59 | size_hint: None, None 60 | font_size: 18 61 | size: 20, 20 62 | # pos_hint: {"center_x": .5, 'center_y': .5} 63 | color: app.theme_cls.primary_color 64 | MDIcon: 65 | theme_text_color: 'Custom' 66 | id: call_typeid 67 | icon: 'arrow-bottom-left' 68 | size_hint_y: None 69 | size_hint_x: None 70 | font_size: 18 71 | size: 20, 20 72 | # pos_hint: {"center_x": .5, 'center_y': .5} 73 | color: [1, 0, 0, 1] if root.isMissed == True else app.primary_color -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/widgets/chat_list_item.kv: -------------------------------------------------------------------------------- 1 | : 2 | ripple_behavior: True 3 | md_bg_color: 0, 0, 0, 0 4 | elevation: 0 5 | size_hint_y: None 6 | padding: [10, 0, 10, 0] 7 | spacing: 10 8 | height: chatAvatar.height + 10 9 | on_press: app.create_chat(root.profile) 10 | Avatar: 11 | id: chatAvatar 12 | source: root.friend_avatar 13 | pos_hint: {"center_y": .5} 14 | radius: [30, ] 15 | MDBoxLayout: 16 | # md_bg_color: 1, 0, 1, 1 17 | orientation: "vertical" 18 | padding: [0, 0, 0, 10] 19 | spacing: 2 20 | Label: 21 | id: chatUsername 22 | text: root.friend_name 23 | theme_text_color: 'Custom' 24 | size: self.texture_size 25 | size_hint_y: None 26 | size_hint_x: None 27 | font_size: 15 28 | color: app.theme_cls.opposite_bg_normal 29 | bold: True 30 | MDLabel: 31 | id: lastMessage 32 | text: root.mssg 33 | height: self.texture_size[1] 34 | theme_text_color: 'Custom' 35 | size_hint_y: None 36 | # size_hint_x: None 37 | bold: True 38 | font_size: 13 39 | color: [.5, .5, .5, 1] if root.isRead != 'new' else app.theme_cls.primary_color 40 | shorten: True 41 | markup: True 42 | shorten_from: 'right' 43 | BoxLayout: 44 | # height: chatCount.height + time.height 45 | # size_hint_y: None 46 | orientation: 'vertical' 47 | width: time.width 48 | size_hint_x: None 49 | pos_hint: {'center_y': .5} 50 | spacing: 2 51 | padding: [0, 15, 0, 5] 52 | Label: 53 | id: time 54 | text: root.timestamp 55 | size: self.texture_size 56 | size_hint_y: None 57 | size_hint_x: None 58 | font_size: 9 59 | color: app.theme_cls.opposite_bg_normal 60 | 61 | MDIcon: 62 | #: set icons {'read': 'checkbox-multiple-marked-circle','delivered': 'checkbox-multiple-marked-circle-outline' ,'new': 'circle'} 63 | id: chatCount 64 | theme_text_color: 'Custom' 65 | icon: icons[root.isRead] if root.isRead in icons.keys() else '' 66 | size_hint: None, None 67 | font_size: 12 68 | size: 20, 20 69 | pos_hint: {"center_x": .5, 'center_y': .5} 70 | text_color: app.theme_cls.primary_color -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/widgets/chatbubble.kv: -------------------------------------------------------------------------------- 1 | : 2 | id: chtbld 3 | md_bg_color: [0, 0, 0, 0] 4 | size_hint_y: None 5 | height: 60 6 | adaptive_height: True 7 | width: root.width 8 | padding: [10, 0, 10, 0] 9 | orientation: 'vertical' 10 | 11 | MDBoxLayout: 12 | height: msg_content.height + timed.height + 10 13 | width: msg_content.width + wid1.width + wid2.width 14 | size_hint: None, None 15 | pos_hint: {'right': 1} if chtbld.sender == 'you' else {'left': 1} 16 | radius: [10, 10, (1, -5), 10] if self.pos_hint == {'right': 1} else [10, 10, 10, (1, -5)] 17 | md_bg_color: app.theme_cls.bg_darkest if app.theme_cls.theme_style == 'Light' else app.theme_cls.bg_dark 18 | Spacer: 19 | id: wid1 20 | MDBoxLayout: 21 | orientation: 'vertical' 22 | height: msg_content.height + tc.height + wid3.height 23 | width: msg_content.width 24 | 25 | MDLabel: 26 | id: msg_content 27 | text: root.msg 28 | width: tc.width if self.texture_size[0] < tc.width else self.texture_size[0] 29 | height: self.texture_size[1] 30 | size_hint_y: None 31 | text_size: chtbld.width-30 if self.width >= chtbld.width-30 else None, None 32 | halign: 'left' 33 | color: app.theme_cls.opposite_bg_normal 34 | 35 | MDBoxLayout: 36 | id: tc 37 | size_hint_y: None 38 | height: timed.height 39 | width: timed.width + reciepticon.width + 3 40 | spacing: 3 41 | MDLabel: 42 | id: timed 43 | text: root.time 44 | size: self.texture_size 45 | size_hint_y: None 46 | font_size: 9 47 | bold: True 48 | halign: 'right' 49 | text_size: None, None 50 | color: [.8, .8, .8, 1] 51 | MDIcon: 52 | id: reciepticon 53 | #: set iconds {'read': 'check-all', 'waiting': 'clock-time-three-outline','delivered': 'check'} 54 | theme_text_color: 'Custom' 55 | icon: iconds[chtbld.isRead] if chtbld.isRead in iconds.keys() else '' 56 | size_hint: None, None 57 | font_size: 12 58 | size: (12, 12) 59 | color: timed.color 60 | Spacer: 61 | id: wid3 62 | height: 5 63 | Spacer: 64 | id: wid2 65 | 66 | : 67 | id: wid 68 | width: 5 69 | size_hint: None, None -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/widgets/group_list_item.kv: -------------------------------------------------------------------------------- 1 | : 2 | ripple_behavior: True 3 | md_bg_color: 0, 0, 0, 0 4 | elevation: 0 5 | size_hint_y: None 6 | padding: [10, 0, 10, 0] 7 | spacing: 10 8 | height: groupAvatar.height + 10 9 | Avatar: 10 | id: groupAvatar 11 | source: root.group_avatar 12 | pos_hint: {"center_y": .5} 13 | radius: [30, ] 14 | MDBoxLayout: 15 | # md_bg_color: 1, 0, 1, 1 16 | orientation: "vertical" 17 | padding: [0, 0, 0, 10] 18 | Label: 19 | id: groupUsername 20 | text: root.group_name 21 | theme_text_color: 'Custom' 22 | size: self.texture_size 23 | # size_hint_y: None 24 | size_hint_x: None 25 | font_size: 15 26 | color: app.theme_cls.opposite_bg_normal 27 | bold: True 28 | MDLabel: 29 | id: lastMessage 30 | text: root.friend_mssg 31 | height: self.texture_size[1] 32 | theme_text_color: 'Custom' 33 | size_hint_y: None 34 | # size_hint_x: None 35 | bold: True 36 | font_size: 13 37 | color: [.5, .5, .5, 1] if root.isRead != 'new' else app.theme_cls.primary_color 38 | shorten: True 39 | markup: True 40 | shorten_from: 'right' 41 | -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/widgets/story_layout.kv: -------------------------------------------------------------------------------- 1 | : 2 | orientation: 'vertical' 3 | size: (60, 80) 4 | size_hint: (None, None) 5 | spacing: 5 6 | width: avatar.width 7 | Avatar: 8 | id: avatar 9 | source: root.source 10 | pos_hint: {'center_x':.5} 11 | MDLabel: 12 | text: root.text 13 | size: self.texture_size 14 | theme_text_color: 'Custom' 15 | size_hint_y: None 16 | # size_hint_x: None 17 | halign: 'center' 18 | font_size: 9 19 | color: [1, 1, 1, 1] 20 | bold: True 21 | 22 | : 23 | orientation: 'vertical' 24 | size: (45, 80) 25 | size_hint: (None, None) 26 | spacing: 5 27 | MDIconButton: 28 | icon: 'camera-outline' 29 | theme_text_color: 'Custom' 30 | pos_hint: {'center_x': .5} 31 | text_color: [1, 1, 1, 1] 32 | md_bg_color: app.theme_cls.accent_color 33 | user_font_size: 18 34 | size: (40, 40) 35 | size_hint: (None, None) 36 | MDLabel: 37 | text: 'Your Story' 38 | size: self.texture_size 39 | theme_text_color: 'Custom' 40 | size_hint_y: None 41 | # size_hint_x: None 42 | halign: 'center' 43 | font_size: 9 44 | color: [1, 1, 1, 1] 45 | bold: True -------------------------------------------------------------------------------- /Whatsapp Clone/kvs/widgets/text_field.kv: -------------------------------------------------------------------------------- 1 | : 2 | md_bg_color: .9, .9, .9, .9 3 | elevation: 0 4 | height: 40 5 | size_hint_y: None 6 | radius: [15, ] 7 | padding: [5, 5, 5, 5] 8 | hint_text: "Type a message" 9 | icon_right: "paperclip" 10 | icon_left: "emoticon-happy-outline" 11 | icon_righty: "microphone-outline" 12 | MDIconButton: 13 | icon: root.icon_left 14 | size_hint_x: None 15 | user_font_size: 16 16 | size_hint: (None, None) 17 | pos_hint: {'center_y':.5} 18 | theme_text_color: 'Custom' 19 | size: 30, 30 20 | padding: 0 21 | TextInput: 22 | id: textinput 23 | font_size: 12 24 | cursor_color: .5, .5, .5, 1 25 | line_color_normal: 0, 0, 0, 0 26 | line_color_focus: 0, 0, 0, 0 27 | color_mode: "custom" 28 | current_hint_text_color: .5, .5, .5, 1 29 | height: 30 30 | background_color: 0, 0, 0, 0 31 | hint_text: root.hint_text 32 | padding: [5, ] 33 | MDIconButton: 34 | icon: root.icon_right 35 | theme_text_color: 'Custom' 36 | size_hint_x: None 37 | user_font_size: 16 38 | size_hint: (None, None) 39 | size: 30, 30 40 | padding: 0 41 | MDIconButton: 42 | icon: root.icon_righty 43 | theme_text_color: 'Custom' 44 | size_hint_x: None 45 | user_font_size: 16 46 | size_hint: (None, None) 47 | size: 30, 30 48 | padding: 0 -------------------------------------------------------------------------------- /Whatsapp Clone/main.kv: -------------------------------------------------------------------------------- 1 | #: import demo demo.demo 2 | 3 | : 4 | 5 | MDBoxLayout: 6 | orientation: "vertical" 7 | md_bg_color: app.theme_cls.bg_normal 8 | MDTopAppBar: 9 | id: logoToolBar 10 | height: 50 11 | title: "Whatsapp" 12 | right_action_items: [['dots-vertical', lambda x: app.show_theme_picker()]] 13 | margin: 0 14 | 15 | ScrollView: 16 | do_scroll_y: True 17 | effect_cls: 'ScrollEffect' 18 | bar_width: 0 19 | MDBoxLayout: 20 | adaptive_height: True 21 | orientation: 'vertical' 22 | md_bg_color: app.theme_cls.primary_color 23 | spacing: 20 24 | MDBoxLayout: 25 | height: 60 26 | size_hint_y: None 27 | ScrollView: 28 | do_scroll_x: True 29 | do_scroll_y: False 30 | bar_width: 0 31 | MDBoxLayout: 32 | id: story_layout 33 | orientation: 'horizontal' 34 | adaptive_width: True 35 | spacing: 10 36 | padding: [10, 0, 0, 0] 37 | StoryWithIcon: 38 | 39 | MDBoxLayout: 40 | orientation: 'vertical' 41 | md_bg_color: app.theme_cls.bg_normal 42 | size_hint_y: None 43 | adaptive_height: True 44 | radius: [20, 20, 0, 0] 45 | padding: [0, 0, 0, 40] 46 | MDList: 47 | id: chatlist 48 | spacing: 10 49 | MDBoxLayout: 50 | size_hint_y: None 51 | md_bg_color: 0, 0, 0, 0 52 | NavBar: 53 | one: [1, 1, 1, 1] -------------------------------------------------------------------------------- /Whatsapp Clone/main.py: -------------------------------------------------------------------------------- 1 | import kivy 2 | from kivymd.app import MDApp 3 | from kivy.lang import Builder 4 | from kivy.core.window import Window 5 | from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition 6 | from kivy.properties import BooleanProperty, DictProperty, ListProperty, NumericProperty, ObjectProperty, OptionProperty, StringProperty 7 | from kivymd.uix.bottomnavigation import MDBottomNavigationItem 8 | from kivymd.uix.boxlayout import MDBoxLayout 9 | from kivy.uix.boxlayout import BoxLayout 10 | from kivymd.uix.card import MDCard 11 | from kivy.uix.relativelayout import RelativeLayout 12 | from kivymd.uix.picker import MDThemePicker 13 | from kivy.uix.scrollview import ScrollView 14 | from kivymd.uix.selectioncontrol import MDSwitch 15 | from kivymd.uix.list import OneLineAvatarIconListItem 16 | from demo.demo import profiles 17 | import demo.group 18 | from kivymd.uix.label import MDLabel 19 | from kivy.uix.label import Label 20 | from kivy.uix.widget import Widget 21 | 22 | Builder.load_file('kvs/pages/group_screen.kv') 23 | Builder.load_file('kvs/pages/call_screen.kv') 24 | Builder.load_file('kvs/pages/chat_screen.kv') 25 | Builder.load_file('kvs/widgets/story_layout.kv') 26 | Builder.load_file('kvs/widgets/avatar.kv') 27 | Builder.load_file('kvs/widgets/chat_list_item.kv') 28 | Builder.load_file('kvs/widgets/group_list_item.kv') 29 | Builder.load_file('kvs/widgets/call_list_item.kv') 30 | Builder.load_file('kvs/widgets/bottom_navigator.kv') 31 | Builder.load_file('kvs/widgets/text_field.kv') 32 | Builder.load_file('kvs/widgets/chatbubble.kv') 33 | 34 | Window.size = (320, 600) 35 | 36 | class WindowManager(ScreenManager): 37 | '''A window manager to manage switching between sceens.''' 38 | 39 | class MessageScreen(Screen): 40 | '''A screen that display the story fleets and all message histories.''' 41 | 42 | class CallScreen(Screen): 43 | '''A screen that display the call histories.''' 44 | 45 | class ChatScreen(Screen): 46 | '''A screen that display messages with a user.''' 47 | 48 | text = StringProperty() 49 | image = ObjectProperty() 50 | active = BooleanProperty(defaultvalue=False) 51 | 52 | class StoryWithImage(MDBoxLayout): 53 | '''A horizontal layout with an image(profile picture) 54 | and a text(username) - The Story.''' 55 | 56 | text = StringProperty() 57 | source = StringProperty() 58 | 59 | class ChatListItem(MDCard): 60 | '''A clickable chat item for the chat timeline.''' 61 | 62 | isRead = OptionProperty(None, options=['delivered', 'read', 'new', 'waiting']) 63 | friend_name = StringProperty() 64 | mssg = StringProperty() 65 | timestamp = StringProperty() 66 | friend_avatar = StringProperty() 67 | profile = DictProperty() 68 | 69 | class GroupListItem(MDCard): 70 | '''A clickable chat item for the group chat timeline.''' 71 | 72 | isRead = OptionProperty(None, options=['delivered', 'read', 'new', 'waiting']) 73 | group_name = StringProperty() 74 | group_avatar = StringProperty() 75 | friend_mssg = StringProperty() 76 | timestamp = StringProperty() 77 | 78 | class ChatBubble(MDBoxLayout): 79 | '''A chat bubble for the chat screen messages.''' 80 | 81 | profile = DictProperty() 82 | msg = StringProperty() 83 | time = StringProperty() 84 | sender = StringProperty() 85 | isRead = OptionProperty('waiting', options=['read', 'delivered', 'waiting']) 86 | 87 | class GroupScreen(Screen): 88 | '''A screen that display messages history in groups .''' 89 | 90 | class Message(MDLabel): 91 | '''A adaptive text for the chat bubble.''' 92 | 93 | class MainApp(MDApp): 94 | ''' The main App class using kivymd's properties.''' 95 | 96 | def build(self): 97 | ''' Initializes the Application 98 | and returns the root widget''' 99 | self.theme_cls.theme_style = 'Dark' 100 | self.theme_cls.primary_palette = 'Teal' 101 | self.theme_cls.accent_palette = 'Teal' 102 | self.theme_cls.accent_hue = '400' 103 | self.title = "WhatsApp" 104 | self.wm = WindowManager(transition=FadeTransition()) 105 | screens = [ 106 | MessageScreen(name='message'), GroupScreen(name='group'), CallScreen(name='call'), 107 | ChatScreen(name='chat') 108 | ] 109 | for screen in screens: 110 | self.wm.add_widget(screen) 111 | 112 | self.story_builder() 113 | self.chatlist_builder() 114 | self.grouplist_builder() 115 | 116 | return self.wm 117 | 118 | def change_screen(self, screen): 119 | '''Change screen using the window manager.''' 120 | self.wm.current = screen 121 | 122 | def show_theme_picker(self): 123 | '''Display a dialog window to change app's color and theme.''' 124 | theme_dialog = MDThemePicker() 125 | theme_dialog.open() 126 | 127 | def create_chat(self, profile): 128 | '''Get all messages and create a chat screen''' 129 | self.chat_screen = ChatScreen() 130 | self.msg_builder(profile, self.chat_screen) 131 | self.chat_screen.text = profile['name'] 132 | self.chat_screen.image = profile['image'] 133 | self.chat_screen.active = profile['active'] 134 | self.wm.switch_to(self.chat_screen) 135 | 136 | def story_builder(self): 137 | '''Create a Story for each user and 138 | adds it to the story layout''' 139 | for profile in demo.demo.profiles: 140 | self.story = StoryWithImage() 141 | self.story.text = profile['name'] 142 | self.story.source = profile['image'] 143 | self.wm.screens[0].ids['story_layout'].add_widget(self.story) 144 | 145 | def chatlist_builder(self): 146 | '''Create a Chat List Item for each user and 147 | adds it to the Message List''' 148 | for messages in profiles: 149 | for message in messages['msg']: 150 | self.chatitem = ChatListItem() 151 | self.chatitem.profile = messages 152 | self.chatitem.friend_name = messages['name'] 153 | self.chatitem.friend_avatar = messages['image'] 154 | 155 | lastmessage, time, isRead, sender = message.split(';') 156 | self.chatitem.mssg = lastmessage 157 | self.chatitem.timestamp = time 158 | self.chatitem.isRead = isRead 159 | self.chatitem.sender = sender 160 | self.wm.screens[0].ids['chatlist'].add_widget(self.chatitem) 161 | 162 | def msg_builder(self, profile, screen): 163 | '''Create a message bubble for creating chat.''' 164 | for prof in profile['msg']: 165 | for messages in prof.split("~"): 166 | if messages != "": 167 | message, time, isRead, sender = messages.split(";") 168 | self.chatmsg = ChatBubble() 169 | self.chatmsg.msg = message 170 | self.chatmsg.time = time 171 | self.chatmsg.isRead = isRead 172 | self.chatmsg.sender = sender 173 | screen.ids['msglist'].add_widget(self.chatmsg) 174 | else: 175 | print("No message") 176 | 177 | print(self.chatmsg.isRead) 178 | 179 | def grouplist_builder(self): 180 | '''Create a Chat List Item for each group and 181 | adds it to the Group List''' 182 | for group in demo.group.groups: 183 | self.groupitem = GroupListItem() 184 | self.groupitem.group = group 185 | self.groupitem.group_name = group['name'] 186 | self.groupitem.group_avatar = group['image'] 187 | self.groupitem.friend_mssg, self.groupitem.timestamp, self.groupitem.isRead = group['msg'].split(';') 188 | self.wm.screens[1].ids['grouplist'].add_widget(self.groupitem) 189 | 190 | if __name__ == "__main__": 191 | MainApp().run() --------------------------------------------------------------------------------