diff --git a/android/app/build.gradle b/android/app/build.gradle index 9a2e79e826f9d67385255e09b0072a84f988b6a5..4cb92c930eb8d23153d82b7143a74c5e85c9e724 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -37,7 +37,7 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 33 + compileSdkVersion 34 namespace "org.benoitharrault.colors" defaultConfig { diff --git a/android/gradle.properties b/android/gradle.properties index 604fc088e204d265443088fe8d1680c63a2b132f..c8bbff9bd599a7c3ffbe76de5a61ead3de90631a 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=0.0.38 -app.versionCode=38 +app.versionName=0.0.39 +app.versionCode=39 diff --git a/assets/icons/colors_5.png b/assets/icons/colors_5.png deleted file mode 100644 index dd0a276e105a79aa25ca36f6cc4d2f69c77df81f..0000000000000000000000000000000000000000 Binary files a/assets/icons/colors_5.png and /dev/null differ diff --git a/assets/icons/colors_6.png b/assets/icons/colors_6.png deleted file mode 100644 index 2a63916ed00f0570bedd1647e34706d041fbec44..0000000000000000000000000000000000000000 Binary files a/assets/icons/colors_6.png and /dev/null differ diff --git a/assets/icons/colors_7.png b/assets/icons/colors_7.png deleted file mode 100644 index fdc1669a1d89ed225cc4624319ff01558ab987b4..0000000000000000000000000000000000000000 Binary files a/assets/icons/colors_7.png and /dev/null differ diff --git a/assets/icons/colors_8.png b/assets/icons/colors_8.png deleted file mode 100644 index b660ef3e29aefc5c940a327aaf7a22d76a73bb23..0000000000000000000000000000000000000000 Binary files a/assets/icons/colors_8.png and /dev/null differ diff --git a/assets/icons/level_easy.png b/assets/icons/level_easy.png deleted file mode 100644 index aa9e2485272c12fd99d9e1faae5d71d027ee5431..0000000000000000000000000000000000000000 Binary files a/assets/icons/level_easy.png and /dev/null differ diff --git a/assets/icons/level_hard.png b/assets/icons/level_hard.png deleted file mode 100644 index 433c686b984fd22c4966def3dedcaf7384951810..0000000000000000000000000000000000000000 Binary files a/assets/icons/level_hard.png and /dev/null differ diff --git a/assets/icons/level_medium.png b/assets/icons/level_medium.png deleted file mode 100644 index 213f2ca844afb0cea47cc4bdd1b865433b068b59..0000000000000000000000000000000000000000 Binary files a/assets/icons/level_medium.png and /dev/null differ diff --git a/assets/icons/level_nightmare.png b/assets/icons/level_nightmare.png deleted file mode 100644 index df4182c1e228bbb33c5546d2df38d16ca1edd4f2..0000000000000000000000000000000000000000 Binary files a/assets/icons/level_nightmare.png and /dev/null differ diff --git a/assets/icons/size_extra.png b/assets/icons/size_extra.png deleted file mode 100644 index d3401d9dd4df7a871eb7ac88592707f63480d0dc..0000000000000000000000000000000000000000 Binary files a/assets/icons/size_extra.png and /dev/null differ diff --git a/assets/icons/size_large.png b/assets/icons/size_large.png deleted file mode 100644 index 18b3420564654a9adf32e5a91d0d41f82fd4e2ce..0000000000000000000000000000000000000000 Binary files a/assets/icons/size_large.png and /dev/null differ diff --git a/assets/icons/size_medium.png b/assets/icons/size_medium.png deleted file mode 100644 index 4b4f7754fb46de7cf2ddfc265da900bf77cc0d3e..0000000000000000000000000000000000000000 Binary files a/assets/icons/size_medium.png and /dev/null differ diff --git a/assets/icons/size_small.png b/assets/icons/size_small.png deleted file mode 100644 index 2c72840d2dfe2dfb36791973a159869a325de758..0000000000000000000000000000000000000000 Binary files a/assets/icons/size_small.png and /dev/null differ diff --git a/assets/icons/skin_default.png b/assets/icons/skin_default.png deleted file mode 100644 index ee53cc12eaad99722e3dd8fadd52e76bdf5ed977..0000000000000000000000000000000000000000 Binary files a/assets/icons/skin_default.png and /dev/null differ diff --git a/assets/skins/default_0.png b/assets/skins/default_0.png deleted file mode 100644 index 4d1712540f2a45d43a2aa512132e7274f1daf686..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_0.png and /dev/null differ diff --git a/assets/skins/default_1.png b/assets/skins/default_1.png deleted file mode 100644 index 3ca3e7164af5cde6e6750172c2149cb63ebb7165..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_1.png and /dev/null differ diff --git a/assets/skins/default_2.png b/assets/skins/default_2.png deleted file mode 100644 index 56ad59eff020c5dd84e9d257ff91c5f8f88e6f33..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_2.png and /dev/null differ diff --git a/assets/skins/default_3.png b/assets/skins/default_3.png deleted file mode 100644 index e92c6694a192606905b8119f2a213b8cadf14ba5..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_3.png and /dev/null differ diff --git a/assets/skins/default_4.png b/assets/skins/default_4.png deleted file mode 100644 index 74feaa46de20c31c30e28c8c1dd96d5bff212f02..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_4.png and /dev/null differ diff --git a/assets/skins/default_5.png b/assets/skins/default_5.png deleted file mode 100644 index abcf897497ebc0ccab435b576985dd854be011fe..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_5.png and /dev/null differ diff --git a/assets/skins/default_6.png b/assets/skins/default_6.png deleted file mode 100644 index aee88ace319e14392688b29f92fa0da137bb4339..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_6.png and /dev/null differ diff --git a/assets/skins/default_7.png b/assets/skins/default_7.png deleted file mode 100644 index 3e0ac15c6eea57e437afc36ebf81a618b342256e..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_7.png and /dev/null differ diff --git a/assets/skins/default_8.png b/assets/skins/default_8.png deleted file mode 100644 index 70b58df7443e74de8523829600b4c6cc19eab5a9..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_8.png and /dev/null differ diff --git a/assets/translations/en.json b/assets/translations/en.json index c40bf79ffe85272000814513df69af38c0612b16..92299163019c59771191b4b86fb4a41f0ece93f1 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -1,8 +1,6 @@ { "app_name": "Colors", - "long_press_to_quit": "Long press to quit game...", - "bottom_nav_home": "Game", "bottom_nav_settings": "Settings", "bottom_nav_about": "About", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 895e185dafe2587e69063bc03ed5fcd1f8dcc27d..dc7d503692165e64de23d0191442b6ada8bacb6d 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -1,8 +1,6 @@ { "app_name": "Colors", - "long_press_to_quit": "Appuyer longtemps pour quitter le jeu...", - "bottom_nav_home": "Jeu", "bottom_nav_settings": "Réglages", "bottom_nav_about": "Infos", diff --git a/fastlane/metadata/android/en-US/changelogs/39.txt b/fastlane/metadata/android/en-US/changelogs/39.txt new file mode 100644 index 0000000000000000000000000000000000000000..9bb4c4dee10043312bc54a49a258422743bdc041 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/39.txt @@ -0,0 +1 @@ +Improve application architecture. diff --git a/fastlane/metadata/android/fr-FR/changelogs/39.txt b/fastlane/metadata/android/fr-FR/changelogs/39.txt new file mode 100644 index 0000000000000000000000000000000000000000..5face79935538bfb3371042404b6c3586cc87f31 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/39.txt @@ -0,0 +1 @@ +Amélioration de l'architecture de l'application. diff --git a/icons/build_game_icons.sh b/icons/build_game_icons.sh index 1817ed00997b8351cf7772ac11dc7dc3c75cde5d..7ea6ed5d23526aa94c9626826ffd4545141a1674 100755 --- a/icons/build_game_icons.sh +++ b/icons/build_game_icons.sh @@ -22,31 +22,6 @@ AVAILABLE_GAME_IMAGES=" game_win " -# Settings images -AVAILABLES_GAME_SETTINGS=" - colors:5,6,7,8 - level:easy,medium,hard,nightmare - size:small,medium,large,extra -" - -# Skins -AVAILABLE_SKINS=" - default -" - -# Images per skin -SKIN_IMAGES=" - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -" - ####################################################### # optimize svg @@ -89,41 +64,13 @@ function build_icon() { optipng ${OPTIPNG_OPTIONS} ${TARGET} } -function build_settings_icons() { - INPUT_STRING="$1" - - SETTING_NAME="$(echo "${INPUT_STRING}" | cut -d":" -f1)" - SETTING_VALUES="$(echo "${INPUT_STRING}" | cut -d":" -f2 | tr "," " ")" - - for SETTING_VALUE in ${SETTING_VALUES} - do - SETTING_CODE="${SETTING_NAME}_${SETTING_VALUE}" - build_icon ${CURRENT_DIR}/${SETTING_CODE}.svg ${ASSETS_DIR}/icons/${SETTING_CODE}.png - done -} - -function build_icon_for_skin() { - SKIN_CODE="$1" - - # skin main image - build_icon ${CURRENT_DIR}/skin_${SKIN_CODE}.svg ${ASSETS_DIR}/icons/skin_${SKIN_CODE}.png - - # skin images - for SKIN_IMAGE in ${SKIN_IMAGES} - do - build_icon ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${ASSETS_DIR}/skins/${SKIN_CODE}_${SKIN_IMAGE}.png - done -} - ####################################################### # Create output folders mkdir -p ${ASSETS_DIR}/icons -mkdir -p ${ASSETS_DIR}/skins # Delete existing generated images find ${ASSETS_DIR}/icons -type f -name "*.png" -delete -find ${ASSETS_DIR}/skins -type f -name "*.png" -delete # build game images for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES} @@ -131,14 +78,3 @@ do build_icon ${CURRENT_DIR}/${GAME_IMAGE}.svg ${ASSETS_DIR}/icons/${GAME_IMAGE}.png done -# build settings images -for GAME_SETTING in ${AVAILABLES_GAME_SETTINGS} -do - build_settings_icons "${GAME_SETTING}" -done - -# build skins images -for SKIN in ${AVAILABLE_SKINS} -do - build_icon_for_skin "${SKIN}" -done diff --git a/icons/colors_5.svg b/icons/colors_5.svg deleted file mode 100644 index 2f218e9986906d5f873c0ff7dbfce088b3a102bf..0000000000000000000000000000000000000000 --- a/icons/colors_5.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#97c05c" stroke="#000" stroke-width="2"/><g transform="translate(-1.0061 .33115)" aria-label="5"><path d="m63.315 55.063q0 2.2656-0.85938 4.2188-0.83984 1.9336-2.4609 3.3203-1.7969 1.4844-4.1406 2.207-2.3242 0.70312-5.3125 0.70312-3.4961-0.01953-5.918-0.56641-2.4023-0.52734-3.9258-1.1914v-6.4258h0.82031q1.7773 1.0547 3.8281 1.7578t4.082 0.70312q1.2305 0 2.6562-0.27344 1.4453-0.29297 2.2852-1.0352 0.66406-0.60547 0.99609-1.2305 0.35156-0.625 0.35156-1.9336 0-1.0156-0.46875-1.7383-0.44922-0.74219-1.1719-1.1914-1.0547-0.64453-2.5391-0.83984-1.4844-0.21484-2.6953-0.21484-1.7578 0-3.3789 0.3125-1.6016 0.29297-2.8125 0.58594h-0.85938v-16.406h20.684v5.5664h-13.633v4.7461q0.60547-0.03906 1.5234-0.05859 0.9375-0.03906 1.6406-0.03906 2.4023 0 4.2773 0.46875 1.8945 0.44922 3.2617 1.2695 1.7773 1.0742 2.7734 2.8516 0.99609 1.7578 0.99609 4.4336z"/></g><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg> diff --git a/icons/colors_6.svg b/icons/colors_6.svg deleted file mode 100644 index 6df1641a1ea326ff73fc5de9229f6722ac9acd11..0000000000000000000000000000000000000000 --- a/icons/colors_6.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#f29c38" stroke="#000" stroke-width="2"/><g transform="translate(3.8694 .21001)" aria-label="6"><path d="m59.025 55.399q0 2.2461-0.82031 4.2188t-2.3047 3.3203q-1.582 1.4453-3.6719 2.207-2.0703 0.76172-4.8633 0.76172-2.6172 0-4.7852-0.70312-2.1484-0.72266-3.6914-2.1875-1.7773-1.6797-2.7148-4.3359t-0.9375-6.3477q0-3.8281 0.87891-6.7969t2.8711-5.2539q1.9141-2.1875 4.9609-3.3984 3.0664-1.2109 7.2852-1.2109 1.4258 0 3.125 0.19531t2.207 0.29297v5.7227h-0.74219q-0.52734-0.25391-1.7969-0.56641-1.25-0.33203-2.8516-0.33203-3.75 0-5.8398 1.8359t-2.5195 5.1172q1.5039-0.89844 3.1641-1.4453 1.6797-0.56641 3.6133-0.56641 1.6992 0 3.1445 0.39062 1.4648 0.39062 2.7148 1.25 1.6211 1.1328 2.5977 3.0469 0.97656 1.9141 0.97656 4.7852zm-8.8867 4.3945q0.60547-0.66406 0.95703-1.5625 0.37109-0.91797 0.37109-2.4805 0-1.4258-0.41016-2.3242-0.41016-0.91797-1.1328-1.4648-0.70312-0.54688-1.6602-0.74219-0.95703-0.21484-1.9727-0.21484-0.85938 0-1.7969 0.19531-0.9375 0.19531-1.7188 0.48828 0 0.19531-0.01953 0.64453t-0.01953 1.1328q0 2.4023 0.46875 3.9648 0.48828 1.543 1.2891 2.3633 0.54688 0.60547 1.2891 0.89844 0.74219 0.27344 1.6016 0.27344 0.64453 0 1.4258-0.29297t1.3281-0.87891z"/></g><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg> diff --git a/icons/colors_7.svg b/icons/colors_7.svg deleted file mode 100644 index 7870bc74ae13133a080de2f02397413b9d611458..0000000000000000000000000000000000000000 --- a/icons/colors_7.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#cd5542" stroke="#000" stroke-width="2"/><g transform="translate(3.9378 .2393)" aria-label="7"><path d="m58.459 42.001-13.164 23.301h-8.3594l13.672-23.516h-14.941v-5.5664h22.793z"/></g><rect x="5.6671" y="67.01" width="29.323" height="29.323" fill="#38ffff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg> diff --git a/icons/colors_8.svg b/icons/colors_8.svg deleted file mode 100644 index 37f394909f7ecc1b5e53a34c304d99742ce6c149..0000000000000000000000000000000000000000 --- a/icons/colors_8.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#6041b0" stroke="#000" stroke-width="2"/><g transform="translate(4.1624 .2393)" aria-label="8"><path d="m59.123 57.177q0 3.8672-3.3008 6.3281-3.2812 2.4609-9.0234 2.4609-3.2227 0-5.5273-0.66406-2.3047-0.66406-3.8086-1.8359-1.4844-1.1523-2.207-2.6953-0.70312-1.543-0.70312-3.3203 0-2.1875 1.2695-3.8672 1.2891-1.6992 4.4336-2.9688v-0.11719q-2.5391-1.1719-3.7305-2.9492t-1.1914-4.1211q0-3.457 3.2031-5.6641 3.2031-2.207 8.3398-2.207 5.3906 0 8.4375 2.0117 3.0664 1.9922 3.0664 5.332 0 2.0703-1.2891 3.6914t-3.9453 2.7539v0.11719q3.0469 1.1523 4.5117 3.1055t1.4648 4.6094zm-8.0664-13.438q0-1.4844-1.1523-2.3633-1.1328-0.87891-3.0273-0.87891-0.70312 0-1.4453 0.17578-0.72266 0.17578-1.3281 0.50781-0.56641 0.33203-0.9375 0.87891-0.37109 0.52734-0.37109 1.2109 0 1.1523 0.64453 1.7969 0.66406 0.64453 2.1484 1.2891 0.54688 0.23438 1.4844 0.58594 0.95703 0.33203 2.3047 0.76172 0.89844-1.0547 1.2891-1.8945 0.39062-0.83984 0.39062-2.0703zm0.60547 13.77q0-1.4062-0.70312-2.1289t-2.8906-1.6602q-0.64453-0.29297-1.875-0.72266-1.2305-0.42969-2.0703-0.74219-0.83984 0.76172-1.5234 1.8555-0.66406 1.0742-0.66406 2.4219 0 2.0312 1.4453 3.2422 1.4648 1.1914 3.8086 1.1914 0.625 0 1.4648-0.17578 0.83984-0.19531 1.4453-0.58594 0.70312-0.44922 1.1328-1.0547 0.42969-0.60547 0.42969-1.6406z"/></g><rect x="5.6671" y="36.339" width="29.323" height="29.323" fill="#f2739d" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="67.01" width="29.323" height="29.323" fill="#38ffff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg> diff --git a/icons/level_easy.svg b/icons/level_easy.svg deleted file mode 100644 index 30048ce976f10fba1ad4233115035786a65d35de..0000000000000000000000000000000000000000 --- a/icons/level_easy.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#97c05c" stroke="#000" stroke-width="2"/><path d="m50.952 32.393c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044s4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#030303" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg> diff --git a/icons/level_hard.svg b/icons/level_hard.svg deleted file mode 100644 index 976249e8b0d2274b791d00e128be518d29a03731..0000000000000000000000000000000000000000 --- a/icons/level_hard.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#cd5542" stroke="#000" stroke-width="2"/><path d="m28.065 11.952c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044s4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#010101" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m73.839 11.952c1.3622-0.0046 4.9652 11.398 6.07 12.195s13.062 0.61914 13.487 1.9133c0.42533 1.2941-9.3059 8.2444-9.7225 9.5414-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#010101" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m50.952 52.835c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133 0.42533 1.2941-9.3059 8.2444-9.7225 9.5414-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 5e-3 -10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434-10.203-8.1785-9.7868-9.4754c0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80442 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#010101" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg> diff --git a/icons/level_medium.svg b/icons/level_medium.svg deleted file mode 100644 index e70fd60d179b05a0db5701e4b7858c214887c6be..0000000000000000000000000000000000000000 --- a/icons/level_medium.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#f29c38" stroke="#000" stroke-width="2"/><path d="m27.72 32.393c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044s4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m74.183 32.393c1.3622-0.0046 4.9652 11.398 6.07 12.195s13.062 0.61914 13.487 1.9133-9.3059 8.2444-9.7225 9.5414c-0.41656 1.297 3.4475 12.614 2.3482 13.418-1.0994 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797-1.1048-0.79696 2.6827-12.14 2.2574-13.434s-10.203-8.1785-9.7868-9.4754c0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg> diff --git a/icons/level_nightmare.svg b/icons/level_nightmare.svg deleted file mode 100644 index 87f28a3defc23c6fe95980cb376efbf56d6885cc..0000000000000000000000000000000000000000 --- a/icons/level_nightmare.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#6041b0" stroke="#000" stroke-width="2"/><path d="m28.929 11.793c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80442-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797-1.1048-0.79696 2.6827-12.14 2.2574-13.434-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m73.125 11.861c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133 0.42533 1.2941-9.3059 8.2444-9.7225 9.5414-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434-10.203-8.1785-9.7868-9.4754c0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80442 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m28.778 52.923c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133 0.42533 1.2941-9.3059 8.2444-9.7225 9.5414s3.4475 12.614 2.3481 13.418c-1.0993 0.80442-10.717-6.3028-12.079-6.2982-1.3622 5e-3 -10.931 7.1767-12.036 6.3797-1.1048-0.79697 2.6827-12.14 2.2574-13.434-0.42533-1.2941-10.203-8.1785-9.7868-9.4754s12.375-1.2 13.474-2.0044c1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m73.104 52.992c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80442-10.717-6.3028-12.079-6.2982-1.3622 5e-3 -10.931 7.1767-12.036 6.3797-1.1048-0.79697 2.6827-12.14 2.2574-13.434-0.42533-1.2941-10.203-8.1785-9.7868-9.4754s12.375-1.2 13.474-2.0044c1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg> diff --git a/icons/size_extra.svg b/icons/size_extra.svg deleted file mode 100644 index fe07dfb952480afa9c7c9e0ab2af9879f9b2ad6a..0000000000000000000000000000000000000000 --- a/icons/size_extra.svg +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#5f41af" stroke="#000" stroke-width="2"/> - <g transform="translate(4.4197 1.4084)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="13.796" y="16.807" width="12.714" height="12.714"/><rect x="26.51" y="16.807" width="12.714" height="12.714"/><rect x="39.223" y="16.807" width="12.714" height="12.714"/><rect x="51.937" y="16.807" width="12.714" height="12.714"/><rect x="64.651" y="16.807" width="12.714" height="12.714"/><rect x="13.796" y="29.521" width="12.714" height="12.714"/><rect x="26.51" y="29.521" width="12.714" height="12.714"/><rect x="39.223" y="29.521" width="12.714" height="12.714"/><rect x="51.937" y="29.521" width="12.714" height="12.714"/><rect x="64.651" y="29.521" width="12.714" height="12.714"/><rect x="13.796" y="42.235" width="12.714" height="12.714"/><rect x="26.51" y="42.235" width="12.714" height="12.714"/><rect x="39.223" y="42.235" width="12.714" height="12.714"/><rect x="51.937" y="42.235" width="12.714" height="12.714"/><rect x="64.651" y="42.235" width="12.714" height="12.714"/><rect x="13.796" y="54.948" width="12.714" height="12.714"/><rect x="26.51" y="54.948" width="12.714" height="12.714"/><rect x="39.223" y="54.948" width="12.714" height="12.714"/><rect x="51.937" y="54.948" width="12.714" height="12.714"/><rect x="64.651" y="54.948" width="12.714" height="12.714"/><rect x="13.796" y="67.662" width="12.714" height="12.714"/><rect x="26.51" y="67.662" width="12.714" height="12.714"/><rect x="39.223" y="67.662" width="12.714" height="12.714"/><rect x="51.937" y="67.662" width="12.714" height="12.714"/><rect x="64.651" y="67.662" width="12.714" height="12.714"/></g></svg> diff --git a/icons/size_large.svg b/icons/size_large.svg deleted file mode 100644 index 174a5301a12bf2137b6e5de4cb2431d56ee4f660..0000000000000000000000000000000000000000 --- a/icons/size_large.svg +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#cd5542" stroke="#000" stroke-width="2"/> - <g transform="translate(6.2763 8.2075)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="18.296" y="16.365" width="12.714" height="12.714"/><rect x="31.01" y="16.365" width="12.714" height="12.714"/><rect x="43.724" y="16.365" width="12.714" height="12.714"/><rect x="56.437" y="16.365" width="12.714" height="12.714"/><rect x="18.296" y="29.079" width="12.714" height="12.714"/><rect x="31.01" y="29.079" width="12.714" height="12.714"/><rect x="43.724" y="29.079" width="12.714" height="12.714"/><rect x="56.437" y="29.079" width="12.714" height="12.714"/><rect x="18.296" y="41.792" width="12.714" height="12.714"/><rect x="31.01" y="41.792" width="12.714" height="12.714"/><rect x="43.724" y="41.792" width="12.714" height="12.714"/><rect x="56.437" y="41.792" width="12.714" height="12.714"/><rect x="18.296" y="54.506" width="12.714" height="12.714"/><rect x="31.01" y="54.506" width="12.714" height="12.714"/><rect x="43.724" y="54.506" width="12.714" height="12.714"/><rect x="56.437" y="54.506" width="12.714" height="12.714"/></g></svg> diff --git a/icons/size_medium.svg b/icons/size_medium.svg deleted file mode 100644 index bcc2fbaa18cd06829e8f6cfd8ab460c699929e9a..0000000000000000000000000000000000000000 --- a/icons/size_medium.svg +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#f29c38" stroke="#000" stroke-width="2"/> - <g transform="translate(11.967 8.1117)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="18.962" y="22.818" width="12.714" height="12.714"/><rect x="31.676" y="22.818" width="12.714" height="12.714"/><rect x="44.389" y="22.818" width="12.714" height="12.714"/><rect x="18.962" y="35.531" width="12.714" height="12.714"/><rect x="31.676" y="35.531" width="12.714" height="12.714"/><rect x="44.389" y="35.531" width="12.714" height="12.714"/><rect x="18.962" y="48.245" width="12.714" height="12.714"/><rect x="31.676" y="48.245" width="12.714" height="12.714"/><rect x="44.389" y="48.245" width="12.714" height="12.714"/></g></svg> diff --git a/icons/size_small.svg b/icons/size_small.svg deleted file mode 100644 index 1ccb6e958123c30999e47b54e784a398205c55d0..0000000000000000000000000000000000000000 --- a/icons/size_small.svg +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#97c05c" stroke="#000" stroke-width="2"/> - <g transform="translate(8.8715 12.603)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="28.415" y="24.683" width="12.714" height="12.714"/><rect x="41.128" y="24.683" width="12.714" height="12.714"/><rect x="28.415" y="37.397" width="12.714" height="12.714"/><rect x="41.128" y="37.397" width="12.714" height="12.714"/></g></svg> diff --git a/icons/skin_default.svg b/icons/skin_default.svg deleted file mode 100644 index 18ae839e20048fd621cd23dcac1eabb5f9200223..0000000000000000000000000000000000000000 --- a/icons/skin_default.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#a4a4a4" stroke="#000" stroke-width="2"/><rect x="-15.387" y="-20.515" width="100" height="100" ry="2" fill="none"/><rect x="5.6673" y="36.339" width="29.323" height="29.323" fill="#f2739d" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6673" y="67.01" width="29.323" height="29.323" fill="#38ffff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6674" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6674" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6673" y="5.6674" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg> diff --git a/icons/skins/default/0.svg b/icons/skins/default/0.svg deleted file mode 100644 index 87a62b1523130f2b611695653a326a4939b1909a..0000000000000000000000000000000000000000 --- a/icons/skins/default/0.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg> diff --git a/icons/skins/default/1.svg b/icons/skins/default/1.svg deleted file mode 100644 index 11201e50147d415106bc969cec7b0f0b7d315fc1..0000000000000000000000000000000000000000 --- a/icons/skins/default/1.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#E63A3F" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg> diff --git a/icons/skins/default/2.svg b/icons/skins/default/2.svg deleted file mode 100644 index 76e07b77bc5bd1d7ba3f486b3da5c9e5bbd166bb..0000000000000000000000000000000000000000 --- a/icons/skins/default/2.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#708CFD" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg> diff --git a/icons/skins/default/3.svg b/icons/skins/default/3.svg deleted file mode 100644 index 092dab6667d3016fbf5f131dba44a3d32533d16e..0000000000000000000000000000000000000000 --- a/icons/skins/default/3.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#359C35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg> diff --git a/icons/skins/default/4.svg b/icons/skins/default/4.svg deleted file mode 100644 index 57094f502ffe53094c4394f0a8bd56d3748eed63..0000000000000000000000000000000000000000 --- a/icons/skins/default/4.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#FFCE2C" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg> diff --git a/icons/skins/default/5.svg b/icons/skins/default/5.svg deleted file mode 100644 index e0f4d96e14d57b85fe4fbff8dd294d1896582043..0000000000000000000000000000000000000000 --- a/icons/skins/default/5.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#FF6F43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg> diff --git a/icons/skins/default/6.svg b/icons/skins/default/6.svg deleted file mode 100644 index feb210edab0ed136cd3aca43b944f8c5a3a83755..0000000000000000000000000000000000000000 --- a/icons/skins/default/6.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#A13CB1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg> diff --git a/icons/skins/default/7.svg b/icons/skins/default/7.svg deleted file mode 100644 index 2b9d0858288a90281d0f9a4184c895da3bb5c3b7..0000000000000000000000000000000000000000 --- a/icons/skins/default/7.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#38FFFF" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg> diff --git a/icons/skins/default/8.svg b/icons/skins/default/8.svg deleted file mode 100644 index 40b80922783bfa5a4a183eaa14a47fdc7f7a4533..0000000000000000000000000000000000000000 --- a/icons/skins/default/8.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#F2739D" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.5e-7"/></svg> diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart new file mode 100644 index 0000000000000000000000000000000000000000..db8841295f53570f90f2a50ea1e6abbca2ac2403 --- /dev/null +++ b/lib/config/default_game_settings.dart @@ -0,0 +1,81 @@ +import 'package:colors/utils/tools.dart'; + +class DefaultGameSettings { + // available game parameters codes + static const String parameterCodeDifficultyLevel = 'difficultyLevel'; + static const String parameterCodeBoardSize = 'boardSize'; + static const String parameterCodeColorsCount = 'colorsCount'; + static const List<String> availableParameters = [ + parameterCodeDifficultyLevel, + parameterCodeBoardSize, + parameterCodeColorsCount, + ]; + + // difficulty level: available values + static const String difficultyLevelValueEasy = 'easy'; + static const String difficultyLevelValueMedium = 'medium'; + static const String difficultyLevelValueHard = 'hard'; + static const String difficultyLevelValueNightmare = 'nightmare'; + static const List<String> allowedDifficultyLevelValues = [ + difficultyLevelValueEasy, + difficultyLevelValueMedium, + difficultyLevelValueHard, + difficultyLevelValueNightmare, + ]; + // difficulty level: default value + static const String defaultDifficultyLevelValue = difficultyLevelValueMedium; + + // board size: available values + static const String boardSizeValueSmall = 'small'; + static const String boardSizeValueMedium = 'medium'; + static const String boardSizeValueLarge = 'large'; + static const String boardSizeValueExtra = 'extra'; + static const List<String> allowedBoardSizeValues = [ + boardSizeValueSmall, + boardSizeValueMedium, + boardSizeValueLarge, + boardSizeValueExtra, + ]; + // board size: default value + static const String defaultBoardSizeValue = boardSizeValueMedium; + + // colors count: available values + static const String colorsCountValueLow = '5'; + static const String colorsCountValueMedium = '6'; + static const String colorsCountValueHigh = '7'; + static const String colorsCountValueVeryHigh = '8'; + static const List<String> allowedColorsCountValues = [ + colorsCountValueLow, + colorsCountValueMedium, + colorsCountValueHigh, + colorsCountValueVeryHigh, + ]; + // colors count: default value + static const String defaultColorsCountValue = colorsCountValueMedium; + + // available values from parameter code + static List<String> getAvailableValues(String parameterCode) { + switch (parameterCode) { + case parameterCodeDifficultyLevel: + return DefaultGameSettings.allowedDifficultyLevelValues; + case parameterCodeBoardSize: + return DefaultGameSettings.allowedBoardSizeValues; + case parameterCodeColorsCount: + return DefaultGameSettings.allowedColorsCountValues; + } + + printlog('Did not find any available value for game parameter "$parameterCode".'); + return []; + } + + static int getMovesCountLimitDeltaFromLevelCode(String parameterLevel) { + const Map<String, int> values = { + difficultyLevelValueEasy: 5, + difficultyLevelValueMedium: 3, + difficultyLevelValueHard: 1, + difficultyLevelValueNightmare: -1, + }; + return values[parameterLevel] ?? + getMovesCountLimitDeltaFromLevelCode(DefaultGameSettings.defaultDifficultyLevelValue); + } +} diff --git a/lib/config/default_global_settings.dart b/lib/config/default_global_settings.dart new file mode 100644 index 0000000000000000000000000000000000000000..3ec1474a9af61c014e5791a793d7205343070dfb --- /dev/null +++ b/lib/config/default_global_settings.dart @@ -0,0 +1,28 @@ +import 'package:colors/utils/tools.dart'; + +class DefaultGlobalSettings { + // available global parameters codes + static const String parameterCodeSkin = 'skin'; + static const List<String> availableParameters = [ + parameterCodeSkin, + ]; + + // skin: available values + static const String skinValueColors = 'colors'; + static const List<String> allowedSkinValues = [ + skinValueColors, + ]; + // skin: default value + static const String defaultSkinValue = skinValueColors; + + // available values from parameter code + static List<String> getAvailableValues(String parameterCode) { + switch (parameterCode) { + case parameterCodeSkin: + return DefaultGlobalSettings.allowedSkinValues; + } + + printlog('Did not find any available value for global parameter "$parameterCode".'); + return []; + } +} diff --git a/lib/config/menu.dart b/lib/config/menu.dart index b969ec5c5b74440763eee143c4674cf0a46adffa..2f9395d83564baa03622ecebe7fdc74e7a68c08c 100644 --- a/lib/config/menu.dart +++ b/lib/config/menu.dart @@ -1,10 +1,9 @@ -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:unicons/unicons.dart'; -import 'package:colors/ui/screens/about_page.dart'; -import 'package:colors/ui/screens/game_page.dart'; -import 'package:colors/ui/screens/settings_page.dart'; +import 'package:colors/ui/screens/page_about.dart'; +import 'package:colors/ui/screens/page_game.dart'; +import 'package:colors/ui/screens/page_settings.dart'; class MenuItem { final String code; @@ -19,35 +18,39 @@ class MenuItem { } class Menu { - static List<MenuItem> items = [ - const MenuItem( - code: 'bottom_nav_home', - icon: Icon(UniconsLine.home), - page: GamePage(), - ), - const MenuItem( - code: 'bottom_nav_settings', - icon: Icon(UniconsLine.setting), - page: SettingsPage(), - ), - const MenuItem( - code: 'bottom_nav_about', - icon: Icon(UniconsLine.info_circle), - page: AboutPage(), - ), - ]; + static const indexGame = 0; + static const menuItemGame = MenuItem( + code: 'bottom_nav_game', + icon: Icon(UniconsLine.home), + page: PageGame(), + ); - static Widget getPageWidget(int pageIndex) { - return Menu.items.elementAt(pageIndex).page; + static const indexSettings = 1; + static const menuItemSettings = MenuItem( + code: 'bottom_nav_settings', + icon: Icon(UniconsLine.setting), + page: PageSettings(), + ); + + static const indexAbout = 2; + static const menuItemAbout = MenuItem( + code: 'bottom_nav_about', + icon: Icon(UniconsLine.info_circle), + page: PageAbout(), + ); + + static Map<int, MenuItem> items = { + indexGame: menuItemGame, + indexSettings: menuItemSettings, + indexAbout: menuItemAbout, + }; + + static bool isIndexAllowed(int pageIndex) { + return items.keys.contains(pageIndex); } - static List<BottomNavigationBarItem> getMenuItems() { - return Menu.items - .map((MenuItem item) => BottomNavigationBarItem( - icon: item.icon, - label: tr(item.code), - )) - .toList(); + static Widget getPageWidget(int pageIndex) { + return items[pageIndex]?.page ?? menuItemGame.page; } static int itemsCount = Menu.items.length; diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..16775c36cca0ee88c6ef2a7470959c51a80dac08 --- /dev/null +++ b/lib/cubit/game_cubit.dart @@ -0,0 +1,170 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:equatable/equatable.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:colors/models/game.dart'; +import 'package:colors/models/settings_game.dart'; +import 'package:colors/models/settings_global.dart'; +import 'package:colors/utils/tools.dart'; + +part 'game_state.dart'; + +class GameCubit extends HydratedCubit<GameState> { + GameCubit() + : super(GameState( + currentGame: Game.createNull(), + )); + + void updateState(Game game) { + emit(GameState( + currentGame: game, + )); + } + + void refresh() { + final Game game = Game( + board: state.currentGame.board, + gameSettings: state.currentGame.gameSettings, + globalSettings: state.currentGame.globalSettings, + isRunning: state.currentGame.isRunning, + isFinished: state.currentGame.isFinished, + gameWon: state.currentGame.gameWon, + movesCount: state.currentGame.movesCount, + maxMovesCount: state.currentGame.maxMovesCount, + animationInProgress: state.currentGame.animationInProgress, + progress: state.currentGame.progress, + progressTotal: state.currentGame.progressTotal, + progressDelta: state.currentGame.progressDelta, + ); + + updateState(game); + } + + void startNewGame({ + required GameSettings gameSettings, + required GlobalSettings globalSettings, + }) { + printlog('Starting new game:'); + printlog('- level: ${gameSettings.difficultyLevel}'); + printlog('- size: ${gameSettings.parameterSize}'); + printlog('- colors: ${gameSettings.parameterColorsCount}'); + + Game newGame = Game.createNew( + gameSettings: gameSettings, + globalSettings: globalSettings, + ); + + newGame.dump(); + + updateState(newGame); + updateGameIsRunning(true); + } + + void quitGame() { + state.currentGame.isRunning = false; + refresh(); + } + + void updateCellValue(int col, int row, int value) { + state.currentGame.board.cells[row][col].value = value; + refresh(); + } + + void increaseMovesCount() { + state.currentGame.movesCount++; + refresh(); + } + + void updateProgressDelta(int progressDelta) { + state.currentGame.progressDelta = progressDelta; + refresh(); + } + + void updateProgress(int progress) { + state.currentGame.progress = progress; + refresh(); + } + + void updateAnimationInProgress(bool inProgress) { + state.currentGame.animationInProgress = inProgress; + refresh(); + } + + void updateGameIsRunning(bool gameIsRunning) { + state.currentGame.isRunning = gameIsRunning; + refresh(); + } + + void updateGameIsFinished(bool gameIsFinished) { + state.currentGame.isFinished = gameIsFinished; + refresh(); + } + + void updateGameWon(bool gameWon) { + state.currentGame.gameWon = gameWon; + refresh(); + } + + fillBoardFromFirstCell(int value) { + List<List<int>> cellsToFill = state.currentGame.board.getSiblingFillableCells(0, 0, []); + final int progressBeforeMove = cellsToFill.length; + + if (value == state.currentGame.board.getFirstCellValue()) { + return; + } + + increaseMovesCount(); + + // Sort cells from the closest to the furthest, relatively to the top left corner + cellsToFill + .sort((a, b) => (pow(a[0], 2) + pow(a[1], 2)).compareTo(pow(b[0], 2) + pow(b[1], 2))); + + const interval = Duration(milliseconds: 10); + int cellIndex = 0; + updateAnimationInProgress(true); + Timer.periodic( + interval, + (Timer timer) { + if (cellIndex < cellsToFill.length) { + updateCellValue(cellsToFill[cellIndex][1], cellsToFill[cellIndex][0], value); + cellIndex++; + } else { + timer.cancel(); + + int progressAfterMove = + state.currentGame.board.getSiblingFillableCells(0, 0, []).length; + int progressDelta = progressAfterMove - progressBeforeMove; + updateProgressDelta(progressDelta); + updateProgress(progressAfterMove); + + updateAnimationInProgress(false); + + if (state.currentGame.board.isBoardSolved()) { + updateGameWon(true); + updateGameIsFinished(true); + } + } + }, + ); + } + + @override + GameState? fromJson(Map<String, dynamic> json) { + Game currentGame = json['currentGame'] as Game; + + return GameState( + currentGame: currentGame, + ); + } + + @override + Map<String, dynamic>? toJson(GameState state) { + return <String, dynamic>{ + 'currentGame': state.currentGame.toJson(), + }; + } +} diff --git a/lib/cubit/game_state.dart b/lib/cubit/game_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..3fd161a0915313722b7a15c55c7cf538a7e3b6e1 --- /dev/null +++ b/lib/cubit/game_state.dart @@ -0,0 +1,19 @@ +part of 'game_cubit.dart'; + +@immutable +class GameState extends Equatable { + const GameState({ + required this.currentGame, + }); + + final Game currentGame; + + @override + List<dynamic> get props => <dynamic>[ + currentGame, + ]; + + Map<String, dynamic> get values => <String, dynamic>{ + 'currentGame': currentGame, + }; +} diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/nav_cubit.dart similarity index 51% rename from lib/cubit/bottom_nav_cubit.dart rename to lib/cubit/nav_cubit.dart index f33dca378aa5fabad4b97268304f15ebdc39b26d..a92b2303c3291813fd5b6bade0b64a69839e151f 100644 --- a/lib/cubit/bottom_nav_cubit.dart +++ b/lib/cubit/nav_cubit.dart @@ -2,26 +2,32 @@ import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:colors/config/menu.dart'; -class BottomNavCubit extends HydratedCubit<int> { - BottomNavCubit() : super(0); +class NavCubit extends HydratedCubit<int> { + NavCubit() : super(0); void updateIndex(int index) { - if (isIndexAllowed(index)) { + if (Menu.isIndexAllowed(index)) { emit(index); } else { - goToHomePage(); + goToGamePage(); } } - bool isIndexAllowed(int index) { - return (index >= 0) && (index < Menu.itemsCount); + void goToGamePage() { + emit(Menu.indexGame); } - void goToHomePage() => emit(0); + void goToSettingsPage() { + emit(Menu.indexSettings); + } + + void goToAboutPage() { + emit(Menu.indexAbout); + } @override int fromJson(Map<String, dynamic> json) { - return 0; + return Menu.indexGame; } @override diff --git a/lib/cubit/settings_game_cubit.dart b/lib/cubit/settings_game_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..f70f2be39c047a76c59c76d016035007a48f8e11 --- /dev/null +++ b/lib/cubit/settings_game_cubit.dart @@ -0,0 +1,84 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:colors/config/default_game_settings.dart'; +import 'package:colors/models/settings_game.dart'; + +part 'settings_game_state.dart'; + +class GameSettingsCubit extends HydratedCubit<GameSettingsState> { + GameSettingsCubit() : super(GameSettingsState(settings: GameSettings.createDefault())); + + void setValues({ + String? difficultyLevel, + String? boardSize, + String? colorsCount, + }) { + emit( + GameSettingsState( + settings: GameSettings( + difficultyLevel: difficultyLevel ?? state.settings.difficultyLevel, + parameterSize: boardSize ?? state.settings.parameterSize, + parameterColorsCount: colorsCount ?? state.settings.parameterColorsCount, + ), + ), + ); + } + + String getParameterValue(String code) { + switch (code) { + case DefaultGameSettings.parameterCodeDifficultyLevel: + return GameSettings.getLevelValueFromUnsafe(state.settings.difficultyLevel); + case DefaultGameSettings.parameterCodeBoardSize: + return GameSettings.getSizeValueFromUnsafe(state.settings.parameterSize); + case DefaultGameSettings.parameterCodeColorsCount: + return GameSettings.getColorsValueFromUnsafe(state.settings.parameterColorsCount); + } + return ''; + } + + void setParameterValue(String code, String value) { + final String difficultyLevel = (code == DefaultGameSettings.parameterCodeDifficultyLevel) + ? value + : getParameterValue(DefaultGameSettings.parameterCodeDifficultyLevel); + final String boardSize = (code == DefaultGameSettings.parameterCodeBoardSize) + ? value + : getParameterValue(DefaultGameSettings.parameterCodeBoardSize); + final String colorsCount = (code == DefaultGameSettings.parameterCodeColorsCount) + ? value + : getParameterValue(DefaultGameSettings.parameterCodeColorsCount); + + setValues( + difficultyLevel: difficultyLevel, + boardSize: boardSize, + colorsCount: colorsCount, + ); + } + + @override + GameSettingsState? fromJson(Map<String, dynamic> json) { + final String difficultyLevel = + json[DefaultGameSettings.parameterCodeDifficultyLevel] as String; + final String boardSize = json[DefaultGameSettings.parameterCodeBoardSize] as String; + final String colorsCount = json[DefaultGameSettings.parameterCodeColorsCount] as String; + + return GameSettingsState( + settings: GameSettings( + difficultyLevel: difficultyLevel, + parameterSize: boardSize, + parameterColorsCount: colorsCount, + ), + ); + } + + @override + Map<String, dynamic>? toJson(GameSettingsState state) { + return <String, dynamic>{ + DefaultGameSettings.parameterCodeDifficultyLevel: state.settings.difficultyLevel, + DefaultGameSettings.parameterCodeBoardSize: state.settings.parameterSize, + DefaultGameSettings.parameterCodeColorsCount: state.settings.parameterColorsCount, + }; + } +} diff --git a/lib/cubit/settings_game_state.dart b/lib/cubit/settings_game_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..b773dc69be12673b158e880e2d7e6e7bec465506 --- /dev/null +++ b/lib/cubit/settings_game_state.dart @@ -0,0 +1,19 @@ +part of 'settings_game_cubit.dart'; + +@immutable +class GameSettingsState extends Equatable { + const GameSettingsState({ + required this.settings, + }); + + final GameSettings settings; + + @override + List<dynamic> get props => <dynamic>[ + settings, + ]; + + Map<String, dynamic> get values => <String, dynamic>{ + 'settings': settings, + }; +} diff --git a/lib/cubit/settings_global_cubit.dart b/lib/cubit/settings_global_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..41d3f191c94ff81119902bab88d3c8b376a11dff --- /dev/null +++ b/lib/cubit/settings_global_cubit.dart @@ -0,0 +1,61 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:colors/config/default_global_settings.dart'; +import 'package:colors/models/settings_global.dart'; + +part 'settings_global_state.dart'; + +class GlobalSettingsCubit extends HydratedCubit<GlobalSettingsState> { + GlobalSettingsCubit() : super(GlobalSettingsState(settings: GlobalSettings.createDefault())); + + void setValues({ + String? skin, + }) { + emit( + GlobalSettingsState( + settings: GlobalSettings( + skin: skin ?? state.settings.skin, + ), + ), + ); + } + + String getParameterValue(String code) { + switch (code) { + case DefaultGlobalSettings.parameterCodeSkin: + return GlobalSettings.getSkinValueFromUnsafe(state.settings.skin); + } + return ''; + } + + void setParameterValue(String code, String value) { + final String skin = (code == DefaultGlobalSettings.parameterCodeSkin) + ? value + : getParameterValue(DefaultGlobalSettings.parameterCodeSkin); + + setValues( + skin: skin, + ); + } + + @override + GlobalSettingsState? fromJson(Map<String, dynamic> json) { + final String skin = json[DefaultGlobalSettings.parameterCodeSkin] as String; + + return GlobalSettingsState( + settings: GlobalSettings( + skin: skin, + ), + ); + } + + @override + Map<String, dynamic>? toJson(GlobalSettingsState state) { + return <String, dynamic>{ + DefaultGlobalSettings.parameterCodeSkin: state.settings.skin, + }; + } +} diff --git a/lib/cubit/settings_global_state.dart b/lib/cubit/settings_global_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..4e4fbdf707b4e805f2092d0ca6a68a2de1c957c6 --- /dev/null +++ b/lib/cubit/settings_global_state.dart @@ -0,0 +1,19 @@ +part of 'settings_global_cubit.dart'; + +@immutable +class GlobalSettingsState extends Equatable { + const GlobalSettingsState({ + required this.settings, + }); + + final GlobalSettings settings; + + @override + List<dynamic> get props => <dynamic>[ + settings, + ]; + + Map<String, dynamic> get values => <String, dynamic>{ + 'settings': settings, + }; +} diff --git a/lib/entities/cell.dart b/lib/entities/cell.dart deleted file mode 100644 index 9617e4c86349bda6532141e47c96f79297866184..0000000000000000000000000000000000000000 --- a/lib/entities/cell.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:colors/provider/data.dart'; -import 'package:colors/utils/board_utils.dart'; - -class Cell { - int value; - - Cell( - this.value, - ); - - Container interactiveWidget(Data myProvider, ColorScheme colorScheme) { - final String imageAsset = 'assets/skins/${myProvider.parameterSkin}_$value.png'; - - return Container( - margin: const EdgeInsets.all(2), - decoration: BoxDecoration( - border: Border.all( - color: colorScheme.onSurface, - width: 4, - ), - ), - child: GestureDetector( - child: Image( - image: AssetImage(imageAsset), - fit: BoxFit.fill, - ), - onTap: () { - if (!myProvider.animationInProgress && myProvider.getFirstCellValue() != value) { - BoardUtils.fillBoardFromFirstCell(myProvider, value); - } - }, - ), - ); - } -} diff --git a/lib/main.dart b/lib/main.dart index a74262fbb5d6b33e3e73d627917c9e3de41d675d..4ffcc22f036fee392607c109e0a71a7098963cea 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,22 +1,22 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:hydrated_bloc/hydrated_bloc.dart'; -import 'package:overlay_support/overlay_support.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:provider/provider.dart'; import 'package:colors/config/theme.dart'; -import 'package:colors/cubit/bottom_nav_cubit.dart'; +import 'package:colors/cubit/game_cubit.dart'; +import 'package:colors/cubit/nav_cubit.dart'; +import 'package:colors/cubit/settings_game_cubit.dart'; +import 'package:colors/cubit/settings_global_cubit.dart'; import 'package:colors/cubit/theme_cubit.dart'; -import 'package:colors/provider/data.dart'; import 'package:colors/ui/skeleton.dart'; void main() async { - /// Initialize packages + // Initialize packages WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); final Directory tmpDir = await getTemporaryDirectory(); @@ -46,34 +46,28 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MultiBlocProvider( providers: [ - BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()), + BlocProvider<NavCubit>(create: (context) => NavCubit()), BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()), + BlocProvider<GameCubit>(create: (context) => GameCubit()), + BlocProvider<GlobalSettingsCubit>(create: (context) => GlobalSettingsCubit()), + BlocProvider<GameSettingsCubit>(create: (context) => GameSettingsCubit()), ], child: BlocBuilder<ThemeCubit, ThemeModeState>( builder: (BuildContext context, ThemeModeState state) { - return ChangeNotifierProvider( - create: (BuildContext context) => Data(), - child: Consumer<Data>( - builder: (context, data, child) { - return OverlaySupport( - child: MaterialApp( - title: 'Minehunter', - home: const SkeletonScreen(), + return MaterialApp( + title: 'Colors', + home: const SkeletonScreen(), - // Theme stuff - theme: lightTheme, - darkTheme: darkTheme, - themeMode: state.themeMode, + // Theme stuff + theme: lightTheme, + darkTheme: darkTheme, + themeMode: state.themeMode, - // Localization stuff - localizationsDelegates: context.localizationDelegates, - supportedLocales: context.supportedLocales, - locale: context.locale, - debugShowCheckedModeBanner: false, - ), - ); - }, - ), + // Localization stuff + localizationsDelegates: context.localizationDelegates, + supportedLocales: context.supportedLocales, + locale: context.locale, + debugShowCheckedModeBanner: false, ); }, ), diff --git a/lib/models/board.dart b/lib/models/board.dart new file mode 100644 index 0000000000000000000000000000000000000000..5d6ccd91949853ddce74c7965e82722c2e694fb1 --- /dev/null +++ b/lib/models/board.dart @@ -0,0 +1,144 @@ +import 'dart:math'; + +import 'package:colors/models/cell.dart'; +import 'package:colors/models/settings_game.dart'; +import 'package:colors/models/types.dart'; +import 'package:colors/utils/tools.dart'; + +class Board { + final BoardCells cells; + + Board({ + required this.cells, + }); + + factory Board.createNull() { + return Board(cells: []); + } + + factory Board.createRandom(GameSettings gameSettings) { + final int boardSizeHorizontal = gameSettings.boardSize; + final int boardSizeVertical = gameSettings.boardSize; + + final rand = Random(); + + BoardCells cells = []; + for (int rowIndex = 0; rowIndex < boardSizeVertical; rowIndex++) { + List<Cell> row = []; + for (int colIndex = 0; colIndex < boardSizeHorizontal; colIndex++) { + final int value = 1 + rand.nextInt(gameSettings.colorsCount); + row.add(Cell(value)); + } + cells.add(row); + } + + return Board( + cells: cells, + ); + } + + int getCellValue(int col, int row) { + return cells[row][col].value; + } + + int getFirstCellValue() { + return cells[0][0].value; + } + + List<List<int>> getSiblingFillableCells( + int row, + int col, + List<List<int>> siblingCells, + ) { + final int boardSize = cells.length; + + if (siblingCells.isEmpty) { + siblingCells = [ + [row, col] + ]; + } + + final int referenceValue = cells[row][col].value; + + for (int deltaRow = -1; deltaRow <= 1; deltaRow++) { + for (int deltaCol = -1; deltaCol <= 1; deltaCol++) { + if (deltaCol == 0 || deltaRow == 0) { + final int candidateRow = row + deltaRow; + final int candidateCol = col + deltaCol; + + if ((candidateRow >= 0 && candidateRow < boardSize) && + (candidateCol >= 0 && candidateCol < boardSize)) { + if (cells[candidateRow][candidateCol].value == referenceValue) { + bool alreadyFound = false; + for (int index = 0; index < siblingCells.length; index++) { + if ((siblingCells[index][0] == candidateRow) && + (siblingCells[index][1] == candidateCol)) { + alreadyFound = true; + } + } + if (!alreadyFound) { + siblingCells.add([candidateRow, candidateCol]); + siblingCells = getSiblingFillableCells( + candidateRow, + candidateCol, + siblingCells, + ); + } + } + } + } + } + } + + return siblingCells; + } + + // check grid contains only one color + bool isBoardSolved() { + final int firstCellValue = cells[0][0].value; + for (int row = 0; row < cells.length; row++) { + for (int col = 0; col < cells[row].length; col++) { + if (cells[row][col].value != firstCellValue) { + return false; + } + } + } + + printlog('-> ok grid fully painted!'); + + return true; + } + + void dump() { + String horizontalRule = '----'; + for (int i = 0; i < cells[0].length; i++) { + horizontalRule += '-'; + } + + printlog('Board:'); + printlog(horizontalRule); + + for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) { + String row = '| '; + for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) { + row += cells[rowIndex][colIndex].value.toString(); + } + row += ' |'; + + printlog(row); + } + + printlog(horizontalRule); + } + + @override + String toString() { + return '$Board(${toJson()})'; + } + + Map<String, dynamic>? toJson() { + return <String, dynamic>{ + 'cells': cells.toString(), + }; + } +} diff --git a/lib/models/cell.dart b/lib/models/cell.dart new file mode 100644 index 0000000000000000000000000000000000000000..54d6e3ad84f10b6b11368f831369fd34798a8b2b --- /dev/null +++ b/lib/models/cell.dart @@ -0,0 +1,18 @@ +class Cell { + Cell( + this.value, + ); + + int value; + + @override + String toString() { + return '$Cell(${toJson()})'; + } + + Map<String, dynamic>? toJson() { + return <String, dynamic>{ + 'value': value, + }; + } +} diff --git a/lib/models/game.dart b/lib/models/game.dart new file mode 100644 index 0000000000000000000000000000000000000000..28b61ead100e1d896811f67e9752e19fc79a9f82 --- /dev/null +++ b/lib/models/game.dart @@ -0,0 +1,114 @@ +import 'package:colors/config/default_game_settings.dart'; +import 'package:colors/models/board.dart'; +import 'package:colors/models/settings_game.dart'; +import 'package:colors/models/settings_global.dart'; +import 'package:colors/utils/tools.dart'; + +class Game { + final Board board; + final GameSettings gameSettings; + final GlobalSettings globalSettings; + bool isRunning = false; + bool isFinished = false; + bool gameWon = false; + + int maxMovesCount = 0; + int movesCount = 0; + + int progress = 0; + int progressTotal = 0; + int progressDelta = 0; + + bool animationInProgress = false; + + Game({ + required this.board, + required this.gameSettings, + required this.globalSettings, + this.isRunning = false, + this.isFinished = false, + this.gameWon = false, + this.maxMovesCount = 0, + this.movesCount = 0, + this.progress = 0, + this.progressTotal = 0, + this.progressDelta = 0, + this.animationInProgress = false, + }); + + factory Game.createNull() { + return Game( + board: Board.createNull(), + gameSettings: GameSettings.createDefault(), + globalSettings: GlobalSettings.createDefault(), + ); + } + + factory Game.createNew({ + GameSettings? gameSettings, + GlobalSettings? globalSettings, + }) { + GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault(); + GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault(); + + final int baseMaxMovesCount = + (30 * (newGameSettings.boardSize * newGameSettings.colorsCount) / (17 * 6)).round(); + final int deltaMovesCountFromLevel = + DefaultGameSettings.getMovesCountLimitDeltaFromLevelCode( + newGameSettings.difficultyLevel); + + return Game( + board: Board.createRandom(newGameSettings), + gameSettings: newGameSettings, + globalSettings: newGlobalSettings, + isRunning: true, + isFinished: false, + gameWon: false, + progress: 1, + progressTotal: newGameSettings.boardSize * newGameSettings.boardSize, + maxMovesCount: baseMaxMovesCount + deltaMovesCountFromLevel, + ); + } + + void dump() { + printlog(''); + printlog('## Current game dump:'); + printlog(''); + gameSettings.dump(); + globalSettings.dump(); + printlog(''); + board.dump(); + printlog(''); + printlog('Game: '); + printlog(' isRunning: $isRunning'); + printlog(' isFinished: $isFinished'); + printlog(' gameWon: $gameWon'); + printlog(' movesCount: $movesCount'); + printlog(' maxMovesCount: $maxMovesCount'); + printlog(' progress: $progress'); + printlog(' progressTotal: $progressTotal'); + printlog(' progressDelta: $progressDelta'); + printlog(''); + } + + @override + String toString() { + return '$Game(${toJson()})'; + } + + Map<String, dynamic>? toJson() { + return <String, dynamic>{ + 'board': board.toJson(), + 'gameSettings': gameSettings.toJson(), + 'globalSettings': globalSettings.toJson(), + 'isRunning': isRunning, + 'isFinished': isFinished, + 'gameWon': gameWon, + 'movesCount': movesCount, + 'maxMovesCount': maxMovesCount, + 'progress': progress, + 'progressTotal': progressTotal, + 'progressDelta': progressDelta, + }; + } +} diff --git a/lib/models/settings_game.dart b/lib/models/settings_game.dart new file mode 100644 index 0000000000000000000000000000000000000000..b5227e80ccf1589646a06dc5e7e186fbc4336e26 --- /dev/null +++ b/lib/models/settings_game.dart @@ -0,0 +1,81 @@ +import 'package:colors/config/default_game_settings.dart'; +import 'package:colors/utils/tools.dart'; + +class GameSettings { + String difficultyLevel; + String parameterSize; + String parameterColorsCount; + + GameSettings({ + required this.difficultyLevel, + required this.parameterSize, + required this.parameterColorsCount, + }); + + static String getLevelValueFromUnsafe(String level) { + if (DefaultGameSettings.allowedDifficultyLevelValues.contains(level)) { + return level; + } + + return DefaultGameSettings.defaultDifficultyLevelValue; + } + + static String getSizeValueFromUnsafe(String size) { + if (DefaultGameSettings.allowedBoardSizeValues.contains(size)) { + return size; + } + + return DefaultGameSettings.defaultBoardSizeValue; + } + + static String getColorsValueFromUnsafe(String colors) { + if (DefaultGameSettings.allowedColorsCountValues.contains(colors)) { + return colors; + } + + return DefaultGameSettings.defaultColorsCountValue; + } + + factory GameSettings.createDefault() { + return GameSettings( + difficultyLevel: DefaultGameSettings.defaultDifficultyLevelValue, + parameterSize: DefaultGameSettings.defaultBoardSizeValue, + parameterColorsCount: DefaultGameSettings.defaultColorsCountValue, + ); + } + + int getBoardSizeFromParameter(String parameterSize) { + const Map<String, int> values = { + DefaultGameSettings.boardSizeValueSmall: 6, + DefaultGameSettings.boardSizeValueMedium: 10, + DefaultGameSettings.boardSizeValueLarge: 14, + DefaultGameSettings.boardSizeValueExtra: 20, + }; + return values[parameterSize] ?? + getBoardSizeFromParameter(DefaultGameSettings.defaultBoardSizeValue); + } + + int get boardSize => getBoardSizeFromParameter(parameterSize); + int get colorsCount => int.parse(parameterColorsCount); + + void dump() { + printlog('$GameSettings:'); + printlog(' ${DefaultGameSettings.parameterCodeDifficultyLevel}: $difficultyLevel'); + printlog(' ${DefaultGameSettings.parameterCodeBoardSize}: $parameterSize'); + printlog(' ${DefaultGameSettings.parameterCodeColorsCount}: $parameterColorsCount'); + printlog(''); + } + + @override + String toString() { + return '$GameSettings(${toJson()})'; + } + + Map<String, dynamic>? toJson() { + return <String, dynamic>{ + DefaultGameSettings.parameterCodeDifficultyLevel: difficultyLevel, + DefaultGameSettings.parameterCodeBoardSize: parameterSize, + DefaultGameSettings.parameterCodeColorsCount: parameterColorsCount, + }; + } +} diff --git a/lib/models/settings_global.dart b/lib/models/settings_global.dart new file mode 100644 index 0000000000000000000000000000000000000000..09994f4124e0761b2da152295f837a0d535514ec --- /dev/null +++ b/lib/models/settings_global.dart @@ -0,0 +1,41 @@ +import 'package:colors/config/default_global_settings.dart'; +import 'package:colors/utils/tools.dart'; + +class GlobalSettings { + String skin; + + GlobalSettings({ + required this.skin, + }); + + static String getSkinValueFromUnsafe(String skin) { + if (DefaultGlobalSettings.allowedSkinValues.contains(skin)) { + return skin; + } + + return DefaultGlobalSettings.defaultSkinValue; + } + + factory GlobalSettings.createDefault() { + return GlobalSettings( + skin: DefaultGlobalSettings.defaultSkinValue, + ); + } + + void dump() { + printlog('$GlobalSettings: '); + printlog(' ${DefaultGlobalSettings.parameterCodeSkin}: $skin'); + printlog(''); + } + + @override + String toString() { + return '$GlobalSettings(${toJson()})'; + } + + Map<String, dynamic>? toJson() { + return <String, dynamic>{ + DefaultGlobalSettings.parameterCodeSkin: skin, + }; + } +} diff --git a/lib/models/types.dart b/lib/models/types.dart new file mode 100644 index 0000000000000000000000000000000000000000..339bfe66331369eb92a4113be046f7a36785b9c6 --- /dev/null +++ b/lib/models/types.dart @@ -0,0 +1,3 @@ +import 'package:colors/models/cell.dart'; + +typedef BoardCells = List<List<Cell>>; diff --git a/lib/provider/data.dart b/lib/provider/data.dart deleted file mode 100644 index dfe31360d790bb8775fd4c78343024c10a400ed4..0000000000000000000000000000000000000000 --- a/lib/provider/data.dart +++ /dev/null @@ -1,340 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -import 'package:colors/entities/cell.dart'; - -typedef Board = List<List<Cell>>; - -class Data extends ChangeNotifier { - // Configuration available parameters - final List<String> _availableParameters = ['level', 'size', 'colors', 'skin']; - List<String> get availableParameters => _availableParameters; - - // Configuration available values - final List<String> _availableLevelValues = ['easy', 'medium', 'hard', 'nightmare']; - final List<String> _availableSizeValues = ['small', 'medium', 'large', 'extra']; - final List<String> _availableColorsValues = ['5', '6', '7', '8']; - final List<String> _availableSkinValues = ['default']; - - List<String> get availableLevelValues => _availableLevelValues; - List<String> get availableSizeValues => _availableSizeValues; - List<String> get availableColorsValues => _availableColorsValues; - List<String> get availableSkinValues => _availableSkinValues; - - // Application default configuration - String _parameterLevel = ''; - final String _parameterLevelDefault = 'medium'; - String _parameterSize = ''; - final String _parameterSizeDefault = 'medium'; - String _parameterColors = ''; - final String _parameterColorsDefault = '6'; - String _parameterSkin = ''; - final String _parameterSkinDefault = 'default'; - - // Application current configuration - String get parameterLevel => _parameterLevel; - String get parameterSize => _parameterSize; - String get parameterColors => _parameterColors; - String get parameterSkin => _parameterSkin; - - // Game data - bool _gameIsRunning = false; - bool _animationInProgress = false; - bool _gameWon = false; - int _boardSize = 0; - int _colorsCount = 0; - int _movesCount = 0; - int _maxMovesCount = 0; - Board _board = []; - - int _progress = 0; - int _progressTotal = 0; - int _progressDelta = 0; - - bool isParameterValueAllowed(String parameterValue, List<String> parametersAllowedValues) { - bool found = false; - for (String item in parametersAllowedValues) { - if (item.contains(parameterValue)) { - found = true; - } - } - return found; - } - - void updateParameterLevel(String parameterLevel) { - if (isParameterValueAllowed(parameterLevel, _availableLevelValues)) { - _parameterLevel = parameterLevel; - } else { - _parameterLevel = _parameterLevelDefault; - } - notifyListeners(); - } - - void updateParameterSize(String parameterSize) { - if (isParameterValueAllowed(parameterSize, _availableSizeValues)) { - _parameterSize = parameterSize; - } else { - _parameterSize = _parameterSizeDefault; - } - updateBoardSize(getBoardSizeFromParameter(parameterSize)); - notifyListeners(); - } - - void updateParameterColors(String parameterColors) { - if (isParameterValueAllowed(parameterColors, _availableColorsValues)) { - _parameterColors = parameterColors; - } else { - _parameterColors = _parameterColorsDefault; - } - updateColorsCount(getColorsCountFromParameter(parameterColors)); - notifyListeners(); - } - - void updateParameterSkin(String parameterSkin) { - if (isParameterValueAllowed(parameterSkin, _availableSkinValues)) { - _parameterSkin = parameterSkin; - } else { - _parameterSkin = _parameterSkinDefault; - } - notifyListeners(); - } - - String getParameterValue(String parameterCode) { - switch (parameterCode) { - case 'level': - { - return _parameterLevel; - } - case 'size': - { - return _parameterSize; - } - case 'colors': - { - return _parameterColors; - } - case 'skin': - { - return _parameterSkin; - } - } - return ''; - } - - List<String> getParameterAvailableValues(String parameterCode) { - switch (parameterCode) { - case 'level': - { - return _availableLevelValues; - } - case 'size': - { - return _availableSizeValues; - } - case 'colors': - { - return _availableColorsValues; - } - case 'skin': - { - return _availableSkinValues; - } - } - return []; - } - - void setParameterValue(String parameterCode, String parameterValue) async { - switch (parameterCode) { - case 'level': - { - updateParameterLevel(parameterValue); - } - break; - case 'size': - { - updateParameterSize(parameterValue); - } - break; - case 'colors': - { - updateParameterColors(parameterValue); - } - break; - case 'skin': - { - updateParameterSkin(parameterValue); - } - break; - } - final prefs = await SharedPreferences.getInstance(); - prefs.setString(parameterCode, parameterValue); - } - - void initParametersValues() async { - final prefs = await SharedPreferences.getInstance(); - setParameterValue('level', prefs.getString('level') ?? _parameterLevelDefault); - setParameterValue('size', prefs.getString('size') ?? _parameterSizeDefault); - setParameterValue('colors', prefs.getString('colors') ?? _parameterColorsDefault); - setParameterValue('skin', prefs.getString('skin') ?? _parameterSkinDefault); - } - - int getBoardSizeFromParameter(String parameterSize) { - switch (parameterSize) { - case 'small': - { - return 6; - } - case 'medium': - { - return 10; - } - case 'large': - { - return 14; - } - case 'extra': - { - return 20; - } - } - return getBoardSizeFromParameter(_parameterSizeDefault); - } - - int getColorsCountFromParameter(String parameterColors) { - switch (parameterColors) { - case '5': - { - return 5; - } - case '6': - { - return 6; - } - case '7': - { - return 7; - } - case '8': - { - return 8; - } - } - return getColorsCountFromParameter(_parameterColorsDefault); - } - - int getMovesCountLimitDeltaFromLevelParameter(String parameterLevel) { - switch (parameterLevel) { - case 'easy': - { - return 5; - } - case 'medium': - { - return 3; - } - case 'hard': - { - return 1; - } - case 'nightmare': - { - return -1; - } - } - return getMovesCountLimitDeltaFromLevelParameter(_parameterLevelDefault); - } - - int get boardSize => _boardSize; - void updateBoardSize(int boardSize) { - _boardSize = boardSize; - _progressTotal = boardSize * boardSize; - } - - int get colorsCount => _colorsCount; - void updateColorsCount(int colorsCount) { - _colorsCount = colorsCount; - } - - Board get board => _board; - void updateBoard(Board board) { - _board = board; - notifyListeners(); - } - - updateCellValue(int col, int row, int value) { - _board[row][col].value = value; - notifyListeners(); - } - - int getFirstCellValue() { - return _board[0][0].value; - } - - int getCellValue(int col, int row) { - return _board[row][col].value; - } - - int get movesCount => _movesCount; - void updateMovesCount(int movesCount) { - _movesCount = movesCount; - notifyListeners(); - } - - void incrementMovesCount() { - updateMovesCount(movesCount + 1); - } - - int get maxMovesCount => _maxMovesCount; - void updateMaxMovesCount(int maxMovesCount) { - _maxMovesCount = maxMovesCount; - } - - int get progress => _progress; - int get progressTotal => _progressTotal; - int get progressDelta => _progressDelta; - void updateProgress(int progress) { - _progress = progress; - notifyListeners(); - } - - void updateProgressTotal(int progressTotal) { - _progressTotal = progressTotal; - notifyListeners(); - } - - void updateProgressDelta(int progressDelta) { - _progressDelta = progressDelta; - notifyListeners(); - } - - bool get gameIsRunning => _gameIsRunning; - void updateGameIsRunning(bool gameIsRunning) { - _gameIsRunning = gameIsRunning; - notifyListeners(); - } - - bool isGameFinished() { - return _gameWon; - } - - bool get gameWon => _gameWon; - void updateGameWon(bool gameWon) { - _gameWon = gameWon; - notifyListeners(); - } - - bool get animationInProgress => _animationInProgress; - void updateAnimationInProgress(bool animationInProgress) { - _animationInProgress = animationInProgress; - notifyListeners(); - } - - void resetGame() { - _gameIsRunning = false; - _gameWon = false; - _movesCount = 0; - _maxMovesCount = 0; - _progress = 0; - notifyListeners(); - } -} diff --git a/lib/ui/layout/game.dart b/lib/ui/layout/game.dart deleted file mode 100644 index a91ceafa7578a1b92617b1406348a4d1c2ae4237..0000000000000000000000000000000000000000 --- a/lib/ui/layout/game.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:colors/ui/layout/tileset.dart'; -import 'package:colors/provider/data.dart'; -import 'package:colors/ui/widgets/game/indicator_top.dart'; -import 'package:colors/ui/widgets/game/message_game_end.dart'; -import 'package:colors/ui/widgets/game/select_color_bar.dart'; - -class Game extends StatelessWidget { - const Game({ - super.key, - required this.myProvider, - required this.boardWidth, - }); - - final Data myProvider; - final double boardWidth; - - @override - Widget build(BuildContext context) { - final bool gameIsFinished = myProvider.isGameFinished(); - - return Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 8), - TopIndicator(myProvider: myProvider), - const SizedBox(height: 2), - Expanded( - child: Tileset(myProvider: myProvider, boardWidth: boardWidth), - ), - const SizedBox(height: 2), - Container( - child: gameIsFinished - ? EndGameMessage(myProvider: myProvider) - : SelectColorBar(myProvider: myProvider), - ), - ], - ); - } -} diff --git a/lib/ui/layout/parameters.dart b/lib/ui/layout/parameters.dart deleted file mode 100644 index 34a9a42e93adfc43b9757bc739f0b21d08a01191..0000000000000000000000000000000000000000 --- a/lib/ui/layout/parameters.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:colors/ui/widgets/home/button_game_start_new.dart'; -import 'package:colors/provider/data.dart'; - -class Parameters extends StatelessWidget { - const Parameters({super.key, required this.myProvider}); - - final Data myProvider; - - static const double separatorHeight = 2.0; - static const double blockMargin = 3.0; - static const double blockPadding = 2.0; - static const Color buttonBackgroundColor = Colors.white; - static const Color buttonBorderColorActive = Colors.blue; - static const Color buttonBorderColorInactive = Colors.white; - static const double buttonBorderWidth = 10.0; - static const double buttonBorderRadius = 8.0; - static const double buttonPadding = 0.0; - static const double buttonMargin = 0.0; - - @override - Widget build(BuildContext context) { - List<Widget> lines = []; - - final List<String> parameters = myProvider.availableParameters; - for (int index = 0; index < parameters.length; index++) { - lines.add(buildParameterSelector(parameters[index])); - lines.add(const SizedBox(height: separatorHeight)); - } - - return Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: separatorHeight), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: lines, - ), - ), - const SizedBox(height: separatorHeight), - StartNewGameButton(myProvider: myProvider), - ], - ); - } - - static Image buildImageWidget(String imageAssetCode) { - return Image( - image: AssetImage('assets/icons/$imageAssetCode.png'), - fit: BoxFit.fill, - ); - } - - static Container buildImageContainerWidget(String imageAssetCode) { - return Container( - child: buildImageWidget(imageAssetCode), - ); - } - - static Column buildDecorationImageWidget() { - return Column( - children: [ - TextButton( - child: buildImageContainerWidget('game_win'), - onPressed: () {}, - ), - ], - ); - } - - Widget buildParameterSelector(String parameterCode) { - final List<String> availableValues = myProvider.getParameterAvailableValues(parameterCode); - - if (availableValues.length == 1) { - return const SizedBox(height: 0.0); - } - - return Table( - defaultColumnWidth: const IntrinsicColumnWidth(), - children: [ - TableRow( - children: [ - for (int index = 0; index < availableValues.length; index++) - Column( - children: [buildParameterButton(parameterCode, availableValues[index])], - ), - ], - ), - ], - ); - } - - Widget buildParameterButton(String parameterCode, String parameterValue) { - final String currentValue = myProvider.getParameterValue(parameterCode).toString(); - - final bool isActive = (parameterValue == currentValue); - final String imageAsset = '${parameterCode}_$parameterValue'; - - return TextButton( - child: Container( - margin: const EdgeInsets.all(buttonMargin), - padding: const EdgeInsets.all(buttonPadding), - decoration: BoxDecoration( - color: buttonBackgroundColor, - borderRadius: BorderRadius.circular(buttonBorderRadius), - border: Border.all( - color: isActive ? buttonBorderColorActive : buttonBorderColorInactive, - width: buttonBorderWidth, - ), - ), - child: buildImageWidget(imageAsset), - ), - onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue), - ); - } -} diff --git a/lib/ui/layout/tileset.dart b/lib/ui/layout/tileset.dart deleted file mode 100644 index f18470dfd99d48971a2d63aa2dc4fd38c5672a11..0000000000000000000000000000000000000000 --- a/lib/ui/layout/tileset.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:colors/ui/painters/board_painter.dart'; -import 'package:colors/provider/data.dart'; -import 'package:colors/utils/board_utils.dart'; - -class Tileset extends StatelessWidget { - const Tileset({ - super.key, - required this.myProvider, - required this.boardWidth, - }); - - final Data myProvider; - final double boardWidth; - - @override - Widget build(BuildContext context) { - return Container( - margin: const EdgeInsets.all(4), - padding: const EdgeInsets.all(4), - child: Column( - children: [ - Center( - child: GestureDetector( - onTapUp: (details) { - final double xTap = details.localPosition.dx; - final double yTap = details.localPosition.dy; - final int boardSize = myProvider.boardSize; - final int col = xTap ~/ (boardWidth / boardSize); - final int row = yTap ~/ (boardWidth / boardSize); - final int cellValue = myProvider.getCellValue(col, row); - BoardUtils.fillBoardFromFirstCell(myProvider, cellValue); - }, - child: CustomPaint( - size: Size(boardWidth, boardWidth), - willChange: false, - painter: BoardPainter( - myProvider: myProvider, - colorScheme: Theme.of(context).colorScheme, - ), - isComplex: true, - ), - ), - ), - ], - ), - ); - } -} diff --git a/lib/ui/painters/board_painter.dart b/lib/ui/painters/board_painter.dart index d1ec5b29629529544e600da0f1cf6807fb0a4a13..42bb2a2a5f7e284f9bc2bd9fb6cda486ea07fe50 100644 --- a/lib/ui/painters/board_painter.dart +++ b/lib/ui/painters/board_painter.dart @@ -1,19 +1,23 @@ import 'package:flutter/material.dart'; -import 'package:colors/entities/cell.dart'; +import 'package:colors/models/cell.dart'; +import 'package:colors/models/game.dart'; +import 'package:colors/models/types.dart'; import 'package:colors/utils/color_theme.dart'; -import 'package:colors/provider/data.dart'; class BoardPainter extends CustomPainter { - const BoardPainter({required this.myProvider, required this.colorScheme}); + const BoardPainter({ + required this.game, + required this.colorScheme, + }); - final Data myProvider; + final Game game; final ColorScheme colorScheme; @override void paint(Canvas canvas, Size size) { - final int boardSize = myProvider.boardSize; - final Board board = myProvider.board; + final int boardSize = game.gameSettings.boardSize; + final BoardCells cells = game.board.cells; final double cellSize = size.width / boardSize; // background @@ -22,9 +26,9 @@ class BoardPainter extends CustomPainter { for (var col = 0; col < boardSize; col++) { final double x = cellSize * col; - final Cell cell = board[row][col]; + final Cell cell = cells[row][col]; final int cellValue = cell.value; - final int colorCode = ColorTheme.getColorCode(myProvider.parameterSkin, cellValue); + final int colorCode = ColorTheme.getColorCode(game.globalSettings.skin, cellValue); final cellPaintBackground = Paint(); cellPaintBackground.color = Color(colorCode); @@ -40,7 +44,7 @@ class BoardPainter extends CustomPainter { // borders const double borderSize = 2; final cellPaintBorder = Paint(); - cellPaintBorder.color = colorScheme.onSurface; + cellPaintBorder.color = colorScheme.onBackground; cellPaintBorder.strokeWidth = borderSize; cellPaintBorder.strokeCap = StrokeCap.round; @@ -49,27 +53,27 @@ class BoardPainter extends CustomPainter { for (var col = 0; col < boardSize; col++) { final double x = cellSize * col; - final Cell cell = board[row][col]; + final Cell cell = cells[row][col]; final int cellValue = cell.value; - if ((row == 0) || (row > 1 && cellValue != myProvider.getCellValue(col, row - 1))) { + if ((row == 0) || (row > 1 && cellValue != game.board.getCellValue(col, row - 1))) { final Offset borderStart = Offset(x, y); final Offset borderStop = Offset(x + cellSize, y); canvas.drawLine(borderStart, borderStop, cellPaintBorder); } if ((row == boardSize - 1) || - ((row + 1) < boardSize && cellValue != myProvider.getCellValue(col, row + 1))) { + ((row + 1) < boardSize && cellValue != game.board.getCellValue(col, row + 1))) { final Offset borderStart = Offset(x, y + cellSize); final Offset borderStop = Offset(x + cellSize, y + cellSize); canvas.drawLine(borderStart, borderStop, cellPaintBorder); } - if ((col == 0) || (col > 1 && cellValue != myProvider.getCellValue(col - 1, row))) { + if ((col == 0) || (col > 1 && cellValue != game.board.getCellValue(col - 1, row))) { final Offset borderStart = Offset(x, y); final Offset borderStop = Offset(x, y + cellSize); canvas.drawLine(borderStart, borderStop, cellPaintBorder); } if ((col == boardSize - 1) || - ((col + 1) < boardSize && cellValue != myProvider.getCellValue(col + 1, row))) { + ((col + 1) < boardSize && cellValue != game.board.getCellValue(col + 1, row))) { final Offset borderStart = Offset(x + cellSize, y); final Offset borderStop = Offset(x + cellSize, y + cellSize); canvas.drawLine(borderStart, borderStop, cellPaintBorder); diff --git a/lib/ui/painters/parameter_painter.dart b/lib/ui/painters/parameter_painter.dart new file mode 100644 index 0000000000000000000000000000000000000000..fb216ed2c3bd02cb57c27c8121ba47de02e637d7 --- /dev/null +++ b/lib/ui/painters/parameter_painter.dart @@ -0,0 +1,372 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +import 'package:colors/config/default_game_settings.dart'; +import 'package:colors/config/default_global_settings.dart'; +import 'package:colors/models/settings_game.dart'; +import 'package:colors/models/settings_global.dart'; +import 'package:colors/utils/color_extensions.dart'; +import 'package:colors/utils/color_theme.dart'; +import 'package:colors/utils/tools.dart'; + +class ParameterPainter extends CustomPainter { + const ParameterPainter({ + required this.code, + required this.value, + required this.isSelected, + required this.gameSettings, + required this.globalSettings, + }); + + final String code; + final String value; + final bool isSelected; + final GameSettings gameSettings; + final GlobalSettings globalSettings; + + @override + void paint(Canvas canvas, Size size) { + // force square + final double canvasSize = min(size.width, size.height); + + const Color borderColorEnabled = Colors.blue; + const Color borderColorDisabled = Colors.white; + + // "enabled/disabled" border + final paint = Paint(); + paint.style = PaintingStyle.stroke; + paint.color = isSelected ? borderColorEnabled : borderColorDisabled; + paint.strokeJoin = StrokeJoin.round; + paint.strokeWidth = 20 / 100 * canvasSize; + canvas.drawRect( + Rect.fromPoints(const Offset(0, 0), Offset(canvasSize, canvasSize)), paint); + + // content + switch (code) { + case DefaultGameSettings.parameterCodeDifficultyLevel: + paintDifficultyLevelParameterItem(value, canvas, canvasSize); + break; + case DefaultGameSettings.parameterCodeBoardSize: + paintBoardSizeParameterItem(value, canvas, canvasSize); + break; + case DefaultGameSettings.parameterCodeColorsCount: + paintColorsCountParameterItem(value, canvas, canvasSize); + break; + case DefaultGlobalSettings.parameterCodeSkin: + paintUnknownParameterItem(value, canvas, canvasSize); + break; + default: + printlog('Unknown parameter: $code/$value'); + paintUnknownParameterItem(value, canvas, canvasSize); + } + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return false; + } + + // "unknown" parameter -> simple block with text + void paintUnknownParameterItem( + final String value, + final Canvas canvas, + final double size, + ) { + final paint = Paint(); + paint.strokeJoin = StrokeJoin.round; + paint.strokeWidth = 3 / 100 * size; + + paint.color = Colors.grey; + paint.style = PaintingStyle.fill; + canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint); + + final textSpan = TextSpan( + text: '?\n$value', + style: const TextStyle( + color: Colors.black, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ); + final textPainter = TextPainter( + text: textSpan, + textDirection: TextDirection.ltr, + ); + textPainter.layout(); + textPainter.paint( + canvas, + Offset( + (size - textPainter.width) * 0.5, + (size - textPainter.height) * 0.5, + ), + ); + } + + void paintDifficultyLevelParameterItem( + final String value, + final Canvas canvas, + final double size, + ) { + Color backgroundColor = Colors.grey; + + final List<dynamic> stars = []; + + switch (value) { + case DefaultGameSettings.difficultyLevelValueEasy: + backgroundColor = Colors.green; + stars.add([0.5, 0.5]); + break; + case DefaultGameSettings.difficultyLevelValueMedium: + backgroundColor = Colors.orange; + stars.add([0.3, 0.5]); + stars.add([0.7, 0.5]); + break; + case DefaultGameSettings.difficultyLevelValueHard: + backgroundColor = Colors.red; + stars.add([0.3, 0.3]); + stars.add([0.7, 0.3]); + stars.add([0.5, 0.7]); + break; + case DefaultGameSettings.difficultyLevelValueNightmare: + backgroundColor = Colors.purple; + stars.add([0.3, 0.3]); + stars.add([0.7, 0.3]); + stars.add([0.3, 0.7]); + stars.add([0.7, 0.7]); + break; + default: + printlog('Wrong value for level parameter value: $value'); + } + + final paint = Paint(); + paint.strokeJoin = StrokeJoin.round; + paint.strokeWidth = 3 / 100 * size; + + // Colored background + paint.color = backgroundColor; + paint.style = PaintingStyle.fill; + canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint); + + // Stars + final textSpan = TextSpan( + text: '⭐', + style: TextStyle( + color: Colors.black, + fontSize: size / 3, + fontWeight: FontWeight.bold, + ), + ); + final textPainter = TextPainter( + text: textSpan, + textDirection: TextDirection.ltr, + ); + textPainter.layout(); + + for (var center in stars) { + textPainter.paint( + canvas, + Offset( + size * center[0] - textPainter.width * 0.5, + size * center[1] - textPainter.height * 0.5, + ), + ); + } + } + + void paintBoardSizeParameterItem( + final String value, + final Canvas canvas, + final double size, + ) { + Color backgroundColor = Colors.grey; + int gridWidth = 1; + + switch (value) { + case DefaultGameSettings.boardSizeValueSmall: + backgroundColor = Colors.green; + gridWidth = 2; + break; + case DefaultGameSettings.boardSizeValueMedium: + backgroundColor = Colors.orange; + gridWidth = 3; + break; + case DefaultGameSettings.boardSizeValueLarge: + backgroundColor = Colors.red; + gridWidth = 4; + break; + case DefaultGameSettings.boardSizeValueExtra: + backgroundColor = Colors.purple; + gridWidth = 5; + break; + default: + printlog('Wrong value for boardSize parameter value: $value'); + } + + final paint = Paint(); + paint.strokeJoin = StrokeJoin.round; + paint.strokeWidth = 3 / 100 * size; + + // Colored background + paint.color = backgroundColor; + paint.style = PaintingStyle.fill; + canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint); + + // Mini grid + final squareBackgroundColor = Colors.grey.shade200; + final squareBorderColor = Colors.grey.shade800; + + final double cellSize = size / 7; + final double origin = (size - gridWidth * cellSize) / 2; + + for (int row = 0; row < gridWidth; row++) { + for (int col = 0; col < gridWidth; col++) { + final Offset topLeft = Offset(origin + col * cellSize, origin + row * cellSize); + final Offset bottomRight = topLeft + Offset(cellSize, cellSize); + + paint.color = squareBackgroundColor; + paint.style = PaintingStyle.fill; + canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint); + + paint.color = squareBorderColor; + paint.style = PaintingStyle.stroke; + canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint); + } + } + } + + void paintColorsCountParameterItem( + final String value, + final Canvas canvas, + final double size, + ) { + Color backgroundColor = Colors.grey; + + switch (value) { + case DefaultGameSettings.colorsCountValueLow: + backgroundColor = Colors.green; + break; + case DefaultGameSettings.colorsCountValueMedium: + backgroundColor = Colors.orange; + break; + case DefaultGameSettings.colorsCountValueHigh: + backgroundColor = Colors.red; + break; + case DefaultGameSettings.colorsCountValueVeryHigh: + backgroundColor = Colors.purple; + break; + default: + printlog('Wrong value for colorsCount parameter value: $value'); + } + + final paint = Paint(); + paint.strokeJoin = StrokeJoin.round; + paint.strokeWidth = 3 / 100 * size; + + // Colored background + paint.color = backgroundColor; + paint.style = PaintingStyle.fill; + canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint); + + // Colors preview + const List<Offset> positions = [ + Offset(0, 0), + Offset(1, 0), + Offset(2, 0), + Offset(2, 1), + Offset(2, 2), + Offset(1, 2), + Offset(0, 2), + Offset(0, 1), + ]; + + const skin = DefaultGlobalSettings.defaultSkinValue; + + final double padding = 4 / 100 * size; + final double margin = 3 / 100 * size; + final double width = ((size - 2 * padding) / 3) - 2 * margin; + + final int maxValue = int.parse(value); + for (int colorIndex = 0; colorIndex < maxValue; colorIndex++) { + final Offset position = positions[colorIndex]; + + final Offset topLeft = Offset(padding + margin + position.dx * (width + 2 * margin), + padding + margin + position.dy * (width + 2 * margin)); + + final Offset bottomRight = topLeft + Offset(width, width); + + final squareColor = Color(ColorTheme.getColorCode(skin, colorIndex + 1)); + paint.color = squareColor; + paint.style = PaintingStyle.fill; + canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint); + + final borderColor = squareColor.darken(20); + paint.color = borderColor; + paint.style = PaintingStyle.stroke; + canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint); + } + + // centered text value + final textSpan = TextSpan( + text: value.toString(), + style: TextStyle( + color: Colors.black, + fontSize: size / 4, + fontWeight: FontWeight.bold, + ), + ); + final textPainter = TextPainter( + text: textSpan, + textDirection: TextDirection.ltr, + ); + textPainter.layout(); + textPainter.paint( + canvas, + Offset( + (size - textPainter.width) * 0.5, + (size - textPainter.height) * 0.5, + ), + ); + } + + void paintColorsThemeParameterItem( + final String value, + final Canvas canvas, + final double size, + ) { + Color backgroundColor = Colors.grey; + const int gridWidth = 4; + + final paint = Paint(); + paint.strokeJoin = StrokeJoin.round; + paint.strokeWidth = 3 / 100 * size; + + // Colored background + paint.color = backgroundColor; + paint.style = PaintingStyle.fill; + canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint); + + // Mini grid + final borderColor = Colors.grey.shade800; + + final double cellSize = size / gridWidth; + final double origin = (size - gridWidth * cellSize) / 2; + + for (int row = 0; row < gridWidth; row++) { + for (int col = 0; col < gridWidth; col++) { + final Offset topLeft = Offset(origin + col * cellSize, origin + row * cellSize); + final Offset bottomRight = topLeft + Offset(cellSize, cellSize); + + const squareColor = Colors.pink; + + paint.color = squareColor; + paint.style = PaintingStyle.fill; + canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint); + + paint.color = borderColor; + paint.style = PaintingStyle.stroke; + canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint); + } + } + } +} diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/about_page.dart deleted file mode 100644 index 459d008ee58602b8b4fd0a391c7cb491d17f87b4..0000000000000000000000000000000000000000 --- a/lib/ui/screens/about_page.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; -import 'package:package_info_plus/package_info_plus.dart'; - -import 'package:colors/ui/widgets/header_app.dart'; - -class AboutPage extends StatelessWidget { - const AboutPage({super.key}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 8), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: <Widget>[ - const SizedBox(height: 8), - const AppHeader(text: 'about_title'), - const Text('about_content').tr(), - FutureBuilder<PackageInfo>( - future: PackageInfo.fromPlatform(), - builder: (context, snapshot) { - switch (snapshot.connectionState) { - case ConnectionState.done: - return const Text('about_version').tr( - namedArgs: { - 'version': snapshot.data!.version, - }, - ); - default: - return const SizedBox(); - } - }, - ), - ], - ), - ); - } -} diff --git a/lib/ui/screens/game_page.dart b/lib/ui/screens/game_page.dart deleted file mode 100644 index d974148b5edbb75ca28499adb6c2d9075c50ac8a..0000000000000000000000000000000000000000 --- a/lib/ui/screens/game_page.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; - -import 'package:colors/ui/layout/game.dart'; -import 'package:colors/ui/layout/parameters.dart'; -import 'package:colors/provider/data.dart'; - -class GamePage extends StatefulWidget { - const GamePage({super.key}); - - @override - GamePageState createState() => GamePageState(); -} - -class GamePageState extends State<GamePage> { - @override - void initState() { - super.initState(); - - final Data myProvider = Provider.of<Data>(context, listen: false); - myProvider.initParametersValues(); - } - - @override - Widget build(BuildContext context) { - final Data myProvider = Provider.of<Data>(context); - final double boardWidth = MediaQuery.of(context).size.width; - - return SafeArea( - child: Center( - child: myProvider.gameIsRunning - ? Game(myProvider: myProvider, boardWidth: boardWidth) - : Parameters(myProvider: myProvider), - ), - ); - } -} diff --git a/lib/ui/screens/page_about.dart b/lib/ui/screens/page_about.dart new file mode 100644 index 0000000000000000000000000000000000000000..a8602ef37637e6f640625560da6a31e461f11238 --- /dev/null +++ b/lib/ui/screens/page_about.dart @@ -0,0 +1,38 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +import 'package:colors/ui/widgets/helpers/header_app.dart'; + +class PageAbout extends StatelessWidget { + const PageAbout({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: <Widget>[ + const SizedBox(height: 8), + const AppHeader(text: 'about_title'), + const Text('about_content').tr(), + FutureBuilder<PackageInfo>( + future: PackageInfo.fromPlatform(), + builder: (context, snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.done: + return const Text('about_version').tr( + namedArgs: { + 'version': snapshot.data!.version, + }, + ); + default: + return const SizedBox(); + } + }, + ), + ], + ); + } +} diff --git a/lib/ui/screens/page_game.dart b/lib/ui/screens/page_game.dart new file mode 100644 index 0000000000000000000000000000000000000000..d3a64ac427c48bfbffc62f0f93e4f2793aaadcd1 --- /dev/null +++ b/lib/ui/screens/page_game.dart @@ -0,0 +1,18 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; + +import 'package:colors/cubit/game_cubit.dart'; +import 'package:colors/ui/widgets/game/game.dart'; +import 'package:colors/ui/widgets/parameters.dart'; + +class PageGame extends StatelessWidget { + const PageGame({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder<GameCubit, GameState>( + builder: (BuildContext context, GameState gameState) { + return gameState.currentGame.isRunning ? const GameWidget() : const Parameters(); + }); + } +} diff --git a/lib/ui/screens/page_settings.dart b/lib/ui/screens/page_settings.dart new file mode 100644 index 0000000000000000000000000000000000000000..d559f9566662c9f3bffaaf35a184e6b79a04feda --- /dev/null +++ b/lib/ui/screens/page_settings.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +import 'package:colors/ui/widgets/helpers/header_app.dart'; +import 'package:colors/ui/widgets/settings/settings_form.dart'; + +class PageSettings extends StatelessWidget { + const PageSettings({super.key}); + + @override + Widget build(BuildContext context) { + return const Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: <Widget>[ + SizedBox(height: 8), + AppHeader(text: 'settings_title'), + SizedBox(height: 8), + SettingsForm(), + ], + ); + } +} diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/settings_page.dart deleted file mode 100644 index dc59bbe6eaddffbfb957beef56e24ca3971ff485..0000000000000000000000000000000000000000 --- a/lib/ui/screens/settings_page.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:colors/ui/widgets/header_app.dart'; -import 'package:colors/ui/widgets/settings/settings_form.dart'; - -class SettingsPage extends StatelessWidget { - const SettingsPage({super.key}); - - @override - Widget build(BuildContext context) { - return const Padding( - padding: EdgeInsets.symmetric(horizontal: 8), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: <Widget>[ - SizedBox(height: 8), - AppHeader(text: 'settings_title'), - SizedBox(height: 8), - SettingsForm(), - ], - ), - ); - } -} diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart index a428bc5bc1686928fb37c90d4f449185c666d792..eaec6f6314be0af2e0ecb1a955db10b90b76f4d8 100644 --- a/lib/ui/skeleton.dart +++ b/lib/ui/skeleton.dart @@ -1,47 +1,28 @@ -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_swipe/flutter_swipe.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter/material.dart'; import 'package:colors/config/menu.dart'; -import 'package:colors/cubit/bottom_nav_cubit.dart'; -import 'package:colors/provider/data.dart'; -import 'package:colors/ui/widgets/app_bar.dart'; -import 'package:colors/ui/widgets/bottom_nav_bar.dart'; +import 'package:colors/cubit/nav_cubit.dart'; +import 'package:colors/ui/widgets/global_app_bar.dart'; -class SkeletonScreen extends StatefulWidget { +class SkeletonScreen extends StatelessWidget { const SkeletonScreen({super.key}); - @override - State<SkeletonScreen> createState() => _SkeletonScreenState(); -} - -class _SkeletonScreenState extends State<SkeletonScreen> { @override Widget build(BuildContext context) { - final Data myProvider = Provider.of<Data>(context); - return Scaffold( + appBar: const GlobalAppBar(), extendBodyBehindAppBar: false, - appBar: StandardAppBar(myProvider: myProvider), - body: Swiper( - itemCount: Menu.itemsCount, - itemBuilder: (BuildContext context, int index) { - return Menu.getPageWidget(index); - }, - pagination: SwiperPagination( - margin: const EdgeInsets.all(0), - builder: SwiperCustomPagination( - builder: (BuildContext context, SwiperPluginConfig config) { - return BottomNavBar(swipeController: config.controller); - }, - ), + body: Material( + color: Theme.of(context).colorScheme.background, + child: BlocBuilder<NavCubit, int>( + builder: (BuildContext context, int pageIndex) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Menu.getPageWidget(pageIndex), + ); + }, ), - onIndexChanged: (newPageIndex) { - BlocProvider.of<BottomNavCubit>(context).updateIndex(newPageIndex); - }, - outer: true, - loop: false, ), backgroundColor: Theme.of(context).colorScheme.background, ); diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart deleted file mode 100644 index c998df686de1518562c0be63d4563946595d6b3e..0000000000000000000000000000000000000000 --- a/lib/ui/widgets/app_bar.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; -import 'package:overlay_support/overlay_support.dart'; - -import 'package:colors/provider/data.dart'; -import 'package:colors/ui/widgets/header_app.dart'; -import 'package:colors/utils/game_utils.dart'; - -class StandardAppBar extends StatelessWidget implements PreferredSizeWidget { - const StandardAppBar({super.key, required this.myProvider}); - - final Data myProvider; - - @override - Widget build(BuildContext context) { - final List<Widget> menuActions = []; - - if (myProvider.gameIsRunning) { - menuActions.add(TextButton( - child: const Image( - image: AssetImage('assets/icons/button_back.png'), - fit: BoxFit.fill, - ), - onPressed: () => toast(tr('long_press_to_quit')), - onLongPress: () => GameUtils.quitGame(myProvider), - )); - } - - return AppBar( - title: const AppHeader(text: 'app_name'), - actions: menuActions, - ); - } - - @override - Size get preferredSize => const Size.fromHeight(50); -} diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart deleted file mode 100644 index 87e30d5a4fe026469ba6feffa70e84dc67f9a4f8..0000000000000000000000000000000000000000 --- a/lib/ui/widgets/bottom_nav_bar.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_swipe/flutter_swipe.dart'; - -import 'package:colors/config/menu.dart'; -import 'package:colors/cubit/bottom_nav_cubit.dart'; - -class BottomNavBar extends StatelessWidget { - const BottomNavBar({super.key, required this.swipeController}); - - final SwiperController swipeController; - - @override - Widget build(BuildContext context) { - return Card( - margin: const EdgeInsets.all(0), - elevation: 4, - shadowColor: Theme.of(context).colorScheme.shadow, - color: Theme.of(context).colorScheme.surfaceVariant, - shape: const ContinuousRectangleBorder(), - child: BlocBuilder<BottomNavCubit, int>( - builder: (BuildContext context, int state) { - return BottomNavigationBar( - currentIndex: state, - onTap: (int index) { - context.read<BottomNavCubit>().updateIndex(index); - swipeController.move(index); - }, - type: BottomNavigationBarType.fixed, - elevation: 0, - backgroundColor: Colors.transparent, - selectedItemColor: Theme.of(context).colorScheme.primary, - unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color, - items: Menu.getMenuItems(), - ); - }, - ), - ); - } -} diff --git a/lib/ui/widgets/button_game_start_new.dart b/lib/ui/widgets/button_game_start_new.dart new file mode 100644 index 0000000000000000000000000000000000000000..613d2fb7cbfca7241b2c7fbf788825a92d412141 --- /dev/null +++ b/lib/ui/widgets/button_game_start_new.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:colors/cubit/game_cubit.dart'; +import 'package:colors/cubit/settings_game_cubit.dart'; +import 'package:colors/cubit/settings_global_cubit.dart'; + +class StartNewGameButton extends StatelessWidget { + const StartNewGameButton({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder<GameSettingsCubit, GameSettingsState>( + builder: (BuildContext context, GameSettingsState gameSettingsState) { + return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>( + builder: (BuildContext context, GlobalSettingsState globalSettingsState) { + final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); + + return TextButton( + child: const Image( + image: AssetImage('assets/icons/button_start.png'), + fit: BoxFit.fill, + ), + onPressed: () => gameCubit.startNewGame( + gameSettings: gameSettingsState.settings, + globalSettings: globalSettingsState.settings, + ), + ); + }, + ); + }, + ); + } +} diff --git a/lib/ui/widgets/home/button_game_restart.dart b/lib/ui/widgets/game/button_game_restart.dart similarity index 62% rename from lib/ui/widgets/home/button_game_restart.dart rename to lib/ui/widgets/game/button_game_restart.dart index 364ca072c680b8b3a7afac129dc85d08750f7c5c..dce403b3cfb2690b2f5abcf0bd9e4559654779c6 100644 --- a/lib/ui/widgets/home/button_game_restart.dart +++ b/lib/ui/widgets/game/button_game_restart.dart @@ -1,15 +1,15 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/material.dart'; -import 'package:colors/provider/data.dart'; -import 'package:colors/utils/game_utils.dart'; +import 'package:colors/cubit/game_cubit.dart'; class RestartGameButton extends StatelessWidget { - const RestartGameButton({super.key, required this.myProvider}); - - final Data myProvider; + const RestartGameButton({super.key}); @override Widget build(BuildContext context) { + final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); + return TextButton( style: ButtonStyle( padding: MaterialStateProperty.all<EdgeInsets>(const EdgeInsets.all(0)), @@ -18,7 +18,7 @@ class RestartGameButton extends StatelessWidget { image: AssetImage('assets/icons/button_back.png'), fit: BoxFit.fill, ), - onPressed: () => GameUtils.quitGame(myProvider), + onPressed: () => gameCubit.quitGame(), ); } } diff --git a/lib/ui/widgets/game/cell_interactive.dart b/lib/ui/widgets/game/cell_interactive.dart new file mode 100644 index 0000000000000000000000000000000000000000..40b67d01db9fb21a8b080f5d7ebc3f40bf6dc29d --- /dev/null +++ b/lib/ui/widgets/game/cell_interactive.dart @@ -0,0 +1,55 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; + +import 'package:colors/cubit/game_cubit.dart'; +import 'package:colors/models/cell.dart'; +import 'package:colors/models/game.dart'; +import 'package:colors/utils/color_theme.dart'; + +class InteractiveCell extends StatelessWidget { + const InteractiveCell({ + super.key, + required this.cell, + required this.colorScheme, + required this.currentGame, + required this.itemWidth, + }); + + final Cell cell; + final ColorScheme colorScheme; + final Game currentGame; + final double itemWidth; + + @override + Widget build(BuildContext context) { + final String skin = currentGame.globalSettings.skin; + final squareColor = Color(ColorTheme.getColorCode(skin, cell.value)); + + return Container( + margin: const EdgeInsets.all(2), + decoration: BoxDecoration( + border: Border.all( + color: colorScheme.onSurface, + width: 3, + ), + ), + child: GestureDetector( + child: Container( + color: squareColor, + padding: const EdgeInsets.all(4), + child: SizedBox.square( + dimension: itemWidth - 19, + ), + ), + onTap: () { + final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); + + if (!currentGame.animationInProgress && + currentGame.board.getFirstCellValue() != cell.value) { + gameCubit.fillBoardFromFirstCell(cell.value); + } + }, + ), + ); + } +} diff --git a/lib/ui/widgets/game/game.dart b/lib/ui/widgets/game/game.dart new file mode 100644 index 0000000000000000000000000000000000000000..870676c265cf9d68145f51223fbcb05494086d8e --- /dev/null +++ b/lib/ui/widgets/game/game.dart @@ -0,0 +1,37 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; + +import 'package:colors/cubit/game_cubit.dart'; +import 'package:colors/models/game.dart'; +import 'package:colors/ui/widgets/game/game_board.dart'; +import 'package:colors/ui/widgets/game/game_top_indicator.dart'; +import 'package:colors/ui/widgets/game/message_game_end.dart'; +import 'package:colors/ui/widgets/game/select_color_bar.dart'; + +class GameWidget extends StatelessWidget { + const GameWidget({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder<GameCubit, GameState>( + builder: (BuildContext context, GameState gameState) { + final Game currentGame = gameState.currentGame; + + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 8), + const GameTopIndicatorWidget(), + const SizedBox(height: 2), + const GameBoard(), + const Expanded( + child: SizedBox(height: 2), + ), + currentGame.isFinished ? const EndGameMessage() : const SelectColorBar(), + ], + ); + }, + ); + } +} diff --git a/lib/ui/widgets/game/game_board.dart b/lib/ui/widgets/game/game_board.dart new file mode 100644 index 0000000000000000000000000000000000000000..385fc17de52368f835b2d83fe25531dc40ce523d --- /dev/null +++ b/lib/ui/widgets/game/game_board.dart @@ -0,0 +1,43 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; + +import 'package:colors/cubit/game_cubit.dart'; +import 'package:colors/models/game.dart'; +import 'package:colors/ui/painters/board_painter.dart'; + +class GameBoard extends StatelessWidget { + const GameBoard({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder<GameCubit, GameState>( + builder: (BuildContext context, GameState gameState) { + final Game currentGame = gameState.currentGame; + final double boardWidth = MediaQuery.of(context).size.width; + + return GestureDetector( + onTapUp: (details) { + final double xTap = details.localPosition.dx; + final double yTap = details.localPosition.dy; + final int boardSize = currentGame.gameSettings.boardSize; + final int col = xTap ~/ (boardWidth / boardSize); + final int row = yTap ~/ (boardWidth / boardSize); + final int cellValue = currentGame.board.getCellValue(col, row); + + final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); + gameCubit.fillBoardFromFirstCell(cellValue); + }, + child: CustomPaint( + size: Size(boardWidth, boardWidth), + willChange: false, + painter: BoardPainter( + game: currentGame, + colorScheme: Theme.of(context).colorScheme, + ), + isComplex: true, + ), + ); + }, + ); + } +} diff --git a/lib/ui/widgets/game/game_top_indicator.dart b/lib/ui/widgets/game/game_top_indicator.dart new file mode 100644 index 0000000000000000000000000000000000000000..93948cd0e17629e81e6f7a90ac1b3de091b3969d --- /dev/null +++ b/lib/ui/widgets/game/game_top_indicator.dart @@ -0,0 +1,70 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; + +import 'package:colors/cubit/game_cubit.dart'; +import 'package:colors/models/game.dart'; + +class GameTopIndicatorWidget extends StatelessWidget { + const GameTopIndicatorWidget({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder<GameCubit, GameState>( + builder: (BuildContext context, GameState gameState) { + final Game currentGame = gameState.currentGame; + + String progressIndicator = '${currentGame.progress}/${currentGame.progressTotal}'; + + if (currentGame.movesCount > 0) { + progressIndicator += ' (+${currentGame.progressDelta})'; + } + + Color maxMovesCountColor = Colors.grey; + if (currentGame.movesCount > currentGame.maxMovesCount) { + maxMovesCountColor = Colors.red; + } + + return Table( + children: [ + TableRow( + children: [ + Column( + children: [ + Text( + currentGame.movesCount.toString(), + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.w600, + color: Theme.of(context).colorScheme.primary, + ), + ) + ], + ), + Column( + children: [ + Text( + '(max: ${currentGame.maxMovesCount})', + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: maxMovesCountColor, + ), + ), + Text( + progressIndicator, + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: Colors.green, + ), + ), + ], + ), + ], + ), + ], + ); + }, + ); + } +} diff --git a/lib/ui/widgets/game/indicator_top.dart b/lib/ui/widgets/game/indicator_top.dart deleted file mode 100644 index 610037e62041a72e5b0cbc246740eb8b35f0e8f4..0000000000000000000000000000000000000000 --- a/lib/ui/widgets/game/indicator_top.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:colors/provider/data.dart'; - -class TopIndicator extends StatelessWidget { - const TopIndicator({super.key, required this.myProvider}); - - final Data myProvider; - - @override - Widget build(BuildContext context) { - String progressIndicator = '${myProvider.progress}/${myProvider.progressTotal}'; - - if (myProvider.movesCount > 0) { - progressIndicator += ' (+${myProvider.progressDelta})'; - } - - Color maxMovesCountColor = Colors.grey; - if (myProvider.movesCount > myProvider.maxMovesCount) { - maxMovesCountColor = Colors.red; - } - - return Table( - children: [ - TableRow( - children: [ - Column( - children: [ - Text( - myProvider.movesCount.toString(), - style: const TextStyle( - fontSize: 35, - fontWeight: FontWeight.w600, - color: Colors.grey, - ), - ), - ], - ), - Column( - children: [ - Text( - '(max: ${myProvider.maxMovesCount})', - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w600, - color: maxMovesCountColor, - ), - ), - Text( - progressIndicator, - style: const TextStyle( - fontSize: 15, - fontWeight: FontWeight.w600, - color: Colors.green, - ), - ), - ], - ), - ], - ), - ], - ); - } -} diff --git a/lib/ui/widgets/game/message_game_end.dart b/lib/ui/widgets/game/message_game_end.dart index 4a9cd90d8a48818ea1f44541a02c9cfe406e3d8f..2a5cae825069b95e1c4cc9865c1c6acf678516ee 100644 --- a/lib/ui/widgets/game/message_game_end.dart +++ b/lib/ui/widgets/game/message_game_end.dart @@ -1,44 +1,50 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/material.dart'; -import 'package:colors/ui/widgets/home/button_game_restart.dart'; -import 'package:colors/provider/data.dart'; +import 'package:colors/cubit/game_cubit.dart'; +import 'package:colors/models/game.dart'; +import 'package:colors/ui/widgets/game/button_game_restart.dart'; class EndGameMessage extends StatelessWidget { - const EndGameMessage({super.key, required this.myProvider}); - - final Data myProvider; + const EndGameMessage({super.key}); @override Widget build(BuildContext context) { - String decorationImageAssetName = ''; - if (myProvider.gameWon) { - decorationImageAssetName = 'assets/icons/game_win.png'; - } else { - decorationImageAssetName = 'assets/icons/game_fail.png'; - } + return BlocBuilder<GameCubit, GameState>( + builder: (BuildContext context, GameState gameState) { + final Game currentGame = gameState.currentGame; - final Image decorationImage = Image( - image: AssetImage(decorationImageAssetName), - fit: BoxFit.fill, - ); + String decorationImageAssetName = ''; + if (currentGame.gameWon) { + decorationImageAssetName = 'assets/icons/game_win.png'; + } else { + decorationImageAssetName = 'assets/icons/game_fail.png'; + } + + final Image decorationImage = Image( + image: AssetImage(decorationImageAssetName), + fit: BoxFit.fill, + ); - return Container( - margin: const EdgeInsets.all(2), - padding: const EdgeInsets.all(2), - child: Table( - defaultColumnWidth: const IntrinsicColumnWidth(), - children: [ - TableRow( + return Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + child: Table( + defaultColumnWidth: const IntrinsicColumnWidth(), children: [ - Column(children: [decorationImage]), - Column(children: [decorationImage]), - Column(children: [RestartGameButton(myProvider: myProvider)]), - Column(children: [decorationImage]), - Column(children: [decorationImage]), + TableRow( + children: [ + Column(children: [decorationImage]), + Column(children: [decorationImage]), + const Column(children: [RestartGameButton()]), + Column(children: [decorationImage]), + Column(children: [decorationImage]), + ], + ), ], ), - ], - ), + ); + }, ); } } diff --git a/lib/ui/widgets/game/select_color_bar.dart b/lib/ui/widgets/game/select_color_bar.dart index 8211b46a9d9d47ab429c4996735c285c26f4aa30..3b8addb9f96cbe10f766008599da87eb98ad518a 100644 --- a/lib/ui/widgets/game/select_color_bar.dart +++ b/lib/ui/widgets/game/select_color_bar.dart @@ -1,36 +1,42 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/material.dart'; -import 'package:colors/entities/cell.dart'; -import 'package:colors/provider/data.dart'; +import 'package:colors/cubit/game_cubit.dart'; +import 'package:colors/models/cell.dart'; +import 'package:colors/ui/widgets/game/cell_interactive.dart'; class SelectColorBar extends StatelessWidget { - const SelectColorBar({super.key, required this.myProvider}); - - final Data myProvider; + const SelectColorBar({super.key}); @override Widget build(BuildContext context) { - final int maxValue = myProvider.colorsCount; - final ColorScheme colorScheme = Theme.of(context).colorScheme; + return BlocBuilder<GameCubit, GameState>( + builder: (BuildContext context, GameState gameState) { + final double blockWidth = MediaQuery.of(context).size.width; + final ColorScheme colorScheme = Theme.of(context).colorScheme; + final int maxValue = gameState.currentGame.gameSettings.colorsCount; - return Container( - margin: const EdgeInsets.all(2), - padding: const EdgeInsets.all(2), - child: Table( - defaultColumnWidth: const IntrinsicColumnWidth(), - children: [ - TableRow( - children: [ - for (int value = 1; value <= maxValue; value++) - Column( - children: [ - Cell(value).interactiveWidget(myProvider, colorScheme), - ], - ), - ], - ), - ], - ), + return Table( + defaultColumnWidth: const IntrinsicColumnWidth(), + children: [ + TableRow( + children: [ + for (int value = 1; value <= maxValue; value++) + Column( + children: [ + InteractiveCell( + cell: Cell(value), + colorScheme: colorScheme, + currentGame: gameState.currentGame, + itemWidth: blockWidth / maxValue, + ), + ], + ), + ], + ), + ], + ); + }, ); } } diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart new file mode 100644 index 0000000000000000000000000000000000000000..b3850bef24b8409f46d88e34ffc3907cff006bbc --- /dev/null +++ b/lib/ui/widgets/global_app_bar.dart @@ -0,0 +1,82 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; + +import 'package:colors/config/menu.dart'; +import 'package:colors/cubit/game_cubit.dart'; +import 'package:colors/cubit/nav_cubit.dart'; +import 'package:colors/models/game.dart'; +import 'package:colors/ui/widgets/helpers/app_titles.dart'; + +class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget { + const GlobalAppBar({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder<GameCubit, GameState>( + builder: (BuildContext context, GameState gameState) { + return BlocBuilder<NavCubit, int>( + builder: (BuildContext context, int pageIndex) { + final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); + final Game currentGame = gameState.currentGame; + + final List<Widget> menuActions = []; + + if (currentGame.isRunning) { + menuActions.add(TextButton( + onPressed: null, + onLongPress: () => gameCubit.quitGame(), + child: const Image( + image: AssetImage('assets/icons/button_back.png'), + fit: BoxFit.fill, + ), + )); + } else { + if (pageIndex == Menu.indexGame) { + // go to Settings page + menuActions.add(ElevatedButton( + onPressed: () { + context.read<NavCubit>().goToSettingsPage(); + }, + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + ), + child: Menu.menuItemSettings.icon, + )); + + // go to About page + menuActions.add(ElevatedButton( + onPressed: () { + context.read<NavCubit>().goToAboutPage(); + }, + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + ), + child: Menu.menuItemAbout.icon, + )); + } else { + // back to Home page + menuActions.add(ElevatedButton( + onPressed: () { + context.read<NavCubit>().goToGamePage(); + }, + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + ), + child: Menu.menuItemGame.icon, + )); + } + } + + return AppBar( + title: const AppTitle(text: 'app_name'), + actions: menuActions, + ); + }, + ); + }, + ); + } + + @override + Size get preferredSize => const Size.fromHeight(50); +} diff --git a/lib/ui/widgets/helpers/app_titles.dart b/lib/ui/widgets/helpers/app_titles.dart new file mode 100644 index 0000000000000000000000000000000000000000..7cbbb2030419047b3dcf093a2195a498bd8e8ce9 --- /dev/null +++ b/lib/ui/widgets/helpers/app_titles.dart @@ -0,0 +1,17 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +class AppTitle extends StatelessWidget { + const AppTitle({super.key, required this.text}); + + final String text; + + @override + Widget build(BuildContext context) { + return Text( + tr(text), + textAlign: TextAlign.start, + style: Theme.of(context).textTheme.headlineLarge!.apply(fontWeightDelta: 2), + ); + } +} diff --git a/lib/ui/widgets/header_app.dart b/lib/ui/widgets/helpers/header_app.dart similarity index 77% rename from lib/ui/widgets/header_app.dart rename to lib/ui/widgets/helpers/header_app.dart index bf54b77375fbd0260f876f2885d0572b71715383..b5c5be05f6636cf488dcdb5bbc4d6f049b98de11 100644 --- a/lib/ui/widgets/header_app.dart +++ b/lib/ui/widgets/helpers/header_app.dart @@ -8,15 +8,16 @@ class AppHeader extends StatelessWidget { @override Widget build(BuildContext context) { - return Row( + return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( tr(text), textAlign: TextAlign.start, - style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2), + style: Theme.of(context).textTheme.headlineSmall!.apply(fontWeightDelta: 2), ), + const SizedBox(height: 8), ], ); } diff --git a/lib/ui/widgets/helpers/outlined_text_widget.dart b/lib/ui/widgets/helpers/outlined_text_widget.dart new file mode 100644 index 0000000000000000000000000000000000000000..8e33709bd71085ea7a64084a231f692953af203d --- /dev/null +++ b/lib/ui/widgets/helpers/outlined_text_widget.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; + +class OutlinedText extends StatelessWidget { + const OutlinedText({ + super.key, + required this.text, + required this.fontSize, + required this.textColor, + required this.outlineColor, + }); + + final String text; + final double fontSize; + final Color textColor; + final Color outlineColor; + + @override + Widget build(BuildContext context) { + final double delta = fontSize / 35; + + return Text( + text, + style: TextStyle( + inherit: true, + fontSize: fontSize, + fontWeight: FontWeight.w600, + color: textColor, + shadows: [ + Shadow( + offset: Offset(-delta, -delta), + color: outlineColor, + ), + Shadow( + offset: Offset(delta, -delta), + color: outlineColor, + ), + Shadow( + offset: Offset(delta, delta), + color: outlineColor, + ), + Shadow( + offset: Offset(-delta, delta), + color: outlineColor, + ), + ], + ), + ); + } +} diff --git a/lib/ui/widgets/home/button_game_start_new.dart b/lib/ui/widgets/home/button_game_start_new.dart deleted file mode 100644 index 80466e2cee86a677b4a3b6754cb2426daa06bddd..0000000000000000000000000000000000000000 --- a/lib/ui/widgets/home/button_game_start_new.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:colors/provider/data.dart'; -import 'package:colors/ui/layout/parameters.dart'; -import 'package:colors/utils/game_utils.dart'; - -class StartNewGameButton extends StatelessWidget { - const StartNewGameButton({super.key, required this.myProvider}); - - final Data myProvider; - - @override - Widget build(BuildContext context) { - return Container( - margin: const EdgeInsets.all(Parameters.blockMargin), - padding: const EdgeInsets.all(Parameters.blockPadding), - child: Table( - defaultColumnWidth: const IntrinsicColumnWidth(), - children: [ - TableRow( - children: [ - Parameters.buildDecorationImageWidget(), - Column( - children: [ - TextButton( - child: Parameters.buildImageContainerWidget('button_start'), - onPressed: () => GameUtils.startNewGame(myProvider), - ), - ], - ), - Parameters.buildDecorationImageWidget(), - ], - ), - ], - ), - ); - } -} diff --git a/lib/ui/widgets/parameters.dart b/lib/ui/widgets/parameters.dart new file mode 100644 index 0000000000000000000000000000000000000000..55525a9b2402805ed513f789958c568493f28089 --- /dev/null +++ b/lib/ui/widgets/parameters.dart @@ -0,0 +1,121 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; + +import 'package:colors/config/default_game_settings.dart'; +import 'package:colors/config/default_global_settings.dart'; +import 'package:colors/cubit/settings_game_cubit.dart'; +import 'package:colors/cubit/settings_global_cubit.dart'; +import 'package:colors/ui/painters/parameter_painter.dart'; +import 'package:colors/ui/widgets/button_game_start_new.dart'; + +class Parameters extends StatelessWidget { + const Parameters({super.key}); + + final double separatorHeight = 8.0; + + @override + Widget build(BuildContext context) { + final List<Widget> lines = []; + + lines.add(SizedBox(height: separatorHeight)); + + // Game settings + for (String code in DefaultGameSettings.availableParameters) { + lines.add(Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: buildParametersLine( + code: code, + isGlobal: false, + ), + )); + + lines.add(SizedBox(height: separatorHeight)); + } + + lines.add(SizedBox(height: separatorHeight)); + lines.add(const Expanded(child: StartNewGameButton())); + lines.add(SizedBox(height: separatorHeight)); + + // Global settings + for (String code in DefaultGlobalSettings.availableParameters) { + lines.add(Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: buildParametersLine( + code: code, + isGlobal: true, + ), + )); + + lines.add(SizedBox(height: separatorHeight)); + } + + return Column( + children: lines, + ); + } + + List<Widget> buildParametersLine({ + required String code, + required bool isGlobal, + }) { + final List<Widget> parameterButtons = []; + + final List<String> availableValues = isGlobal + ? DefaultGlobalSettings.getAvailableValues(code) + : DefaultGameSettings.getAvailableValues(code); + + if (availableValues.length <= 1) { + return []; + } + + for (String value in availableValues) { + final Widget parameterButton = BlocBuilder<GameSettingsCubit, GameSettingsState>( + builder: (BuildContext context, GameSettingsState gameSettingsState) { + return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>( + builder: (BuildContext context, GlobalSettingsState globalSettingsState) { + final GameSettingsCubit gameSettingsCubit = + BlocProvider.of<GameSettingsCubit>(context); + final GlobalSettingsCubit globalSettingsCubit = + BlocProvider.of<GlobalSettingsCubit>(context); + + final String currentValue = isGlobal + ? globalSettingsCubit.getParameterValue(code) + : gameSettingsCubit.getParameterValue(code); + + final bool isActive = (value == currentValue); + + final double displayWidth = MediaQuery.of(context).size.width; + final double itemWidth = displayWidth / availableValues.length - 30; + + return TextButton( + child: Container( + margin: const EdgeInsets.all(0), + padding: const EdgeInsets.all(0), + child: CustomPaint( + size: Size(itemWidth, itemWidth), + willChange: false, + painter: ParameterPainter( + code: code, + value: value, + isSelected: isActive, + gameSettings: gameSettingsState.settings, + globalSettings: globalSettingsState.settings, + ), + isComplex: true, + ), + ), + onPressed: () => isGlobal + ? globalSettingsCubit.setParameterValue(code, value) + : gameSettingsCubit.setParameterValue(code, value), + ); + }, + ); + }, + ); + + parameterButtons.add(parameterButton); + } + + return parameterButtons; + } +} diff --git a/lib/ui/widgets/settings/theme_card.dart b/lib/ui/widgets/settings/theme_card.dart index 5fd7bd79e680c32a419bc9bea0c80e1fdec49348..834c67dbd317b84767c411f3a6b1822cfa1ed9f1 100644 --- a/lib/ui/widgets/settings/theme_card.dart +++ b/lib/ui/widgets/settings/theme_card.dart @@ -1,5 +1,5 @@ -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; import 'package:colors/cubit/theme_cubit.dart'; diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart deleted file mode 100644 index 7a63ce83b58e8024c8b31bd36d37276c606c27f4..0000000000000000000000000000000000000000 --- a/lib/utils/board_utils.dart +++ /dev/null @@ -1,168 +0,0 @@ -import 'dart:math'; -import 'dart:async'; - -import 'package:colors/entities/cell.dart'; -import 'package:colors/provider/data.dart'; -import 'package:colors/utils/tools.dart'; - -class BoardUtils { - static printGrid(List board) { - const String stringValues = '012345678'; - printlog(''); - printlog('-------'); - for (int rowIndex = 0; rowIndex < board.length; rowIndex++) { - String row = ''; - for (int colIndex = 0; colIndex < board[rowIndex].length; colIndex++) { - row += stringValues[board[rowIndex][colIndex].value]; - } - printlog(row); - } - printlog('-------'); - printlog(''); - } - - static createNewBoard(Data myProvider) { - final int boardSize = myProvider.boardSize; - final int maxValue = myProvider.colorsCount; - - Random rand = Random(); - - Board board = []; - for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) { - List<Cell> row = []; - for (int colIndex = 0; colIndex < boardSize; colIndex++) { - final int value = 1 + rand.nextInt(maxValue); - row.add(Cell(value)); - } - board.add(row); - } - printGrid(board); - - myProvider.resetGame(); - myProvider.updateBoard(board); - myProvider.updateMaxMovesCount(computeMaxMovesCountLimit(myProvider)); - - final int initProgress = BoardUtils.getSiblingFillableCells(myProvider, 0, 0, [ - [0, 0] - ]).length; - myProvider.updateProgress(initProgress); - } - - static int computeMaxMovesCountLimit(myProvider) { - final int boardSize = myProvider.boardSize; - final int colorsCount = myProvider.colorsCount; - - final int baseMaxMovesCount = (30 * (boardSize * colorsCount) / (17 * 6)).round(); - final int deltaFromLevel = - myProvider.getMovesCountLimitDeltaFromLevelParameter(myProvider.parameterLevel); - - return baseMaxMovesCount + deltaFromLevel; - } - - static fillBoardFromFirstCell(Data myProvider, int value) { - List<List<int>> cellsToFill = BoardUtils.getSiblingFillableCells(myProvider, 0, 0, [ - [0, 0] - ]); - final int progressBeforeMove = cellsToFill.length; - - myProvider.incrementMovesCount(); - - // Sort cells from the closest to the furthest, relatively to the top left corner - cellsToFill - .sort((a, b) => (pow(a[0], 2) + pow(a[1], 2)).compareTo(pow(b[0], 2) + pow(b[1], 2))); - - const interval = Duration(milliseconds: 10); - int cellIndex = 0; - myProvider.updateAnimationInProgress(true); - Timer.periodic( - interval, - (Timer timer) { - if (cellIndex < cellsToFill.length) { - myProvider.updateCellValue( - cellsToFill[cellIndex][1], cellsToFill[cellIndex][0], value); - cellIndex++; - } else { - timer.cancel(); - - int progressAfterMove = BoardUtils.getSiblingFillableCells(myProvider, 0, 0, [ - [0, 0] - ]).length; - int progressDelta = progressAfterMove - progressBeforeMove; - myProvider.updateProgressDelta(progressDelta); - myProvider.updateProgress(progressAfterMove); - - myProvider.updateAnimationInProgress(false); - - if (BoardUtils.checkBoardIsSolved(myProvider)) { - myProvider.updateGameWon(true); - } - } - }, - ); - } - - static List<List<int>> getSiblingFillableCells( - Data myProvider, - int row, - int col, - List<List<int>> siblingCells, - ) { - final Board board = myProvider.board; - final int boardSize = myProvider.boardSize; - - final int referenceValue = board[row][col].value; - - for (int deltaRow = -1; deltaRow <= 1; deltaRow++) { - for (int deltaCol = -1; deltaCol <= 1; deltaCol++) { - if (deltaCol == 0 || deltaRow == 0) { - final int candidateRow = row + deltaRow; - final int candidateCol = col + deltaCol; - - if ((candidateRow >= 0 && candidateRow < boardSize) && - (candidateCol >= 0 && candidateCol < boardSize)) { - if (board[candidateRow][candidateCol].value == referenceValue) { - bool alreadyFound = false; - for (int index = 0; index < siblingCells.length; index++) { - if ((siblingCells[index][0] == candidateRow) && - (siblingCells[index][1] == candidateCol)) { - alreadyFound = true; - } - } - if (!alreadyFound) { - siblingCells.add([candidateRow, candidateCol]); - siblingCells = getSiblingFillableCells( - myProvider, - candidateRow, - candidateCol, - siblingCells, - ); - } - } - } - } - } - } - - return siblingCells; - } - - static bool checkBoardIsSolved(Data myProvider) { - final Board board = myProvider.board; - final int boardSize = myProvider.boardSize; - - // check grid is fully completed and does not contain conflict - int previousValue = board[0][0].value; - for (int row = 0; row < boardSize; row++) { - for (int col = 0; col < boardSize; col++) { - if (board[row][col].value == 0 || board[row][col].value != previousValue) { - return false; - } - previousValue = board[row][col].value; - } - } - - printlog('-> ok grid solved!'); - - return true; - } -} diff --git a/lib/utils/color_extensions.dart b/lib/utils/color_extensions.dart new file mode 100644 index 0000000000000000000000000000000000000000..39c9322574b0fbfae3a7b9ba4eb964942b807d37 --- /dev/null +++ b/lib/utils/color_extensions.dart @@ -0,0 +1,35 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; + +extension ColorExtension on Color { + Color darken([int percent = 40]) { + assert(1 <= percent && percent <= 100); + final value = 1 - percent / 100; + return Color.fromARGB( + alpha, + (red * value).round(), + (green * value).round(), + (blue * value).round(), + ); + } + + Color lighten([int percent = 40]) { + assert(1 <= percent && percent <= 100); + final value = percent / 100; + return Color.fromARGB( + alpha, + (red + ((255 - red) * value)).round(), + (green + ((255 - green) * value)).round(), + (blue + ((255 - blue) * value)).round(), + ); + } + + Color avg(Color other) { + final red = (this.red + other.red) ~/ 2; + final green = (this.green + other.green) ~/ 2; + final blue = (this.blue + other.blue) ~/ 2; + final alpha = (this.alpha + other.alpha) ~/ 2; + return Color.fromARGB(alpha, red, green, blue); + } +} diff --git a/lib/utils/color_theme.dart b/lib/utils/color_theme.dart index 476f82bd0fc18b97835e2dcfc101eff1365b53cb..73d2e37c974ac8b52a94839906e4f73e5246670e 100644 --- a/lib/utils/color_theme.dart +++ b/lib/utils/color_theme.dart @@ -1,6 +1,8 @@ +import 'package:colors/config/default_global_settings.dart'; + class ColorTheme { static const Map<String, List<int>> borderColors = { - 'default': [ + DefaultGlobalSettings.skinValueColors: [ 0xffffff, 0xe63a3f, 0x708cfd, diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart deleted file mode 100644 index 6b7e2cf53e809c641481d45bf950fa8d0d682d6f..0000000000000000000000000000000000000000 --- a/lib/utils/game_utils.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:colors/provider/data.dart'; -import 'package:colors/utils/board_utils.dart'; -import 'package:colors/utils/tools.dart'; - -class GameUtils { - static void quitGame(Data myProvider) { - myProvider.updateGameIsRunning(false); - } - - static void startNewGame(Data myProvider) { - printlog('Starting game'); - printlog('- level: ${myProvider.parameterLevel}'); - printlog('- size: ${myProvider.boardSize}'); - printlog('- colors: ${myProvider.colorsCount}'); - - BoardUtils.createNewBoard(myProvider); - - myProvider.updateGameIsRunning(true); - } -} diff --git a/lib/utils/tools.dart b/lib/utils/tools.dart index fd48b2b009b80b22248d6e7f08a63e96c4065bd7..8ed7a5313f39ef5257deba3c3119c0f41ab10cd9 100644 --- a/lib/utils/tools.dart +++ b/lib/utils/tools.dart @@ -1,7 +1,15 @@ import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; void printlog(String message) { if (!kReleaseMode) { debugPrint(message); } } + +Widget buildImageContainerWidget(String imageAssetCode) { + return Image( + image: AssetImage('assets/icons/$imageAssetCode.png'), + fit: BoxFit.fill, + ); +} diff --git a/pubspec.lock b/pubspec.lock index 2885f1ae8482614c38711b57e048f2bd0e10e178..25b5be0248780b099e0f72fc5dab70bd5ce13f92 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.5.0" async: dependency: transitive description: @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: bloc - sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e + sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e" url: "https://pub.dev" source: hosted - version: "8.1.3" + version: "8.1.4" characters: dependency: transitive description: @@ -61,10 +61,10 @@ packages: dependency: "direct main" description: name: easy_localization - sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c + sha256: "432698c31a488dd64c56d4759f20d04844baba5e9e4f2cb1abb9676257918b17" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" easy_logger: dependency: transitive description: @@ -106,31 +106,23 @@ packages: dependency: "direct main" description: name: flutter_bloc - sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1" + sha256: f0ecf6e6eb955193ca60af2d5ca39565a86b8a142452c5b24d96fb477428f4d2 url: "https://pub.dev" source: hosted - version: "8.1.4" + version: "8.1.5" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" flutter_localizations: dependency: transitive description: flutter source: sdk version: "0.0.0" - flutter_swipe: - dependency: "direct main" - description: - name: flutter_swipe - sha256: dc6541bac3a0545ce15a3fa15913f6250532062960bf6b0ad4562d02f14a8545 - url: "https://pub.dev" - source: hosted - version: "1.0.1" flutter_web_plugins: dependency: transitive description: flutter @@ -148,10 +140,10 @@ packages: dependency: transitive description: name: http - sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" http_parser: dependency: transitive description: @@ -164,10 +156,10 @@ packages: dependency: "direct main" description: name: hydrated_bloc - sha256: "00a2099680162e74b5a836b8a7f446e478520a9cae9f6032e028ad8129f4432d" + sha256: af35b357739fe41728df10bec03aad422cdc725a1e702e03af9d2a41ea05160c url: "https://pub.dev" source: hosted - version: "9.1.4" + version: "9.1.5" intl: dependency: transitive description: @@ -208,32 +200,24 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" - overlay_support: - dependency: "direct main" - description: - name: overlay_support - sha256: fc39389bfd94e6985e1e13b2a88a125fc4027608485d2d4e2847afe1b2bb339c - url: "https://pub.dev" - source: hosted - version: "2.1.0" package_info_plus: dependency: "direct main" description: name: package_info_plus - sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79" + sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0 url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "8.0.0" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6" + sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.0" path: - dependency: "direct main" + dependency: transitive description: name: path sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" @@ -244,18 +228,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.4" path_provider_foundation: dependency: transitive description: @@ -305,7 +289,7 @@ packages: source: hosted version: "2.1.8" provider: - dependency: "direct main" + dependency: transitive description: name: provider sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c @@ -313,21 +297,21 @@ packages: source: hosted version: "6.1.2" shared_preferences: - dependency: "direct main" + dependency: transitive description: name: shared_preferences - sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_foundation: dependency: transitive description: @@ -356,10 +340,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" + sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.0" shared_preferences_windows: dependency: transitive description: @@ -433,18 +417,18 @@ packages: dependency: transitive description: name: web - sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05" + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.4.2" + version: "0.5.1" win32: dependency: transitive description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.5.0" xdg_directories: dependency: transitive description: @@ -454,5 +438,5 @@ packages: source: hosted version: "1.0.4" sdks: - dart: ">=3.3.0-279.1.beta <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/pubspec.yaml b/pubspec.yaml index 5e4adf9edb3365b8d4d013bb786614487cf26b61..e6b8af0dde4d69af11d8f3a645b1418b75662251 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: colors description: Fill the board, a colorfull game! publish_to: 'none' -version: 0.0.38+38 +version: 0.0.39+39 environment: sdk: '^3.0.0' @@ -14,15 +14,10 @@ dependencies: easy_localization: ^3.0.1 equatable: ^2.0.5 flutter_bloc: ^8.1.1 - flutter_swipe: ^1.0.1 hive: ^2.2.3 hydrated_bloc: ^9.0.0 - overlay_support: ^2.1.0 - shared_preferences: ^2.2.1 - package_info_plus: ^5.0.1 - path: ^1.9.0 + package_info_plus: ^8.0.0 path_provider: ^2.0.11 - provider: ^6.0.5 unicons: ^2.1.1 dev_dependencies: @@ -32,7 +27,6 @@ flutter: uses-material-design: true assets: - assets/icons/ - - assets/skins/ - assets/translations/ fonts: