diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..9751e5e --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,13 @@ +# Each line is a file pattern followed by one or more owners. + +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# the global owners will be requested for +# review when someone opens a pull request. +* @lishaduck @MattsAttack + +*.dart @lishaduck @MattsAttack +/.github/ @lishaduck +/assets/ @MattsAttack +/tests/ @lishaduck @MattsAttack +pubspec.* @lishaduck diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..0aabbc7 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,41 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "github-actions" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" + assignees: + - "lishaduck" + groups: + github: + patterns: + - "actions/*" + + - package-ecosystem: "pub" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" + assignees: + - "lishaduck" + groups: + riverpod: + patterns: + - "*riverpod*" + go_router: + patterns: + - "go_router*" + freezed: + patterns: + - "freezed*" + - "json_*" + build: + patterns: + - "build*" + envied: + patterns: + - "envied*" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..8aaca46 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,335 @@ +--- +name: CI/CD + +on: + push: + branches: + - main + pull_request: + types: + - opened + - synchronize + merge_group: + schedule: + - cron: "0 14 * * 1" # every monday at 9 in the morning CST + workflow_dispatch: + +env: + CI: true + +permissions: + contents: read + +jobs: + setup: + name: Setup + needs: [] + timeout-minutes: 5 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + steps: + - name: ๐Ÿ“š Git checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + submodules: recursive + clean: true + persist-credentials: false + set-safe-directory: true + - name: ๐Ÿฆ Set up Flutter + id: flutter + uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # v2.16.0 + with: + flutter-version-file: true + cache: true + - name: ๐ŸŒ Disable analytics + run: flutter --disable-analytics + - name: ๐Ÿ“ฆ Install dependencies + run: flutter pub get + - name: โš™๏ธ Cache generated files + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: | + .dart_tool/ + lib/gen/*.gen.dart + lib/features/**/*.g.dart + lib/features/**/*.freezed.dart + lib/utils/*.g.dart + lib/utils/*.freezed.dart + lib/app/*.gr.dart + lib/app/*.gm.dart + lib/l10n/app_localizations.dart + lib/l10n/app_localizations_*.dart + key: ${{ runner.os }}-${{ steps.flutter.outputs.CHANNEL }}-dart-${{ hashFiles('**/build.yaml') }} + - name: ๐Ÿ”Œ Generate files + run: | + flutter gen-l10n + dart run build_runner build -d + + build: + name: Build + needs: ["setup"] + timeout-minutes: ${{ (matrix.target == 'web') && 5 || 10 }} + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + target: + - web + - appbundle + # - ios + # - macos + # - windows + include: + - target: web + os: ubuntu-latest + flutter-flags: --release + - target: appbundle + os: ubuntu-latest + flutter-flags: --debug --no-tree-shake-icons --no-shrink + # - target: ios + # os: macos-latest + # flutter-flags: --debug --no-tree-shake-icons + # - target: macos + # os: macos-latest + # flutter-flags: --debug --no-tree-shake-icons + # - target: windows + # os: windows-latest + # flutter-flags: --debug --no-tree-shake-icons + + steps: + - name: ๐Ÿ“š Git checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + submodules: recursive + clean: true + persist-credentials: false + set-safe-directory: true + - name: ๐Ÿฆ Set up Flutter + id: flutter + uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # v2.16.0 + with: + flutter-version-file: true + cache: true + - name: ๐ŸŒ Disable analytics + run: flutter --disable-analytics + - name: ๐Ÿ“ฆ Install dependencies + run: flutter pub get + - name: โš™๏ธ Cache generated files + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: | + .dart_tool/ + lib/gen/*.gen.dart + lib/features/**/*.g.dart + lib/features/**/*.freezed.dart + lib/utils/*.g.dart + lib/utils/*.freezed.dart + lib/app/*.gr.dart + lib/app/*.gm.dart + lib/l10n/app_localizations.dart + lib/l10n/app_localizations_*.dart + key: ${{ runner.os }}-${{ steps.flutter.outputs.CHANNEL }}-dart-${{ hashFiles('**/build.yaml') }} + - name: ๐Ÿ”Œ Generate files + run: | + flutter gen-l10n + dart run build_runner build -d + - name: ๐Ÿ”ง Build + run: | + flutter build ${{ matrix.target }} ${{ matrix.flutter-flags }} + # - name: โš™๏ธ Upload build + # if: matrix.target == 'web' + # uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + # with: + # name: build-directory-${{ matrix.target }}-${{ steps.flutter.outputs.CHANNEL }} + # path: ./build + # if-no-files-found: error + + lint: + name: Linting + needs: ["setup"] + timeout-minutes: 5 + runs-on: ubuntu-latest + + steps: + - name: ๐Ÿ“š Git checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + submodules: recursive + clean: true + persist-credentials: false + set-safe-directory: true + - name: ๐Ÿฆ Set up Flutter + id: flutter + uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # v2.16.0 + with: + flutter-version-file: true + cache: true + - name: ๐ŸŒ Disable analytics + run: flutter --disable-analytics + - name: ๐Ÿ“ฆ Install dependencies + run: flutter pub get + - name: โš™๏ธ Cache generated files + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: | + .dart_tool/ + lib/gen/*.gen.dart + lib/features/**/*.g.dart + lib/features/**/*.freezed.dart + lib/utils/*.g.dart + lib/utils/*.freezed.dart + lib/app/*.gr.dart + lib/app/*.gm.dart + lib/l10n/app_localizations.dart + lib/l10n/app_localizations_*.dart + key: ${{ runner.os }}-${{ steps.flutter.outputs.CHANNEL }}-dart-${{ hashFiles('**/build.yaml') }} + - name: ๐Ÿ”Œ Generate files + run: | + flutter gen-l10n + dart run build_runner build -d + - name: ๐Ÿ•ต๏ธ Analyze project source + run: flutter analyze --fatal-infos + - name: ๐Ÿ•ต๏ธ Run Custom Lint Rules + run: dart run custom_lint --fatal-infos + + test: + name: Testing + needs: ["setup"] + timeout-minutes: 7 + runs-on: ubuntu-latest + + steps: + - name: ๐Ÿ“š Git checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + submodules: recursive + clean: true + persist-credentials: false + set-safe-directory: true + - name: ๐Ÿฆ Set up Flutter + id: flutter + uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # v2.16.0 + with: + flutter-version-file: true + cache: true + - name: ๐ŸŒ Disable analytics + run: flutter --disable-analytics + - name: ๐Ÿ“ฆ Install dependencies + run: flutter pub get + - name: โš™๏ธ Cache generated files + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: | + .dart_tool/ + lib/gen/*.gen.dart + lib/features/**/*.g.dart + lib/features/**/*.freezed.dart + lib/utils/*.g.dart + lib/utils/*.freezed.dart + lib/app/*.gr.dart + lib/app/*.gm.dart + lib/l10n/app_localizations.dart + lib/l10n/app_localizations_*.dart + key: ${{ runner.os }}-${{ steps.flutter.outputs.CHANNEL }}-dart-${{ hashFiles('**/build.yaml') }} + - name: ๐Ÿ”Œ Generate files + run: | + flutter gen-l10n + dart run build_runner build -d + - name: ๐Ÿงช Run tests + run: dart run very_good_cli:very_good test --coverage --test-randomize-ordering-seed random + - name: ๐Ÿ“Š Check code coverage + uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # v3.0.0 + with: + path: coverage/lcov.info + min_coverage: 10 # 100 + + format: + name: Formatting + needs: ["setup"] + timeout-minutes: 3 + runs-on: ubuntu-latest + + steps: + - name: ๐Ÿ“š Git checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + submodules: recursive + clean: true + persist-credentials: false + set-safe-directory: true + - name: ๐Ÿฆ Set up Flutter + id: flutter + uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # v2.16.0 + with: + flutter-version-file: true + cache: true + - name: ๐ŸŒ Disable analytics + run: flutter --disable-analytics + - name: โœจ Verify formatting + run: dart format --output=none --set-exit-if-changed . + + spell-check: + name: Check Spelling + needs: [] + runs-on: ubuntu-latest + + steps: + - name: ๐Ÿ“š Git Checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + submodules: recursive + clean: true + persist-credentials: false + set-safe-directory: true + + - name: ๐Ÿช„ Spell Check + uses: streetsidesoftware/cspell-action@807d7d92b7057593a2de102168506f298405339d # v6.2.0 + with: + files: | + **/*.md + **/*.dart + **/*.yaml + **/*.toml + **/*.json + incremental_files_only: false + + link-check: + name: Check Links + needs: [] + timeout-minutes: 2 + runs-on: ubuntu-latest + + steps: + - name: ๐Ÿช„ Link check + uses: gaurav-nelson/github-action-markdown-link-check@d53a906aa6b22b8979d33bc86170567e619495ec # 1.0.15 + with: + use-quiet-mode: "yes" + use-verbose-mode: "yes" + base-branch: "main" + + markdownlint: + name: Lint Markdown + needs: [] + timeout-minutes: 4 + runs-on: ubuntu-latest + + steps: + - name: ๐Ÿ“š Git Checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + submodules: recursive + clean: true + persist-credentials: false + set-safe-directory: true + - name: ๐Ÿ•ต๏ธ Markdown linting + uses: DavidAnson/markdownlint-cli2-action@510b996878fc0d1a46c8a04ec86b06dbfba09de7 # v16.0.0 + id: markdownlint + with: + fix: true + globs: | + **/*.md + continue-on-error: true diff --git a/.gitignore b/.gitignore index 29a3a50..56dec33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ +# l10n +lib/src/l10n/app_localizations*.dart + +# Testing +test/.test_optimizer.dart + # Miscellaneous *.class *.log @@ -10,26 +16,22 @@ .svn/ migrate_working_dir/ -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - # Flutter/Dart/Pub related **/doc/api/ **/ios/Flutter/.last_build_id .dart_tool/ .flutter-plugins .flutter-plugins-dependencies +.packages .pub-cache/ .pub/ /build/ +coverage/ +lib/gen/ +**/*.g.dart +**/*.gr.dart +**/*.gm.dart +**/*.freezed.dart # Symbolication related app.*.symbols @@ -41,3 +43,129 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + + +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +build/ +# If you're building an application, you may want to check-in your pubspec.lock +# pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +# dotenv environment variables file +.env* +!.env.example + +# Avoid committing generated Javascript files: +*.dart.js +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your + # project includes source files written in JavaScript. +*.js_ +*.js.deps +*.js.map + +.flutter-plugins +.flutter-plugins-dependencies + + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +.idea/modules.xml +# .idea/*.iml +# .idea/modules +*.iml +*.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + diff --git a/.idea/runConfigurations/main_dart.xml b/.idea/runConfigurations/main_dart.xml new file mode 100644 index 0000000..aab7b5c --- /dev/null +++ b/.idea/runConfigurations/main_dart.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc new file mode 100644 index 0000000..e95d9b8 --- /dev/null +++ b/.markdownlint-cli2.jsonc @@ -0,0 +1,6 @@ +{ + "config": { + "line-length": false, // no one cares + "no-emphasis-as-heading": false // to many false positives + } +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..9896930 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,14 @@ +{ + "recommendations": [ + "dart-code.dart-code", + "dart-code.flutter", + "robert-brunhage.flutter-riverpod-snippets", + "lsaudon.l10nization", + "google.arb-editor", + "redhat.vscode-yaml", + "sndst00m.vscode-native-svg-preview", + "streetsidesoftware.code-spell-checker", + "streetsidesoftware.code-spell-checker-spanish", + "joshbolduc.commitlint" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b83f07a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch app", + "request": "launch", + "type": "dart", + "program": "lib/main.dart", + "flutterMode": "debug" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..68ceac0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,119 @@ +{ + // Causes the debug view to automatically appear when a breakpoint is hit. This + // setting is global and not configurable per-language. + "debug.openDebug": "openOnDebugBreak", + + // By default, VS Code will only switch to the Debug Console when you start + // debugging the first time in a session. This setting tells VS Code to always + // switch to the Debug Console when starting a session, so you can see the + // programs output. + "debug.internalConsoleOptions": "openOnSessionStart", + + "[dart]": { + // Automatically format code on save and during typing of certain characters + // (like `;` and `}`). + "editor.formatOnSave": true, + "editor.formatOnType": true, + + // Draw a guide line at 80 characters, where Dart's formatting will wrap code. + // "editor.rulers": [80], + + // Disables built-in highlighting of words that match your selection. Without + // this, all instances of the selected text will be highlighted, interfering + // with Dart's ability to highlight only exact references to the selected variable. + "editor.selectionHighlight": false, + + // By default, VS Code prevents code completion from popping open when in + // "snippet mode" (editing placeholders in inserted code). Setting this option + // to `false` stops that and allows completion to open as normal, as if you + // weren't in a snippet placeholder. + "editor.suggest.snippetsPreventQuickSuggestions": false, + + // By default, VS Code will pre-select the most recently used item from code + // completion. This is usually not the most relevant item. + // + // "first" will always select top item + // "recentlyUsedByPrefix" will filter the recently used items based on the + // text immediately preceding where completion was invoked. + "editor.suggestSelection": "first", + + // Allows pressing to complete snippets such as `for` even when the + // completion list is not visible. + "editor.tabCompletion": "onlySnippets", + + // By default, VS Code will populate code completion with words found in the + // current file when a language service does not provide its own completions. + // This results in code completion suggesting words when editing comments and + // strings. This setting will prevent that. + "editor.wordBasedSuggestions": "off" + }, + "explorer.fileNesting.enabled": true, + "explorer.fileNesting.patterns": { + "pubspec.yaml": ".metadata, analysis_options.yaml, pubspec.lock, build.yaml, dartdoc_options.yaml, l10n.yaml, pubspec_overrides.yaml, dart_test.yaml", + "README.*": "*.md", + "*.dart": "${capture}.*.dart, ${capture}_*.dart", + "cspell.json": ".markdownlint*, project_words.txt", + ".flutter-plugins": ".flutter-plugins-dependencies", + "untranslated.json": "*.log", + ".env": ".env.example", + "app.iml": "*.iml" + }, + "yaml.schemas": { + "https://json.schemastore.org/github-issue-config.json": [ + ".github/ISSUE_TEMPLATE/config.yml" + ], + "https://json.schemastore.org/dart-build": [ + "build.yaml", + "*.build.yaml", + "build.*.yaml" + ] + }, + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true, + "**/.dart_tool": true + }, + "l10nization.haveDescription": true, + "dart.renameFilesWithClasses": "prompt", + "dart.previewFlutterUiGuides": true, + "commitlint.config.extend.rules": { + "body-leading-blank": [1, "always"], + "body-max-line-length": [2, "always", 72], + "body-case": [1, "always", ["sentence-case"]], + "footer-leading-blank": [1, "always"], + "footer-max-line-length": [2, "always", 72], + "header-max-length": [2, "always", 50], + "scope-case": [2, "always", "lower-case"], + "subject-case": [ + 2, + "never", + ["sentence-case", "start-case", "pascal-case", "upper-case"] + ], + "subject-empty": [2, "never"], + "subject-full-stop": [2, "never", "."], + "type-case": [2, "always", "lower-case"], + "type-empty": [2, "never"], + "type-enum": [ + 2, + "always", + [ + "feat", + "fix", + "docs", + "perf", + "refactor", + "build", + "ci", + "revert", + "style", + "test", + "chore" + ] + ] + }, + "github-actions.workflows.pinned.workflows": [".github/workflows/dart.yaml"] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..d1f6cbd --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,143 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "dart", + "command": "dart", + "cwd": ".", + "args": ["run", "build_runner", "${input:runtype}"], + "problemMatcher": ["$dart-build_runner"], + "group": { + "kind": "build", + "isDefault": true + }, + "label": "Dart: run build_runner", + "detail": "Run a build_runner task.", + "runOptions": { + "runOn": "folderOpen" + }, + "icon": { + "color": "terminal.ansiCyan", + "id": "gear" + }, + "dependsOn": ["Flutter: gen-l10n"] + }, + { + "type": "dart", + "command": "dart", + "cwd": ".", + "args": ["doc", "."], + "problemMatcher": [], + "group": "none", + "label": "Dart: doc", + "detail": "View the documentation.", + "icon": { + "color": "terminal.ansiGreen", + "id": "book" + } + }, + { + "type": "flutter", + "command": "flutter", + "args": [ + "build", + "${input:target}", + "--release", + ], + "problemMatcher": [], + "group": "build", + "label": "Flutter: build", + "detail": "Build a flutter app.", + "icon": { + "color": "terminal.ansiBlue", + "id": "gear" + } + }, + { + "type": "flutter", + "command": "flutter", + "args": ["gen-l10n"], + "problemMatcher": [], + "group": "build", + "label": "Flutter: gen-l10n", + "detail": "Generate the localization files.", + "icon": { + "color": "terminal.ansiYellow", + "id": "comment-discussion" + } + }, + { + "type": "flutter", + "command": "flutter", + "args": [ + "build", + "${input:target}", + "--release", + ], + "problemMatcher": [], + "group": "build", + "label": "Flutter: build", + "detail": "Build a flutter app.", + "icon": { + "color": "terminal.ansiBlue", + "id": "gear" + } + }, + { + "type": "dart", + "command": "dart", + "cwd": ".", + "args": [ + "run", + "very_good_cli:very_good", + "test", + "--coverage", + "--test-randomize-ordering-seed", + "random" + ], + "group": { + "kind": "test", + "isDefault": true + }, + "label": "Very Good Test", + "detail": "Run tests with the very_good_cli.", + "icon": { + "color": "terminal.ansiWhite", + "id": "beaker" + } + } + ], + "inputs": [ + { + "id": "target", + "options": [ + { "label": "Repository", "value": "arr" }, + { "label": "Android APK", "value": "apk" }, + { "label": "Android App Bundle", "value": "appbundle" }, + { "label": "Flutter assets directory", "value": "bundle" }, + { "label": "iOS", "value": "ios" }, + { "label": ".xcframework (iOS)", "value": "ios-framework" }, + { "label": "App Store Bundle", "value": "ipa" }, + { "label": "macOS", "value": "macos" }, + { "label": ".xcframework (macOS)", "value": "macos-framework" }, + { "label": "Webapp bundle", "value": "web" }, + { "label": "Windows", "value": "windows" } + ], + "type": "pickString", + "description": "the target to target", + "default": "web" + }, + { + "id": "runtype", + "options": [ + { "label": "run a build", "value": "build" }, + { "label": "watch the filesystem, run many builds", "value": "watch" }, + { "label": "clean up from old builds", "value": "clean" }, + { "label": "verify the build.yaml", "value": "doctor" } + ], + "type": "pickString", + "description": "the type of build_runner run", + "default": "watch" + } + ] +} diff --git a/README.md b/README.md index 2969a4d..cd6aa9c 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,11 @@ -# duly_noted +# Duly Noted -A new Flutter project. +[![Dart][ci_dart_badge]][ci_dart_link] +[![style: very good analysis][very_good_analysis_badge]][very_good_analysis_link] -## Getting Started +Better time management for busy people. -This project is a starting point for a Flutter application that follows the -[simple app state management -tutorial](https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple). - -For help getting started with Flutter development, view the -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. - -## Assets - -The `assets` directory houses images, fonts, and any other files you want to -include with your application. - -The `assets/images` directory contains [resolution-aware -images](https://flutter.dev/docs/development/ui/assets-and-images#resolution-aware). - -## Localization - -This project generates localized messages based on arb files found in -the `lib/src/localization` directory. - -To support additional languages, please visit the tutorial on -[Internationalizing Flutter -apps](https://flutter.dev/docs/development/accessibility-and-localization/internationalization) +[ci_dart_badge]: https://github.com/PHS-TSA/duly_noted/actions/workflows/ci.yaml/badge.svg?branch=main +[ci_dart_link]: https://github.com/PHS-TSA/duly_noted/actions/workflows/ci.yaml +[very_good_analysis_badge]: https://img.shields.io/badge/style-very_good_analysis-B22C89.svg +[very_good_analysis_link]: https://pub.dev/packages/very_good_analysis diff --git a/analysis_options.yaml b/analysis_options.yaml index 0d29021..5c1d820 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -7,7 +7,25 @@ # The following line activates a set of recommended lints for Flutter apps, # packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml +include: package:very_good_analysis/analysis_options.yaml + +analyzer: + exclude: + - "lib/gen/**" + - "lib/src/l10n/app_localizations*.dart" + - "build/**" + - "**/*.g.dart" + - "**/*.gr.dart" + - "**/*.gen.dart" + - "**/*.freezed.dart" + language: + strict-casts: true + strict-inference: true + strict-raw-types: true + errors: + close_sinks: error + plugins: + - custom_lint linter: # The lint rules applied to this project can be customized in the @@ -21,8 +39,11 @@ linter: # `// ignore_for_file: name_of_lint` syntax on the line or in the file # producing the lint. rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - + prefer_relative_imports: true + always_use_package_imports: false + discarded_futures: true + lines_longer_than_80_chars: false + avoid_classes_with_only_static_members: true + one_member_abstracts: false # Additional information about this file can be found at # https://dart.dev/guides/language/analysis-options diff --git a/android/app/build.gradle b/android/app/build.gradle index c5bb5f1..2b0008a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -25,6 +25,7 @@ if (flutterVersionName == null) { android { namespace "org.psdr3.duly_noted" compileSdk flutter.compileSdkVersion + compileSdkVersion 21 ndkVersion flutter.ndkVersion compileOptions { @@ -41,7 +42,6 @@ android { } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "org.psdr3.duly_noted" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 0bb2a7f..29e0908 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:icon="@mipmap/launcher_icon"> + diff --git a/android/app/src/main/res/drawable-hdpi/splash.png b/android/app/src/main/res/drawable-hdpi/splash.png new file mode 100644 index 0000000..54cf9c1 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-mdpi/splash.png b/android/app/src/main/res/drawable-mdpi/splash.png new file mode 100644 index 0000000..5cdb723 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-night-v21/background.png b/android/app/src/main/res/drawable-night-v21/background.png new file mode 100644 index 0000000..74d4117 Binary files /dev/null and b/android/app/src/main/res/drawable-night-v21/background.png differ diff --git a/android/app/src/main/res/drawable-night-v21/launch_background.xml b/android/app/src/main/res/drawable-night-v21/launch_background.xml new file mode 100644 index 0000000..3cc4948 --- /dev/null +++ b/android/app/src/main/res/drawable-night-v21/launch_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/android/app/src/main/res/drawable-night/background.png b/android/app/src/main/res/drawable-night/background.png new file mode 100644 index 0000000..74d4117 Binary files /dev/null and b/android/app/src/main/res/drawable-night/background.png differ diff --git a/android/app/src/main/res/drawable-night/launch_background.xml b/android/app/src/main/res/drawable-night/launch_background.xml new file mode 100644 index 0000000..3cc4948 --- /dev/null +++ b/android/app/src/main/res/drawable-night/launch_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/android/app/src/main/res/drawable-v21/background.png b/android/app/src/main/res/drawable-v21/background.png new file mode 100644 index 0000000..f3967ff Binary files /dev/null and b/android/app/src/main/res/drawable-v21/background.png differ diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml index f74085f..3cc4948 100644 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -1,12 +1,9 @@ - - - - - + + + + + + diff --git a/android/app/src/main/res/drawable-xhdpi/splash.png b/android/app/src/main/res/drawable-xhdpi/splash.png new file mode 100644 index 0000000..757c555 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/splash.png b/android/app/src/main/res/drawable-xxhdpi/splash.png new file mode 100644 index 0000000..68d99ee Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/splash.png b/android/app/src/main/res/drawable-xxxhdpi/splash.png new file mode 100644 index 0000000..cf2fda0 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable/background.png b/android/app/src/main/res/drawable/background.png new file mode 100644 index 0000000..f3967ff Binary files /dev/null and b/android/app/src/main/res/drawable/background.png differ diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index 304732f..3cc4948 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -1,12 +1,9 @@ - - - - - + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png new file mode 100644 index 0000000..0287dc7 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/launcher_icon.png b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png new file mode 100644 index 0000000..c8b39bf Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png new file mode 100644 index 0000000..d07b1a4 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png new file mode 100644 index 0000000..bfe1117 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png new file mode 100644 index 0000000..7c1128f Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/values-night-v31/styles.xml b/android/app/src/main/res/values-night-v31/styles.xml new file mode 100644 index 0000000..c846a66 --- /dev/null +++ b/android/app/src/main/res/values-night-v31/styles.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml index 06952be..3c4a1fe 100644 --- a/android/app/src/main/res/values-night/styles.xml +++ b/android/app/src/main/res/values-night/styles.xml @@ -5,6 +5,10 @@ @drawable/launch_background + false + true + true + shortEdges + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index cb1ef88..847e1be 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -5,6 +5,10 @@ @drawable/launch_background + false + true + true + shortEdges - - - - - - - - - - - - - - - - duly_noted - - - - - - - - + + + + + + + + + + + + +
+
+
+ + - + + function beginPreloading(manifestAssets) { + var assets = [ + "flutter.js", + "main.dart.js", + "canvaskit/canvaskit.wasm", + "canvaskit/canvaskit.js", + ...additionalScripts, + ...manifestAssets, + ]; + let totalAssets = assets.length + 1; + let loaded = 0; + + const batchSize = 20; + + async function reportProgress() { + loaded++; + const value = Math.floor((loaded / totalAssets) * 100) + "%"; + progressIndicator.style.width = value; + + if (assets.length == 0) { + dispatchAppLoad(); + } else { + load(assets.shift()); + } + } + + function load(url) { + const req = new XMLHttpRequest(); + req.onload = reportProgress; + req.open("get", url); + req.send(); + } + + function startBatch() { + const end = Math.min(batchSize, assets.length); + for (let i = 0; i < end; i++) { + load(assets.shift()); + } + } + + var scriptLoaded = false; + async function dispatchAppLoad() { + if (scriptLoaded) { + return; + } + scriptLoaded = true; + + for (let i = 0; i < additionalScripts.length; i++) { + await injectScript(additionalScripts[i]); + } + + await injectScript("flutter.js"); + + // Download main.dart.js + _flutter.loader.loadEntrypoint({ + serviceWorker: { + serviceWorkerVersion: serviceWorkerVersion, + }, + onEntrypointLoaded: function (engineInitializer) { + engineInitializer + .initializeEngine() + .then(async function (appRunner) { + window.addEventListener("flutter-first-frame", function () { + progressBar.remove(); + document.body.classList.remove("loading-mode"); + }); + + appRunner.runApp(); + }); + }, + }); + } + + startBatch(); + } + + window.addEventListener("load", async function (ev) { + const response = await fetch("assets/AssetManifest.json"); + const manifest = await response.json(); + const assets = Object.values(manifest) + .map((list) => list.map((url) => "assets/" + url)) + .reduce((arr, cur) => [...arr, ...cur]); + + beginPreloading(assets); + }); + } + + run(); + + diff --git a/web/manifest.json b/web/manifest.json index 0eba435..daef9b7 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -1,11 +1,11 @@ { - "name": "duly_noted", - "short_name": "duly_noted", + "name": "Duly Noted", + "short_name": "Duly Noted", "start_url": ".", "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", + "background_color": "#0a9f06", + "theme_color": "#0a9f06", + "description": "Better time management for busy people.", "orientation": "portrait-primary", "prefer_related_applications": false, "icons": [ @@ -32,4 +32,4 @@ "purpose": "maskable" } ] -} +} \ No newline at end of file diff --git a/web/splash/img/dark-1x.png b/web/splash/img/dark-1x.png new file mode 100644 index 0000000..5cdb723 Binary files /dev/null and b/web/splash/img/dark-1x.png differ diff --git a/web/splash/img/dark-2x.png b/web/splash/img/dark-2x.png new file mode 100644 index 0000000..757c555 Binary files /dev/null and b/web/splash/img/dark-2x.png differ diff --git a/web/splash/img/dark-3x.png b/web/splash/img/dark-3x.png new file mode 100644 index 0000000..68d99ee Binary files /dev/null and b/web/splash/img/dark-3x.png differ diff --git a/web/splash/img/dark-4x.png b/web/splash/img/dark-4x.png new file mode 100644 index 0000000..cf2fda0 Binary files /dev/null and b/web/splash/img/dark-4x.png differ diff --git a/web/splash/img/light-1x.png b/web/splash/img/light-1x.png new file mode 100644 index 0000000..5cdb723 Binary files /dev/null and b/web/splash/img/light-1x.png differ diff --git a/web/splash/img/light-2x.png b/web/splash/img/light-2x.png new file mode 100644 index 0000000..757c555 Binary files /dev/null and b/web/splash/img/light-2x.png differ diff --git a/web/splash/img/light-3x.png b/web/splash/img/light-3x.png new file mode 100644 index 0000000..68d99ee Binary files /dev/null and b/web/splash/img/light-3x.png differ diff --git a/web/splash/img/light-4x.png b/web/splash/img/light-4x.png new file mode 100644 index 0000000..cf2fda0 Binary files /dev/null and b/web/splash/img/light-4x.png differ diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc index 1a5f927..9496e64 100644 --- a/windows/runner/Runner.rc +++ b/windows/runner/Runner.rc @@ -90,12 +90,12 @@ BEGIN BLOCK "040904e4" BEGIN VALUE "CompanyName", "org.psdr3" "\0" - VALUE "FileDescription", "duly_noted" "\0" + VALUE "FileDescription", "Duly Noted" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "duly_noted" "\0" + VALUE "InternalName", "Duly Noted" "\0" VALUE "LegalCopyright", "Copyright (C) 2024 org.psdr3. All rights reserved." "\0" VALUE "OriginalFilename", "duly_noted.exe" "\0" - VALUE "ProductName", "duly_noted" "\0" + VALUE "ProductName", "Duly Noted" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" END END diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp index 78fbd7a..702ce53 100644 --- a/windows/runner/main.cpp +++ b/windows/runner/main.cpp @@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.Create(L"duly_noted", origin, size)) { + if (!window.Create(L"Duly Noted", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index c04e20c..a029587 100644 Binary files a/windows/runner/resources/app_icon.ico and b/windows/runner/resources/app_icon.ico differ