diff --git a/android/app/build.gradle b/android/app/build.gradle index a825b724eb743febe03843329a8a9ba26f74fa9f..a9a76844cfad54447a79f35209b776f8f40e963f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -44,7 +44,7 @@ android { defaultConfig { applicationId "org.benoitharrault.twister" - minSdkVersion 16 + minSdkVersion flutter.minSdkVersion targetSdkVersion 30 versionCode appVersionCode.toInteger() versionName appVersionName diff --git a/android/gradle.properties b/android/gradle.properties index 4bb5439f682100f8ef4ba80a557fe4f2f0ab14c2..6bf54a6ed821c19f76d860d4a24e7c85d440b575 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.9 -app.versionCode=9 +app.versionName=0.0.10 +app.versionCode=10 diff --git a/assets/fonts/Nunito-Bold.ttf b/assets/fonts/Nunito-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6519feb781449ebe0015cbc74dfd9e13110fbba9 Binary files /dev/null and b/assets/fonts/Nunito-Bold.ttf differ diff --git a/assets/fonts/Nunito-Light.ttf b/assets/fonts/Nunito-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8a0736c41cd6c2a1225d356bf274de1d0afc3497 Binary files /dev/null and b/assets/fonts/Nunito-Light.ttf differ diff --git a/assets/fonts/Nunito-Medium.ttf b/assets/fonts/Nunito-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..88fccdc0638b6f5d6ac49d9d269dc3d518618ad1 Binary files /dev/null and b/assets/fonts/Nunito-Medium.ttf differ diff --git a/assets/fonts/Nunito-Regular.ttf b/assets/fonts/Nunito-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e7b8375a896ef0cd8e06730a78c84532b377e784 Binary files /dev/null and b/assets/fonts/Nunito-Regular.ttf differ diff --git a/assets/icons/button_back.png b/assets/icons/button_back.png deleted file mode 100644 index cc48ffb1dbb653d9a996f139dfbe02969724bfa5..0000000000000000000000000000000000000000 Binary files a/assets/icons/button_back.png and /dev/null differ diff --git a/assets/icons/button_start.png b/assets/icons/button_start.png deleted file mode 100644 index 6845e2f5c21598ab61f1684d2075aeec0334bf23..0000000000000000000000000000000000000000 Binary files a/assets/icons/button_start.png and /dev/null differ diff --git a/assets/icons/game_fail.png b/assets/icons/game_fail.png deleted file mode 100644 index 93f2801f9d6bb2ce508e1293cd64d6ff2e9970ec..0000000000000000000000000000000000000000 Binary files a/assets/icons/game_fail.png and /dev/null differ diff --git a/assets/icons/game_win.png b/assets/icons/game_win.png deleted file mode 100644 index 876334279c1711b349a62131a33607eecf924eb6..0000000000000000000000000000000000000000 Binary files a/assets/icons/game_win.png and /dev/null differ diff --git a/assets/icons/level_easy.png b/assets/icons/level_easy.png deleted file mode 100644 index 6e53deb037691967b94968c8a546ec3ebb48d158..0000000000000000000000000000000000000000 Binary files a/assets/icons/level_easy.png and /dev/null differ diff --git a/assets/icons/level_normal.png b/assets/icons/level_normal.png deleted file mode 100644 index f5f175d6286aac3f31a8525377dd3a9b342856f7..0000000000000000000000000000000000000000 Binary files a/assets/icons/level_normal.png and /dev/null differ diff --git a/assets/icons/skin_default.png b/assets/icons/skin_default.png deleted file mode 100644 index fbe9cb151a27e54b848f7cd48e397cd308f51dad..0000000000000000000000000000000000000000 Binary files a/assets/icons/skin_default.png and /dev/null differ diff --git a/assets/skins/default_empty.png b/assets/skins/default_empty.png deleted file mode 100644 index b5261e3248aa6c8ea427463b0a70a3b5d2241bb1..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_empty.png and /dev/null differ diff --git a/assets/translations/en.json b/assets/translations/en.json new file mode 100644 index 0000000000000000000000000000000000000000..655cd96fa7ee3282acb235d37e4eee28ca8a8580 --- /dev/null +++ b/assets/translations/en.json @@ -0,0 +1,7 @@ +{ + "app_name": "Twister", + + "bottom_nav_game": "Game", + + "lang_prefix": "en" +} diff --git a/assets/translations/fr.json b/assets/translations/fr.json new file mode 100644 index 0000000000000000000000000000000000000000..c7fb863f774d66cdc73203db8d321d86e8e351f9 --- /dev/null +++ b/assets/translations/fr.json @@ -0,0 +1,7 @@ +{ + "app_name": "Twister", + + "bottom_nav_game": "Jeu", + + "lang_prefix": "fr" +} diff --git a/fastlane/metadata/android/en-US/changelogs/10.txt b/fastlane/metadata/android/en-US/changelogs/10.txt new file mode 100644 index 0000000000000000000000000000000000000000..24fcfae4df957e362bf68e64d18341582dfb1fe2 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/10.txt @@ -0,0 +1 @@ +Update / improve application architecture. diff --git a/fastlane/metadata/android/fr-FR/changelogs/10.txt b/fastlane/metadata/android/fr-FR/changelogs/10.txt new file mode 100644 index 0000000000000000000000000000000000000000..09fd50540289ad7402860b50dcbb57acca27e859 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/10.txt @@ -0,0 +1 @@ +Mise à jour / améliorations de l'architecture de l'application. diff --git a/icons/build_game_icons.sh b/icons/build_game_icons.sh deleted file mode 100755 index 303f1846524a0cb711e8a72403054afa85364676..0000000000000000000000000000000000000000 --- a/icons/build_game_icons.sh +++ /dev/null @@ -1,103 +0,0 @@ -#! /bin/bash - -# Check dependencies -command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; } -command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; } -command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; } - -CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" -BASE_DIR="$(dirname "${CURRENT_DIR}")" - -OPTIPNG_OPTIONS="-preserve -quiet -o7" -ICON_SIZE=192 - -####################################################### - -# Game images -AVAILABLE_GAME_IMAGES=" - button_back - button_start - game_fail - game_win - level_easy - level_normal -" - -# Skins -AVAILABLE_SKINS=" - default -" - -# Images per skin -SKIN_IMAGES=" - empty -" - -####################################################### - -# optimize svg -function optimize_svg() { - SOURCE="$1" - - cp ${SOURCE} ${SOURCE}.tmp - scour \ - --remove-descriptive-elements \ - --enable-id-stripping \ - --enable-viewboxing \ - --enable-comment-stripping \ - --nindent=4 \ - --quiet \ - -i ${SOURCE}.tmp \ - -o ${SOURCE} - rm ${SOURCE}.tmp -} - -# build icons -function build_icon() { - SOURCE="$1" - TARGET="$2" - - echo "Building ${TARGET}" - - if [ ! -f "${SOURCE}" ]; then - echo "Missing file: ${SOURCE}" - fi - - optimize_svg "${SOURCE}" - - inkscape \ - --export-width=${ICON_SIZE} \ - --export-height=${ICON_SIZE} \ - --export-filename=${TARGET} \ - ${SOURCE} - - optipng ${OPTIPNG_OPTIONS} ${TARGET} -} - -function build_icon_for_skin() { - SKIN_CODE="$1" - - # skin main image - build_icon ${CURRENT_DIR}/skin_${SKIN_CODE}.svg ${BASE_DIR}/assets/icons/skin_${SKIN_CODE}.png - - # skin images - for SKIN_IMAGE in ${SKIN_IMAGES} - do - build_icon ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${BASE_DIR}/assets/skins/${SKIN_CODE}_${SKIN_IMAGE}.png - done -} - -mkdir -p ${BASE_DIR}/assets/icons -mkdir -p ${BASE_DIR}/assets/skins - -# build game images -for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES} -do - build_icon ${CURRENT_DIR}/${GAME_IMAGE}.svg ${BASE_DIR}/assets/icons/${GAME_IMAGE}.png -done - -# build skins images -for SKIN in ${AVAILABLE_SKINS} -do - build_icon_for_skin "${SKIN}" -done diff --git a/icons/build_application_icons.sh b/icons/build_repository_icons.sh similarity index 100% rename from icons/build_application_icons.sh rename to icons/build_repository_icons.sh diff --git a/icons/button_back.svg b/icons/button_back.svg deleted file mode 100644 index 2622a578dba53ce582afabfc587c2a85a1fb6eaa..0000000000000000000000000000000000000000 --- a/icons/button_back.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 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#e41578" stroke="#fff" stroke-width=".238"/><path d="m59.387 71.362c1.1248 1.1302 4.0012 1.1302 4.0012 0v-45.921c0-1.1316-2.8832-1.1316-4.0121 0l-37.693 20.918c-1.1289 1.1248-1.1479 2.9551-0.02171 4.084z" fill="#fefeff" stroke="#930e4e" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m57.857 68.048c0.96243 0.96706 3.4236 0.96706 3.4236 0v-39.292c0-0.96825-2.467-0.96825-3.4329 0l-32.252 17.898c-0.96594 0.96243-0.9822 2.5285-0.01858 3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg> diff --git a/icons/button_start.svg b/icons/button_start.svg deleted file mode 100644 index e9d49d2172b9a0305db82779971e3c1e12f34a70..0000000000000000000000000000000000000000 --- a/icons/button_start.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 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m34.852 25.44c-1.1248-1.1302-4.0012-1.1302-4.0012 0v45.921c0 1.1316 2.8832 1.1316 4.0121 0l37.693-20.918c1.1289-1.1248 1.1479-2.9551 0.02171-4.084z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m36.382 28.754c-0.96243-0.96706-3.4236-0.96706-3.4236 0v39.292c0 0.96825 2.467 0.96825 3.4329 0l32.252-17.898c0.96594-0.96243 0.9822-2.5285 0.01858-3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg> diff --git a/icons/game_fail.svg b/icons/game_fail.svg deleted file mode 100644 index 2922fd7adc2bd2e813836c728f095376c73d4143..0000000000000000000000000000000000000000 --- a/icons/game_fail.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 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#d11717" stroke="#fff" stroke-width=".238"/><path d="m71.624 59.304c3.5089 3.5089 3.5089 9.0561 0 12.565-1.6976 1.6976-3.9623 2.6034-6.2261 2.6034s-4.5275-0.90569-6.2261-2.6034l-12.452-12.452-12.452 12.452c-1.6976 1.6976-3.9623 2.6034-6.2261 2.6034s-4.5275-0.90569-6.2261-2.6034c-3.5089-3.5089-3.5089-9.0561 0-12.565l12.452-12.452-12.452-12.452c-3.5089-3.5089-3.5089-9.0561 0-12.565s9.0561-3.5089 12.565 0l12.452 12.452 12.452-12.452c3.5089-3.5089 9.0561-3.5089 12.565 0s3.5089 9.0561 0 12.565l-12.452 12.452z" fill="#e7e7e7" stroke-width=".20213"/></svg> diff --git a/icons/game_win.svg b/icons/game_win.svg deleted file mode 100644 index fe20923864d0c5d39168eced03038b65106a596b..0000000000000000000000000000000000000000 --- a/icons/game_win.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 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.17604 0 0 .17604 7.9341 1.7716)"><path d="m101.92 496.35c-1.8555 0-3.7109-0.69532-5.1484-2.0898-2.9297-2.8438-3-7.5234-0.15234-10.453l9.1875-9.4648c2.8438-2.9297 7.5234-3 10.453-0.15625s3 7.5234 0.15625 10.453l-9.1914 9.4648c-1.4492 1.4961-3.375 2.2461-5.3047 2.2461z" fill="#ff4e61"/><path d="m201.65 133.26c-1.8516 0-3.7109-0.69531-5.1445-2.0898-2.9297-2.8438-3-7.5234-0.15625-10.449l9.1914-9.4688c2.8438-2.9297 7.5195-3 10.449-0.15625s3 7.5234 0.15625 10.453l-9.1914 9.4688c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#ff4e61"/><path d="m413.8 100.39c-1.8555 0-3.7109-0.69141-5.1484-2.0859-2.9297-2.8438-3-7.5234-0.15625-10.453l9.1914-9.4688c2.8438-2.9258 7.5234-2.9961 10.453-0.15234 2.9297 2.8398 3 7.5234 0.15625 10.449l-9.1914 9.4688c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#5c73bc"/><path d="m413.8 463.77c-1.8555 0-3.7109-0.69532-5.1484-2.0859-2.9297-2.8438-3-7.5234-0.15625-10.453l9.1914-9.4688c2.8438-2.9258 7.5234-3 10.453-0.15625s3 7.5234 0.15625 10.453l-9.1914 9.4688c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#fa0"/><path d="m63.07 112.91c-1.8516 0-3.7109-0.69141-5.1445-2.0859-2.9297-2.8438-3-7.5234-0.15625-10.453l9.1914-9.4687c2.8438-2.9258 7.5234-2.9961 10.453-0.15234 2.9258 2.8438 2.9961 7.5234 0.15234 10.449l-9.1914 9.4688c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#fa0"/><path d="m12.309 278.82c-1.8516 0-3.7109-0.69141-5.1445-2.0859-2.9297-2.8438-3-7.5234-0.15625-10.453l9.1875-9.4688c2.8438-2.9297 7.5234-3 10.453-0.15625 2.9297 2.8438 3 7.5234 0.15625 10.453l-9.1914 9.4688c-1.4453 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#2dc471"/><path d="m216.29 278.49-23.996 12.996c-6.2226 3.3711-13.496-2.0742-12.309-9.2148l4.582-27.523c0.47266-2.8359-0.4375-5.7266-2.4375-7.7344l-19.414-19.496c-5.0352-5.0547-2.2578-13.863 4.7031-14.906l26.824-4.0156c2.7656-0.41407 5.1524-2.1992 6.3867-4.7812l12-25.043c3.1133-6.4922 12.102-6.4922 15.215 0l11.996 25.043c1.2383 2.582 3.625 4.3672 6.3867 4.7812l26.828 4.0156c6.957 1.043 9.7344 9.8516 4.6992 14.906l-19.41 19.496c-2 2.0078-2.9141 4.8984-2.4414 7.7344l4.582 27.523c1.1914 7.1406-6.082 12.586-12.305 9.2148l-23.996-12.996c-2.4727-1.3398-5.4258-1.3398-7.8945 0z" fill="#ffd02f"/><path d="m220.24 512c-4.082 0-7.3906-3.3086-7.3906-7.3906v-115.59c0-4.082 3.3086-7.3945 7.3906-7.3945s7.3906 3.3125 7.3906 7.3945v115.59c0 4.082-3.3086 7.3906-7.3906 7.3906z" fill="#5c73bc"/><path d="m220.3 357.42h-0.11328c-4.082 0-7.3945-3.3125-7.3945-7.3945s3.3086-7.3906 7.3945-7.3906h0.11328c4.082 0 7.3906 3.3086 7.3906 7.3906s-3.3086 7.3945-7.3906 7.3945z" fill="#5c73bc"/><path d="m220.3 332h-0.14838c-4.082-0.0156-7.375-3.3398-7.3594-7.4219 0.0195-4.0742 3.3242-7.3594 7.3906-7.3594h0.14848c4.082 0.0156 7.375 3.3398 7.3594 7.4219-0.0156 4.0703-3.3242 7.3594-7.3906 7.3594z" fill="#fa0"/><path d="m87.234 230.89c-1.9297 0-3.8555-0.75-5.3047-2.2422l-79.34-81.738c-2.8438-2.9297-2.7773-7.6094 0.15234-10.449 2.9297-2.8438 7.6094-2.7734 10.453 0.15235l79.344 81.738c2.8438 2.9258 2.7734 7.6094-0.15625 10.449-1.4375 1.3945-3.293 2.0898-5.1484 2.0898z" fill="#ff4e61"/><path d="m113.95 258.5c-1.8633 0-3.7266-0.69922-5.1641-2.1055-2.9219-2.8516-2.9766-7.5312-0.125-10.453l0.082-0.082c2.8516-2.918 7.5312-2.9766 10.453-0.12109 2.9219 2.8516 2.9766 7.5312 0.12109 10.453l-0.0781 0.082c-1.4492 1.4805-3.3672 2.2266-5.2891 2.2266z" fill="#fa0"/><path d="m131.4 276.48c-1.8555 0-3.7109-0.69531-5.1484-2.0898-2.9258-2.8438-2.9961-7.5234-0.15235-10.449l0.0781-0.0859c2.8476-2.9297 7.5273-2.9961 10.453-0.15235 2.9297 2.8438 3 7.5234 0.15625 10.453l-0.082 0.082c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#5c73bc"/><path d="m353.24 227.99c-1.8555 0-3.7109-0.69141-5.1445-2.0859-2.9297-2.8438-3-7.5234-0.15625-10.453l79.34-81.734c2.8438-2.9297 7.5234-3 10.453-0.15625 2.9297 2.8438 3 7.5234 0.15625 10.453l-79.344 81.734c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#fa0"/><path d="m326.52 255.6c-1.9141 0-3.8242-0.73828-5.2695-2.2109l-0.082-0.082c-2.8633-2.9141-2.8203-7.5938 0.0899-10.453 2.9141-2.8633 7.5938-2.8203 10.453 0.0898l0.082 0.082c2.8594 2.9141 2.8203 7.5938-0.0937 10.453-1.4375 1.4141-3.3086 2.1211-5.1797 2.1211z" fill="#ff4e61"/><path d="m309.07 273.58c-1.9297 0-3.8555-0.75-5.3047-2.2422l-0.082-0.082c-2.8398-2.9297-2.7734-7.6094 0.15625-10.453s7.6094-2.7734 10.453 0.15234l0.082 0.082c2.8398 2.9297 2.7734 7.6094-0.15625 10.453-1.4375 1.3945-3.293 2.0898-5.1484 2.0898z" fill="#fa0"/><path d="m300.65 116.69c-1.2422 0-2.5-0.3125-3.6523-0.97266-3.5469-2.0234-4.7812-6.5391-2.7578-10.082l56.863-99.652c2.0234-3.543 6.5352-4.7773 10.082-2.7539 3.5469 2.0234 4.7812 6.5391 2.7578 10.082l-56.863 99.652c-1.3633 2.3867-3.8594 3.7266-6.4297 3.7266z" fill="#62d38f"/><path d="m281.52 150.33c-1.293 0-2.5977-0.33593-3.7891-1.0469l-0.0976-0.0586c-3.5-2.0938-4.6445-6.6328-2.5469-10.137 2.0938-3.5078 6.6328-4.6445 10.137-2.5508l0.0977 0.0586c3.5039 2.0938 4.6445 6.6328 2.5508 10.137-1.3867 2.3164-3.8359 3.5976-6.3516 3.5976z" fill="#fa0"/><path d="m269.02 172.25c-1.3008 0-2.6172-0.34375-3.8086-1.0625l-0.0977-0.0586c-3.4961-2.1094-4.6211-6.6523-2.5156-10.148 2.1094-3.4961 6.6523-4.6172 10.148-2.5117l0.0976 0.0586c3.4961 2.1094 4.6211 6.6523 2.5117 10.148-1.3867 2.3008-3.832 3.5742-6.3359 3.5742z" fill="#2dc471"/><path d="m139.96 116.69c-2.5703 0-5.0664-1.3398-6.4297-3.7305l-56.863-99.648c-2.0234-3.5469-0.78906-8.0586 2.7539-10.082 3.5469-2.0234 8.0625-0.79297 10.086 2.7539l56.863 99.648c2.0234 3.5469 0.78906 8.0625-2.7539 10.086-1.1562 0.66016-2.4141 0.97266-3.6562 0.97266z" fill="#5c73bc"/><path d="m159.09 150.33c-2.5078 0-4.957-1.2773-6.3438-3.582-2.1016-3.5-0.96875-8.043 2.5273-10.145l0.10157-0.0586c3.5-2.1016 8.0391-0.97266 10.141 2.5273 2.1055 3.5 0.97266 8.0391-2.5273 10.145l-0.0977 0.0586c-1.1914 0.71484-2.5039 1.0547-3.8008 1.0547z" fill="#ff4e61"/><path d="m171.6 172.25c-2.5 0-4.9375-1.2656-6.3281-3.5625-2.1172-3.4922-1-8.0352 2.4883-10.152l0.0977-0.0586c3.4961-2.1133 8.0391-1 10.156 2.4922 2.1133 3.4922 1 8.0352-2.4922 10.152l-0.0977 0.0586c-1.1992 0.72656-2.5195 1.0703-3.8242 1.0703z" fill="#fa0"/><path d="m402.14 357.28-15.523 11.602c-4.0234 3.0117-9.6523-0.043-9.5234-5.1641l0.5039-19.75c0.0508-2.0352-0.87109-3.9648-2.4688-5.1641l-15.508-11.621c-4.0234-3.0156-2.9453-9.4726 1.8242-10.93l18.391-5.6094c1.8906-0.57812 3.3906-2.082 4-4.0156l5.9375-18.785c1.5391-4.875 7.8359-5.8125 10.652-1.5898l10.863 16.285c1.1211 1.6758 2.9688 2.6797 4.9414 2.6797l19.18 0.0117c4.9766 4e-3 7.7891 5.8828 4.7578 9.9492l-11.676 15.672c-1.2031 1.6172-1.5586 3.7383-0.94922 5.6719l5.918 18.797c1.5312 4.875-3.0273 9.4453-7.7148 7.7344l-18.078-6.5977c-1.8594-0.67969-3.9258-0.37109-5.5273 0.82422z" fill="#ffd02f"/><path d="m261.51 512c-4.082 0-7.3906-3.3086-7.3906-7.3906 0-57.23 22.832-95.922 41.984-118.3 20.828-24.332 41.613-35.023 42.488-35.469 3.6406-1.8477 8.0898-0.39063 9.9336 3.2539 1.8438 3.6367 0.39453 8.0781-3.2422 9.9297-0.3125 0.16016-19.5 10.164-38.367 32.395-25.227 29.719-38.016 66.121-38.016 108.2 0 4.082-3.3086 7.3906-7.3906 7.3906z" fill="#ff4e61"/><path d="m102.86 397.35 11.766 15.605c3.0547 4.0469 9.2852 2.7305 10.547-2.2266l4.8633-19.113c0.5-1.9648 1.9102-3.5547 3.7695-4.2461l18.039-6.707c4.6797-1.7383 5.3906-8.25 1.207-11.016l-16.141-10.672c-1.6602-1.1016-2.6914-2.9726-2.7578-5.0039l-0.61719-19.75c-0.15625-5.1211-5.9492-7.832-9.7969-4.5859l-14.84 12.516c-1.5312 1.2891-3.5781 1.7227-5.4726 1.1562l-18.422-5.5c-4.7773-1.4258-9.0703 3.4102-7.2617 8.1836l6.9688 18.41c0.71875 1.8945 0.48438 4.0352-0.625 5.7188l-10.77 16.348c-2.793 4.2422 0.34375 9.9375 5.3125 9.6445l19.145-1.1406c1.9727-0.11719 3.875 0.77343 5.0859 2.3789z" fill="#ffd02f"/><path d="m179.02 512c-4.082 0-7.3906-3.3086-7.3906-7.3906 0-30.059-6.6797-57.559-19.852-81.734-1.9531-3.5859-0.62891-8.0742 2.957-10.027 3.5859-1.9531 8.0742-0.62891 10.027 2.9531 14.363 26.375 21.648 56.254 21.648 88.809 0 4.082-3.3086 7.3906-7.3906 7.3906z" fill="#fa0"/><path d="m268.93 55.898c0-11.285-8.8828-20.434-19.836-20.434-10.957 0-19.836 9.1484-19.836 20.434 0 11.285 8.8789 20.438 19.836 20.438 10.953 0 19.836-9.1523 19.836-20.438z" fill="#ffd02f"/><path d="m373.08 446.81c0-11.285-8.8789-20.434-19.832-20.434-10.957 0-19.836 9.1484-19.836 20.434s8.8789 20.434 19.836 20.434c10.953 0 19.832-9.1484 19.832-20.434z" fill="#5c73bc"/><path d="m44.129 450.86c0-9.0508-7.1211-16.387-15.91-16.387-8.7852 0-15.906 7.3359-15.906 16.387 0 9.0547 7.1211 16.391 15.906 16.391 8.7891 0 15.91-7.3359 15.91-16.391z" fill="#62d38f"/><path d="m88.172 288.35c0-9.0508-7.1211-16.387-15.91-16.387-8.7852 0-15.906 7.3359-15.906 16.387s7.1211 16.391 15.906 16.391c8.7891 0 15.91-7.3398 15.91-16.391z" fill="#5c73bc"/><g fill="#ff4e61"><path d="m210.84 16.391c0-9.0547-7.1211-16.391-15.906-16.391-8.7891 0-15.91 7.3359-15.91 16.391 0 9.0508 7.1211 16.387 15.91 16.387 8.7852 0 15.906-7.3359 15.906-16.387z"/><path d="m365.23 152.88c0-9.0508-7.125-16.391-15.91-16.391-8.7852 0-15.91 7.3398-15.91 16.391s7.125 16.387 15.91 16.387c8.7852 0 15.91-7.3359 15.91-16.387z"/><path d="m139.96 32.746c-1.8555 0-3.7109-0.69141-5.1484-2.0898-2.9297-2.8438-3-7.5195-0.15625-10.449l9.1914-9.4688c2.8438-2.9297 7.5234-3 10.449-0.15625 2.9297 2.8438 3 7.5234 0.15625 10.453l-9.1875 9.4688c-1.4492 1.4922-3.3789 2.2422-5.3047 2.2422z"/></g></g></svg> diff --git a/icons/level_easy.svg b/icons/level_easy.svg deleted file mode 100644 index b6505a4bc70481202c814a3e3bbe3c992bc9c33c..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="#6ade98" stroke="#000" stroke-width="2"/></svg> diff --git a/icons/level_normal.svg b/icons/level_normal.svg deleted file mode 100644 index a9533abd6476a37a9910b070c2f4183869143692..0000000000000000000000000000000000000000 --- a/icons/level_normal.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="#6a78de" stroke="#000" stroke-width="2"/></svg> diff --git a/icons/skin_default.svg b/icons/skin_default.svg deleted file mode 100644 index f7344d57776c1eb3ca5699290db81c999f83cc0a..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="#be6ade" stroke="#000" stroke-width="2"/></svg> diff --git a/icons/skins/default/empty.svg b/icons/skins/default/empty.svg deleted file mode 100644 index 3999633fc33857ce7e886751d61b279424c55492..0000000000000000000000000000000000000000 --- a/icons/skins/default/empty.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="#c5c5c5" stroke="#505050" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.6"/></svg> diff --git a/icons/skins/images/empty.svg b/icons/skins/images/empty.svg deleted file mode 100644 index 2efc6b3b84e5600df108c9451786710a8cf0b287..0000000000000000000000000000000000000000 --- a/icons/skins/images/empty.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="#c5c5c5" stroke="#505050" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.6"/><path transform="translate(17.493 20.91)" d="m52.013 48.572c-1.2644 1.2655-14.711-7.2436-16.478-6.963s-11.915 12.538-13.509 11.726c-1.5943-0.81141 2.3431-16.23 1.5302-17.823s-15.606-7.4574-15.327-9.2244 16.159-2.7868 17.424-4.0523c1.2644-1.2655 2.2698-17.147 4.0366-17.427 1.7667-0.28064 7.644 14.507 9.2382 15.319 1.5943 0.81141 17.009-3.1399 17.822-1.5464 0.81286 1.5935-11.435 11.753-11.714 13.52s8.2423 15.206 6.9779 16.472z" fill="#6a78de" stroke="#505050" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.6"/></svg> diff --git a/lib/config/theme.dart b/lib/config/theme.dart new file mode 100644 index 0000000000000000000000000000000000000000..be390348c7868e7c63387df13e13c46de43f8a23 --- /dev/null +++ b/lib/config/theme.dart @@ -0,0 +1,196 @@ +import 'package:flutter/material.dart'; + +/// Colors from Tailwind CSS (v3.0) - June 2022 +/// +/// https://tailwindcss.com/docs/customizing-colors + +const int _primaryColor = 0xFF6366F1; +const MaterialColor primarySwatch = MaterialColor(_primaryColor, <int, Color>{ + 50: Color(0xFFEEF2FF), // indigo-50 + 100: Color(0xFFE0E7FF), // indigo-100 + 200: Color(0xFFC7D2FE), // indigo-200 + 300: Color(0xFFA5B4FC), // indigo-300 + 400: Color(0xFF818CF8), // indigo-400 + 500: Color(_primaryColor), // indigo-500 + 600: Color(0xFF4F46E5), // indigo-600 + 700: Color(0xFF4338CA), // indigo-700 + 800: Color(0xFF3730A3), // indigo-800 + 900: Color(0xFF312E81), // indigo-900 +}); + +const int _textColor = 0xFF64748B; +const MaterialColor textSwatch = MaterialColor(_textColor, <int, Color>{ + 50: Color(0xFFF8FAFC), // slate-50 + 100: Color(0xFFF1F5F9), // slate-100 + 200: Color(0xFFE2E8F0), // slate-200 + 300: Color(0xFFCBD5E1), // slate-300 + 400: Color(0xFF94A3B8), // slate-400 + 500: Color(_textColor), // slate-500 + 600: Color(0xFF475569), // slate-600 + 700: Color(0xFF334155), // slate-700 + 800: Color(0xFF1E293B), // slate-800 + 900: Color(0xFF0F172A), // slate-900 +}); + +const Color errorColor = Color(0xFFDC2626); // red-600 + +final ColorScheme lightColorScheme = ColorScheme.light( + primary: primarySwatch.shade500, + secondary: primarySwatch.shade500, + onSecondary: Colors.white, + error: errorColor, + background: textSwatch.shade200, + onBackground: textSwatch.shade500, + onSurface: textSwatch.shade500, + surface: textSwatch.shade50, + surfaceVariant: Colors.white, + shadow: textSwatch.shade900.withOpacity(.1), +); + +final ColorScheme darkColorScheme = ColorScheme.dark( + primary: primarySwatch.shade500, + secondary: primarySwatch.shade500, + onSecondary: Colors.white, + error: errorColor, + background: const Color(0xFF171724), + onBackground: textSwatch.shade400, + onSurface: textSwatch.shade300, + surface: const Color(0xFF262630), + surfaceVariant: const Color(0xFF282832), + shadow: textSwatch.shade900.withOpacity(.2), +); + +final ThemeData lightTheme = ThemeData( + colorScheme: lightColorScheme, + fontFamily: 'Nunito', + textTheme: TextTheme( + displayLarge: TextStyle( + color: textSwatch.shade700, + fontFamily: 'Nunito', + ), + displayMedium: TextStyle( + color: textSwatch.shade600, + fontFamily: 'Nunito', + ), + displaySmall: TextStyle( + color: textSwatch.shade500, + fontFamily: 'Nunito', + ), + headlineLarge: TextStyle( + color: textSwatch.shade700, + fontFamily: 'Nunito', + ), + headlineMedium: TextStyle( + color: textSwatch.shade600, + fontFamily: 'Nunito', + ), + headlineSmall: TextStyle( + color: textSwatch.shade500, + fontFamily: 'Nunito', + ), + titleLarge: TextStyle( + color: textSwatch.shade700, + fontFamily: 'Nunito', + ), + titleMedium: TextStyle( + color: textSwatch.shade600, + fontFamily: 'Nunito', + ), + titleSmall: TextStyle( + color: textSwatch.shade500, + fontFamily: 'Nunito', + ), + bodyLarge: TextStyle( + color: textSwatch.shade700, + fontFamily: 'Nunito', + ), + bodyMedium: TextStyle( + color: textSwatch.shade600, + fontFamily: 'Nunito', + ), + bodySmall: TextStyle( + color: textSwatch.shade500, + fontFamily: 'Nunito', + ), + labelLarge: TextStyle( + color: textSwatch.shade700, + fontFamily: 'Nunito', + ), + labelMedium: TextStyle( + color: textSwatch.shade600, + fontFamily: 'Nunito', + ), + labelSmall: TextStyle( + color: textSwatch.shade500, + fontFamily: 'Nunito', + ), + ), +); + +final ThemeData darkTheme = lightTheme.copyWith( + colorScheme: darkColorScheme, + textTheme: TextTheme( + displayLarge: TextStyle( + color: textSwatch.shade200, + fontFamily: 'Nunito', + ), + displayMedium: TextStyle( + color: textSwatch.shade300, + fontFamily: 'Nunito', + ), + displaySmall: TextStyle( + color: textSwatch.shade400, + fontFamily: 'Nunito', + ), + headlineLarge: TextStyle( + color: textSwatch.shade200, + fontFamily: 'Nunito', + ), + headlineMedium: TextStyle( + color: textSwatch.shade300, + fontFamily: 'Nunito', + ), + headlineSmall: TextStyle( + color: textSwatch.shade400, + fontFamily: 'Nunito', + ), + titleLarge: TextStyle( + color: textSwatch.shade200, + fontFamily: 'Nunito', + ), + titleMedium: TextStyle( + color: textSwatch.shade300, + fontFamily: 'Nunito', + ), + titleSmall: TextStyle( + color: textSwatch.shade400, + fontFamily: 'Nunito', + ), + bodyLarge: TextStyle( + color: textSwatch.shade200, + fontFamily: 'Nunito', + ), + bodyMedium: TextStyle( + color: textSwatch.shade300, + fontFamily: 'Nunito', + ), + bodySmall: TextStyle( + color: textSwatch.shade400, + fontFamily: 'Nunito', + ), + labelLarge: TextStyle( + color: textSwatch.shade200, + fontFamily: 'Nunito', + ), + labelMedium: TextStyle( + color: textSwatch.shade300, + fontFamily: 'Nunito', + ), + labelSmall: TextStyle( + color: textSwatch.shade400, + fontFamily: 'Nunito', + ), + ), +); + +final ThemeData appTheme = darkTheme; diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/bottom_nav_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..c633c6515b0fcb4e19a521e45b579f178d605970 --- /dev/null +++ b/lib/cubit/bottom_nav_cubit.dart @@ -0,0 +1,31 @@ +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +class BottomNavCubit extends HydratedCubit<int> { + BottomNavCubit() : super(0); + + int pagesCount = 2; + + void updateIndex(int index) { + if (isIndexAllowed(index)) { + emit(index); + } else { + goToHomePage(); + } + } + + bool isIndexAllowed(int index) { + return (index >= 0) && (index < pagesCount); + } + + void goToHomePage() => emit(0); + + @override + int? fromJson(Map<String, dynamic> json) { + return 0; + } + + @override + Map<String, dynamic>? toJson(int state) { + return <String, int>{'pageIndex': state}; + } +} diff --git a/lib/layout/game.dart b/lib/layout/game.dart deleted file mode 100644 index 095c8fc69ce0e3e001f8c92e512326f6553aa3bd..0000000000000000000000000000000000000000 --- a/lib/layout/game.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../provider/data.dart'; -import '../utils/game_utils.dart'; - -class Game { - static Container buildGameWidget(Data myProvider) { - bool gameIsFinished = myProvider.isGameFinished(); - - return Container( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Text('❇️'), - ), - SizedBox(height: 2), - Container( - height: 150, - width: double.maxFinite, - child: gameIsFinished ? Game.buildEndGameMessage(myProvider) : Text('❇️'), - ), - ], - ), - ); - } - - static TextButton buildRestartGameButton(Data myProvider) { - return TextButton( - child: Container( - child: Image( - image: AssetImage('assets/icons/button_back.png'), - fit: BoxFit.fill, - ), - ), - onPressed: () => GameUtils.resetGame(myProvider), - ); - } - - static Container buildEndGameMessage(Data myProvider) { - String decorationImageAssetName = ''; - if (myProvider.gameWon) { - decorationImageAssetName = 'assets/icons/game_win.png'; - } else { - decorationImageAssetName = 'assets/icons/game_fail.png'; - } - - Image decorationImage = Image( - image: AssetImage(decorationImageAssetName), - fit: BoxFit.fill, - ); - - return Container( - margin: EdgeInsets.all(2), - padding: EdgeInsets.all(2), - child: Table( - defaultColumnWidth: IntrinsicColumnWidth(), - children: [ - TableRow( - children: [ - Column(children: [decorationImage]), - Column(children: [buildRestartGameButton(myProvider)]), - Column(children: [decorationImage]), - ], - ), - ], - ), - ); - } -} diff --git a/lib/layout/parameters.dart b/lib/layout/parameters.dart deleted file mode 100644 index f66b024567e9091019bfd4c350fafb21816bf45d..0000000000000000000000000000000000000000 --- a/lib/layout/parameters.dart +++ /dev/null @@ -1,115 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../provider/data.dart'; -import '../utils/game_utils.dart'; - -class Parameters { - static Container buildParametersSelector(Data myProvider) { - return Container( - padding: EdgeInsets.all(2), - margin: EdgeInsets.all(2), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Parameters.buildParameterSelector(myProvider, 'level'), - SizedBox(height: 5), - Parameters.buildParameterSelector(myProvider, 'skin'), - SizedBox(height: 5), - Parameters.buildStartGameButton(myProvider), - ], - ), - ); - } - - static Container buildStartGameButton(Data myProvider) { - Column decorationImage = Column( - children: [ - Image( - image: AssetImage('assets/icons/game_win.png'), - fit: BoxFit.fill, - ), - ], - ); - - return Container( - margin: EdgeInsets.all(2), - padding: EdgeInsets.all(2), - child: Table( - defaultColumnWidth: IntrinsicColumnWidth(), - children: [ - TableRow( - children: [ - decorationImage, - Column( - children: [ - TextButton( - child: Container( - child: Image( - image: AssetImage('assets/icons/button_start.png'), - fit: BoxFit.fill, - ), - ), - onPressed: () => GameUtils.startGame(myProvider), - ), - ], - ), - decorationImage, - ], - ), - ], - ), - ); - } - - static Widget buildParameterSelector(Data myProvider, String parameterCode) { - List availableValues = myProvider.getParameterAvailableValues(parameterCode); - - if (availableValues.length == 1) { - return SizedBox(height: 1); - } - - return Table( - defaultColumnWidth: IntrinsicColumnWidth(), - children: [ - TableRow( - children: [ - for (var index = 0; index < availableValues.length; index++) - Column( - children: [ - _buildParameterButton(myProvider, parameterCode, availableValues[index]) - ], - ), - ], - ), - ], - ); - } - - static TextButton _buildParameterButton( - Data myProvider, String parameterCode, String parameterValue) { - String currentValue = myProvider.getParameterValue(parameterCode).toString(); - - bool isActive = (parameterValue == currentValue); - String imageAsset = 'assets/icons/' + parameterCode + '_' + parameterValue + '.png'; - - return TextButton( - child: Container( - padding: EdgeInsets.all(2), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10), - border: Border.all( - color: isActive ? Colors.blue : Colors.white, - width: 10, - ), - ), - child: Image( - image: AssetImage(imageAsset), - fit: BoxFit.fill, - ), - ), - onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue), - ); - } -} diff --git a/lib/main.dart b/lib/main.dart index f4e8d27fb5fb887c9185aa132a18e36b21263aa9..4d188e4b5d0abf06e30e991143d1fd38d710c110 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,36 +1,60 @@ +import 'dart:io'; + +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:provider/provider.dart'; -import 'package:overlay_support/overlay_support.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:hive/hive.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; +import 'package:path_provider/path_provider.dart'; -import 'provider/data.dart'; -import 'screens/home.dart'; +import 'package:twister/config/theme.dart'; +import 'package:twister/cubit/bottom_nav_cubit.dart'; +import 'package:twister/ui/skeleton.dart'; -void main() { +void main() async { + /// Initialize packages WidgetsFlutterBinding.ensureInitialized(); - SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) - .then((value) => runApp(MyApp())); + await EasyLocalization.ensureInitialized(); + final Directory tmpDir = await getTemporaryDirectory(); + Hive.init(tmpDir.toString()); + HydratedBloc.storage = await HydratedStorage.build( + storageDirectory: tmpDir, + ); + + runApp( + EasyLocalization( + path: 'assets/translations', + supportedLocales: const <Locale>[ + Locale('en'), + Locale('fr'), + ], + fallbackLocale: const Locale('en'), + useFallbackTranslations: true, + child: const MyApp(), + ), + ); } class MyApp extends StatelessWidget { + const MyApp({super.key}); + @override Widget build(BuildContext context) { - return ChangeNotifierProvider( - create: (BuildContext context) => Data(), - child: Consumer<Data>(builder: (context, data, child) { - return OverlaySupport( - child: MaterialApp( - debugShowCheckedModeBanner: false, - theme: ThemeData( - primaryColor: Colors.blue, - visualDensity: VisualDensity.adaptivePlatformDensity, - ), - home: Home(), - routes: { - Home.id: (context) => Home(), - }, - )); - }), + return MultiBlocProvider( + providers: [ + BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()), + ], + child: MaterialApp( + title: 'Twister', + theme: appTheme, + home: const SkeletonScreen(), + + // Localization stuff + localizationsDelegates: context.localizationDelegates, + supportedLocales: context.supportedLocales, + locale: context.locale, + debugShowCheckedModeBanner: false, + ), ); } } diff --git a/lib/provider/data.dart b/lib/provider/data.dart deleted file mode 100644 index 9a56217316ec151cdc4ced711b498e209707992e..0000000000000000000000000000000000000000 --- a/lib/provider/data.dart +++ /dev/null @@ -1,101 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -class Data extends ChangeNotifier { - // Configuration available values - List _availableLevelValues = ['easy', 'normal']; - List _availableSkinValues = ['default']; - - List get availableLevelValues => _availableLevelValues; - List get availableSkinValues => _availableSkinValues; - - // Application default configuration - String _level = ''; - String _levelDefault = 'normal'; - String _skin = ''; - String _skinDefault = 'default'; - - // Game data - bool _gameIsRunning = false; - bool _gameWon = false; - - String get level => _level; - void updateLevel(String level) { - _level = level; - notifyListeners(); - } - - String get skin => _skin; - void updateSkin(String skin) { - _skin = skin; - notifyListeners(); - } - - getParameterValue(String parameterCode) { - switch (parameterCode) { - case 'level': - { - return _level; - } - case 'skin': - { - return _skin; - } - } - } - - List getParameterAvailableValues(String parameterCode) { - switch (parameterCode) { - case 'level': - { - return _availableLevelValues; - } - case 'skin': - { - return _availableSkinValues; - } - } - return []; - } - - setParameterValue(String parameterCode, String parameterValue) async { - switch (parameterCode) { - case 'level': - { - updateLevel(parameterValue); - } - break; - case 'skin': - { - updateSkin(parameterValue); - } - break; - } - final prefs = await SharedPreferences.getInstance(); - prefs.setString(parameterCode, parameterValue); - } - - void initParametersValues() async { - final prefs = await SharedPreferences.getInstance(); - setParameterValue('level', prefs.getString('level') ?? _levelDefault); - setParameterValue('skin', prefs.getString('skin') ?? _skinDefault); - } - - bool get gameIsRunning => _gameIsRunning; - void updateGameIsRunning(bool gameIsRunning) { - _gameIsRunning = gameIsRunning; - notifyListeners(); - } - - bool isGameFinished() { - return false; - } - - bool get gameWon => _gameWon; - - void resetGame() { - _gameIsRunning = false; - _gameWon = false; - notifyListeners(); - } -} diff --git a/lib/screens/home.dart b/lib/screens/home.dart deleted file mode 100644 index f634d8165dede4d18cb8ef5564fb10f357176d5b..0000000000000000000000000000000000000000 --- a/lib/screens/home.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:overlay_support/overlay_support.dart'; - -import '../layout/game.dart'; -import '../layout/parameters.dart'; -import '../provider/data.dart'; -import '../utils/game_utils.dart'; - -class Home extends StatefulWidget { - static const String id = 'home'; - - @override - _HomeState createState() => _HomeState(); -} - -class _HomeState extends State<Home> { - @override - void initState() { - super.initState(); - - Data myProvider = Provider.of<Data>(context, listen: false); - myProvider.initParametersValues(); - } - - @override - Widget build(BuildContext context) { - Data myProvider = Provider.of<Data>(context); - - List<Widget> menuActions = []; - - if (myProvider.gameIsRunning) { - menuActions = [ - TextButton( - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - border: Border.all( - color: Colors.blue, - width: 4, - ), - ), - margin: EdgeInsets.all(8), - child: Image( - image: AssetImage('assets/icons/button_back.png'), - fit: BoxFit.fill, - ), - ), - onPressed: () => toast('Long press to quit game...'), - onLongPress: () => GameUtils.resetGame(myProvider), - ), - ]; - } - - return Scaffold( - appBar: AppBar( - actions: menuActions, - ), - body: SafeArea( - child: Center( - child: myProvider.gameIsRunning - ? Game.buildGameWidget(myProvider) - : Parameters.buildParametersSelector(myProvider), - ), - ), - ); - } -} diff --git a/lib/ui/screens/home.dart b/lib/ui/screens/home.dart new file mode 100644 index 0000000000000000000000000000000000000000..d5ba4dfcd554d16c88f2c1a3664f2c5cd689629b --- /dev/null +++ b/lib/ui/screens/home.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:unicons/unicons.dart'; + +class ScreenHome extends StatelessWidget { + const ScreenHome({super.key}); + + static Icon navBarIcon = const Icon(UniconsLine.home); + static String navBarText = 'bottom_nav_game'; + + @override + Widget build(BuildContext context) { + return Material( + color: Theme.of(context).colorScheme.background, + child: ListView( + padding: const EdgeInsets.symmetric(horizontal: 4), + physics: const BouncingScrollPhysics(), + children: <Widget>[ + const SizedBox(height: 8), + const Text('HOME'), + const SizedBox(height: 36), + ], + ), + ); + } +} diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart new file mode 100644 index 0000000000000000000000000000000000000000..4d56b2330306d3fed579f2963c5a7abcb6081624 --- /dev/null +++ b/lib/ui/skeleton.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:twister/cubit/bottom_nav_cubit.dart'; +import 'package:twister/ui/screens/home.dart'; +import 'package:twister/ui/widgets/app_bar.dart'; +import 'package:twister/ui/widgets/bottom_nav_bar.dart'; + +class SkeletonScreen extends StatefulWidget { + const SkeletonScreen({super.key}); + + @override + State<SkeletonScreen> createState() => _SkeletonScreenState(); +} + +class _SkeletonScreenState extends State<SkeletonScreen> { + @override + Widget build(BuildContext context) { + List<Widget> pageNavigation = <Widget>[ + const ScreenHome(), + const ScreenHome(), + ]; + + return Scaffold( + appBar: StandardAppBar(), + extendBodyBehindAppBar: false, + body: BlocBuilder<BottomNavCubit, int>( + builder: (BuildContext context, int state) { + return AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: pageNavigation.elementAt(state)); + }, + ), + backgroundColor: Theme.of(context).colorScheme.background, + bottomNavigationBar: BottomNavBar(), + ); + } +} diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart new file mode 100644 index 0000000000000000000000000000000000000000..edcc6ac364cc8df8c0bf30ba54cdb3712faf92d6 --- /dev/null +++ b/lib/ui/widgets/app_bar.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +import 'package:twister/ui/widgets/app_titles.dart'; + +class StandardAppBar extends StatelessWidget implements PreferredSizeWidget { + const StandardAppBar({super.key}); + + @override + Widget build(BuildContext context) { + return AppBar( + title: const AppTitle(text: 'app_name'), + actions: [], + ); + } + + @override + Size get preferredSize => const Size.fromHeight(50); +} diff --git a/lib/ui/widgets/app_titles.dart b/lib/ui/widgets/app_titles.dart new file mode 100644 index 0000000000000000000000000000000000000000..93541243613b0f20e76485520a275d1527a6fcc9 --- /dev/null +++ b/lib/ui/widgets/app_titles.dart @@ -0,0 +1,47 @@ +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), + ); + } +} + +class AppTitle1 extends StatelessWidget { + const AppTitle1({super.key, required this.text}); + + final String text; + + @override + Widget build(BuildContext context) { + return Text( + text, + textAlign: TextAlign.start, + style: Theme.of(context).textTheme.titleLarge!.apply(fontWeightDelta: 2), + ); + } +} + +class AppTitle2 extends StatelessWidget { + const AppTitle2({super.key, required this.text}); + + final String text; + + @override + Widget build(BuildContext context) { + return Text( + text, + textAlign: TextAlign.start, + style: Theme.of(context).textTheme.titleMedium!.apply(fontWeightDelta: 2), + ); + } +} diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart new file mode 100644 index 0000000000000000000000000000000000000000..5181bb9d3b09cf5ea9e1f67fdafe1376e503097a --- /dev/null +++ b/lib/ui/widgets/bottom_nav_bar.dart @@ -0,0 +1,47 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:twister/cubit/bottom_nav_cubit.dart'; +import 'package:twister/ui/screens/home.dart'; + +class BottomNavBar extends StatelessWidget { + const BottomNavBar({super.key}); + + @override + Widget build(BuildContext context) { + return Card( + margin: const EdgeInsets.only(top: 1, right: 4, left: 4), + elevation: 4, + shadowColor: Theme.of(context).colorScheme.shadow, + color: Theme.of(context).colorScheme.surfaceVariant, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), + ), + child: BlocBuilder<BottomNavCubit, int>(builder: (BuildContext context, int state) { + return BottomNavigationBar( + currentIndex: state, + onTap: (int index) => context.read<BottomNavCubit>().updateIndex(index), + type: BottomNavigationBarType.fixed, + elevation: 0, + backgroundColor: Colors.transparent, + selectedItemColor: Theme.of(context).colorScheme.primary, + unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color, + items: <BottomNavigationBarItem>[ + BottomNavigationBarItem( + icon: ScreenHome.navBarIcon, + label: tr(ScreenHome.navBarText), + ), + BottomNavigationBarItem( + icon: ScreenHome.navBarIcon, + label: tr(ScreenHome.navBarText), + ), + ], + ); + }), + ); + } +} diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart deleted file mode 100644 index 58e9792f1553e6defa99e30a712efe8e26508346..0000000000000000000000000000000000000000 --- a/lib/utils/game_utils.dart +++ /dev/null @@ -1,18 +0,0 @@ -import '../provider/data.dart'; - -class GameUtils { - - static Future<void> resetGame(Data myProvider) async { - myProvider.updateGameIsRunning(false); - } - - static Future<void> startGame(Data myProvider) async { - print('Starting game'); - print('- level: ' + myProvider.level); - - myProvider.resetGame(); - - myProvider.updateGameIsRunning(true); - } - -} diff --git a/pubspec.lock b/pubspec.lock index f78ae3bfbc5b91625f56452dcbc944e3e78db356..d54095c61378821fb5ed1ba0ae8819e1fd7e7c12 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,14 +1,22 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - async: + args: dependency: transitive description: - name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.4.2" + bloc: + dependency: transitive + description: + name: bloc + sha256: "3820f15f502372d979121de1f6b97bfcf1630ebff8fe1d52fb2b0bfa49be5b49" + url: "https://pub.dev" + source: hosted + version: "8.1.2" characters: dependency: transitive description: @@ -17,14 +25,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" collection: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + easy_localization: + dependency: "direct main" + description: + name: easy_localization + sha256: de63e3b422adfc97f256cbb3f8cf12739b6a4993d390f3cadb3f51837afaefe5 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + easy_logger: + dependency: transitive + description: + name: easy_logger + sha256: c764a6e024846f33405a2342caf91c62e357c24b02c04dbc712ef232bf30ffb7 + url: "https://pub.dev" + source: hosted + version: "0.0.2" + equatable: + dependency: "direct main" + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "2.0.5" ffi: dependency: transitive description: @@ -37,20 +85,57 @@ packages: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "7.0.0" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: e74efb89ee6945bcbce74a5b3a5a3376b088e5f21f55c263fc38cbdc6237faae + url: "https://pub.dev" + source: hosted + version: "8.1.3" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_web_plugins: dependency: transitive description: flutter source: sdk version: "0.0.0" + hive: + dependency: transitive + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + hydrated_bloc: + dependency: "direct main" + description: + name: hydrated_bloc + sha256: c925e49704c052a8f249226ae7603f86bfa776b910816390763b956c71d2cbaf + url: "https://pub.dev" + source: hosted + version: "9.1.3" + intl: + dependency: transitive + description: + name: intl + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.dev" + source: hosted + version: "0.18.1" material_color_utilities: dependency: transitive description: @@ -63,10 +148,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" nested: dependency: transitive description: @@ -75,14 +160,6 @@ 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" path: dependency: transitive description: @@ -91,6 +168,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + url: "https://pub.dev" + source: hosted + version: "2.1.1" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + url: "https://pub.dev" + source: hosted + version: "2.3.1" path_provider_linux: dependency: transitive description: @@ -119,34 +220,34 @@ packages: dependency: transitive description: name: platform - sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 + sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.7" provider: - dependency: "direct main" + dependency: transitive description: name: provider - sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" url: "https://pub.dev" source: hosted - version: "6.0.5" + version: "6.1.1" shared_preferences: - dependency: "direct main" + dependency: transitive description: name: shared_preferences - sha256: b7f41bad7e521d205998772545de63ff4e6c97714775902c199353f8bf1511ac + sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_android: dependency: transitive description: @@ -167,10 +268,10 @@ packages: dependency: transitive description: name: shared_preferences_linux - sha256: c2eb5bf57a2fe9ad6988121609e47d3e07bb3bdca5b6f8444e4cf302428a128a + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" shared_preferences_platform_interface: dependency: transitive description: @@ -183,23 +284,47 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: f763a101313bd3be87edffe0560037500967de9c394a714cd598d945517f694f + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + unicons: + dependency: "direct main" + description: + name: unicons + sha256: dbfcf93ff4d4ea19b324113857e358e4882115ab85db04417a4ba1c72b17a670 + url: "https://pub.dev" + source: hosted + version: "2.1.1" vector_math: dependency: transitive description: @@ -212,18 +337,18 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" win32: dependency: transitive description: name: win32 - sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" + sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 url: "https://pub.dev" source: hosted - version: "5.0.9" + version: "5.1.1" xdg_directories: dependency: transitive description: @@ -233,5 +358,5 @@ packages: source: hosted version: "1.0.3" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" - flutter: ">=3.7.0" + dart: ">=3.2.0 <4.0.0" + flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index f3b674c0229d7540513d10d1dcac54ce526b227b..9b820cb51cd529829f84fa142a1b927c5108f810 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,9 @@ name: twister description: twister game companion + publish_to: 'none' -version: 0.0.9+9 + +version: 0.0.10+10 environment: sdk: '^3.0.0' @@ -9,11 +11,27 @@ environment: dependencies: flutter: sdk: flutter - provider: ^6.0.5 - shared_preferences: ^2.2.1 - overlay_support: ^2.1.0 + + easy_localization: ^3.0.1 + equatable: ^2.0.5 + flutter_bloc: ^8.1.1 + path_provider: ^2.0.11 + hydrated_bloc: ^9.0.0 + unicons: ^2.1.1 flutter: - uses-material-design: true + uses-material-design: false assets: - - assets/icons/ + - assets/translations/ + + fonts: + - family: Nunito + fonts: + - asset: assets/fonts/Nunito-Bold.ttf + weight: 700 + - asset: assets/fonts/Nunito-Medium.ttf + weight: 500 + - asset: assets/fonts/Nunito-Regular.ttf + weight: 400 + - asset: assets/fonts/Nunito-Light.ttf + weight: 300