├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md └── workflows │ ├── build-and-deploy.yaml │ └── pr-checker.yaml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Fastfile ├── LICENSE ├── README.md ├── SECURITY.md ├── analysis_options.yaml ├── android ├── .gitignore ├── Gemfile ├── app │ ├── build.gradle.kts │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── adeeteya │ │ │ │ └── font_gallery │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-night-v21 │ │ │ ├── background.png │ │ │ └── launch_background.xml │ │ │ ├── drawable-night │ │ │ ├── background.png │ │ │ └── launch_background.xml │ │ │ ├── drawable-v21 │ │ │ ├── background.png │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ ├── background.png │ │ │ └── launch_background.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ └── ic_launcher.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_monochrome.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_monochrome.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_monochrome.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_monochrome.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_monochrome.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle.kts ├── fastlane │ ├── Appfile │ ├── Fastfile │ ├── Pluginfile │ └── README.md ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle.kts ├── assets └── theme_switch.json ├── fastlane └── metadata │ └── android │ └── en-US │ ├── full_description.txt │ ├── images │ ├── featureGraphic.png │ ├── icon.png │ └── phoneScreenshots │ │ ├── 1_en-US.png │ │ ├── 2_en-US.png │ │ ├── 3_en-US.png │ │ ├── 4_en-US.png │ │ └── 5_en-US.png │ ├── short_description.txt │ ├── title.txt │ └── video.txt ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Gemfile ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── AppIcon-20@2x.png │ │ │ ├── AppIcon-20@2x~ipad.png │ │ │ ├── AppIcon-20@3x.png │ │ │ ├── AppIcon-20~ipad.png │ │ │ ├── AppIcon-29.png │ │ │ ├── AppIcon-29@2x.png │ │ │ ├── AppIcon-29@2x~ipad.png │ │ │ ├── AppIcon-29@3x.png │ │ │ ├── AppIcon-29~ipad.png │ │ │ ├── AppIcon-40@2x.png │ │ │ ├── AppIcon-40@2x~ipad.png │ │ │ ├── AppIcon-40@3x.png │ │ │ ├── AppIcon-40~ipad.png │ │ │ ├── AppIcon-60@2x~car.png │ │ │ ├── AppIcon-60@3x~car.png │ │ │ ├── AppIcon-83.5@2x~ipad.png │ │ │ ├── AppIcon@2x.png │ │ │ ├── AppIcon@2x~ipad.png │ │ │ ├── AppIcon@3x.png │ │ │ ├── AppIcon~ios-marketing.png │ │ │ ├── AppIcon~ipad.png │ │ │ └── Contents.json │ │ ├── LaunchBackground.imageset │ │ │ ├── Contents.json │ │ │ ├── background.png │ │ │ └── darkbackground.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── RunnerTests │ └── RunnerTests.swift └── fastlane │ ├── Appfile │ ├── Fastfile │ ├── Matchfile │ └── Pluginfile ├── lib ├── constants.dart ├── controllers │ └── settings_controller.dart ├── helpers.dart ├── main.dart ├── models │ ├── font_model.dart │ └── settings_model.dart ├── views │ ├── compare_page.dart │ ├── font_page.dart │ ├── font_search_delegate.dart │ └── home.dart └── widgets │ ├── compare_button.dart │ ├── font_card.dart │ └── theme_mode_toggle.dart ├── linux ├── .gitignore ├── CMakeLists.txt ├── flutter │ ├── CMakeLists.txt │ ├── generated_plugin_registrant.cc │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake └── runner │ ├── CMakeLists.txt │ ├── main.cc │ ├── my_application.cc │ └── my_application.h ├── macos ├── .gitignore ├── Flutter │ ├── Flutter-Debug.xcconfig │ ├── Flutter-Release.xcconfig │ └── GeneratedPluginRegistrant.swift ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ ├── Base.lproj │ │ └── MainMenu.xib │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ ├── DebugProfile.entitlements │ ├── Info.plist │ ├── MainFlutterWindow.swift │ └── Release.entitlements └── RunnerTests │ └── RunnerTests.swift ├── privacy-policy.md ├── pubspec.lock ├── pubspec.yaml ├── pull_request_template.md ├── screenshots ├── app_screenshot_1.jpg ├── app_screenshot_2.jpg ├── app_screenshot_3.jpg ├── app_screenshot_4.jpg ├── app_screenshot_5.jpg └── app_screenshot_6.jpg ├── scripts └── windows-setup.iss ├── snap ├── gui │ ├── font-gallery.desktop │ └── font-gallery.png └── snapcraft.yaml ├── terms-and-conditions.md ├── web ├── favicon.ico ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png ├── index.html └── manifest.json └── windows ├── .gitignore ├── CMakeLists.txt ├── flutter ├── CMakeLists.txt ├── generated_plugin_registrant.cc ├── generated_plugin_registrant.h └── generated_plugins.cmake └── runner ├── CMakeLists.txt ├── Runner.rc ├── flutter_window.cpp ├── flutter_window.h ├── main.cpp ├── resource.h ├── resources └── app_icon.ico ├── runner.exe.manifest ├── utils.cpp ├── utils.h ├── win32_window.cpp └── win32_window.h /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [adeeteya] 2 | patreon: adeeteya 3 | ko_fi: adeeteya 4 | liberapay: adeeteya 5 | custom: ['https://www.buymeacoffee.com/adeeteya','https://www.paypal.me/adityar224'] 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/build-and-deploy.yaml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy Releases 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version_number: 7 | description: 'Release Version Number' 8 | required: true 9 | type: string 10 | android: 11 | description: 'Build Android Release' 12 | type: boolean 13 | default: true 14 | windows: 15 | description: 'Build Windows Release' 16 | type: boolean 17 | default: true 18 | web: 19 | description: 'Build Web Release' 20 | type: boolean 21 | default: true 22 | 23 | env: 24 | FLUTTER_CHANNEL: "stable" 25 | RUBY_VERSION: "3.2.2" 26 | 27 | jobs: 28 | 29 | create_github_release: 30 | name: Create GitHub Release 31 | runs-on: ubuntu-latest 32 | steps: 33 | - name: Checkout 34 | uses: actions/checkout@v4 35 | 36 | - name: Create a GitHub Release 37 | run: | 38 | if gh release view "${{ inputs.version_number }}" > /dev/null 2>&1; then 39 | echo "Release '${{ inputs.version_number }}' already exists. Skipping release creation." 40 | else 41 | echo "Release '${{ inputs.version_number }}' does not exist. Creating release..." 42 | gh release create "${{ inputs.version_number }}" --title "Version ${{ inputs.version_number }}" --generate-notes 43 | fi 44 | env: 45 | GH_TOKEN: ${{ secrets.GH_TOKEN }} 46 | 47 | build_web: 48 | if: ${{ inputs.web }} 49 | name: Build Web 50 | runs-on: ubuntu-latest 51 | steps: 52 | - uses: actions/checkout@v4 53 | 54 | - name: Run Flutter tasks 55 | uses: subosito/flutter-action@v2 56 | with: 57 | flutter-version-file: 'pubspec.yaml' 58 | channel: ${{ env.FLUTTER_CHANNEL }} 59 | 60 | - uses: bluefireteam/flutter-gh-pages@v9 61 | with: 62 | baseHref: /FontGallery/ 63 | 64 | build_windows: 65 | if: ${{ inputs.windows }} 66 | name: Build Windows 67 | runs-on: windows-latest 68 | steps: 69 | - uses: actions/checkout@v4 70 | 71 | - name: Install yq 72 | run: choco install yq 73 | 74 | - name: Setup Flutter 75 | uses: subosito/flutter-action@v2 76 | with: 77 | flutter-version-file: 'pubspec.yaml' 78 | channel: ${{ env.FLUTTER_CHANNEL }} 79 | 80 | - name: Build Windows Release 81 | run: flutter build windows --release 82 | 83 | - name: Install Inno Setup 84 | run: | 85 | Invoke-WebRequest -Uri http://files.jrsoftware.org/is/6/innosetup-6.4.2.exe -OutFile build\installer.exe 86 | git clone https://github.com/DomGries/InnoDependencyInstaller.git build\inno-depend 87 | Start-Process -Wait -FilePath build\installer.exe -ArgumentList '/verysilent', '/allusers', '/dir=build\iscc' 88 | 89 | - name: Run Inno Setup to Build Installer 90 | run: | 91 | build\iscc\iscc.exe scripts\windows-setup.iss /DMyAppVersion=${{ inputs.version_number }} 92 | 93 | - name: Upload Windows Release Artifact to GitHub Release 94 | shell: cmd 95 | run: | 96 | gh release upload ${{ inputs.version_number }} D:\a\FontGallery\FontGallery\FontGallery-Windows.exe 97 | env: 98 | GH_TOKEN: ${{ secrets.GH_TOKEN }} 99 | 100 | build_android: 101 | if: ${{ inputs.android }} 102 | name: Build Android 103 | runs-on: ubuntu-latest 104 | timeout-minutes: 40 105 | steps: 106 | - name: Checkout 107 | uses: actions/checkout@v4 108 | 109 | - name: Set up Ruby 110 | uses: ruby/setup-ruby@v1 111 | with: 112 | ruby-version: ${{ env.RUBY_VERSION }} 113 | bundler-cache: true 114 | working-directory: 'android' 115 | 116 | - name: Run Flutter tasks 117 | uses: subosito/flutter-action@v2.16.0 118 | with: 119 | flutter-version-file: 'pubspec.yaml' 120 | channel: ${{ env.FLUTTER_CHANNEL }} 121 | cache: true 122 | 123 | - name: Create google_service_account.json 124 | run: | 125 | echo "${{ secrets.FIREBASE_SERVICE_ACCOUNT_BASE64 }}" | base64 --decode > google_service_account.json 126 | 127 | - name: Create key.jks 128 | run: | 129 | echo "${{ secrets.ANDROID_KEYSTORE_FILE_BASE64 }}" | base64 --decode > android/key.jks 130 | 131 | - name: Create key.properties 132 | run: | 133 | cat < android/key.properties 134 | storePassword=${{ secrets.ANDROID_KEY_STORE_PASSWORD }} 135 | keyPassword=${{ secrets.ANDROID_KEY_STORE_PASSWORD }} 136 | keyAlias=upload 137 | storeFile=../key.jks 138 | EOF 139 | env: 140 | ANDROID_KEY_STORE_PASSWORD: ${{ secrets.ANDROID_KEY_STORE_PASSWORD }} 141 | 142 | - name: Release To Play Store 143 | uses: maierj/fastlane-action@v3.1.0 144 | with: 145 | lane: 'release_play_store' 146 | subdirectory: android 147 | options: '{ "version_number": "${{ inputs.version_number }}" }' 148 | env: 149 | APP_PACKAGE_NAME: ${{ secrets.APP_PACKAGE_NAME }} 150 | 151 | - name: Build APK 152 | uses: maierj/fastlane-action@v3.1.0 153 | with: 154 | lane: 'build_apk' 155 | subdirectory: android 156 | options: '{ "version_number": "${{ inputs.version_number }}" }' 157 | 158 | - name: Upload APK Artifact to GitHub Release 159 | run: gh release upload ${{ inputs.version_number }} build/app/outputs/flutter-apk/FontGallery-Android.apk 160 | env: 161 | GH_TOKEN: ${{ secrets.GH_TOKEN }} 162 | -------------------------------------------------------------------------------- /.github/workflows/pr-checker.yaml: -------------------------------------------------------------------------------- 1 | name: PR Check 2 | 3 | on: 4 | pull_request: 5 | 6 | env: 7 | FLUTTER_VERSION: 3.29.3 8 | 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | ref: ${{ github.event.pull_request.head.sha }} 16 | - uses: subosito/flutter-action@v2 17 | with: 18 | flutter-version: ${{ env.FLUTTER_VERSION }} 19 | 20 | - name: Configure repo 21 | run: | 22 | flutter pub get 23 | 24 | - name: Lint Dart files 25 | run: | 26 | dart analyze --no-fatal-warnings 27 | 28 | - name: Run Flutter Tests 29 | run: | 30 | flutter test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | /build/ 34 | 35 | # Web related 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | /android/fastlane/play-store-credentials.json 48 | .env 49 | *.jks 50 | key.properties 51 | google_service_account.json 52 | **/fastlane/report.xml 53 | **/fastlane/Preview.html 54 | **/fastlane/screenshots 55 | **/fastlane/test_output 56 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "ea121f8859e4b13e47a8f845e4586164519588bc" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: ea121f8859e4b13e47a8f845e4586164519588bc 17 | base_revision: ea121f8859e4b13e47a8f845e4586164519588bc 18 | - platform: android 19 | create_revision: ea121f8859e4b13e47a8f845e4586164519588bc 20 | base_revision: ea121f8859e4b13e47a8f845e4586164519588bc 21 | - platform: ios 22 | create_revision: ea121f8859e4b13e47a8f845e4586164519588bc 23 | base_revision: ea121f8859e4b13e47a8f845e4586164519588bc 24 | - platform: linux 25 | create_revision: ea121f8859e4b13e47a8f845e4586164519588bc 26 | base_revision: ea121f8859e4b13e47a8f845e4586164519588bc 27 | - platform: macos 28 | create_revision: ea121f8859e4b13e47a8f845e4586164519588bc 29 | base_revision: ea121f8859e4b13e47a8f845e4586164519588bc 30 | - platform: web 31 | create_revision: ea121f8859e4b13e47a8f845e4586164519588bc 32 | base_revision: ea121f8859e4b13e47a8f845e4586164519588bc 33 | - platform: windows 34 | create_revision: ea121f8859e4b13e47a8f845e4586164519588bc 35 | base_revision: ea121f8859e4b13e47a8f845e4586164519588bc 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ✨ removed maxLines property on font pages 2 | 3 | ✨ updated models 4 | 5 | ✨ added tooltips and modified theme 6 | 7 | ✨ updated project to latest flutter version 8 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | adeeteya@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for considering and taking the time to contribute to this project! 4 | 5 | When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. 6 | 7 | Please note we have a code of conduct, please follow it in all your interactions with the project. 8 | 9 | ## Code of Conduct 10 | 11 | Examples of behavior that contributes to creating a positive environment 12 | include: 13 | 14 | * Using welcoming and inclusive language 15 | * Being respectful of differing viewpoints and experiences 16 | * Gracefully accepting constructive criticism 17 | * Focusing on what is best for the community 18 | * Showing empathy towards other community members 19 | 20 | Examples of unacceptable behavior by participants include: 21 | 22 | * The use of sexualized language or imagery and unwelcome sexual attention or 23 | advances 24 | * Trolling, insulting/derogatory comments, and personal or political attacks 25 | * Public or private harassment 26 | * Publishing others' private information, such as a physical or electronic 27 | address, without explicit permission 28 | * Other conduct which could reasonably be considered inappropriate in a 29 | professional setting 30 | 31 | 32 | ## Download & install 33 | 34 | First, clone the repository with the 'clone' command, or just download the zip. 35 | 36 | ``` 37 | $ git clone git@github.com:adeeteya/FontGallery.git 38 | ``` 39 | 40 | Then, download either Android Studio or Visual Studio Code, with their respective [Flutter editor plugins](https://flutter.io/get-started/editor/). For more information about Flutter installation procedure, check the [official install guide](https://flutter.io/get-started/install/). 41 | 42 | Install dependencies from pubspec.yaml by running `flutter packages get` from the project root (see [using packages documentation](https://flutter.io/using-packages/#adding-a-package-dependency-to-an-app) for details and how to do this in the editor). 43 | 44 | There you go, you can now open & edit the project. Enjoy! 45 | 46 | ## How to Report Bugs and Request Feature 47 | 48 | Please open [a new issue in the GitHub repository](https://github.com/adeeteya/FontGallery/issues) with steps to reproduce the problem you're experiencing. 49 | 50 | Be sure to include as much information including screenshots, text output, and both your expected and actual results. -------------------------------------------------------------------------------- /Fastfile: -------------------------------------------------------------------------------- 1 | opt_out_usage 2 | 3 | # Have an easy way to get the root of the project 4 | def root_path 5 | Dir.pwd.sub(/.*\Kfastlane/, '').sub(/.*\Kandroid/, '').sub(/.*\Kios/, '').sub(/.*\K\/\//, '') 6 | end 7 | 8 | # Have an easy way to run flutter tasks on the root of the project 9 | lane :sh_on_root do |options| 10 | command = options[:command] 11 | sh("cd #{root_path} && #{command}") 12 | end 13 | 14 | # Tasks to be reused on each platform flow 15 | lane :fetch_dependencies do 16 | sh_on_root(command: "flutter pub get --suppress-analytics") 17 | end 18 | 19 | # Tasks to be reused on each platform flow 20 | lane :build_autogenerated_code do 21 | sh_on_root(command: "flutter pub run build_runner build --delete-conflicting-outputs") 22 | end 23 | 24 | # Tasks to be reused on each platform flow 25 | lane :lint do 26 | sh_on_root(command: "flutter format --suppress-analytics --set-exit-if-changed -n lib/main.dart lib/src/ test/") 27 | end 28 | 29 | lane :build_flutter_app do |options| 30 | pubspec_version_number = get_version_from_pubspec() 31 | 32 | type = options[:type] 33 | build_number = options[:build_number] || get_build_number(options[:store]) 34 | version_number = options[:version_number] || pubspec_version_number 35 | no_codesign = options[:no_codesign] || false 36 | config_only = options[:config_only] || false 37 | obfuscate = options[:obfuscate] || true 38 | commit = last_git_commit 39 | 40 | command = "flutter build #{type} --release --no-pub --suppress-analytics" 41 | command += " --build-number=#{build_number}" if build_number.to_s != "" 42 | command += " --build-name=#{version_number}" if version_number.to_s != "" 43 | command += " --no-codesign" if no_codesign 44 | command += " --config-only" if config_only 45 | command += " --obfuscate" if obfuscate 46 | command += " --split-debug-info=./build/app/outputs/symbols" if obfuscate 47 | 48 | UI.message("Building #{type} - version: #{version_number} - build: #{build_number} - commit: #{commit[:abbreviated_commit_hash]}") 49 | 50 | fetch_dependencies 51 | 52 | # Check if build_runner exists in pubspec.yaml 53 | # If it does, run the build_runner command 54 | if File.exist?("#{root_path}/pubspec.yaml") 55 | pubspec_content = File.read("#{root_path}/pubspec.yaml") 56 | if pubspec_content.include?("build_runner:") 57 | build_autogenerated_code 58 | end 59 | end 60 | 61 | sh_on_root(command: command) 62 | end 63 | 64 | # Tasks to be reused on each platform flow 65 | lane :test do |options| 66 | sh_on_root(command: "flutter test --no-pub --coverage --suppress-analytics") 67 | end 68 | 69 | 70 | # Private lane to verify all environment variables are set 71 | private_lane :verify_env do |options| 72 | # array of ENVS to check 73 | envs = options.fetch(:envs, []) 74 | 75 | envs.each do |env| 76 | if ENV[env].nil? || ENV[env].empty? 77 | UI.user_error!("ENV \"#{env}\" is not set. Please set it in your environment variables (e.g. ios/fastlane/.env)") 78 | end 79 | end 80 | end 81 | 82 | # A helper method to get the path to the firebase service account json file 83 | def google_service_account_json_path 84 | root_path + '/' + (ENV["GOOGLE_SERVICE_ACCOUNT_JSON_PATH"] || 'google_service_account.json') 85 | end 86 | 87 | # Build number is a unique identifier for each build that is uploaded to the app store. 88 | # This method will get the latest build number from the app store and increment it by 1. 89 | # Ensure authenticate_apple_store is called before this method 90 | def get_build_number(store) 91 | return get_new_build_number( 92 | bundle_identifier: store == "appstore" ? ENV["APP_BUNDLE_ID"] : nil, 93 | package_name: store == "playstore" ? ENV["APP_PACKAGE_NAME"] : nil, 94 | google_play_json_key_path: google_service_account_json_path 95 | ).to_s 96 | end 97 | 98 | 99 | def get_version_from_pubspec 100 | require 'yaml' 101 | 102 | # Define the correct path to pubspec.yaml relative to the Fastlane directory 103 | pubspec_path = File.expand_path("#{root_path}/pubspec.yaml") 104 | 105 | # Check if the file exists to avoid errors 106 | unless File.exist?(pubspec_path) 107 | UI.error("pubspec.yaml file not found at path: #{pubspec_path}") 108 | return nil 109 | end 110 | 111 | # Parse the pubspec.yaml file 112 | pubspec_content = File.read(pubspec_path) 113 | 114 | # Use regex to find the version number line and extract both version number and build number 115 | version_line = pubspec_content.match(/version:\s*(\d+\.\d+\.\d+)\+(\d+)/) 116 | if version_line 117 | version_number = version_line[1] 118 | else 119 | UI.error("Version number not found in pubspec.yaml") 120 | return nil 121 | end 122 | 123 | return version_number 124 | end 125 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Aditya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 📜🖼️ Font Gallery 2 | 3 | Font Gallery app showcases how different Font Families with their different variations (Style, Weight and Size) look. You could switch between light and dark modes and also compare different font families. 4 | 5 | There's a handy search feature to easily search for your favorite fonts and the text to compare the font's could also be changed to a custom user set text. 6 | 7 | The Fonts are sourced from Google Fonts and even the Font Author information is displayed. 8 | 9 | Please star⭐ the repo if you like what you see😊. 10 | 11 | ## 💻 Installation and Usage 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 33 | 34 | 35 | 36 | 37 | 42 | 43 | 44 | 45 | 46 | 51 | 52 | 53 | 54 | 55 | 60 | 61 | 62 |
PlatformInstallation Links
Android 21 | 22 | Get it on Google Play 23 | 24 |
25 | 26 | Get it on F-Droid 27 | 28 |
29 | 30 | APK download 31 | 32 |
Linux 38 | 39 | Get it from the Snap Store 40 | 41 |
Windows 47 | 48 | Windows App 49 | 50 |
Web App 56 | 57 | Web App 58 | 59 |
63 | 64 | ## ✨ Features 65 | 66 | - [x] Display Different Fonts 67 | - [x] Search for Fonts using their name 68 | - [x] Dark/Light Theme Modes 69 | - [x] Input Text to preview how it would look with the selected Font 70 | - [x] Change Font Size 71 | - [x] Display all the Font Weights 72 | - [x] Option to Display a different Font style 73 | - [x] Display Font Author Information 74 | - [x] Compare Fonts 75 | - [ ] Change Font Colors 76 | - [ ] Generate an Image for the font 77 | - [ ] Multi-Language Support 78 | 79 | ## 📸 Screenshots 80 | Light Mode Image Dark Mode Image Search Screen Image Input Text Image Input Text Image Input Text Image 81 | 82 | ## 🔌 Plugins 83 | 84 | | Name | Usage | 85 | |-----------------------------------------------------------------------|-------------------------------------| 86 | | [**shared_preferences**](https://pub.dev/packages/shared_preferences) | To store theme mode preference | 87 | | [**flutter_lints**](https://pub.dev/packages/flutter_lints) | For linting | 88 | | [**lottie**](https://pub.dev/packages/lottie) | For Theme Switch Animation | 89 | | [**google_fonts**](https://pub.dev/packages/google_fonts) | For downloading the different fonts | 90 | | [**flutter_riverpod**](https://pub.dev/packages/flutter_riverpod) | For managing the state | 91 | 92 | ## 🤓 Author 93 | 94 | **[Aditya R](https://github.com/adeeteya)** 95 | 96 | ## 🔖 LICENSE 97 | Copyright (c) 2023 **[Aditya R](https://github.com/adeeteya)** 98 | [MIT LICENSE](https://github.com/adeeteya/FontGallery/blob/master/LICENSE) 99 | 100 | ## 🙏 Attributions 101 | Font size icons created by Freepik - Flaticon 102 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | |---------|--------------------| 7 | | 1.3.0 | :white_check_mark: | 8 | | 1.2.1 | :white_check_mark: | 9 | | 1.2.0 | :white_check_mark: | 10 | | 1.0.0 | :white_check_mark: | 11 | 12 | ## Reporting a Vulnerability 13 | 14 | Either mail to me at adeeteya@gmail.com or open a [Issue](https://www.github.com/FontGallery/issues) -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | always_declare_return_types: true 28 | always_use_package_imports: true 29 | avoid_escaping_inner_quotes: true 30 | avoid_relative_lib_imports: true 31 | avoid_redundant_argument_values: true 32 | avoid_single_cascade_in_expression_statements: true 33 | avoid_unused_constructor_parameters: true 34 | avoid_void_async: true 35 | constant_identifier_names: true 36 | directives_ordering: true 37 | discarded_futures: true 38 | eol_at_end_of_file: true 39 | literal_only_boolean_expressions: true 40 | matching_super_parameters: true 41 | no_literal_bool_comparisons: true 42 | only_throw_errors: true 43 | parameter_assignments: true 44 | prefer_const_constructors: true 45 | prefer_const_declarations: true 46 | prefer_const_literals_to_create_immutables: true 47 | prefer_final_in_for_each: true 48 | prefer_final_locals: true 49 | prefer_null_aware_method_calls: true 50 | require_trailing_commas: true 51 | sort_pub_dependencies: true 52 | sort_unnamed_constructors_first: true 53 | type_annotate_public_apis: true 54 | unnecessary_await_in_return: true 55 | unnecessary_lambdas: true 56 | unnecessary_parenthesis: true 57 | unnecessary_statements: true 58 | unreachable_from_main: true 59 | unawaited_futures: true 60 | use_colored_box: true 61 | use_decorated_box: true 62 | use_enums: true 63 | use_named_constants: true 64 | use_setters_to_change_properties: true 65 | 66 | # Additional information about this file can be found at 67 | # https://dart.dev/guides/language/analysis-options 68 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | .cxx/ 9 | 10 | # Remember to never publicly share your keystore. 11 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 12 | key.properties 13 | **/*.keystore 14 | **/*.jks 15 | -------------------------------------------------------------------------------- /android/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | # takes version from flutter (pubspec.yaml) 5 | gem "fastlane-plugin-flutter_version", git: "https://github.com/tianhaoz95/fastlane-plugin-flutter-version" 6 | 7 | plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') 8 | eval_gemfile(plugins_path) if File.exist?(plugins_path) 9 | -------------------------------------------------------------------------------- /android/app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.util.Properties 2 | import java.io.FileInputStream 3 | import java.io.FileNotFoundException 4 | 5 | plugins { 6 | id("com.android.application") 7 | id("kotlin-android") 8 | id("dev.flutter.flutter-gradle-plugin") 9 | } 10 | 11 | val keystoreProperties = Properties() 12 | try { 13 | val keystorePropertiesFile = rootProject.file("key.properties") 14 | keystoreProperties.load(FileInputStream(keystorePropertiesFile)) 15 | } catch (e: FileNotFoundException) { 16 | println("Warning: key.properties file not found. Ensure the file is present before building the release version.") 17 | } 18 | 19 | android { 20 | namespace = "com.adeeteya.font_gallery" 21 | compileSdk = flutter.compileSdkVersion 22 | ndkVersion = "27.0.12077973" 23 | 24 | compileOptions { 25 | sourceCompatibility = JavaVersion.VERSION_11 26 | targetCompatibility = JavaVersion.VERSION_11 27 | } 28 | 29 | kotlinOptions { 30 | jvmTarget = JavaVersion.VERSION_11.toString() 31 | } 32 | 33 | defaultConfig { 34 | applicationId = "com.adeeteya.font_gallery" 35 | minSdk = flutter.minSdkVersion 36 | targetSdk = flutter.targetSdkVersion 37 | versionCode = flutter.versionCode 38 | versionName = flutter.versionName 39 | ndk.abiFilters.addAll(arrayOf("armeabi-v7a", "arm64-v8a", "x86_64")) 40 | } 41 | 42 | signingConfigs { 43 | create("release") { 44 | keyAlias = keystoreProperties["keyAlias"] as? String 45 | keyPassword = keystoreProperties["keyPassword"] as? String 46 | storePassword = keystoreProperties["storePassword"] as? String 47 | val storeFilePath = keystoreProperties["storeFile"] as? String 48 | if (storeFilePath != null) { 49 | storeFile = file(keystoreProperties["storeFile"] as String) 50 | } 51 | } 52 | } 53 | 54 | buildTypes { 55 | getByName("debug") { 56 | signingConfig = signingConfigs.getByName("debug") 57 | } 58 | getByName("release") { 59 | signingConfig = signingConfigs.getByName("release") 60 | } 61 | } 62 | } 63 | 64 | flutter { 65 | source = "../.." 66 | } 67 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 17 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/adeeteya/font_gallery/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.adeeteya.font_gallery 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-v21/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/drawable-night-v21/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/drawable-night/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/drawable-v21/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/drawable/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/build.gradle.kts: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get() 9 | rootProject.layout.buildDirectory.value(newBuildDir) 10 | 11 | subprojects { 12 | val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) 13 | project.layout.buildDirectory.value(newSubprojectBuildDir) 14 | } 15 | subprojects { 16 | project.evaluationDependsOn(":app") 17 | } 18 | 19 | tasks.register("clean") { 20 | delete(rootProject.layout.buildDirectory) 21 | } 22 | -------------------------------------------------------------------------------- /android/fastlane/Appfile: -------------------------------------------------------------------------------- 1 | json_key_file("../google_service_account.json") 2 | package_name(ENV["APP_PACKAGE_NAME"]) -------------------------------------------------------------------------------- /android/fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | import "../../Fastfile" 2 | 3 | default_platform(:android) 4 | 5 | platform :android do 6 | 7 | # Build flutter Android app 8 | lane :build do |options| 9 | 10 | # Verify 'firebase_app_distribution_service_account.json' file exists 11 | unless File.exist?(google_service_account_json_path) 12 | UI.user_error!("google_service_account.json file not found. Please add it to the root of the flutter project. See https://docs.fastlane.tools/actions/supply/") 13 | end 14 | 15 | # Verify version number is correct 16 | if !is_ci && (!options[:version_number]) 17 | version_number = get_version_from_pubspec() 18 | continue = UI.confirm("Deploying version #{version_number} (from pubspec.yaml) to Play Store. Continue?") 19 | 20 | unless continue 21 | UI.user_error!("Aborted") 22 | end 23 | end 24 | 25 | build_flutter_app( 26 | type: options[:type] || "appbundle", 27 | no_codesign: options[:no_codesign], 28 | config_only: options[:config_only], 29 | build_number: options[:build_number], 30 | version_number: options[:version_number], 31 | store: "playstore" 32 | ) 33 | end 34 | 35 | # Release to Play Store using Fastlane Supply (https://docs.fastlane.tools/actions/supply/) 36 | desc "Release to Play Store" 37 | lane :release_play_store do |options| 38 | begin 39 | build( 40 | no_codesign: options[:no_codesign], 41 | config_only: options[:config_only], 42 | build_number: options[:build_number], 43 | version_number: options[:version_number] 44 | ) 45 | 46 | symbols_file_path = File.expand_path(File.join("..", "..", "native-debug-symbols.zip"), Dir.pwd) 47 | 48 | symbols_folder_path = File.expand_path(File.join( 49 | "..", "..", "build", "app", "intermediates", "merged_native_libs", 50 | "release", "mergeReleaseNativeLibs", "out", "lib" 51 | ), Dir.pwd) 52 | 53 | # Check platform to use appropriate zip command 54 | if Gem.win_platform? 55 | system("powershell -Command \"Compress-Archive -Path '#{symbols_folder_path}/*' -DestinationPath '#{symbols_file_path}' -Force\"") 56 | else 57 | system("cd #{symbols_folder_path} && zip -r #{symbols_file_path} .") 58 | end 59 | 60 | supply( 61 | track: 'internal', 62 | # Uncomment this if getting error "Only releases with status draft may be created on draft app." 63 | # release_status: 'draft', 64 | aab: File.expand_path(File.join("..", "..", "build", "app", "outputs", "bundle", "release", "app-release.aab"), Dir.pwd), 65 | mapping_paths: [symbols_file_path, File.expand_path(File.join("..", "..", "build", "app", "outputs", "mapping", "release", "mapping.txt"), Dir.pwd)], 66 | metadata_path:"../fastlane/metadata/android", 67 | json_key: google_service_account_json_path, 68 | skip_upload_apk: true, # Upload the aab instead of apk 69 | skip_upload_metadata: true, 70 | skip_upload_changelogs: true, 71 | skip_upload_images: true, 72 | skip_upload_screenshots: true, 73 | timeout:600 74 | ) 75 | end 76 | end 77 | 78 | desc "Build Apk" 79 | lane :build_apk do |options| 80 | begin 81 | build( 82 | type: 'apk', 83 | no_codesign: options[:no_codesign], 84 | config_only: options[:config_only], 85 | build_number: options[:build_number], 86 | version_number: options[:version_number] 87 | ) 88 | 89 | File.rename("#{root_path}/build/app/outputs/flutter-apk/app-release.apk", "#{root_path}/build/app/outputs/flutter-apk/FontGallery-Android.apk") 90 | end 91 | end 92 | 93 | # Release to Play Store using Firebase App Distribution (https://docs.fastlane.tools/actions/firebase_app_distribution/) 94 | desc "Release to Play Store using Firebase App Distribution" 95 | lane :release_play_store_using_firebase do |options| 96 | begin 97 | build( 98 | type: 'apk', 99 | no_codesign: options[:no_codesign], 100 | config_only: options[:config_only], 101 | build_number: options[:build_number], 102 | version_number: options[:version_number] 103 | ) 104 | 105 | firebase_app_distribution( 106 | app: ENV["FIREBASE_APP_ID"], 107 | android_artifact_path: "#{root_path}/build/app/outputs/flutter-apk/app-release.apk", 108 | service_credentials_file: google_service_account_json_path, 109 | # Use the following to enable debug mode 110 | debug: true 111 | ) 112 | end 113 | end 114 | end -------------------------------------------------------------------------------- /android/fastlane/Pluginfile: -------------------------------------------------------------------------------- 1 | # Autogenerated by fastlane 2 | # 3 | # Ensure this file is checked in to source control! 4 | 5 | gem 'fastlane-plugin-firebase_app_distribution' 6 | gem 'fastlane-plugin-get_new_build_number' 7 | -------------------------------------------------------------------------------- /android/fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ---- 3 | 4 | # Installation 5 | 6 | Make sure you have the latest version of the Xcode command line tools installed: 7 | 8 | ```sh 9 | xcode-select --install 10 | ``` 11 | 12 | For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) 13 | 14 | # Available Actions 15 | 16 | ### sh_on_root 17 | 18 | ```sh 19 | [bundle exec] fastlane sh_on_root 20 | ``` 21 | 22 | 23 | 24 | ### fetch_dependencies 25 | 26 | ```sh 27 | [bundle exec] fastlane fetch_dependencies 28 | ``` 29 | 30 | 31 | 32 | ### build_autogenerated_code 33 | 34 | ```sh 35 | [bundle exec] fastlane build_autogenerated_code 36 | ``` 37 | 38 | 39 | 40 | ### lint 41 | 42 | ```sh 43 | [bundle exec] fastlane lint 44 | ``` 45 | 46 | 47 | 48 | ### build_flutter_app 49 | 50 | ```sh 51 | [bundle exec] fastlane build_flutter_app 52 | ``` 53 | 54 | 55 | 56 | ### test 57 | 58 | ```sh 59 | [bundle exec] fastlane test 60 | ``` 61 | 62 | 63 | 64 | ---- 65 | 66 | 67 | ## Android 68 | 69 | ### android build 70 | 71 | ```sh 72 | [bundle exec] fastlane android build 73 | ``` 74 | 75 | 76 | 77 | ### android release_play_store 78 | 79 | ```sh 80 | [bundle exec] fastlane android release_play_store 81 | ``` 82 | 83 | Release to Play Store 84 | 85 | ### android build_apk 86 | 87 | ```sh 88 | [bundle exec] fastlane android build_apk 89 | ``` 90 | 91 | Build Apk 92 | 93 | ### android release_play_store_using_firebase 94 | 95 | ```sh 96 | [bundle exec] fastlane android release_play_store_using_firebase 97 | ``` 98 | 99 | Release to Play Store using Firebase App Distribution 100 | 101 | ---- 102 | 103 | This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. 104 | 105 | More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). 106 | 107 | The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 108 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | android.enableJetifier=true -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip -------------------------------------------------------------------------------- /android/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | val flutterSdkPath = run { 3 | val properties = java.util.Properties() 4 | file("local.properties").inputStream().use { properties.load(it) } 5 | val flutterSdkPath = properties.getProperty("flutter.sdk") 6 | require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } 7 | flutterSdkPath 8 | } 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id("dev.flutter.flutter-plugin-loader") version "1.0.0" 21 | id("com.android.application") version "8.7.0" apply false 22 | id("org.jetbrains.kotlin.android") version "1.8.22" apply false 23 | } 24 | 25 | include(":app") -------------------------------------------------------------------------------- /assets/theme_switch.json: -------------------------------------------------------------------------------- 1 | {"v":"5.9.6","fr":30,"ip":0,"op":19,"w":1000,"h":1000,"nm":"Google Light Dark Toggle","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Toggle Button","sr":1.25,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2,"l":2},"a":{"a":0,"k":[499.76,467.729,0],"ix":1,"l":2},"s":{"a":0,"k":[110.554,110.554,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-47.262],[47.263,0],[0,47.263],[-47.263,0]],"o":[[0,47.263],[-47.263,0],[0,-47.262],[47.263,0]],"v":[[85.576,0],[0,85.576],[-85.576,0],[0,-85.576]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.999]},"o":{"x":[0.167],"y":[0.001]},"t":0,"s":[0.121568627656,0.129411771894,0.137254908681,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":18.75,"s":[1,1,1,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":56.25,"s":[1,1,1,1]},{"t":75,"s":[0.121568627656,0.129411771894,0.137254908681,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":0.159,"s":[545.971,466.814],"to":[6.083,0],"ti":[-6.083,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":18.75,"s":[582.471,466.814],"to":[0,0],"ti":[0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":56.25,"s":[582.471,466.814],"to":[-6.083,0],"ti":[6.083,0]},{"t":75.1591796875,"s":[545.971,466.814]}],"ix":2},"a":{"a":0,"k":[82.709,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":0.159,"s":[125,125]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":18.75,"s":[100,100]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":56.25,"s":[100,100]},{"t":75.1591796875,"s":[125,125]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[62.09,0],[0,62.09],[-62.09,0],[0,-62.09]],"o":[[-62.09,0],[0,-62.09],[62.09,0],[0,62.09]],"v":[[0,112.421],[-112.42,0.001],[0,-112.419],[112.431,0.001]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,-236.87],[-236.87,0.001],[0,236.87],[236.87,0.001]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.999]},"o":{"x":[0.167],"y":[0.001]},"t":0,"s":[0.121568627656,0.129411771894,0.137254908681,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":18.75,"s":[1,1,1,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":56.25,"s":[1,1,1,1]},{"t":75,"s":[0.121568627656,0.129411771894,0.137254908681,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[499.76,467.729],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[62.09,0],[0,62.09],[-62.09,0],[0,-62.09]],"o":[[-62.09,0],[0,-62.09],[62.09,0],[0,62.09]],"v":[[0,112.421],[-112.42,0.001],[0,-112.419],[112.431,0.001]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-167.49,167.489],[167.49,167.489],[167.49,-167.489],[-167.49,-167.489]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.999]},"o":{"x":[0.167],"y":[0.001]},"t":0,"s":[0.121568627656,0.129411771894,0.137254908681,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":18.75,"s":[1,1,1,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":56.25,"s":[1,1,1,1]},{"t":75,"s":[0.121568627656,0.129411771894,0.137254908681,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[499.76,467.73],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[499.76,467.729],"ix":2},"a":{"a":0,"k":[499.76,467.729],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[180]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":18.75,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":56.25,"s":[0]},{"t":75,"s":[180]}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":-37.5,"ct":1,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/full_description.txt: -------------------------------------------------------------------------------- 1 | Font Gallery app showcases how different Font Families with their different variations (Style, Weight and Size) look. You could switch between light and dark modes and also compare different font families. 2 | 3 | There's a handy search feature to easily search for your favorite fonts and the text to compare the font's could also be changed to a custom user set text. 4 | 5 | The Fonts are sourced from Google Fonts and even the Font Author information is displayed. -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/featureGraphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/fastlane/metadata/android/en-US/images/featureGraphic.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/fastlane/metadata/android/en-US/images/icon.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/2_en-US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/fastlane/metadata/android/en-US/images/phoneScreenshots/2_en-US.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/3_en-US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/fastlane/metadata/android/en-US/images/phoneScreenshots/3_en-US.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/4_en-US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/fastlane/metadata/android/en-US/images/phoneScreenshots/4_en-US.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/5_en-US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/fastlane/metadata/android/en-US/images/phoneScreenshots/5_en-US.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/short_description.txt: -------------------------------------------------------------------------------- 1 | An App to display how different fonts families and their variations look. -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/title.txt: -------------------------------------------------------------------------------- 1 | Font Gallery -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/video.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/fastlane/metadata/android/en-US/video.txt -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | # takes version from flutter (pubspec.yaml) 5 | gem "fastlane-plugin-flutter_version", git: "https://github.com/tianhaoz95/fastlane-plugin-flutter-version" 6 | 7 | plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') 8 | eval_gemfile(plugins_path) if File.exist?(plugins_path) 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "AppIcon@2x.png", 5 | "idiom": "iphone", 6 | "scale": "2x", 7 | "size": "60x60" 8 | }, 9 | { 10 | "filename": "AppIcon@3x.png", 11 | "idiom": "iphone", 12 | "scale": "3x", 13 | "size": "60x60" 14 | }, 15 | { 16 | "filename": "AppIcon~ipad.png", 17 | "idiom": "ipad", 18 | "scale": "1x", 19 | "size": "76x76" 20 | }, 21 | { 22 | "filename": "AppIcon@2x~ipad.png", 23 | "idiom": "ipad", 24 | "scale": "2x", 25 | "size": "76x76" 26 | }, 27 | { 28 | "filename": "AppIcon-83.5@2x~ipad.png", 29 | "idiom": "ipad", 30 | "scale": "2x", 31 | "size": "83.5x83.5" 32 | }, 33 | { 34 | "filename": "AppIcon-40@2x.png", 35 | "idiom": "iphone", 36 | "scale": "2x", 37 | "size": "40x40" 38 | }, 39 | { 40 | "filename": "AppIcon-40@3x.png", 41 | "idiom": "iphone", 42 | "scale": "3x", 43 | "size": "40x40" 44 | }, 45 | { 46 | "filename": "AppIcon-40~ipad.png", 47 | "idiom": "ipad", 48 | "scale": "1x", 49 | "size": "40x40" 50 | }, 51 | { 52 | "filename": "AppIcon-40@2x~ipad.png", 53 | "idiom": "ipad", 54 | "scale": "2x", 55 | "size": "40x40" 56 | }, 57 | { 58 | "filename": "AppIcon-20@2x.png", 59 | "idiom": "iphone", 60 | "scale": "2x", 61 | "size": "20x20" 62 | }, 63 | { 64 | "filename": "AppIcon-20@3x.png", 65 | "idiom": "iphone", 66 | "scale": "3x", 67 | "size": "20x20" 68 | }, 69 | { 70 | "filename": "AppIcon-20~ipad.png", 71 | "idiom": "ipad", 72 | "scale": "1x", 73 | "size": "20x20" 74 | }, 75 | { 76 | "filename": "AppIcon-20@2x~ipad.png", 77 | "idiom": "ipad", 78 | "scale": "2x", 79 | "size": "20x20" 80 | }, 81 | { 82 | "filename": "AppIcon-29.png", 83 | "idiom": "iphone", 84 | "scale": "1x", 85 | "size": "29x29" 86 | }, 87 | { 88 | "filename": "AppIcon-29@2x.png", 89 | "idiom": "iphone", 90 | "scale": "2x", 91 | "size": "29x29" 92 | }, 93 | { 94 | "filename": "AppIcon-29@3x.png", 95 | "idiom": "iphone", 96 | "scale": "3x", 97 | "size": "29x29" 98 | }, 99 | { 100 | "filename": "AppIcon-29~ipad.png", 101 | "idiom": "ipad", 102 | "scale": "1x", 103 | "size": "29x29" 104 | }, 105 | { 106 | "filename": "AppIcon-29@2x~ipad.png", 107 | "idiom": "ipad", 108 | "scale": "2x", 109 | "size": "29x29" 110 | }, 111 | { 112 | "filename": "AppIcon-60@2x~car.png", 113 | "idiom": "car", 114 | "scale": "2x", 115 | "size": "60x60" 116 | }, 117 | { 118 | "filename": "AppIcon-60@3x~car.png", 119 | "idiom": "car", 120 | "scale": "3x", 121 | "size": "60x60" 122 | }, 123 | { 124 | "filename": "AppIcon~ios-marketing.png", 125 | "idiom": "ios-marketing", 126 | "scale": "1x", 127 | "size": "1024x1024" 128 | } 129 | ], 130 | "info": { 131 | "author": "iconkitchen", 132 | "version": 1 133 | } 134 | } -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "background.png", 5 | "idiom" : "universal" 6 | }, 7 | { 8 | "appearances" : [ 9 | { 10 | "appearance" : "luminosity", 11 | "value" : "dark" 12 | } 13 | ], 14 | "filename" : "darkbackground.png", 15 | "idiom" : "universal" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "LaunchImage.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "LaunchImage@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "LaunchImage@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Font Gallery 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | Font Gallery 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | CADisableMinimumFrameDurationOnPhone 47 | 48 | UIStatusBarHidden 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /ios/fastlane/Appfile: -------------------------------------------------------------------------------- 1 | app_identifier(ENV["DEVELOPER_APP_IDENTIFIER"]) 2 | apple_id(ENV["FASTLANE_APPLE_ID"]) 3 | 4 | itc_team_id(ENV["APP_STORE_CONNECT_TEAM_ID"]) 5 | team_id(ENV["DEVELOPER_PORTAL_TEAM_ID"]) 6 | -------------------------------------------------------------------------------- /ios/fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | import "../../Fastfile" 2 | 3 | default_platform(:ios) 4 | 5 | 6 | platform :ios do 7 | # Authenticate with Apple Store 8 | private_lane :authenticate_apple_store do 9 | app_store_connect_api_key( 10 | key_id: ENV["ASC_KEY_ID"], 11 | issuer_id: ENV["ASC_ISSUER_ID"], 12 | key_content: ENV["ASC_KEY_P8_BASE64"], 13 | is_key_content_base64: true, 14 | in_house: false 15 | ) 16 | end 17 | 18 | # Build iOS app 19 | lane :build_ipa do |options| 20 | authenticate_apple_store 21 | 22 | build_flutter_app( 23 | type: "ipa", 24 | no_codesign: options[:no_codesign] || false, 25 | config_only: options[:config_only] || false, 26 | build_number: options[:build_number] || get_build_number('appstore'), 27 | version_number: options[:version_number] || get_version_from_pubspec(), 28 | store: "appstore" 29 | ) 30 | end 31 | 32 | 33 | desc "Release a new build to Apple Store" 34 | lane :release_app_store do |options| 35 | verify_env(envs: [ 36 | "ASC_KEY_ID", 37 | "ASC_ISSUER_ID", 38 | "ASC_KEY_P8_BASE64", 39 | "APP_BUNDLE_ID", 40 | "MATCH_PASSWORD", 41 | "MATCH_GIT_BASIC_AUTHORIZATION", 42 | ]) 43 | 44 | authenticate_apple_store 45 | 46 | build_number = options.fetch(:build_number, get_build_number('appstore')) 47 | version_number = options.fetch(:version_number, get_version_from_pubspec()) 48 | 49 | # Verify version number is correct 50 | if !is_ci && (!options[:version_number]) 51 | continue = UI.confirm("Deploying version #{version_number} (from pubspec.yaml) to App Store. Continue?") 52 | 53 | unless continue 54 | UI.user_error!("Aborted") 55 | end 56 | end 57 | 58 | # Sync certificates and profiles using match 59 | UI.message("Syncing certificates and profiles") 60 | 61 | if is_ci 62 | UI.message("CI detected. Setting up CI environment") 63 | setup_ci 64 | end 65 | 66 | sync_code_signing( 67 | type: "appstore", 68 | readonly: is_ci, 69 | ) 70 | 71 | build_ipa( 72 | build_number: build_number, 73 | version_number: version_number 74 | ) 75 | 76 | build_app( 77 | skip_build_archive: true, 78 | archive_path: "../build/ios/archive/Runner.xcarchive", 79 | ) 80 | 81 | # If GoogleService-Info.plist exists and Pods/FirebaseCrashlytics exists 82 | # Upload symbols to Firebase Crashlytics 83 | if File.file?("../ios/Runner/GoogleService-Info.plist") && File.directory?("../ios/Pods/FirebaseCrashlytics") 84 | upload_symbols_to_crashlytics( 85 | gsp_path: "../ios/Runner/GoogleService-Info.plist" 86 | ) 87 | end 88 | 89 | upload_to_testflight( 90 | skip_waiting_for_build_processing: true 91 | ) 92 | end 93 | 94 | # This is a work in progress, requiring ad-hoc export method 95 | # desc "Release to Play Store using Firebase App Distribution" 96 | # lane :release_to_firebase do |options| 97 | # begin 98 | # build_ipa 99 | 100 | # firebase_app_distribution( 101 | # app: ENV["FIREBASE_APP_ID"], 102 | # service_credentials_file: google_service_account_json_path, 103 | # ipa_path: "../build/ios/Runner.ipa" 104 | # ) 105 | # end 106 | # end 107 | end 108 | -------------------------------------------------------------------------------- /ios/fastlane/Matchfile: -------------------------------------------------------------------------------- 1 | git_url("https://github.com/your/app-certificates-and-profiles.git") 2 | storage_mode("git") 3 | type("appstore") # The default type, can be: appstore, adhoc, enterprise or development 4 | 5 | app_identifier([ENV["APP_BUNDLE_ID"]]) 6 | -------------------------------------------------------------------------------- /ios/fastlane/Pluginfile: -------------------------------------------------------------------------------- 1 | # Autogenerated by fastlane 2 | # 3 | # Ensure this file is checked in to source control! 4 | 5 | gem 'fastlane-plugin-firebase_app_distribution' 6 | gem 'fastlane-plugin-get_new_build_number' 7 | -------------------------------------------------------------------------------- /lib/constants.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const kDefaultText = "Whereas Recognition of the Inherent Dignity"; 4 | 5 | const kLightSplashColor = Color(0xFFF9F9F9); 6 | const kLightDividerColor = Color(0xFFDADCE0); 7 | const kLightInputFillColor = Color(0xFFE0E0E0); 8 | const kDarkSplashColor = Color(0xFF28292C); 9 | const kDarkDividerColor = Color(0xFF606367); 10 | const kDarkInputFillColor = Color(0xFF363636); 11 | const kDarkScaffoldColor = Color(0xFF202124); 12 | 13 | const kSearchFieldDecoration = InputDecoration( 14 | hintText: "Type Something", 15 | border: UnderlineInputBorder( 16 | borderSide: BorderSide.none, 17 | borderRadius: BorderRadius.only( 18 | topLeft: Radius.circular(30), 19 | bottomLeft: Radius.circular(30), 20 | ), 21 | ), 22 | ); 23 | const kInputTextFormDecoration = InputDecoration( 24 | hintText: "Type Something", 25 | border: UnderlineInputBorder( 26 | borderSide: BorderSide.none, 27 | borderRadius: BorderRadius.only( 28 | topLeft: Radius.circular(30), 29 | bottomLeft: Radius.circular(30), 30 | ), 31 | ), 32 | ); 33 | const kDropdownButtonDecoration = InputDecoration( 34 | prefixIcon: Center(child: Icon(Icons.format_size)), 35 | prefixIconConstraints: BoxConstraints(maxWidth: 32, maxHeight: 24), 36 | border: UnderlineInputBorder( 37 | borderSide: BorderSide.none, 38 | borderRadius: BorderRadius.only( 39 | topRight: Radius.circular(30), 40 | bottomRight: Radius.circular(30), 41 | ), 42 | ), 43 | ); 44 | -------------------------------------------------------------------------------- /lib/controllers/settings_controller.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:font_gallery/constants.dart'; 4 | import 'package:font_gallery/models/font_model.dart'; 5 | import 'package:font_gallery/models/settings_model.dart'; 6 | import 'package:shared_preferences/shared_preferences.dart'; 7 | 8 | class SharedPrefs { 9 | static late final SharedPreferences prefs; 10 | 11 | Future initPrefs() async { 12 | prefs = await SharedPreferences.getInstance(); 13 | } 14 | } 15 | 16 | final settingsProvider = NotifierProvider( 17 | SettingsController.new, 18 | ); 19 | 20 | class SettingsController extends Notifier { 21 | @override 22 | SettingsModel build() { 23 | return SettingsModel( 24 | SharedPrefs.prefs.getBool("isDarkMode") ?? 25 | PlatformDispatcher.instance.platformBrightness == Brightness.dark, 26 | kDefaultText, 27 | null, 28 | null, 29 | ); 30 | } 31 | 32 | bool lastSelectedFirstPosition = true; 33 | 34 | Future switchTheme() async { 35 | state = state.copyWith( 36 | state.selectedFontModel, 37 | state.selectedFontModel2, 38 | isDark: !state.isDark, 39 | ); 40 | await SharedPrefs.prefs.setBool("isDarkMode", state.isDark); 41 | } 42 | 43 | void changeDisplayText(String newText) { 44 | if (newText.isEmpty) { 45 | state = state.copyWith( 46 | state.selectedFontModel, 47 | state.selectedFontModel2, 48 | displayText: kDefaultText, 49 | ); 50 | } else { 51 | state = state.copyWith( 52 | state.selectedFontModel, 53 | state.selectedFontModel2, 54 | displayText: newText, 55 | ); 56 | } 57 | } 58 | 59 | void onFontCardAction(FontModel clickedFontModel) { 60 | //remove 61 | if (state.selectedFontModel == clickedFontModel) { 62 | state = state.copyWith(null, state.selectedFontModel2); 63 | } else if (state.selectedFontModel2 == clickedFontModel) { 64 | state = state.copyWith(state.selectedFontModel, null); 65 | } else { 66 | //add 67 | if (state.selectedFontModel == null) { 68 | state = state.copyWith(clickedFontModel, state.selectedFontModel2); 69 | } else if (state.selectedFontModel2 == null) { 70 | state = state.copyWith(state.selectedFontModel, clickedFontModel); 71 | } else { 72 | if (lastSelectedFirstPosition) { 73 | lastSelectedFirstPosition = false; 74 | state = state.copyWith(clickedFontModel, state.selectedFontModel2); 75 | } else { 76 | lastSelectedFirstPosition = true; 77 | state = state.copyWith(state.selectedFontModel, clickedFontModel); 78 | } 79 | } 80 | } 81 | } 82 | 83 | bool isFontModelSelected(FontModel fontModel) { 84 | if (state.selectedFontModel?.name == fontModel.name || 85 | state.selectedFontModel2?.name == fontModel.name) { 86 | return true; 87 | } else { 88 | return false; 89 | } 90 | } 91 | 92 | void removeSelectedFontModel() { 93 | state = state.copyWith(null, state.selectedFontModel2); 94 | } 95 | 96 | void removeSelectedFontModel2() { 97 | state = state.copyWith(state.selectedFontModel, null); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/helpers.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Helpers { 4 | static String getWeightText(FontWeight fontWeight) { 5 | switch (fontWeight) { 6 | case FontWeight.w100: 7 | return "Thin 100"; 8 | case FontWeight.w200: 9 | return "ExtraLight 200"; 10 | case FontWeight.w300: 11 | return "Light 300"; 12 | case FontWeight.w400: 13 | return "Regular 400"; 14 | case FontWeight.w500: 15 | return "Medium 500"; 16 | case FontWeight.w600: 17 | return "SemiBold 600"; 18 | case FontWeight.w700: 19 | return "Bold 700"; 20 | case FontWeight.w800: 21 | return "ExtraBold 800"; 22 | case FontWeight.w900: 23 | return "Black 900"; 24 | default: 25 | return "Regular 400"; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | import 'package:font_gallery/constants.dart'; 5 | import 'package:font_gallery/controllers/settings_controller.dart'; 6 | import 'package:font_gallery/views/home.dart'; 7 | import 'package:google_fonts/google_fonts.dart'; 8 | 9 | Future main() async { 10 | WidgetsFlutterBinding.ensureInitialized(); 11 | await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); 12 | await SharedPrefs().initPrefs(); 13 | runApp(const ProviderScope(child: FontGalleryApp())); 14 | } 15 | 16 | class FontGalleryApp extends ConsumerWidget { 17 | const FontGalleryApp({super.key}); 18 | 19 | @override 20 | Widget build(BuildContext context, WidgetRef ref) { 21 | final bool isDark = ref.watch( 22 | settingsProvider.select((value) => value.isDark), 23 | ); 24 | if (isDark) { 25 | SystemChrome.setSystemUIOverlayStyle( 26 | const SystemUiOverlayStyle( 27 | statusBarColor: kDarkScaffoldColor, 28 | systemNavigationBarColor: kDarkScaffoldColor, 29 | statusBarIconBrightness: Brightness.light, 30 | systemNavigationBarIconBrightness: Brightness.light, 31 | ), 32 | ); 33 | } else { 34 | SystemChrome.setSystemUIOverlayStyle( 35 | const SystemUiOverlayStyle( 36 | statusBarColor: Colors.white, 37 | systemNavigationBarColor: Colors.white, 38 | statusBarIconBrightness: Brightness.dark, 39 | systemNavigationBarIconBrightness: Brightness.dark, 40 | ), 41 | ); 42 | } 43 | return MaterialApp( 44 | title: 'Font Gallery', 45 | debugShowCheckedModeBanner: false, 46 | themeMode: isDark ? ThemeMode.dark : ThemeMode.light, 47 | theme: ThemeData( 48 | useMaterial3: true, 49 | brightness: Brightness.light, 50 | scaffoldBackgroundColor: Colors.white, 51 | splashColor: kLightSplashColor, 52 | dividerColor: kLightDividerColor, 53 | primarySwatch: Colors.indigo, 54 | textTheme: GoogleFonts.notoSansTextTheme(), 55 | inputDecorationTheme: const InputDecorationTheme( 56 | filled: true, 57 | fillColor: kLightInputFillColor, 58 | ), 59 | outlinedButtonTheme: OutlinedButtonThemeData( 60 | style: ButtonStyle( 61 | side: WidgetStateProperty.all( 62 | const BorderSide(color: Colors.indigo), 63 | ), 64 | shape: WidgetStateProperty.all( 65 | RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), 66 | ), 67 | ), 68 | ), 69 | appBarTheme: const AppBarTheme( 70 | elevation: 0, 71 | titleSpacing: 0, 72 | foregroundColor: Colors.black, 73 | backgroundColor: Colors.white, 74 | ), 75 | ), 76 | darkTheme: ThemeData( 77 | useMaterial3: true, 78 | brightness: Brightness.dark, 79 | scaffoldBackgroundColor: kDarkScaffoldColor, 80 | splashColor: kDarkSplashColor, 81 | dividerColor: kDarkDividerColor, 82 | primarySwatch: Colors.indigo, 83 | textTheme: GoogleFonts.notoSansTextTheme( 84 | ThemeData(brightness: Brightness.dark).textTheme, 85 | ), 86 | inputDecorationTheme: const InputDecorationTheme( 87 | filled: true, 88 | fillColor: kDarkInputFillColor, 89 | ), 90 | outlinedButtonTheme: OutlinedButtonThemeData( 91 | style: ButtonStyle( 92 | side: WidgetStateProperty.all( 93 | const BorderSide(color: Colors.indigo), 94 | ), 95 | shape: WidgetStateProperty.all( 96 | RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), 97 | ), 98 | ), 99 | ), 100 | appBarTheme: const AppBarTheme( 101 | elevation: 0, 102 | titleSpacing: 0, 103 | foregroundColor: Color(0xFFE8EAED), 104 | backgroundColor: Color(0xFF202124), 105 | ), 106 | ), 107 | home: const Home(), 108 | ); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /lib/models/settings_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:font_gallery/models/font_model.dart'; 2 | 3 | class SettingsModel { 4 | final bool isDark; 5 | final String displayText; 6 | final FontModel? selectedFontModel; 7 | final FontModel? selectedFontModel2; 8 | 9 | SettingsModel( 10 | this.isDark, 11 | this.displayText, 12 | this.selectedFontModel, 13 | this.selectedFontModel2, 14 | ); 15 | 16 | SettingsModel copyWith( 17 | FontModel? selectedFontModel, 18 | FontModel? selectedFontModel2, { 19 | bool? isDark, 20 | String? displayText, 21 | }) { 22 | return SettingsModel( 23 | isDark ?? this.isDark, 24 | displayText ?? this.displayText, 25 | selectedFontModel, 26 | selectedFontModel2, 27 | ); 28 | } 29 | 30 | @override 31 | String toString() { 32 | return 'SettingsModel{isDark: $isDark, displayText: $displayText, selectedFontModel: $selectedFontModel, selectedFontModel2: $selectedFontModel2}'; 33 | } 34 | 35 | @override 36 | bool operator ==(Object other) { 37 | return other is SettingsModel && 38 | isDark == other.isDark && 39 | displayText == other.displayText && 40 | selectedFontModel == other.selectedFontModel && 41 | selectedFontModel2 == other.selectedFontModel2; 42 | } 43 | 44 | @override 45 | int get hashCode => 46 | Object.hash(isDark, displayText, selectedFontModel, selectedFontModel2); 47 | } 48 | -------------------------------------------------------------------------------- /lib/views/font_search_delegate.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:font_gallery/models/font_model.dart'; 4 | import 'package:font_gallery/widgets/compare_button.dart'; 5 | import 'package:font_gallery/widgets/font_card.dart'; 6 | 7 | class FontSearchDelegate extends SearchDelegate { 8 | final List emptySearchResultEmojis = [ 9 | "(^_^)b", 10 | "\\(^Д^)/", 11 | "(˚Δ˚)b", 12 | "(^-^*)", 13 | "(·_·)", 14 | "(>_<)", 15 | "(·.·)", 16 | "\\(o_o)/", 17 | "(≥o≤)", 18 | "(='X'=)", 19 | ]; 20 | FontSearchDelegate(); 21 | 22 | @override 23 | List? buildActions(BuildContext context) { 24 | return (query.isEmpty) 25 | ? null 26 | : [ 27 | IconButton( 28 | onPressed: () { 29 | query = ""; 30 | }, 31 | tooltip: "Clear", 32 | icon: const Icon(Icons.clear), 33 | ), 34 | ]; 35 | } 36 | 37 | @override 38 | Widget? buildLeading(BuildContext context) { 39 | return IconButton( 40 | onPressed: () { 41 | close(context, null); 42 | }, 43 | tooltip: "Back", 44 | icon: const Icon(Icons.arrow_back), 45 | ); 46 | } 47 | 48 | @override 49 | Widget buildResults(BuildContext context) { 50 | final List resultsList = 51 | fontList 52 | .where( 53 | (element) => 54 | element.name.toLowerCase().contains(query.toLowerCase()), 55 | ) 56 | .toList(); 57 | if (resultsList.isEmpty) { 58 | final int randomEmptyResultIndex = Random().nextInt(10); 59 | return Center( 60 | child: Padding( 61 | padding: const EdgeInsets.symmetric(horizontal: 20), 62 | child: Column( 63 | mainAxisAlignment: MainAxisAlignment.center, 64 | children: [ 65 | Text( 66 | emptySearchResultEmojis[randomEmptyResultIndex], 67 | style: const TextStyle(fontSize: 80), 68 | ), 69 | const SizedBox(height: 20), 70 | const Text( 71 | "We couldn't find any fonts matching that. Maybe try a different search?", 72 | style: TextStyle(fontSize: 20), 73 | textAlign: TextAlign.center, 74 | ), 75 | const SizedBox(height: 20), 76 | OutlinedButton( 77 | onPressed: () { 78 | query = ""; 79 | showSuggestions(context); 80 | }, 81 | child: const Text("Clear your filters and try again"), 82 | ), 83 | ], 84 | ), 85 | ), 86 | ); 87 | } else { 88 | return SafeArea( 89 | child: StatefulBuilder( 90 | builder: (context, setState) { 91 | return Stack( 92 | children: [ 93 | ListView.separated( 94 | padding: const EdgeInsets.symmetric( 95 | vertical: 10, 96 | horizontal: 8, 97 | ), 98 | itemCount: resultsList.length, 99 | itemBuilder: 100 | (context, index) => 101 | FontCard(fontModel: resultsList[index]), 102 | separatorBuilder: 103 | (context, index) => const SizedBox(height: 8), 104 | ), 105 | const Padding( 106 | padding: EdgeInsets.only(bottom: 16), 107 | child: Align( 108 | alignment: Alignment.bottomCenter, 109 | child: CompareButton(), 110 | ), 111 | ), 112 | ], 113 | ); 114 | }, 115 | ), 116 | ); 117 | } 118 | } 119 | 120 | @override 121 | Widget buildSuggestions(BuildContext context) { 122 | return buildResults(context); 123 | } 124 | 125 | @override 126 | PreferredSizeWidget buildBottom(BuildContext context) { 127 | return const PreferredSize( 128 | preferredSize: Size.fromHeight(2), 129 | child: Divider(height: 0), 130 | ); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /lib/views/home.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:font_gallery/models/font_model.dart'; 3 | import 'package:font_gallery/views/font_search_delegate.dart'; 4 | import 'package:font_gallery/widgets/compare_button.dart'; 5 | import 'package:font_gallery/widgets/font_card.dart'; 6 | import 'package:font_gallery/widgets/theme_mode_toggle.dart'; 7 | 8 | class Home extends StatelessWidget { 9 | const Home({super.key}); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Scaffold( 14 | appBar: AppBar( 15 | leading: IconButton( 16 | onPressed: () async { 17 | await showSearch(context: context, delegate: FontSearchDelegate()); 18 | }, 19 | icon: const Icon(Icons.search), 20 | tooltip: "Search", 21 | ), 22 | title: const Text("Font Gallery"), 23 | bottom: const PreferredSize( 24 | preferredSize: Size.fromHeight(2), 25 | child: Divider(height: 0), 26 | ), 27 | actions: const [ThemeModeToggle()], 28 | ), 29 | floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, 30 | floatingActionButton: const CompareButton(), 31 | body: ListView.separated( 32 | clipBehavior: Clip.none, 33 | padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8), 34 | itemCount: fontList.length, 35 | itemBuilder: (context, index) => FontCard(fontModel: fontList[index]), 36 | separatorBuilder: (context, index) => const SizedBox(height: 8), 37 | ), 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/widgets/compare_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | import 'package:font_gallery/controllers/settings_controller.dart'; 5 | import 'package:font_gallery/views/compare_page.dart'; 6 | 7 | class CompareButton extends ConsumerWidget { 8 | const CompareButton({super.key}); 9 | 10 | @override 11 | Widget build(BuildContext context, WidgetRef ref) { 12 | final themeContext = Theme.of(context); 13 | final settingsModel = ref.watch(settingsProvider); 14 | if (settingsModel.selectedFontModel == null && 15 | settingsModel.selectedFontModel2 == null) { 16 | return const Offstage(); 17 | } 18 | return FloatingActionButton.extended( 19 | label: Row( 20 | children: [ 21 | if (settingsModel.selectedFontModel != null) 22 | GestureDetector( 23 | onTap: 24 | () => 25 | ref 26 | .read(settingsProvider.notifier) 27 | .removeSelectedFontModel(), 28 | child: Stack( 29 | children: [ 30 | CircleAvatar( 31 | backgroundColor: themeContext.scaffoldBackgroundColor, 32 | child: Text( 33 | settingsModel.selectedFontModel?.name.substring(0, 3) ?? 34 | "", 35 | style: const TextStyle(fontSize: 12), 36 | ), 37 | ), 38 | Positioned( 39 | right: 0, 40 | top: 0, 41 | child: CircleAvatar( 42 | radius: 8, 43 | backgroundColor: themeContext.colorScheme.surface, 44 | child: const Icon(Icons.remove, size: 12), 45 | ), 46 | ), 47 | ], 48 | ), 49 | ), 50 | const SizedBox(width: 5), 51 | if (settingsModel.selectedFontModel2 != null) 52 | GestureDetector( 53 | onTap: 54 | () => 55 | ref 56 | .read(settingsProvider.notifier) 57 | .removeSelectedFontModel2(), 58 | child: Stack( 59 | children: [ 60 | CircleAvatar( 61 | backgroundColor: themeContext.scaffoldBackgroundColor, 62 | child: Text( 63 | settingsModel.selectedFontModel2?.name.substring(0, 3) ?? 64 | "", 65 | style: const TextStyle(fontSize: 12), 66 | ), 67 | ), 68 | Positioned( 69 | right: 0, 70 | top: 0, 71 | child: CircleAvatar( 72 | radius: 8, 73 | backgroundColor: themeContext.colorScheme.surface, 74 | child: const Icon(Icons.remove, size: 12), 75 | ), 76 | ), 77 | ], 78 | ), 79 | ), 80 | const SizedBox(width: 16), 81 | Text( 82 | "Compare", 83 | style: TextStyle( 84 | color: 85 | (settingsModel.selectedFontModel == null || 86 | settingsModel.selectedFontModel2 == null) 87 | ? Colors.grey.shade400 88 | : null, 89 | ), 90 | ), 91 | Icon( 92 | Icons.chevron_right, 93 | color: 94 | (settingsModel.selectedFontModel == null || 95 | settingsModel.selectedFontModel2 == null) 96 | ? Colors.grey.shade400 97 | : null, 98 | ), 99 | ], 100 | ), 101 | onPressed: 102 | (settingsModel.selectedFontModel == null || 103 | settingsModel.selectedFontModel2 == null) 104 | ? null 105 | : () async { 106 | await Navigator.push( 107 | context, 108 | CupertinoPageRoute( 109 | builder: (context) => const CompareFontsPage(), 110 | ), 111 | ); 112 | }, 113 | ); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /lib/widgets/font_card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | import 'package:font_gallery/controllers/settings_controller.dart'; 5 | import 'package:font_gallery/models/font_model.dart'; 6 | import 'package:font_gallery/views/font_page.dart'; 7 | 8 | class FontCard extends ConsumerWidget { 9 | const FontCard({super.key, required this.fontModel}); 10 | final FontModel fontModel; 11 | @override 12 | Widget build(BuildContext context, WidgetRef ref) { 13 | final themeContext = Theme.of(context); 14 | final settingsModel = ref.watch(settingsProvider); 15 | return InkWell( 16 | borderRadius: BorderRadius.circular(6), 17 | onTap: () async { 18 | await Navigator.push( 19 | context, 20 | CupertinoPageRoute( 21 | builder: (context) => FontPage(fontModel: fontModel), 22 | ), 23 | ); 24 | }, 25 | child: Ink( 26 | padding: const EdgeInsets.fromLTRB(8, 8, 8, 16), 27 | decoration: BoxDecoration( 28 | border: Border.all(color: themeContext.dividerColor), 29 | borderRadius: BorderRadius.circular(6), 30 | ), 31 | child: Column( 32 | crossAxisAlignment: CrossAxisAlignment.start, 33 | children: [ 34 | Row( 35 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 36 | children: [ 37 | Column( 38 | crossAxisAlignment: CrossAxisAlignment.start, 39 | children: [ 40 | Text( 41 | fontModel.name, 42 | style: themeContext.textTheme.titleMedium, 43 | ), 44 | Text( 45 | fontModel.author, 46 | style: themeContext.textTheme.bodyMedium?.copyWith( 47 | color: themeContext.textTheme.bodySmall?.color, 48 | ), 49 | ), 50 | ], 51 | ), 52 | IconButton( 53 | onPressed: 54 | () => ref 55 | .read(settingsProvider.notifier) 56 | .onFontCardAction(fontModel), 57 | icon: 58 | (settingsModel.selectedFontModel?.name == 59 | fontModel.name || 60 | settingsModel.selectedFontModel2?.name == 61 | fontModel.name) 62 | ? const Icon(Icons.remove) 63 | : const Icon(Icons.add), 64 | ), 65 | ], 66 | ), 67 | const SizedBox(height: 10), 68 | Text( 69 | settingsModel.displayText, 70 | style: fontModel.textStyle().copyWith(fontSize: 20), 71 | maxLines: 3, 72 | ), 73 | ], 74 | ), 75 | ), 76 | ); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/widgets/theme_mode_toggle.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 5 | import 'package:font_gallery/controllers/settings_controller.dart'; 6 | import 'package:lottie/lottie.dart'; 7 | 8 | class ThemeModeToggle extends ConsumerStatefulWidget { 9 | const ThemeModeToggle({super.key}); 10 | 11 | @override 12 | ConsumerState createState() => _ThemeModeToggleState(); 13 | } 14 | 15 | class _ThemeModeToggleState extends ConsumerState 16 | with SingleTickerProviderStateMixin { 17 | late final AnimationController animationController; 18 | late bool isDark; 19 | @override 20 | void initState() { 21 | animationController = AnimationController(vsync: this); 22 | isDark = ref.read(settingsProvider.select((value) => value.isDark)); 23 | if (isDark) { 24 | animationController 25 | ..duration = Duration.zero 26 | ..forward(); 27 | } 28 | super.initState(); 29 | } 30 | 31 | @override 32 | void dispose() { 33 | animationController.dispose(); 34 | super.dispose(); 35 | } 36 | 37 | Future switchTheme() async { 38 | if (animationController.isAnimating) { 39 | return; 40 | } 41 | if (animationController.isCompleted) { 42 | unawaited(animationController.reverse()); 43 | } else { 44 | unawaited(animationController.forward()); 45 | } 46 | await ref.read(settingsProvider.notifier).switchTheme(); 47 | } 48 | 49 | @override 50 | Widget build(BuildContext context) { 51 | return IconButton( 52 | onPressed: switchTheme, 53 | tooltip: "Switch Theme", 54 | icon: Lottie.asset( 55 | "assets/theme_switch.json", 56 | controller: animationController, 57 | onLoaded: (composition) { 58 | animationController.duration = composition.duration; 59 | }, 60 | ), 61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.13) 3 | project(runner LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "font_gallery") 8 | # The unique GTK application identifier for this application. See: 9 | # https://wiki.gnome.org/HowDoI/ChooseApplicationID 10 | set(APPLICATION_ID "com.adeeteya.font_gallery") 11 | 12 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 13 | # versions of CMake. 14 | cmake_policy(SET CMP0063 NEW) 15 | 16 | # Load bundled libraries from the lib/ directory relative to the binary. 17 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 18 | 19 | # Root filesystem for cross-building. 20 | if(FLUTTER_TARGET_PLATFORM_SYSROOT) 21 | set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) 22 | set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) 23 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 24 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 25 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 26 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 27 | endif() 28 | 29 | # Define build configuration options. 30 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 31 | set(CMAKE_BUILD_TYPE "Debug" CACHE 32 | STRING "Flutter build mode" FORCE) 33 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 34 | "Debug" "Profile" "Release") 35 | endif() 36 | 37 | # Compilation settings that should be applied to most targets. 38 | # 39 | # Be cautious about adding new options here, as plugins use this function by 40 | # default. In most cases, you should add new options to specific targets instead 41 | # of modifying this function. 42 | function(APPLY_STANDARD_SETTINGS TARGET) 43 | target_compile_features(${TARGET} PUBLIC cxx_std_14) 44 | target_compile_options(${TARGET} PRIVATE -Wall -Werror) 45 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") 46 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") 47 | endfunction() 48 | 49 | # Flutter library and tool build rules. 50 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 51 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 52 | 53 | # System-level dependencies. 54 | find_package(PkgConfig REQUIRED) 55 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 56 | 57 | # Application build; see runner/CMakeLists.txt. 58 | add_subdirectory("runner") 59 | 60 | # Run the Flutter tool portions of the build. This must not be removed. 61 | add_dependencies(${BINARY_NAME} flutter_assemble) 62 | 63 | # Only the install-generated bundle's copy of the executable will launch 64 | # correctly, since the resources must in the right relative locations. To avoid 65 | # people trying to run the unbundled copy, put it in a subdirectory instead of 66 | # the default top-level location. 67 | set_target_properties(${BINARY_NAME} 68 | PROPERTIES 69 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" 70 | ) 71 | 72 | 73 | # Generated plugin build rules, which manage building the plugins and adding 74 | # them to the application. 75 | include(flutter/generated_plugins.cmake) 76 | 77 | 78 | # === Installation === 79 | # By default, "installing" just makes a relocatable bundle in the build 80 | # directory. 81 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") 82 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 83 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 84 | endif() 85 | 86 | # Start with a clean build bundle directory every time. 87 | install(CODE " 88 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") 89 | " COMPONENT Runtime) 90 | 91 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 92 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") 93 | 94 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 95 | COMPONENT Runtime) 96 | 97 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 98 | COMPONENT Runtime) 99 | 100 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 101 | COMPONENT Runtime) 102 | 103 | foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) 104 | install(FILES "${bundled_library}" 105 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 106 | COMPONENT Runtime) 107 | endforeach(bundled_library) 108 | 109 | # Copy the native assets provided by the build.dart from all packages. 110 | set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") 111 | install(DIRECTORY "${NATIVE_ASSETS_DIR}" 112 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 113 | COMPONENT Runtime) 114 | 115 | # Fully re-copy the assets directory on each build to avoid having stale files 116 | # from a previous install. 117 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 118 | install(CODE " 119 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 120 | " COMPONENT Runtime) 121 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 122 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 123 | 124 | # Install the AOT library on non-Debug builds only. 125 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") 126 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 127 | COMPONENT Runtime) 128 | endif() 129 | -------------------------------------------------------------------------------- /linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.10) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | 12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 13 | # which isn't available in 3.10. 14 | function(list_prepend LIST_NAME PREFIX) 15 | set(NEW_LIST "") 16 | foreach(element ${${LIST_NAME}}) 17 | list(APPEND NEW_LIST "${PREFIX}${element}") 18 | endforeach(element) 19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 20 | endfunction() 21 | 22 | # === Flutter Library === 23 | # System-level dependencies. 24 | find_package(PkgConfig REQUIRED) 25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 28 | 29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 30 | 31 | # Published to parent scope for install step. 32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 36 | 37 | list(APPEND FLUTTER_LIBRARY_HEADERS 38 | "fl_basic_message_channel.h" 39 | "fl_binary_codec.h" 40 | "fl_binary_messenger.h" 41 | "fl_dart_project.h" 42 | "fl_engine.h" 43 | "fl_json_message_codec.h" 44 | "fl_json_method_codec.h" 45 | "fl_message_codec.h" 46 | "fl_method_call.h" 47 | "fl_method_channel.h" 48 | "fl_method_codec.h" 49 | "fl_method_response.h" 50 | "fl_plugin_registrar.h" 51 | "fl_plugin_registry.h" 52 | "fl_standard_message_codec.h" 53 | "fl_standard_method_codec.h" 54 | "fl_string_codec.h" 55 | "fl_value.h" 56 | "fl_view.h" 57 | "flutter_linux.h" 58 | ) 59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 60 | add_library(flutter INTERFACE) 61 | target_include_directories(flutter INTERFACE 62 | "${EPHEMERAL_DIR}" 63 | ) 64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 65 | target_link_libraries(flutter INTERFACE 66 | PkgConfig::GTK 67 | PkgConfig::GLIB 68 | PkgConfig::GIO 69 | ) 70 | add_dependencies(flutter flutter_assemble) 71 | 72 | # === Flutter tool backend === 73 | # _phony_ is a non-existent file to force this command to run every time, 74 | # since currently there's no way to get a full input/output list from the 75 | # flutter tool. 76 | add_custom_command( 77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 79 | COMMAND ${CMAKE_COMMAND} -E env 80 | ${FLUTTER_TOOL_ENVIRONMENT} 81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 83 | VERBATIM 84 | ) 85 | add_custom_target(flutter_assemble DEPENDS 86 | "${FLUTTER_LIBRARY}" 87 | ${FLUTTER_LIBRARY_HEADERS} 88 | ) 89 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | 10 | void fl_register_plugins(FlPluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | ) 7 | 8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 9 | ) 10 | 11 | set(PLUGIN_BUNDLED_LIBRARIES) 12 | 13 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 18 | endforeach(plugin) 19 | 20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 23 | endforeach(ffi_plugin) 24 | -------------------------------------------------------------------------------- /linux/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} 10 | "main.cc" 11 | "my_application.cc" 12 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 13 | ) 14 | 15 | # Apply the standard set of build settings. This can be removed for applications 16 | # that need different build settings. 17 | apply_standard_settings(${BINARY_NAME}) 18 | 19 | # Add preprocessor definitions for the application ID. 20 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") 21 | 22 | # Add dependency libraries. Add any application-specific dependencies here. 23 | target_link_libraries(${BINARY_NAME} PRIVATE flutter) 24 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) 25 | 26 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 27 | -------------------------------------------------------------------------------- /linux/runner/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /linux/runner/my_application.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | #include 4 | #ifdef GDK_WINDOWING_X11 5 | #include 6 | #endif 7 | 8 | #include "flutter/generated_plugin_registrant.h" 9 | 10 | struct _MyApplication { 11 | GtkApplication parent_instance; 12 | char** dart_entrypoint_arguments; 13 | }; 14 | 15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) 16 | 17 | // Implements GApplication::activate. 18 | static void my_application_activate(GApplication* application) { 19 | MyApplication* self = MY_APPLICATION(application); 20 | GtkWindow* window = 21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); 22 | 23 | // Use a header bar when running in GNOME as this is the common style used 24 | // by applications and is the setup most users will be using (e.g. Ubuntu 25 | // desktop). 26 | // If running on X and not using GNOME then just use a traditional title bar 27 | // in case the window manager does more exotic layout, e.g. tiling. 28 | // If running on Wayland assume the header bar will work (may need changing 29 | // if future cases occur). 30 | gboolean use_header_bar = TRUE; 31 | #ifdef GDK_WINDOWING_X11 32 | GdkScreen* screen = gtk_window_get_screen(window); 33 | if (GDK_IS_X11_SCREEN(screen)) { 34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); 35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) { 36 | use_header_bar = FALSE; 37 | } 38 | } 39 | #endif 40 | if (use_header_bar) { 41 | GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); 42 | gtk_widget_show(GTK_WIDGET(header_bar)); 43 | gtk_header_bar_set_title(header_bar, "Font Gallery"); 44 | gtk_header_bar_set_show_close_button(header_bar, TRUE); 45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); 46 | } else { 47 | gtk_window_set_title(window, "Font Gallery"); 48 | } 49 | 50 | gtk_window_set_default_size(window, 1280, 720); 51 | gtk_widget_show(GTK_WIDGET(window)); 52 | 53 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 54 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 55 | 56 | FlView* view = fl_view_new(project); 57 | gtk_widget_show(GTK_WIDGET(view)); 58 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 59 | 60 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 61 | 62 | gtk_widget_grab_focus(GTK_WIDGET(view)); 63 | } 64 | 65 | // Implements GApplication::local_command_line. 66 | static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { 67 | MyApplication* self = MY_APPLICATION(application); 68 | // Strip out the first argument as it is the binary name. 69 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); 70 | 71 | g_autoptr(GError) error = nullptr; 72 | if (!g_application_register(application, nullptr, &error)) { 73 | g_warning("Failed to register: %s", error->message); 74 | *exit_status = 1; 75 | return TRUE; 76 | } 77 | 78 | g_application_activate(application); 79 | *exit_status = 0; 80 | 81 | return TRUE; 82 | } 83 | 84 | // Implements GApplication::startup. 85 | static void my_application_startup(GApplication* application) { 86 | //MyApplication* self = MY_APPLICATION(object); 87 | 88 | // Perform any actions required at application startup. 89 | 90 | G_APPLICATION_CLASS(my_application_parent_class)->startup(application); 91 | } 92 | 93 | // Implements GApplication::shutdown. 94 | static void my_application_shutdown(GApplication* application) { 95 | //MyApplication* self = MY_APPLICATION(object); 96 | 97 | // Perform any actions required at application shutdown. 98 | 99 | G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); 100 | } 101 | 102 | // Implements GObject::dispose. 103 | static void my_application_dispose(GObject* object) { 104 | MyApplication* self = MY_APPLICATION(object); 105 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); 106 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object); 107 | } 108 | 109 | static void my_application_class_init(MyApplicationClass* klass) { 110 | G_APPLICATION_CLASS(klass)->activate = my_application_activate; 111 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; 112 | G_APPLICATION_CLASS(klass)->startup = my_application_startup; 113 | G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; 114 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose; 115 | } 116 | 117 | static void my_application_init(MyApplication* self) {} 118 | 119 | MyApplication* my_application_new() { 120 | // Set the program name to the application ID, which helps various systems 121 | // like GTK and desktop environments map this running application to its 122 | // corresponding .desktop file. This ensures better integration by allowing 123 | // the application to be recognized beyond its binary name. 124 | g_set_prgname(APPLICATION_ID); 125 | 126 | return MY_APPLICATION(g_object_new(my_application_get_type(), 127 | "application-id", APPLICATION_ID, 128 | "flags", G_APPLICATION_NON_UNIQUE, 129 | nullptr)); 130 | } 131 | -------------------------------------------------------------------------------- /linux/runner/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import path_provider_foundation 9 | import shared_preferences_foundation 10 | 11 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 12 | PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) 13 | SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) 14 | } 15 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 64 | 66 | 72 | 73 | 74 | 75 | 81 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @main 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | 10 | override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { 11 | return true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = font_gallery 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.adeeteya.fontGallery 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2025 com.adeeteya. All rights reserved. 15 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /privacy-policy.md: -------------------------------------------------------------------------------- 1 | **Privacy Policy** 2 | 3 | Aditya R built the Font Gallery app as an Open Source app. This SERVICE is provided by Aditya R at no cost and is intended for use as is. 4 | 5 | This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service. 6 | 7 | If you choose to use my Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that I collect is used for providing and improving the Service. I will not use or share your information with anyone except as described in this Privacy Policy. 8 | 9 | The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which are accessible at Font Gallery unless otherwise defined in this Privacy Policy. 10 | 11 | **Information Collection and Use** 12 | 13 | For a better experience, while using our Service, I may require you to provide us with certain personally identifiable information. The information that I request will be retained on your device and is not collected by me in any way. 14 | 15 | The app does use third-party services that may collect information used to identify you. 16 | 17 | Link to the privacy policy of third-party service providers used by the app 18 | 19 | * [Google Play Services](https://www.google.com/policies/privacy/) 20 | 21 | **Log Data** 22 | 23 | I want to inform you that whenever you use my Service, in a case of an error in the app I collect data and information (through third-party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics. 24 | 25 | **Cookies** 26 | 27 | Cookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory. 28 | 29 | This Service does not use these “cookies” explicitly. However, the app may use third-party code and libraries that use “cookies” to collect information and improve their services. You have the option to either accept or refuse these cookies and know when a cookie is being sent to your device. If you choose to refuse our cookies, you may not be able to use some portions of this Service. 30 | 31 | **Service Providers** 32 | 33 | I may employ third-party companies and individuals due to the following reasons: 34 | 35 | * To facilitate our Service; 36 | * To provide the Service on our behalf; 37 | * To perform Service-related services; or 38 | * To assist us in analyzing how our Service is used. 39 | 40 | I want to inform users of this Service that these third parties have access to their Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose. 41 | 42 | **Security** 43 | 44 | I value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and I cannot guarantee its absolute security. 45 | 46 | **Links to Other Sites** 47 | 48 | This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by me. Therefore, I strongly advise you to review the Privacy Policy of these websites. I have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services. 49 | 50 | **Children’s Privacy** 51 | 52 | These Services do not address anyone under the age of 13. I do not knowingly collect personally identifiable information from children under 13 years of age. In the case I discover that a child under 13 has provided me with personal information, I immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact me so that I will be able to do the necessary actions. 53 | 54 | **Changes to This Privacy Policy** 55 | 56 | I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page. 57 | 58 | This policy is effective as of 2023-01-01 59 | 60 | **Contact Us** 61 | 62 | If you have any questions or suggestions about my Privacy Policy, do not hesitate to contact me at lightningbolt340@gmail.com. 63 | 64 | This privacy policy page was created at [privacypolicytemplate.net](https://privacypolicytemplate.net) and modified/generated by [App Privacy Policy Generator](https://app-privacy-policy-generator.nisrulz.com/) -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: font_gallery 2 | description: An app which showcases the different fonts 3 | publish_to: 'none' 4 | version: 1.3.0+7 5 | 6 | environment: 7 | sdk: ^3.7.0 8 | flutter: 3.29.3 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | flutter_riverpod: ^2.6.1 14 | google_fonts: ^6.2.1 15 | lottie: ^3.3.1 16 | shared_preferences: ^2.5.3 17 | 18 | dev_dependencies: 19 | flutter_lints: ^5.0.0 20 | flutter_test: 21 | sdk: flutter 22 | 23 | flutter: 24 | uses-material-design: true 25 | assets: 26 | - assets/ -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | All Submissions: 2 | 3 | * [ ] Have you followed the guidelines in our Contributing document? 4 | * [ ] Have you checked to ensure there aren't other open [Pull Requests](www.github.com/adeeteya/FontGallery/pulls) for the same update/change? 5 | 6 | 7 | 8 | ### New Feature Submissions: 9 | 10 | 1. [ ] Does your submission work for all the platforms? 11 | 2. [ ] Have you lint your code locally before submission? (using flutter_lints package) 12 | 13 | ### Changes to Core Features: 14 | 15 | * [ ] Have you added an explanation of what your changes do and why you'd like us to include them? 16 | * [ ] Have you added the feature to the features column of ```readme.md``` ? -------------------------------------------------------------------------------- /screenshots/app_screenshot_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/screenshots/app_screenshot_1.jpg -------------------------------------------------------------------------------- /screenshots/app_screenshot_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/screenshots/app_screenshot_2.jpg -------------------------------------------------------------------------------- /screenshots/app_screenshot_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/screenshots/app_screenshot_3.jpg -------------------------------------------------------------------------------- /screenshots/app_screenshot_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/screenshots/app_screenshot_4.jpg -------------------------------------------------------------------------------- /screenshots/app_screenshot_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/screenshots/app_screenshot_5.jpg -------------------------------------------------------------------------------- /screenshots/app_screenshot_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/screenshots/app_screenshot_6.jpg -------------------------------------------------------------------------------- /scripts/windows-setup.iss: -------------------------------------------------------------------------------- 1 | #define MyAppName "Font Gallery" 2 | #define MyAppPublisher "Adeeteya" 3 | #define MyAppPublisherURL "https://github.com/adeeteya/" 4 | #define MyAppURL "https://github.com/adeeteya/FontGallery" 5 | #define MyAppExeName "font_gallery.exe" 6 | #define MyAppContact "adeeteya@gmail.com" 7 | #define MyAppCopyright "Copyright (C) 2023 Adeeteya" 8 | 9 | [Setup] 10 | ; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. 11 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 12 | AppId={{34B5DDF1-B8AD-469A-8B13-BD18C05565BE} 13 | AppName={#MyAppName} 14 | AppVersion={#MyAppVersion} 15 | AppVerName={#MyAppName} {#MyAppVersion} 16 | AppPublisher={#MyAppPublisher} 17 | AppPublisherURL={#MyAppPublisherURL} 18 | AppSupportURL={#MyAppURL} 19 | AppReadmeFile={#MyAppURL}/README.md 20 | AppUpdatesURL={#MyAppURL}/releases/latest 21 | AppComments={#MyAppName} 22 | AppContact={#MyAppContact} 23 | AppCopyright={#MyAppCopyright} 24 | DefaultDirName={autopf}\{#MyAppName} 25 | DisableProgramGroupPage=yes 26 | OutputDir=D:\a\FontGallery\FontGallery\ 27 | OutputBaseFilename=FontGallery-Windows 28 | SetupIconFile=D:\a\FontGallery\FontGallery\windows\runner\resources\app_icon.ico 29 | Compression=lzma 30 | SolidCompression=yes 31 | WizardStyle=modern 32 | VersionInfoProductName={#MyAppName} 33 | VersionInfoDescription={#MyAppName} Setup 34 | VersionInfoCompany={#MyAppPublisher} 35 | VersionInfoVersion={#MyAppVersion}.0 36 | VersionInfoProductTextVersion={#MyAppVersion} 37 | VersionInfoCopyright={#MyAppCopyright} 38 | UninstallDisplayIcon={app}\{#MyAppExeName} 39 | UninstallDisplayName={#MyAppName} 40 | 41 | [Languages] 42 | Name: "english"; MessagesFile: "compiler:Default.isl" 43 | 44 | [Tasks] 45 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked 46 | 47 | [Files] 48 | Source: "D:\a\FontGallery\FontGallery\build\windows\x64\runner\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs 49 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files 50 | 51 | [Icons] 52 | Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" 53 | Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon 54 | Name: "{app}\Uninstall {#MyAppName}"; Filename: "{uninstallexe}" 55 | 56 | [Run] 57 | Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent 58 | -------------------------------------------------------------------------------- /snap/gui/font-gallery.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.3.0 3 | Name=Font Gallery 4 | Comment=An app which showcases and compares different fonts 5 | Exec=font-gallery 6 | Icon=${SNAP}/meta/gui/font-gallery.png 7 | Terminal=false 8 | Type=Application 9 | Categories=Utility;Application; -------------------------------------------------------------------------------- /snap/gui/font-gallery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/snap/gui/font-gallery.png -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: font-gallery 2 | version: 1.3.0 3 | summary: An app which showcases and compares different fonts 4 | description: Font Gallery app showcases how different Font Families with their different variations (Style, Weight and Size) look. You could switch between light and dark modes and also compare different font families. There's a handy search feature to easily search for your favorite fonts and the text to compare the font's could also be changed to a custom user set text. 5 | icon: snap/gui/font-gallery.png 6 | contact: mailto:adeeteya@gmail.com 7 | source-code: https://github.com/adeeteya/FontGallery 8 | issues: https://github.com/adeeteya/FontGallery/issues 9 | license: MIT 10 | 11 | confinement: strict 12 | base: core22 13 | grade: stable 14 | 15 | slots: 16 | font-gallery: 17 | interface: dbus 18 | bus: session 19 | name: com.adeeteya.font_gallery 20 | 21 | apps: 22 | font-gallery: 23 | command: font_gallery 24 | extensions: [gnome] 25 | plugs: 26 | - network 27 | - desktop 28 | - home 29 | slots: 30 | - font-gallery 31 | parts: 32 | font-gallery: 33 | source: . 34 | plugin: flutter 35 | flutter-target: lib/main.dart 36 | -------------------------------------------------------------------------------- /terms-and-conditions.md: -------------------------------------------------------------------------------- 1 | **Terms & Conditions** 2 | 3 | By downloading or using the app, these terms will automatically apply to you – you should make sure therefore that you read them carefully before using the app. You’re not allowed to copy or modify the app, any part of the app, or our trademarks in any way. You’re not allowed to attempt to extract the source code of the app, and you also shouldn’t try to translate the app into other languages or make derivative versions. The app itself, and all the trademarks, copyright, database rights, and other intellectual property rights related to it, still belong to Aditya R. 4 | 5 | Aditya R is committed to ensuring that the app is as useful and efficient as possible. For that reason, we reserve the right to make changes to the app or to charge for its services, at any time and for any reason. We will never charge you for the app or its services without making it very clear to you exactly what you’re paying for. 6 | 7 | The Font Gallery app stores and processes personal data that you have provided to us, to provide my Service. It’s your responsibility to keep your phone and access to the app secure. We therefore recommend that you do not jailbreak or root your phone, which is the process of removing software restrictions and limitations imposed by the official operating system of your device. It could make your phone vulnerable to malware/viruses/malicious programs, compromise your phone’s security features and it could mean that the Font Gallery app won’t work properly or at all. 8 | 9 | The app does use third-party services that declare their Terms and Conditions. 10 | 11 | Link to Terms and Conditions of third-party service providers used by the app 12 | 13 | * [Google Play Services](https://policies.google.com/terms) 14 | 15 | You should be aware that there are certain things that Aditya R will not take responsibility for. Certain functions of the app will require the app to have an active internet connection. The connection can be Wi-Fi or provided by your mobile network provider, but Aditya R cannot take responsibility for the app not working at full functionality if you don’t have access to Wi-Fi, and you don’t have any of your data allowance left. 16 | 17 | If you’re using the app outside of an area with Wi-Fi, you should remember that the terms of the agreement with your mobile network provider will still apply. As a result, you may be charged by your mobile provider for the cost of data for the duration of the connection while accessing the app, or other third-party charges. In using the app, you’re accepting responsibility for any such charges, including roaming data charges if you use the app outside of your home territory (i.e. region or country) without turning off data roaming. If you are not the bill payer for the device on which you’re using the app, please be aware that we assume that you have received permission from the bill payer for using the app. 18 | 19 | Along the same lines, Aditya R cannot always take responsibility for the way you use the app i.e. You need to make sure that your device stays charged – if it runs out of battery and you can’t turn it on to avail the Service, Aditya R cannot accept responsibility. 20 | 21 | With respect to Aditya R’s responsibility for your use of the app, when you’re using the app, it’s important to bear in mind that although we endeavor to ensure that it is updated and correct at all times, we do rely on third parties to provide information to us so that we can make it available to you. Aditya R accepts no liability for any loss, direct or indirect, you experience as a result of relying wholly on this functionality of the app. 22 | 23 | At some point, we may wish to update the app. The app is currently available on Android & iOS – the requirements for the both systems(and for any additional systems we decide to extend the availability of the app to) may change, and you’ll need to download the updates if you want to keep using the app. Aditya R does not promise that it will always update the app so that it is relevant to you and/or works with the Android & iOS version that you have installed on your device. However, you promise to always accept updates to the application when offered to you, We may also wish to stop providing the app, and may terminate use of it at any time without giving notice of termination to you. Unless we tell you otherwise, upon any termination, (a) the rights and licenses granted to you in these terms will end; (b) you must stop using the app, and (if needed) delete it from your device. 24 | 25 | **Changes to This Terms and Conditions** 26 | 27 | I may update our Terms and Conditions from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Terms and Conditions on this page. 28 | 29 | These terms and conditions are effective as of 2023-01-01 30 | 31 | **Contact Us** 32 | 33 | If you have any questions or suggestions about my Terms and Conditions, do not hesitate to contact me at adeeteya@gmail.com. 34 | 35 | This Terms and Conditions page was generated by [App Privacy Policy Generator](https://app-privacy-policy-generator.nisrulz.com/) -------------------------------------------------------------------------------- /web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/web/favicon.ico -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/web/icons/Icon-512.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Font Gallery 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Font Gallery", 3 | "short_name": "Font Gallery", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#FFFFFF", 7 | "theme_color": "#FFFFFF", 8 | "description": "An app which showcases the different fonts", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.14) 3 | project(font_gallery LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "font_gallery") 8 | 9 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 10 | # versions of CMake. 11 | cmake_policy(SET CMP0063 NEW) 12 | 13 | # Define build configuration option. 14 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 15 | if(IS_MULTICONFIG) 16 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" 17 | CACHE STRING "" FORCE) 18 | else() 19 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 20 | set(CMAKE_BUILD_TYPE "Debug" CACHE 21 | STRING "Flutter build mode" FORCE) 22 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 23 | "Debug" "Profile" "Release") 24 | endif() 25 | endif() 26 | # Define settings for the Profile build mode. 27 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 28 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") 29 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") 30 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 31 | 32 | # Use Unicode for all projects. 33 | add_definitions(-DUNICODE -D_UNICODE) 34 | 35 | # Compilation settings that should be applied to most targets. 36 | # 37 | # Be cautious about adding new options here, as plugins use this function by 38 | # default. In most cases, you should add new options to specific targets instead 39 | # of modifying this function. 40 | function(APPLY_STANDARD_SETTINGS TARGET) 41 | target_compile_features(${TARGET} PUBLIC cxx_std_17) 42 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") 43 | target_compile_options(${TARGET} PRIVATE /EHsc) 44 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") 45 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") 46 | endfunction() 47 | 48 | # Flutter library and tool build rules. 49 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 50 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 51 | 52 | # Application build; see runner/CMakeLists.txt. 53 | add_subdirectory("runner") 54 | 55 | # Generated plugin build rules, which manage building the plugins and adding 56 | # them to the application. 57 | include(flutter/generated_plugins.cmake) 58 | 59 | 60 | # === Installation === 61 | # Support files are copied into place next to the executable, so that it can 62 | # run in place. This is done instead of making a separate bundle (as on Linux) 63 | # so that building and running from within Visual Studio will work. 64 | set(BUILD_BUNDLE_DIR "$") 65 | # Make the "install" step default, as it's required to run. 66 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) 67 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 68 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 69 | endif() 70 | 71 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 72 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") 73 | 74 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 75 | COMPONENT Runtime) 76 | 77 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 78 | COMPONENT Runtime) 79 | 80 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 81 | COMPONENT Runtime) 82 | 83 | if(PLUGIN_BUNDLED_LIBRARIES) 84 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 85 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 86 | COMPONENT Runtime) 87 | endif() 88 | 89 | # Fully re-copy the assets directory on each build to avoid having stale files 90 | # from a previous install. 91 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 92 | install(CODE " 93 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 94 | " COMPONENT Runtime) 95 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 96 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 97 | 98 | # Install the AOT library on non-Debug builds only. 99 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 100 | CONFIGURATIONS Profile;Release 101 | COMPONENT Runtime) 102 | -------------------------------------------------------------------------------- /windows/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.14) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") 12 | 13 | # Set fallback configurations for older versions of the flutter tool. 14 | if (NOT DEFINED FLUTTER_TARGET_PLATFORM) 15 | set(FLUTTER_TARGET_PLATFORM "windows-x64") 16 | endif() 17 | 18 | # === Flutter Library === 19 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") 20 | 21 | # Published to parent scope for install step. 22 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 23 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 24 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 25 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) 26 | 27 | list(APPEND FLUTTER_LIBRARY_HEADERS 28 | "flutter_export.h" 29 | "flutter_windows.h" 30 | "flutter_messenger.h" 31 | "flutter_plugin_registrar.h" 32 | "flutter_texture_registrar.h" 33 | ) 34 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") 35 | add_library(flutter INTERFACE) 36 | target_include_directories(flutter INTERFACE 37 | "${EPHEMERAL_DIR}" 38 | ) 39 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") 40 | add_dependencies(flutter flutter_assemble) 41 | 42 | # === Wrapper === 43 | list(APPEND CPP_WRAPPER_SOURCES_CORE 44 | "core_implementations.cc" 45 | "standard_codec.cc" 46 | ) 47 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") 48 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN 49 | "plugin_registrar.cc" 50 | ) 51 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") 52 | list(APPEND CPP_WRAPPER_SOURCES_APP 53 | "flutter_engine.cc" 54 | "flutter_view_controller.cc" 55 | ) 56 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") 57 | 58 | # Wrapper sources needed for a plugin. 59 | add_library(flutter_wrapper_plugin STATIC 60 | ${CPP_WRAPPER_SOURCES_CORE} 61 | ${CPP_WRAPPER_SOURCES_PLUGIN} 62 | ) 63 | apply_standard_settings(flutter_wrapper_plugin) 64 | set_target_properties(flutter_wrapper_plugin PROPERTIES 65 | POSITION_INDEPENDENT_CODE ON) 66 | set_target_properties(flutter_wrapper_plugin PROPERTIES 67 | CXX_VISIBILITY_PRESET hidden) 68 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) 69 | target_include_directories(flutter_wrapper_plugin PUBLIC 70 | "${WRAPPER_ROOT}/include" 71 | ) 72 | add_dependencies(flutter_wrapper_plugin flutter_assemble) 73 | 74 | # Wrapper sources needed for the runner. 75 | add_library(flutter_wrapper_app STATIC 76 | ${CPP_WRAPPER_SOURCES_CORE} 77 | ${CPP_WRAPPER_SOURCES_APP} 78 | ) 79 | apply_standard_settings(flutter_wrapper_app) 80 | target_link_libraries(flutter_wrapper_app PUBLIC flutter) 81 | target_include_directories(flutter_wrapper_app PUBLIC 82 | "${WRAPPER_ROOT}/include" 83 | ) 84 | add_dependencies(flutter_wrapper_app flutter_assemble) 85 | 86 | # === Flutter tool backend === 87 | # _phony_ is a non-existent file to force this command to run every time, 88 | # since currently there's no way to get a full input/output list from the 89 | # flutter tool. 90 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") 91 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) 92 | add_custom_command( 93 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 94 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} 95 | ${CPP_WRAPPER_SOURCES_APP} 96 | ${PHONY_OUTPUT} 97 | COMMAND ${CMAKE_COMMAND} -E env 98 | ${FLUTTER_TOOL_ENVIRONMENT} 99 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" 100 | ${FLUTTER_TARGET_PLATFORM} $ 101 | VERBATIM 102 | ) 103 | add_custom_target(flutter_assemble DEPENDS 104 | "${FLUTTER_LIBRARY}" 105 | ${FLUTTER_LIBRARY_HEADERS} 106 | ${CPP_WRAPPER_SOURCES_CORE} 107 | ${CPP_WRAPPER_SOURCES_PLUGIN} 108 | ${CPP_WRAPPER_SOURCES_APP} 109 | ) 110 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | 10 | void RegisterPlugins(flutter::PluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | ) 7 | 8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 9 | ) 10 | 11 | set(PLUGIN_BUNDLED_LIBRARIES) 12 | 13 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 18 | endforeach(plugin) 19 | 20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 23 | endforeach(ffi_plugin) 24 | -------------------------------------------------------------------------------- /windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} WIN32 10 | "flutter_window.cpp" 11 | "main.cpp" 12 | "utils.cpp" 13 | "win32_window.cpp" 14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 15 | "Runner.rc" 16 | "runner.exe.manifest" 17 | ) 18 | 19 | # Apply the standard set of build settings. This can be removed for applications 20 | # that need different build settings. 21 | apply_standard_settings(${BINARY_NAME}) 22 | 23 | # Add preprocessor definitions for the build version. 24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") 25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") 26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") 27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") 28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") 29 | 30 | # Disable Windows macros that collide with C++ standard library functions. 31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 32 | 33 | # Add dependency libraries and include directories. Add any application-specific 34 | # dependencies here. 35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 36 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 37 | 38 | # Run the Flutter tool portions of the build. This must not be removed. 39 | add_dependencies(${BINARY_NAME} flutter_assemble) 40 | -------------------------------------------------------------------------------- /windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) 64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0,0 67 | #endif 68 | 69 | #if defined(FLUTTER_VERSION) 70 | #define VERSION_AS_STRING FLUTTER_VERSION 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "com.adeeteya" "\0" 93 | VALUE "FileDescription", "font_gallery" "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "font_gallery" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2022 com.adeeteya. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "font_gallery.exe" "\0" 98 | VALUE "ProductName", "font_gallery" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project) 8 | : project_(project) {} 9 | 10 | FlutterWindow::~FlutterWindow() {} 11 | 12 | bool FlutterWindow::OnCreate() { 13 | if (!Win32Window::OnCreate()) { 14 | return false; 15 | } 16 | 17 | RECT frame = GetClientArea(); 18 | 19 | // The size here must match the window dimensions to avoid unnecessary surface 20 | // creation / destruction in the startup path. 21 | flutter_controller_ = std::make_unique( 22 | frame.right - frame.left, frame.bottom - frame.top, project_); 23 | // Ensure that basic setup of the controller was successful. 24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 25 | return false; 26 | } 27 | RegisterPlugins(flutter_controller_->engine()); 28 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 29 | return true; 30 | } 31 | 32 | void FlutterWindow::OnDestroy() { 33 | if (flutter_controller_) { 34 | flutter_controller_ = nullptr; 35 | } 36 | 37 | Win32Window::OnDestroy(); 38 | } 39 | 40 | LRESULT 41 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 42 | WPARAM const wparam, 43 | LPARAM const lparam) noexcept { 44 | // Give Flutter, including plugins, an opportunity to handle window messages. 45 | if (flutter_controller_) { 46 | std::optional result = 47 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 48 | lparam); 49 | if (result) { 50 | return *result; 51 | } 52 | } 53 | 54 | switch (message) { 55 | case WM_FONTCHANGE: 56 | flutter_controller_->engine()->ReloadSystemFonts(); 57 | break; 58 | } 59 | 60 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 61 | } 62 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.CreateAndShow(L"Font Gallery", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeeteya/FontGallery/03fcfb1aa0a03a09e303b78c75febf3948f366b5/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr); 51 | std::string utf8_string; 52 | if (target_length == 0 || target_length > utf8_string.max_size()) { 53 | return utf8_string; 54 | } 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | -------------------------------------------------------------------------------- /windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_WIN32_WINDOW_H_ 2 | #define RUNNER_WIN32_WINDOW_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 11 | // inherited from by classes that wish to specialize with custom 12 | // rendering and input handling 13 | class Win32Window { 14 | public: 15 | struct Point { 16 | unsigned int x; 17 | unsigned int y; 18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 19 | }; 20 | 21 | struct Size { 22 | unsigned int width; 23 | unsigned int height; 24 | Size(unsigned int width, unsigned int height) 25 | : width(width), height(height) {} 26 | }; 27 | 28 | Win32Window(); 29 | virtual ~Win32Window(); 30 | 31 | // Creates and shows a win32 window with |title| and position and size using 32 | // |origin| and |size|. New windows are created on the default monitor. Window 33 | // sizes are specified to the OS in physical pixels, hence to ensure a 34 | // consistent size to will treat the width height passed in to this function 35 | // as logical pixels and scale to appropriate for the default monitor. Returns 36 | // true if the window was created successfully. 37 | bool CreateAndShow(const std::wstring& title, 38 | const Point& origin, 39 | const Size& size); 40 | 41 | // Release OS resources associated with window. 42 | void Destroy(); 43 | 44 | // Inserts |content| into the window tree. 45 | void SetChildContent(HWND content); 46 | 47 | // Returns the backing Window handle to enable clients to set icon and other 48 | // window properties. Returns nullptr if the window has been destroyed. 49 | HWND GetHandle(); 50 | 51 | // If true, closing this window will quit the application. 52 | void SetQuitOnClose(bool quit_on_close); 53 | 54 | // Return a RECT representing the bounds of the current client area. 55 | RECT GetClientArea(); 56 | 57 | protected: 58 | // Processes and route salient window messages for mouse handling, 59 | // size change and DPI. Delegates handling of these to member overloads that 60 | // inheriting classes can handle. 61 | virtual LRESULT MessageHandler(HWND window, 62 | UINT const message, 63 | WPARAM const wparam, 64 | LPARAM const lparam) noexcept; 65 | 66 | // Called when CreateAndShow is called, allowing subclass window-related 67 | // setup. Subclasses should return false if setup fails. 68 | virtual bool OnCreate(); 69 | 70 | // Called when Destroy is called. 71 | virtual void OnDestroy(); 72 | 73 | private: 74 | friend class WindowClassRegistrar; 75 | 76 | // OS callback called by message pump. Handles the WM_NCCREATE message which 77 | // is passed when the non-client area is being created and enables automatic 78 | // non-client DPI scaling so that the non-client area automatically 79 | // responsponds to changes in DPI. All other messages are handled by 80 | // MessageHandler. 81 | static LRESULT CALLBACK WndProc(HWND const window, 82 | UINT const message, 83 | WPARAM const wparam, 84 | LPARAM const lparam) noexcept; 85 | 86 | // Retrieves a class instance pointer for |window| 87 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 88 | 89 | bool quit_on_close_ = false; 90 | 91 | // window handle for top level window. 92 | HWND window_handle_ = nullptr; 93 | 94 | // window handle for hosted content. 95 | HWND child_content_ = nullptr; 96 | }; 97 | 98 | #endif // RUNNER_WIN32_WINDOW_H_ 99 | --------------------------------------------------------------------------------