Full Code of wgh136/pixes for AI

master abf249b941dd cached
173 files
679.3 KB
166.0k tokens
932 symbols
1 requests
Download .txt
Showing preview only (735K chars total). Download the full file or copy to clipboard to get everything.
Repository: wgh136/pixes
Branch: master
Commit: abf249b941dd
Files: 173
Total size: 679.3 KB

Directory structure:
gitextract_i0cj6x04/

├── .github/
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .metadata
├── .vscode/
│   └── settings.json
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android/
│   ├── .gitignore
│   ├── app/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── debug/
│   │       │   └── AndroidManifest.xml
│   │       ├── main/
│   │       │   ├── AndroidManifest.xml
│   │       │   ├── kotlin/
│   │       │   │   └── com/
│   │       │   │       └── github/
│   │       │   │           └── wgh136/
│   │       │   │               └── pixes/
│   │       │   │                   └── MainActivity.kt
│   │       │   └── res/
│   │       │       ├── drawable/
│   │       │       │   └── launch_background.xml
│   │       │       ├── drawable-v21/
│   │       │       │   └── launch_background.xml
│   │       │       ├── mipmap-anydpi-v26/
│   │       │       │   └── ic_launcher.xml
│   │       │       ├── values/
│   │       │       │   └── styles.xml
│   │       │       └── values-night/
│   │       │           └── styles.xml
│   │       └── profile/
│   │           └── AndroidManifest.xml
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       └── gradle-wrapper.properties
│   ├── gradle.properties
│   └── settings.gradle
├── assets/
│   └── tr.json
├── debian/
│   ├── build.py
│   ├── debian.yaml
│   └── gui/
│       └── pixes.desktop
├── ios/
│   ├── .gitignore
│   ├── Flutter/
│   │   ├── AppFrameworkInfo.plist
│   │   ├── Debug.xcconfig
│   │   └── Release.xcconfig
│   ├── Podfile
│   ├── Runner/
│   │   ├── AppDelegate.swift
│   │   ├── Assets.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   └── LaunchImage.imageset/
│   │   │       ├── Contents.json
│   │   │       └── README.md
│   │   ├── Base.lproj/
│   │   │   ├── LaunchScreen.storyboard
│   │   │   └── Main.storyboard
│   │   ├── Info.plist
│   │   └── Runner-Bridging-Header.h
│   ├── 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
│   └── RunnerTests/
│       └── RunnerTests.swift
├── lib/
│   ├── appdata.dart
│   ├── components/
│   │   ├── animated_image.dart
│   │   ├── batch_download.dart
│   │   ├── button.dart
│   │   ├── grid.dart
│   │   ├── illust_widget.dart
│   │   ├── keyboard.dart
│   │   ├── loading.dart
│   │   ├── md.dart
│   │   ├── message.dart
│   │   ├── novel.dart
│   │   ├── page_route.dart
│   │   ├── search_field.dart
│   │   ├── segmented_button.dart
│   │   ├── title_bar.dart
│   │   ├── ugoira.dart
│   │   └── user_preview.dart
│   ├── foundation/
│   │   ├── app.dart
│   │   ├── cache_manager.dart
│   │   ├── history.dart
│   │   ├── image_provider.dart
│   │   ├── log.dart
│   │   ├── navigation.dart
│   │   ├── pair.dart
│   │   ├── state_controller.dart
│   │   └── widget_utils.dart
│   ├── main.dart
│   ├── network/
│   │   ├── app_dio.dart
│   │   ├── download.dart
│   │   ├── models.dart
│   │   ├── network.dart
│   │   ├── novel.dart
│   │   ├── res.dart
│   │   └── translator.dart
│   ├── pages/
│   │   ├── bookmarks.dart
│   │   ├── comments_page.dart
│   │   ├── downloaded_page.dart
│   │   ├── downloading_page.dart
│   │   ├── following_artworks.dart
│   │   ├── following_novels_page.dart
│   │   ├── following_users_page.dart
│   │   ├── history.dart
│   │   ├── illust_page.dart
│   │   ├── image_page.dart
│   │   ├── login_page.dart
│   │   ├── logs.dart
│   │   ├── main_page.dart
│   │   ├── novel_bookmarks_page.dart
│   │   ├── novel_page.dart
│   │   ├── novel_ranking_page.dart
│   │   ├── novel_reading_page.dart
│   │   ├── novel_recommendation_page.dart
│   │   ├── ranking.dart
│   │   ├── recommendation_page.dart
│   │   ├── related_page.dart
│   │   ├── search_page.dart
│   │   ├── settings_page.dart
│   │   ├── user_info_page.dart
│   │   └── webview_page.dart
│   └── utils/
│       ├── app_links.dart
│       ├── block.dart
│       ├── debounce.dart
│       ├── debug.dart
│       ├── ext.dart
│       ├── io.dart
│       ├── loop.dart
│       ├── mouse_listener.dart
│       ├── translation.dart
│       ├── update.dart
│       └── window.dart
├── linux/
│   ├── .gitignore
│   ├── CMakeLists.txt
│   ├── flutter/
│   │   ├── CMakeLists.txt
│   │   ├── generated_plugin_registrant.cc
│   │   ├── generated_plugin_registrant.h
│   │   └── generated_plugins.cmake
│   ├── main.cc
│   ├── my_application.cc
│   └── my_application.h
├── macos/
│   ├── .gitignore
│   ├── Flutter/
│   │   ├── Flutter-Debug.xcconfig
│   │   ├── Flutter-Release.xcconfig
│   │   └── GeneratedPluginRegistrant.swift
│   ├── Podfile
│   ├── Runner/
│   │   ├── AppDelegate.swift
│   │   ├── Assets.xcassets/
│   │   │   └── AppIcon.appiconset/
│   │   │       └── Contents.json
│   │   ├── Base.lproj/
│   │   │   └── MainMenu.xib
│   │   ├── Configs/
│   │   │   ├── AppInfo.xcconfig
│   │   │   ├── Debug.xcconfig
│   │   │   ├── Release.xcconfig
│   │   │   └── Warnings.xcconfig
│   │   ├── DebugProfile.entitlements
│   │   ├── Info.plist
│   │   ├── MainFlutterWindow.swift
│   │   └── Release.entitlements
│   ├── Runner.xcodeproj/
│   │   ├── project.pbxproj
│   │   ├── project.xcworkspace/
│   │   │   └── xcshareddata/
│   │   │       └── IDEWorkspaceChecks.plist
│   │   └── xcshareddata/
│   │       └── xcschemes/
│   │           └── Runner.xcscheme
│   ├── Runner.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcshareddata/
│   │       └── IDEWorkspaceChecks.plist
│   └── RunnerTests/
│       └── RunnerTests.swift
├── pubspec.yaml
├── test/
│   └── widget_test.dart
└── windows/
    ├── .gitignore
    ├── CMakeLists.txt
    ├── build.iss
    ├── build.py
    ├── flutter/
    │   ├── CMakeLists.txt
    │   ├── generated_plugin_registrant.cc
    │   ├── generated_plugin_registrant.h
    │   └── generated_plugins.cmake
    └── runner/
        ├── CMakeLists.txt
        ├── RCa14464
        ├── RCa18972
        ├── Runner.aps
        ├── Runner.rc
        ├── flutter_window.cpp
        ├── flutter_window.h
        ├── main.cpp
        ├── resource.h
        ├── runner.exe.manifest
        ├── utils.cpp
        ├── utils.h
        ├── win32_window.cpp
        └── win32_window.h

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/main.yml
================================================
name: Build ALL
run-name: Build ALL
on:
  workflow_dispatch:
    inputs:
      # macOS build disabled: the macOS job frequently exceeds GitHub Actions' job time limit during Flutter builds.
      # build_macos:
      #   description: Build macOS
      #   type: boolean
      #   default: true
      build_ios:
        description: Build iOS
        type: boolean
        default: true
      build_android:
        description: Build Android
        type: boolean
        default: true
      build_windows:
        description: Build Windows
        type: boolean
        default: true
      build_linux:
        description: Build Linux (x64)
        type: boolean
        default: true
      build_linux_arm64:
        description: Build Linux (ARM64)
        type: boolean
        default: true
  release:
    types: [published]

jobs:
  # macOS build disabled: macOS builds on GitHub-hosted runners often hit the job timeout.
  # Build_MacOS:
  #   if: github.event_name == 'release' || github.event.inputs.build_macos == 'true'
  #   runs-on: macos-15
  #   steps:
  #     - uses: actions/checkout@v3
  #     - uses: subosito/flutter-action@v2
  #       with:
  #         channel: "stable"
  #         flutter-version-file: pubspec.yaml
  #     - run: sudo xcode-select --switch /Applications/Xcode_16.4.0.app
  #     - run: flutter pub get
  #       # Step 1: Decode and install the certificate
  #     - name: Decode and install certificate
  #       env:
  #         CERTIFICATE: ${{ secrets.CERTIFICATE }}
  #         CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
  #       run: |
  #         echo "$CERTIFICATE" | base64 --decode > signing_certificate.p12
  #         security import signing_certificate.p12 -k ~/Library/Keychains/login.keychain -P "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign
  #
  #     # Step 2: Build the Flutter macOS app
  #     - name: Build Flutter macOS App
  #       run: flutter build macos --release
  #
  #     # Step 3: Create the DMG file
  #     - name: Create DMG
  #       run: |
  #         mkdir -p dist
  #         mkdir -p dist/dmg_contents
  #         cp -R build/macos/Build/Products/Release/pixes.app dist/dmg_contents/
  #         ln -s /Applications dist/dmg_contents/Applications
  #         hdiutil create -volname "pixes" -srcfolder dist/dmg_contents -ov -format UDZO "dist/pixes.dmg"
  #
  #     - name: Add version to filename
  #       run: |
  #         APP_VERSION=$(grep "version:" pubspec.yaml | cut -d':' -f2 | tr -d ' ')
  #         mkdir -p result
  #         mv dist/pixes.dmg result/pixes-$APP_VERSION.dmg
  #
  #     # Step 4: Attach and upload artifacts (optional)
  #     - name: Upload DMG
  #       uses: actions/upload-artifact@v4
  #       with:
  #         name: macos_build
  #         path: result/
  Build_IOS:
    if: github.event_name == 'release' || github.event.inputs.build_ios == 'true'
    runs-on: macos-26
    steps:
      - uses: actions/checkout@v4
      - uses: subosito/flutter-action@v2
        with:
          channel: "stable"
          flutter-version-file: pubspec.yaml
      - run: sudo xcode-select --switch /Applications/Xcode_26.4.0.app
      - run: flutter pub get
      - run: flutter build ios --release --no-codesign
      - run: |
          mkdir -p /Users/runner/work/pixes/pixes/build/ios/iphoneos/Payload
          mv /Users/runner/work/pixes/pixes/build/ios/iphoneos/Runner.app /Users/runner/work/pixes/pixes/build/ios/iphoneos/Payload
          cd /Users/runner/work/pixes/pixes/build/ios/iphoneos/
          zip -r pixes-ios.ipa Payload
      - uses: actions/upload-artifact@v4
        with:
          name: app-ios.ipa
          path: /Users/runner/work/pixes/pixes/build/ios/iphoneos/pixes-ios.ipa
  Build_Android:
    if: github.event_name == 'release' || github.event.inputs.build_android == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: subosito/flutter-action@v2
        with:
          channel: "stable"
          flutter-version-file: pubspec.yaml
          architecture: x64
      - name: Decode and install certificate
        env:
          STORE_FILE: ${{ secrets.ANDROID_KEYSTORE }}
          PROPERTY_FILE: ${{ secrets.ANDROID_KEY_PROPERTIES }}
        run: |
          echo "$STORE_FILE" | base64 --decode > android/keystore.jks
          echo "$PROPERTY_FILE" > android/key.properties
      - uses: actions/setup-java@v4
        with:
          distribution: 'oracle'
          java-version: '17'
      - run: flutter pub get
      - run: flutter build apk --release
      - uses: actions/upload-artifact@v4
        with:
          name: apks
          path: build/app/outputs/apk/release
  Build_Windows:
    if: github.event_name == 'release' || github.event.inputs.build_windows == 'true'
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4
      - name: install dependencies
        run: |
          choco install yq -y
      - uses: subosito/flutter-action@v2
        with:
          channel: "stable"
          flutter-version-file: pubspec.yaml
          architecture: x64
      - name: Decode and install certificate
        shell: bash
        env:
          STORE_FILE: ${{ secrets.WINDOWS_KEYSTORE }}
        run: |
          echo "$STORE_FILE" | base64 --decode > windows/app.pfx
      - name: build
        env:
          CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_KEYSTORE_PASSWORD }}
        run: |
          flutter pub get
          dart run msix:create -p ${{ env.CERTIFICATE_PASSWORD }} --install-certificate false
      - uses: actions/upload-artifact@v4
        with:
          name: windows_build
          path: build/windows/x64/runner/Release/pixes.msix
  Build_Linux:
    if: github.event_name == 'release' || github.event.inputs.build_linux == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: subosito/flutter-action@v2
        with:
          channel: 'stable'
          flutter-version-file: pubspec.yaml
          architecture: x64
      - run: |
          sudo apt-get update -y
          sudo apt-get install -y ninja-build libgtk-3-dev webkit2gtk-4.1
          dart pub global activate flutter_to_debian
      - run: python3 debian/build.py x64
      - run: dart run flutter_to_arch
      - run: |
          sudo rm -rf build/linux/arch/app.tar.gz
          sudo rm -rf build/linux/arch/pkg
          sudo rm -rf build/linux/arch/src
          sudo rm -rf build/linux/arch/PKGBUILD
      - uses: actions/upload-artifact@v4
        with:
          name: deb_build
          path: build/linux/x64/release/debian
      - uses: actions/upload-artifact@v4
        with:
          name: arch_build
          path: build/linux/arch/
  Build_Linux_ARM64:
    if: github.event_name == 'release' || github.event.inputs.build_linux_arm64 == 'true'
    runs-on: ubuntu-22.04-arm
    steps:
      - uses: actions/checkout@v4
      - uses: subosito/flutter-action@v2
        with:
          channel: 'master'
          flutter-version-file: pubspec.yaml
      - run: |
          flutter pub get
          sudo apt-get update -y
          sudo apt-get install -y ninja-build libgtk-3-dev webkit2gtk-4.1
          dart pub global activate flutter_to_debian
      - run: python3 debian/build.py arm64
      - uses: actions/upload-artifact@v4
        with:
          name: deb_arm64_build
          path: build/linux/x64/release/debian # This is a bug related to flutter_to_debian, but it's not a big deal.
  Release:
    runs-on: ubuntu-latest
    needs: [Build_IOS, Build_Android, Build_Windows, Build_Linux, Build_Linux_ARM64]
    if: github.event_name == 'release'
    steps:
      # macOS artifact: disabled together with Build_MacOS (was macos.zip / DMG from that job).
      # - uses: actions/download-artifact@v4
      #   with:
      #     name: macos.zip
      #     path: outputs
      - uses: actions/download-artifact@v4
        with:
          name: app-ios.ipa
          path: outputs
      - uses: actions/download-artifact@v4
        with:
          name: apks
          path: outputs
      - uses: actions/download-artifact@v4
        with:
          name: windows_build
          path: outputs
      - uses: actions/download-artifact@v4
        with:
          name: deb_build
          path: outputs
      - uses: actions/download-artifact@v4
        with:
          name: arch_build
          path: outputs
      - uses: actions/download-artifact@v4
        with:
          name: deb_arm64_build
          path: outputs
      - name: Download public key
        run: wget https://nyne.dev/files/windows_app.cer
      - uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ github.ref_name }}
          files: |
            outputs/*.ipa
            outputs/*.dmg
            outputs/*.apk
            outputs/*.zip
            outputs/*.exe
            outputs/*.deb
            outputs/*.zst
            outputs/*.msix
            windows_app.cer
          token: ${{ secrets.ACTION_GITHUB_TOKEN }}


================================================
FILE: .gitignore
================================================
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

*.pfx

================================================
FILE: .metadata
================================================
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
  revision: "54e66469a933b60ddf175f858f82eaeb97e48c8d"
  channel: "stable"

project_type: app

# Tracks metadata for the flutter migrate command
migration:
  platforms:
    - platform: root
      create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
      base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
    - platform: android
      create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
      base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
    - platform: ios
      create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
      base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
    - platform: linux
      create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
      base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
    - platform: macos
      create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
      base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
    - platform: windows
      create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
      base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d

  # User provided section

  # List of Local paths (relative to this file) that should be
  # ignored by the migrate tool.
  #
  # Files that are not part of the templates will be ignored by default.
  unmanaged_files:
    - 'lib/main.dart'
    - 'ios/Runner.xcodeproj/project.pbxproj'


================================================
FILE: .vscode/settings.json
================================================
{
    "cSpell.words": [
        "appdata",
        "Bungo",
        "gjzr",
        "microtask",
        "mypixiv",
        "pawoo",
        "Rorigod",
        "sleepinglife",
        "Ugoira",
        "vocaloidhm",
        "vsync"
    ]
}

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2024 nyne

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# pixes

[![flutter](https://img.shields.io/badge/flutter-3.32.5-blue)](https://flutter.dev/) 
[![License](https://img.shields.io/github/license/wgh136/pixes)](https://github.com/wgh136/pixes/blob/master/LICENSE)
[![Download](https://img.shields.io/github/v/release/wgh136/pixes)](https://github.com/wgh136/pixes)
[![stars](https://img.shields.io/github/stars/wgh136/pixes)](https://github.com/wgh136/pixes/stargazers)

Unofficial Pixiv app, support Windows, Android, iOS, macOS, linux

All main features are implemented.

## Download

Download from [Release](https://github.com/wgh136/pixes/releases)

## Build from source

### Install Flutter

View [Flutter Document](https://flutter.dev/docs/get-started/install)

### Build Android

Put your keystore file (`key.jks`, `key.properties`) in `android/`

Run `flutter build apk`

### Build iOS/Windows/macOS

Run `flutter build ios/windows/macos`

### Build Linux

Use`python3 debian/build.py {ARCH}` to build deb package. Replace {ARCH} with `x64` or `arm64`.

For other linux distributions, you can use `flutter build linux` to build. 
You must register the `pixiv` scheme in the `.desktop` file, otherwise the login will not work.

## Screenshots

<img src="screenshots/1.png" style="width: 400px">
<img src="screenshots/2.png" style="width: 400px">
<img src="screenshots/3.png" style="width: 400px">
<img src="screenshots/4.png" style="width: 400px">


================================================
FILE: analysis_options.yaml
================================================
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

linter:
  # The lint rules applied to this project can be customized in the
  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
  # included above or to enable additional rules. A list of all available lints
  # and their documentation is published at https://dart.dev/lints.
  #
  # Instead of disabling a lint rule for the entire project in the
  # section below, it can also be suppressed for a single line of code
  # or a specific dart file by using the `// ignore: name_of_lint` and
  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
  # producing the lint.
  rules:
    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options


================================================
FILE: android/.gitignore
================================================
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks


================================================
FILE: android/app/build.gradle
================================================
plugins {
    id "com.android.application"
    id "kotlin-android"
    id "dev.flutter.flutter-gradle-plugin"
}

ext.abiCodes = ["armeabi-v7a": 1, "arm64-v8a": 2, "x86_64": 3]

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
   keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    namespace "com.github.wgh136.pixes"
    compileSdk flutter.compileSdkVersion
    ndkVersion flutter.ndkVersion

    packaging {
        jniLibs {
            useLegacyPackaging true
        }
    }

    splits{
        abi {
            reset()
            include 'armeabi-v7a', 'arm64-v8a', 'x86_64'
            enable true
            universalApk true
        }
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }
    kotlinOptions{
        jvmTarget = JavaVersion.VERSION_17
    }

    defaultConfig {
        applicationId "com.github.wgh136.pixes"
        // You can update the following values to match your application needs.
        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
        minSdkVersion flutter.minSdkVersion
        targetSdk = flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
            storePassword keystoreProperties['storePassword']
        }
        debug {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
            storePassword keystoreProperties['storePassword']
        }
    }

    buildTypes {
        release {
            ndk {
                abiFilters "armeabi-v7a", "arm64-v8a", "x86_64"
            }
            signingConfig signingConfigs.release
            applicationVariants.all { variant ->
                variant.outputs.all { output ->
                    def abi = output.getFilter(com.android.build.OutputFile.ABI)
                    if (abi != null) {
                        outputFileName = "pixes-${variant.versionName}-${abi}.apk"
                        def abiVersionCode = project.ext.abiCodes.get(abi)
                        if (abiVersionCode != null) {
                            versionCodeOverride = variant.versionCode * 10 + abiVersionCode
                        }
                    } else {
                        outputFileName = "pixes-${variant.versionName}.apk"
                        versionCodeOverride = variant.versionCode * 10
                    }
                }
            }
        }
    }
}

flutter {
    source '../..'
}

dependencies {}


================================================
FILE: android/app/src/debug/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- The INTERNET permission is required for development. Specifically,
         the Flutter tool needs it to communicate with the running application
         to allow setting breakpoints, to provide hot reload, etc.
    -->
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>


================================================
FILE: android/app/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <application
        android:label="pixes"
        android:name="${applicationName}"
        android:enableOnBackInvokedCallback="true"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter android:label="login">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- Accepts URIs that begin with "example://gizmos” -->
                <data android:scheme="pixiv"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="https" android:host="www.pixiv.net" android:pathPrefix="/users"/>
                <data android:scheme="https" android:host="www.pixiv.net" android:pathPrefix="/novel"/>
                <data android:scheme="https" android:host="www.pixiv.net" android:pathPrefix="/tags"/>
                <data android:scheme="https" android:host="www.pixiv.net" android:pathPrefix="/artworks"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
        <meta-data android:name="io.flutter.embedding.android.EnableImpeller" android:value="false"/>
    </application>
    <!-- Required to query activities that can process text, see:
         https://developer.android.com/training/package-visibility?hl=en and
         https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.

         In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
    <queries>
        <intent>
            <action android:name="android.intent.action.PROCESS_TEXT"/>
            <data android:mimeType="text/plain"/>
        </intent>
    </queries>
</manifest>


================================================
FILE: android/app/src/main/kotlin/com/github/wgh136/pixes/MainActivity.kt
================================================
package com.github.wgh136.pixes

import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugin.common.MethodChannel
import io.flutter.embedding.engine.FlutterEngine

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)
        //获取http代理
        MethodChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            "pixes/proxy"
        ).setMethodCallHandler { _, res ->
            res.success(getProxy())
        }
    }

    private fun getProxy(): String{
        val host = System.getProperty("http.proxyHost")
        val port = System.getProperty("http.proxyPort")
        return if(host!=null&&port!=null){
            "$host:$port"
        }else{
            "No Proxy"
        }
    }
}

================================================
FILE: android/app/src/main/res/drawable/launch_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/white" />

    <!-- You can insert your own image assets here -->
    <!-- <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/launch_image" />
    </item> -->
</layer-list>


================================================
FILE: android/app/src/main/res/drawable-v21/launch_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="?android:colorBackground" />

    <!-- You can insert your own image assets here -->
    <!-- <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/launch_image" />
    </item> -->
</layer-list>


================================================
FILE: android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
  <background android:drawable="@mipmap/ic_launcher_background"/>
  <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
  <monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
</adaptive-icon>

================================================
FILE: android/app/src/main/res/values/styles.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
        <!-- Show a splash screen on the activity. Automatically removed when
             the Flutter engine draws its first frame -->
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>
    <!-- Theme applied to the Android Window as soon as the process has started.
         This theme determines the color of the Android Window while your
         Flutter UI initializes, as well as behind your Flutter UI while its
         running.

         This Theme is only used starting with V2 of Flutter's Android embedding. -->
    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
        <item name="android:windowBackground">?android:colorBackground</item>
        <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
        <item name="android:navigationBarColor">@android:color/transparent</item>
    </style>
</resources>


================================================
FILE: android/app/src/main/res/values-night/styles.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
        <!-- Show a splash screen on the activity. Automatically removed when
             the Flutter engine draws its first frame -->
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>
    <!-- Theme applied to the Android Window as soon as the process has started.
         This theme determines the color of the Android Window while your
         Flutter UI initializes, as well as behind your Flutter UI while its
         running.

         This Theme is only used starting with V2 of Flutter's Android embedding. -->
    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
        <item name="android:windowBackground">?android:colorBackground</item>
        <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
        <item name="android:navigationBarColor">@android:color/transparent</item>
    </style>
</resources>


================================================
FILE: android/app/src/profile/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- The INTERNET permission is required for development. Specifically,
         the Flutter tool needs it to communicate with the running application
         to allow setting breakpoints, to provide hot reload, etc.
    -->
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>


================================================
FILE: android/build.gradle
================================================
allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.buildDir = '../build'
subprojects {
    project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
    project.evaluationDependsOn(':app')
}

tasks.register("clean", Delete) {
    delete rootProject.buildDir
}


================================================
FILE: android/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip

================================================
FILE: android/gradle.properties
================================================
org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true
android.enableJetifier=true


================================================
FILE: android/settings.gradle
================================================
pluginManagement {
    def flutterSdkPath = {
        def properties = new Properties()
        file("local.properties").withInputStream { properties.load(it) }
        def flutterSdkPath = properties.getProperty("flutter.sdk")
        assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
        return flutterSdkPath
    }
    settings.ext.flutterSdkPath = flutterSdkPath()

    includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")

    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

plugins {
    id "dev.flutter.flutter-plugin-loader" version "1.0.0"
    id "com.android.application" version '8.12.3' apply false
    id "org.jetbrains.kotlin.android" version "2.1.0" apply false
}

include ":app"


================================================
FILE: assets/tr.json
================================================
{
    "zh_CN": {
        "Search": "搜索",
        "Downloading": "下载中",
        "Downloaded": "已下载",
        "Artwork": "插画",
        "Explore": "探索",
        "Bookmarks": "收藏",
        "Following": "关注",
        "History": "历史",
        "Ranking": "排行",
        "Settings": "设置",
        "Artworks": "作品",
        "Mangas": "漫画",
        "Users": "用户",
        "Search artwork": "搜索作品",
        "Search Settings": "搜索设置",
        "Match": "匹配",
        "Favorite number": "收藏数",
        "Sort": "排序",
        "Age limit": "年龄限制",
        "Search novel": "搜索小说",
        "Search user": "搜索用户",
        "Artwork ID": "作品ID",
        "Artist ID": "画师ID",
        "Novel ID": "小说ID",
        "Search artworks": "搜索作品",
        "Speed": "速度",
        "View": "查看",
        "Info": "信息",
        "Delete": "删除",
        "Are you sure you want to delete?": "确定要删除吗?",
        "Yes": "是",
        "Views": "浏览数",
        "Favorites": "收藏数",
        "Private": "私人",
        "Share": "分享",
        "Link": "链接",
        "Unfollow": "取消关注",
        "Favorite": "收藏",
        "Comment": "评论",
        "Comments": "评论",
        "Follows: ": "关注:",
        "Information": "信息",
        "Introduction": "简介",
        "Birthday": "生日",
        "Job": "职业",
        "Gender": "性别",
        "Social Network": "社交网络",
        "Batch download": "批量下载",
        "Maximum number of downloads": "最大下载数",
        "Cancel": "取消",
        "Continue": "继续",
        "Public": "公开",
        "All": "全部",
        "Daily": "每日",
        "Weekly": "每周",
        "Monthly": "每月",
        "For male": "男性向",
        "For female": "女性向",
        "Originals": "原创",
        "Rookies": "新人",
        "Daily Manga": "每日漫画",
        "Weekly Manga": "每周漫画",
        "Monthly Manga": "每月漫画",
        "R18": "R18",
        "Account": "账号",
        "Logout": "登出",
        "Account Settings": "账号设置",
        "Edit": "编辑",
        "Download": "下载",
        "Manage": "管理",
        "About": "关于",
        "Are you sure you want to logout?": "确定要登出吗?",
        "Download Path": "下载路径",
        "Confirm": "确认",
        "Download subpath": "下载子路径",
        "Rule": "规则",
        "Weights of the tags": "标签权重",
        "Use translated tag name": "使用翻译后的标签名",
        "Edit the rule for where to save an image.": "编辑保存图片的规则",
        "Note: The rule should include the filename.": "注意:规则应包含文件名",
        "Title of the work": "作品标题",
        "Name of the author": "作者名",
        "Index of the image in the artwork": "作品中的图片序号",
        "File extension": "文件扩展名",
        "Tags: Tags will be sorted by the \"Weights of tags\" setting and replaced by the following rule:": "标签:标签将按照“标签权重”设置排序,并按照以下规则替换:",
        "The final text will be affected by the \"Use translated tag name\" setting.": "最终文本将受“使用翻译后的标签名”设置影响",
        "The first tag of the artwork": "作品的第一个标签",
        "The second tag of the artwork": "作品的第二个标签",
        "Follow": "关注",
        "Save to": "保存到",
        "Filled with tags. The tags should be separated by a space. The tag in front has higher weight.": "填写标签, 标签应该用空格分隔, 前面的标签权重更高. ",
        "It is required to use the original name instead of the translated name.": "必须使用原始名称而不是翻译后的名称",
        "Some keywords will be replaced by the following rule:": "一些关键词将按照以下规则替换:",
        "Subpath": "子路径",
        "Tags partial match": "标签部分匹配",
        "Tags exact match": "标签完全匹配",
        "Title or description search": "标题或描述搜索",
        "Unlimited": "无限制",
        "New to old": "新到旧",
        "Old to new": "旧到新",
        "Popular": "热门",
        "Popular(limited)": "热门(受限)",
        "Popular(Male)": "热门(男性向)",
        "Popular(Female)": "热门(女性向)",
        "Start Time": "开始时间",
        "End Time": "结束时间",
        "Max parallels": "最大并行数",
        "Replace with 'AI' if the work was generated by AI, otherwise replace with blank": "替换为'AI'如果作品是由AI生成的, 否则替换为空白",
        "Replace with * if the work have tag *, otherwise replace with blank.": "替换为*如果作品包含标签*, 否则替换为空白",
        "Multiple path separators will be automatically replaced with a single": "多个路径分隔符将被自动替换为单个",
        "Login": "登录",
        "You need to complete the login operation in the browser window that will open.": "您需要在打开的浏览器窗口中完成登录操作",
        "Waiting..." : "等待中...",
        "Waiting for authentication. Please finished in the browser." : "等待验证. 请在浏览器中完成.",
        "Back" : "返回",
        "Logging in" : "登录中",
        "Browse": "浏览",
        "Proxy": "代理",
        "Appearance": "外观",
        "Language": "语言",
        "Theme": "主题",
        "Pause": "暂停",
        "Resume": "继续",
        "Paused": "已暂停",
        "Delete all": "删除全部",
        "Related": "相关",
        "Related artworks": "相关作品",
        "Related users": "相关用户",
        "Replace with '-p${index}' if the work have more than one images, otherwise replace with blank.": "替换为'-p${index}'如果作品有多张图片, 否则替换为空白",
        "Recommendation": "推荐",
        "Novel": "小说",
        "Novels": "小说",
        "Reading Settings": "阅读设置",
        "Font Size": "字体大小",
        "Line Height": "行高",
        "Paragraph Spacing": "段间距",
        "light": "浅色",
        "dark": "深色",
        "block": "屏蔽",
        "Block": "屏蔽",
        "Block(Account)": "屏蔽(账号)",
        "Block(Local)": "屏蔽(本地)",
        "Add": "添加",
        "Submit": "提交",
        "Local": "本地",
        "Both": "同时",
        "This artwork is blocked": "此作品已被屏蔽",
        "Delete Invalid Items": "删除无效项目",
        "Private Favorite": "私人收藏",
        "Shortcuts": "快捷键",
        "Page down": "向下翻页",
        "Page up": "向上翻页",
        "Next work": "下一作品",
        "Previous work": "上一作品",
        "Add to favorites": "添加收藏",
        "Follow the artist": "关注画师",
        "Manga": "漫画",
        "Actions": "操作",
        "Current quantity": "当前数量",
        "Display the original image on the details page": "在详情页显示原图",
        "Open link": "打开链接",
        "Read": "阅读",
        "Error": "错误",
        "Failed to register URL scheme.": "注册URL协议失败",
        "Retry": "重试",
        "Network": "网络",
        "Save to gallery": "保存到相册",
        "Choose a way to login": "选择登录方式",
        "Use Webview: you cannot sign in with Google.": "使用Webview: 无法使用Google登录",
        "Use an external browser: You can sign in using Google. However, some browsers may not be compatible with the application": "使用外部浏览器: 可以使用Google登录. 但是, 一些浏览器可能与应用程序不兼容",
        "External browser": "外部浏览器",
        "Show comments": "显示评论",
        "Show original image": "显示原图",
        "Illustrations": "插画",
        "New version available": "新版本可用",
        "A new version of Pixes is available. Do you want to update now?" : "Pixes有新版本可用. 您要立即更新吗?",
        "Update": "更新",
        "Check for updates": "检查更新",
        "Check for updates on startup": "启动时检查更新",
        "I understand pixes is a free unofficial application.": "我了解Pixes是一个免费的非官方应用程序",
        "Related Artworks": "相关作品",
        "Emphasize artworks from following artists": "强调关注画师的作品",
        "The border of the artworks will be darker": "作品的边框将被加深",
        "Initial Page": "初始页面",
        "Close the pane to apply the settings": "关闭面板以应用设置",
        "No results found": "未找到结果"
    },
    "zh_TW": {
        "Search": "搜索",
        "Downloading": "下載中",
        "Downloaded": "已下載",
        "Artwork": "作品",
        "Explore": "探索",
        "Bookmarks": "收藏",
        "Following": "關注",
        "History": "歷史",
        "Ranking": "排行",
        "Settings": "設置",
        "Artworks": "作品",
        "Mangas": "漫畫",
        "Users": "用戶",
        "Search artwork": "搜索作品",
        "Search Settings": "搜索設置",
        "Match": "匹配",
        "Favorite number": "收藏數",
        "Sort": "排序",
        "Age limit": "年齡限制",
        "Search novel": "搜索小說",
        "Search user": "搜索用戶",
        "Artwork ID": "作品ID",
        "Artist ID": "畫師ID",
        "Novel ID": "小說ID",
        "Search artworks": "搜索作品",
        "Speed": "速度",
        "View": "查看",
        "Info": "信息",
        "Delete": "刪除",
        "Are you sure you want to delete?": "確定要刪除嗎?",
        "Yes": "是",
        "Views": "瀏覽數",
        "Favorites": "收藏數",
        "Private": "私人",
        "Share": "分享",
        "Link": "鏈接",
        "Unfollow": "取消關注",
        "Favorite": "收藏",
        "Comment": "評論",
        "Comments": "評論",
        "Follows: ": "關注:",
        "Information": "信息",
        "Introduction": "簡介",
        "Birthday": "生日",
        "Job": "職業",
        "Gender": "性別",
        "Social Network": "社交網絡",
        "Batch download": "批量下載",
        "Maximum number of downloads": "最大下載數",
        "Cancel": "取消",
        "Continue": "繼續",
        "Public": "公開",
        "All": "全部",
        "Daily": "每日",
        "Weekly": "每周",
        "Monthly": "每月",
        "For male": "男性向",
        "For female": "女性向",
        "Originals": "原創",
        "Rookies": "新人",
        "Daily Manga": "每日漫畫",
        "Weekly Manga": "每周漫畫",
        "Monthly Manga": "每月漫畫",
        "R18": "R18",
        "Account": "賬戶",
        "Logout": "登出",
        "Account Settings": "賬戶設置",
        "Edit": "編輯",
        "Download": "下載",
        "Manage": "管理",
        "About": "關於",
        "Are you sure you want to logout?": "確定要登出嗎?",
        "Download Path": "下載路徑",
        "Confirm": "確認",
        "Download subpath": "下載子路徑",
        "Rule": "規則",
        "Weights of the tags": "標籤權重",
        "Use translated tag name": "使用翻譯後的標籤名",
        "Edit the rule for where to save an image.": "編輯保存圖片的規則",
        "Note: The rule should include the filename.": "注意:規則應包含文件名",
        "Title of the work": "作品標題",
        "Name of the author": "作者名",
        "Index of the image in the artwork": "作品中的圖片序號",
        "File extension": "文件擴展名",
        "Tags: Tags will be sorted by the \"Weights of tags\" setting and replaced by the following rule:": "標籤:標籤將按照“標籤權重”設置排序,並按照以下規則替換:",
        "The final text will be affected by the \"Use translated tag name\" setting.": "最終文本將受“使用翻譯後的標籤名”設置影響",
        "The first tag of the artwork": "作品的第一個標籤",
        "The second tag of the artwork": "作品的第二個標籤",
        "Follow": "關注",
        "Save to": "保存到",
        "Filled with tags. The tags should be separated by a space. The tag in front has higher weight.": "填寫標籤, 標籤應該用空格分隔, 前面的標籤權重更高. ",
        "It is required to use the original name instead of the translated name.": "必須使用原始名稱而不是翻譯後的名稱",
        "Some keywords will be replaced by the following rule:": "一些關鍵詞將按照以下規則替換:",
        "Subpath": "子路徑",
        "Tags partial match": "標籤部分匹配",
        "Tags exact match": "標籤完全匹配",
        "Title or description search": "標題或描述搜索",
        "Unlimited": "無限制",
        "New to old": "新到舊",
        "Old to new": "舊到新",
        "Popular": "熱門",
        "Popular(limited)": "熱門(受限)",
        "Popular(Male)": "熱門(男性)",
        "Popular(Female)": "熱門(女性)",
        "Start Time": "開始時間",
        "End Time": "結束時間",
        "Max parallels": "最大並行數",
        "Replace with 'AI' if the work was generated by AI, otherwise replace with blank": "替換為'AI'如果作品是由AI生成的, 否則替換為空白",
        "Replace with * if the work have tag *, otherwise replace with blank.": "替換為*如果作品包含標籤*, 否則替換為空白",
        "Multiple path separators will be automatically replaced with a single": "多個路徑分隔符號將自動替換為單一",
        "Login": "登錄",
        "You need to complete the login operation in the browser window that will open.": "您需要在打開的瀏覽器窗口中完成登錄操作",
        "Waiting..." : "等待中...",
        "Waiting for authentication. Please finished in the browser." : "等待驗證. 請在瀏覽器中完成.",
        "Back" : "返回",
        "Logging in" : "登錄中",
        "Browse": "瀏覽",
        "Proxy": "代理",
        "Appearance": "外觀",
        "Language": "語言",
        "Theme": "主題",
        "Pause": "暫停",
        "Resume": "繼續",
        "Paused": "已暫停",
        "Delete all": "刪除全部",
        "Related": "相關",
        "Related artworks": "相關作品",
        "Related users": "相關用戶",
        "Replace with '-p${index}' if the work have more than one images, otherwise replace with blank.": "替換為'-p${index}'如果作品有多張圖片, 否則替換為空白",
        "Recommendation": "推薦",
        "Novel": "小說",
        "Novels": "小說",
        "Reading Settings": "閱讀設置",
        "Font Size": "字體大小",
        "Line Height": "行高",
        "Paragraph Spacing": "段間距",
        "light": "淺色",
        "dark": "深色",
        "block": "屏蔽",
        "Block": "屏蔽",
        "Block(Account)": "屏蔽(賬戶)",
        "Block(Local)": "屏蔽(本地)",
        "Add": "添加",
        "Submit": "提交",
        "Local": "本地",
        "Both": "同時",
        "This artwork is blocked": "此作品已被屏蔽",
        "Delete Invalid Items": "刪除無效項目",
        "Private Favorite": "私人收藏",
        "Shortcuts": "快捷鍵",
        "Page down": "向下翻頁",
        "Page up": "向上翻頁",
        "Next work": "下一作品",
        "Previous work": "上一作品",
        "Add to favorites": "添加收藏",
        "Follow the artist": "關注畫師",
        "Manga": "漫畫",
        "Actions": "操作",
        "Current quantity": "當前數量",
        "Display the original image on the details page": "在詳情頁顯示原圖",
        "Open link": "打開鏈接",
        "Read": "閱讀",
        "Error": "錯誤",
        "Failed to register URL scheme.": "註冊URL協議失敗",
        "Retry": "重試",
        "Network": "網絡",
        "Save to gallery": "保存到相冊",
        "Choose a way to login": "選擇登錄方式",
        "Use Webview: you cannot sign in with Google.": "使用Webview: 無法使用Google登錄",
        "Use an external browser: You can sign in using Google. However, some browsers may not be compatible with the application": "使用外部瀏覽器: 可以使用Google登錄. 但是, 一些瀏覽器可能與應用程序不兼容",
        "External browser": "外部瀏覽器",
        "Show comments": "顯示評論",
        "Show original image": "顯示原圖",
        "Illustrations": "插畫",
        "New version available": "新版本可用",
        "A new version of Pixes is available. Do you want to update now?" : "Pixes有新版本可用. 您要立即更新嗎?",
        "Update": "更新",
        "Check for updates": "檢查更新",
        "Check for updates on startup": "啟動時檢查更新",
        "I understand pixes is a free unofficial application.": "我了解Pixes是一個免費的非官方應用程序",
        "Related Artworks": "相關作品",
        "Emphasize artworks from following artists": "強調關注畫師的作品",
        "The border of the artworks will be darker": "作品的邊框將被加深",
        "Initial Page": "初始頁面",
        "Close the pane to apply the settings": "關閉面板以應用設置",
        "No results found": "未找到結果"
    },
    "ko_KR": {
        "Search": "검색",
        "Downloading": "다운로드 중",
        "Downloaded": "다운로드 완료",
        "Artwork": "작품",
        "Explore": "탐색",
        "Bookmarks": "북마크",
        "Following": "팔로잉",
        "History": "기록",
        "Ranking": "랭킹",
        "Settings": "설정",
        "Artworks": "작품",
        "Mangas": "만화",
        "Users": "사용자",
        "Search artwork": "작품 검색",
        "Search Settings": "검색 설정",
        "Match": "일치",
        "Favorite number": "북마크 수",
        "Sort": "정렬",
        "Age limit": "연령 제한",
        "Search novel": "소설 검색",
        "Search user": "사용자 검색",
        "Artwork ID": "작품 ID",
        "Artist ID": "작가 ID",
        "Novel ID": "소설 ID",
        "Search artworks": "작품 검색",
        "Speed": "속도",
        "View": "보기",
        "Info": "정보",
        "Delete": "삭제",
        "Are you sure you want to delete?": "정말 삭제하시겠습니까?",
        "Yes": "예",
        "Views": "조회수",
        "Favorites": "북마크 수",
        "Private": "비공개",
        "Share": "공유",
        "Link": "링크",
        "Unfollow": "언팔로우",
        "Favorite": "북마크",
        "Comment": "댓글",
        "Comments": "댓글",
        "Follows: ": "팔로우: ",
        "Information": "정보",
        "Introduction": "소개",
        "Birthday": "생일",
        "Job": "직업",
        "Gender": "성별",
        "Social Network": "소셜 네트워크",
        "Batch download": "일괄 다운로드",
        "Maximum number of downloads": "최대 다운로드 수",
        "Cancel": "취소",
        "Continue": "계속",
        "Public": "공개",
        "All": "전체",
        "Daily": "일간",
        "Weekly": "주간",
        "Monthly": "월간",
        "For male": "남성향",
        "For female": "여성향",
        "Originals": "오리지널",
        "Rookies": "루키",
        "Daily Manga": "일간 만화",
        "Weekly Manga": "주간 만화",
        "Monthly Manga": "월간 만화",
        "R18": "R18",
        "Account": "계정",
        "Logout": "로그아웃",
        "Account Settings": "계정 설정",
        "Edit": "편집",
        "Download": "다운로드",
        "Manage": "관리",
        "About": "정보",
        "Are you sure you want to logout?": "정말 로그아웃하시겠습니까?",
        "Download Path": "다운로드 경로",
        "Confirm": "확인",
        "Download subpath": "다운로드 하위 경로",
        "Rule": "규칙",
        "Weights of the tags": "태그 가중치",
        "Use translated tag name": "번역된 태그 이름 사용",
        "Edit the rule for where to save an image.": "이미지를 저장할 위치 규칙을 편집합니다.",
        "Note: The rule should include the filename.": "참고: 규칙에 파일 이름이 포함되어야 합니다.",
        "Title of the work": "작품 제목",
        "Name of the author": "작가 이름",
        "Index of the image in the artwork": "작품 내 이미지 인덱스",
        "File extension": "파일 확장자",
        "Tags: Tags will be sorted by the \"Weights of tags\" setting and replaced by the following rule:": "태그: 태그는 \"태그 가중치\" 설정에 따라 정렬되며 다음 규칙으로 대체됩니다:",
        "The final text will be affected by the \"Use translated tag name\" setting.": "최종 텍스트는 \"번역된 태그 이름 사용\" 설정의 영향을 받습니다.",
        "The first tag of the artwork": "작품의 첫 번째 태그",
        "The second tag of the artwork": "작품의 두 번째 태그",
        "Follow": "팔로우",
        "Save to": "저장 위치",
        "Filled with tags. The tags should be separated by a space. The tag in front has higher weight.": "태그를 입력하세요. 태그는 공백으로 구분해야 하며, 앞의 태그가 가중치가 더 높습니다.",
        "It is required to use the original name instead of the translated name.": "번역된 이름 대신 원본 이름을 사용해야 합니다.",
        "Some keywords will be replaced by the following rule:": "일부 키워드는 다음 규칙으로 대체됩니다:",
        "Subpath": "하위 경로",
        "Tags partial match": "태그 부분 일치",
        "Tags exact match": "태그 완전 일치",
        "Title or description search": "제목 또는 설명 검색",
        "Unlimited": "무제한",
        "New to old": "최신순",
        "Old to new": "오래된 순",
        "Popular": "인기",
        "Popular(limited)": "인기(제한됨)",
        "Popular(Male)": "인기(남성향)",
        "Popular(Female)": "인기(여성향)",
        "Start Time": "시작 시간",
        "End Time": "종료 시간",
        "Max parallels": "최대 동시 작업 수",
        "Replace with 'AI' if the work was generated by AI, otherwise replace with blank": "AI가 생성한 작품인 경우 'AI'로 대체하고, 그렇지 않으면 공백으로 둡니다.",
        "Replace with * if the work have tag *, otherwise replace with blank.": "작품에 * 태그가 있는 경우 *로 대체하고, 그렇지 않으면 공백으로 둡니다.",
        "Multiple path separators will be automatically replaced with a single": "다중 경로 구분 기호는 자동으로 하나로 대체됩니다",
        "Login": "로그인",
        "You need to complete the login operation in the browser window that will open.": "열리는 브라우저 창에서 로그인 작업을 완료해야 합니다.",
        "Waiting..." : "대기 중...",
        "Waiting for authentication. Please finished in the browser." : "인증 대기 중입니다. 브라우저에서 완료해 주세요.",
        "Back" : "뒤로",
        "Logging in" : "로그인 중",
        "Browse": "둘러보기",
        "Proxy": "프록시",
        "Appearance": "모양",
        "Language": "언어",
        "Theme": "테마",
        "Pause": "일시 정지",
        "Resume": "재개",
        "Paused": "일시 정지됨",
        "Delete all": "모두 삭제",
        "Related": "관련",
        "Related artworks": "관련 작품",
        "Related users": "관련 사용자",
        "Replace with '-p${index}' if the work have more than one images, otherwise replace with blank.": "작품에 이미지가 한 장 이상인 경우 '-p${index}'로 대체하고, 그렇지 않으면 공백으로 둡니다.",
        "Recommendation": "추천",
        "Novel": "소설",
        "Novels": "소설",
        "Reading Settings": "읽기 설정",
        "Font Size": "글꼴 크기",
        "Line Height": "줄 간격",
        "Paragraph Spacing": "문단 간격",
        "light": "라이트",
        "dark": "다크",
        "block": "차단",
        "Block": "차단",
        "Block(Account)": "차단(계정)",
        "Block(Local)": "차단(로컬)",
        "Add": "추가",
        "Submit": "제출",
        "Local": "로컬",
        "Both": "모두",
        "This artwork is blocked": "이 작품은 차단되었습니다",
        "Delete Invalid Items": "잘못된 항목 삭제",
        "Private Favorite": "비공개 북마크",
        "Shortcuts": "단축키",
        "Page down": "페이지 다운",
        "Page up": "페이지 업",
        "Next work": "다음 작품",
        "Previous work": "이전 작품",
        "Add to favorites": "북마크에 추가",
        "Follow the artist": "작가 팔로우",
        "Manga": "만화",
        "Actions": "작업",
        "Current quantity": "현재 수량",
        "Display the original image on the details page": "상세 페이지에 원본 이미지 표시",
        "Open link": "링크 열기",
        "Read": "읽기",
        "Error": "오류",
        "Failed to register URL scheme.": "URL 스킴 등록에 실패했습니다.",
        "Retry": "다시 시도",
        "Network": "네트워크",
        "Save to gallery": "갤러리에 저장",
        "Choose a way to login": "로그인 방식을 선택하세요",
        "Use Webview: you cannot sign in with Google.": "Webview 사용: Google로 로그인할 수 없습니다.",
        "Use an external browser: You can sign in using Google. However, some browsers may not be compatible with the application": "외부 브라우저 사용: Google 계정으로 로그인할 수 있습니다. 단, 일부 브라우저는 어플리케이션과 호환되지 않을 수 있습니다.",
        "External browser": "외부 브라우저",
        "Show comments": "댓글 표시",
        "Show original image": "원본 이미지 표시",
        "Illustrations": "일러스트",
        "New version available": "새 버전 사용 가능",
        "A new version of Pixes is available. Do you want to update now?" : "Pixes의 새 버전이 출시되었습니다. 지금 업데이트하시겠습니까?",
        "Update": "업데이트",
        "Check for updates": "업데이트 확인",
        "Check for updates on startup": "시작 시 업데이트 확인",
        "I understand pixes is a free unofficial application.": "Pixes가 무료 비공식 앱임을 이해합니다.",
        "Related Artworks": "관련 작품",
        "Emphasize artworks from following artists": "팔로우한 작가의 작품 강조",
        "The border of the artworks will be darker": "해당 작품들의 테두리가 더 어두워집니다.",
        "Initial Page": "시작 페이지",
        "Close the pane to apply the settings": "설정을 적용하려면 창을 닫으세요",
        "No results found": "결과를 찾을 수 없음"
    }
}


================================================
FILE: debian/build.py
================================================
import subprocess
import sys

arch = sys.argv[1]
debianContent = ''
desktopContent = ''
version = ''

with open('debian/debian.yaml', 'r') as f:
    debianContent = f.read()
with open('debian/gui/pixes.desktop', 'r') as f:
    desktopContent = f.read()
with open('pubspec.yaml', 'r') as f:
    version = str.split(str.split(f.read(), 'version: ')[1], '+')[0]

with open('debian/debian.yaml', 'w') as f:
    content = debianContent.replace('{{Version}}', version)
    if arch == 'x64':
        content = content.replace('{{Arch}}', 'x64')
        content = content.replace('{{Architecture}}', 'amd64')
    elif arch == 'arm64':
        content = content.replace('{{Arch}}', 'arm64')
        content = content.replace('{{Architecture}}', 'arm64')
    f.write(content)
with open('debian/gui/pixes.desktop', 'w') as f:
    f.write(desktopContent.replace('{{Version}}', version))

subprocess.run(["flutter", "build", "linux"])

subprocess.run(["$HOME/.pub-cache/bin/flutter_to_debian"], shell=True)

with open('debian/debian.yaml', 'w') as f:
    f.write(debianContent)
with open('debian/gui/pixes.desktop', 'w') as f:
    f.write(desktopContent)


================================================
FILE: debian/debian.yaml
================================================
flutter_app: 
  command: pixes
  arch: {{Arch}}
  parent: /usr/local/lib
  nonInteractive: true
  execFieldCodes: u

control:
  Package: pixes
  Version: {{Version}}
  Architecture: {{Architecture}}
  Priority: optional
  Depends: libwebkit2gtk-4.1-0, libgtk-3-0
  Maintainer: nyne
  Description: Unofficial pixiv application
  
#options:
#  exec_out_dir: debian/packages


================================================
FILE: debian/gui/pixes.desktop
================================================
[Desktop Entry]
Name=Pixes
GenericName=Pixes
Comment=Unofficial pixiv application
Terminal=false
Type=Application
Categories=Utility
Keywords=Flutter;share;images;
MimeType=x-scheme-handler/pixiv;
Icon=pixes

================================================
FILE: ios/.gitignore
================================================
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*

# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3


================================================
FILE: ios/Flutter/AppFrameworkInfo.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleDevelopmentRegion</key>
  <string>en</string>
  <key>CFBundleExecutable</key>
  <string>App</string>
  <key>CFBundleIdentifier</key>
  <string>io.flutter.flutter.app</string>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundleName</key>
  <string>App</string>
  <key>CFBundlePackageType</key>
  <string>FMWK</string>
  <key>CFBundleShortVersionString</key>
  <string>1.0</string>
  <key>CFBundleSignature</key>
  <string>????</string>
  <key>CFBundleVersion</key>
  <string>1.0</string>
  <key>MinimumOSVersion</key>
  <string>12.0</string>
</dict>
</plist>


================================================
FILE: ios/Flutter/Debug.xcconfig
================================================
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"


================================================
FILE: ios/Flutter/Release.xcconfig
================================================
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"


================================================
FILE: ios/Podfile
================================================
# Uncomment this line to define a global platform for your project
# platform :ios, '13.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}

def flutter_root
  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
  unless File.exist?(generated_xcode_build_settings_path)
    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
  end

  File.foreach(generated_xcode_build_settings_path) do |line|
    matches = line.match(/FLUTTER_ROOT\=(.*)/)
    return matches[1].strip if matches
  end
  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'Runner' do
  use_frameworks!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
  target 'RunnerTests' do
    inherit! :search_paths
  end
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
  end
end


================================================
FILE: ios/Runner/AppDelegate.swift
================================================
import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
    let methodChannel = FlutterMethodChannel(name: "pixes/proxy", binaryMessenger: controller.binaryMessenger)
    methodChannel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
        if let proxySettings = CFNetworkCopySystemProxySettings()?.takeUnretainedValue() as NSDictionary?,
           let dict = proxySettings.object(forKey: kCFNetworkProxiesHTTPProxy) as? NSDictionary,
           let host = dict.object(forKey: kCFNetworkProxiesHTTPProxy) as? String,
           let port = dict.object(forKey: kCFNetworkProxiesHTTPPort) as? Int {
            let proxyConfig = "\(host):\(port)"
            result(proxyConfig)
        } else {
            result("no proxy")
        }
    }

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}


================================================
FILE: ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images": [
    {
      "filename": "AppIcon@2x.png",
      "idiom": "iphone",
      "scale": "2x",
      "size": "60x60"
    },
    {
      "filename": "AppIcon@3x.png",
      "idiom": "iphone",
      "scale": "3x",
      "size": "60x60"
    },
    {
      "filename": "AppIcon~ipad.png",
      "idiom": "ipad",
      "scale": "1x",
      "size": "76x76"
    },
    {
      "filename": "AppIcon@2x~ipad.png",
      "idiom": "ipad",
      "scale": "2x",
      "size": "76x76"
    },
    {
      "filename": "AppIcon-83.5@2x~ipad.png",
      "idiom": "ipad",
      "scale": "2x",
      "size": "83.5x83.5"
    },
    {
      "filename": "AppIcon-40@2x.png",
      "idiom": "iphone",
      "scale": "2x",
      "size": "40x40"
    },
    {
      "filename": "AppIcon-40@3x.png",
      "idiom": "iphone",
      "scale": "3x",
      "size": "40x40"
    },
    {
      "filename": "AppIcon-40~ipad.png",
      "idiom": "ipad",
      "scale": "1x",
      "size": "40x40"
    },
    {
      "filename": "AppIcon-40@2x~ipad.png",
      "idiom": "ipad",
      "scale": "2x",
      "size": "40x40"
    },
    {
      "filename": "AppIcon-20@2x.png",
      "idiom": "iphone",
      "scale": "2x",
      "size": "20x20"
    },
    {
      "filename": "AppIcon-20@3x.png",
      "idiom": "iphone",
      "scale": "3x",
      "size": "20x20"
    },
    {
      "filename": "AppIcon-20~ipad.png",
      "idiom": "ipad",
      "scale": "1x",
      "size": "20x20"
    },
    {
      "filename": "AppIcon-20@2x~ipad.png",
      "idiom": "ipad",
      "scale": "2x",
      "size": "20x20"
    },
    {
      "filename": "AppIcon-29.png",
      "idiom": "iphone",
      "scale": "1x",
      "size": "29x29"
    },
    {
      "filename": "AppIcon-29@2x.png",
      "idiom": "iphone",
      "scale": "2x",
      "size": "29x29"
    },
    {
      "filename": "AppIcon-29@3x.png",
      "idiom": "iphone",
      "scale": "3x",
      "size": "29x29"
    },
    {
      "filename": "AppIcon-29~ipad.png",
      "idiom": "ipad",
      "scale": "1x",
      "size": "29x29"
    },
    {
      "filename": "AppIcon-29@2x~ipad.png",
      "idiom": "ipad",
      "scale": "2x",
      "size": "29x29"
    },
    {
      "filename": "AppIcon-60@2x~car.png",
      "idiom": "car",
      "scale": "2x",
      "size": "60x60"
    },
    {
      "filename": "AppIcon-60@3x~car.png",
      "idiom": "car",
      "scale": "3x",
      "size": "60x60"
    },
    {
      "filename": "AppIcon~ios-marketing.png",
      "idiom": "ios-marketing",
      "scale": "1x",
      "size": "1024x1024"
    }
  ],
  "info": {
    "author": "iconkitchen",
    "version": 1
  }
}

================================================
FILE: ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "LaunchImage.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "LaunchImage@2x.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "filename" : "LaunchImage@3x.png",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}


================================================
FILE: ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
================================================
# Launch Screen Assets

You can customize the launch screen with your own desired assets by replacing the image files in this directory.

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.

================================================
FILE: ios/Runner/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
                        <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
                            </imageView>
                        </subviews>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
                        </constraints>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
    <resources>
        <image name="LaunchImage" width="168" height="185"/>
    </resources>
</document>


================================================
FILE: ios/Runner/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
    </dependencies>
    <scenes>
        <!--Flutter View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
        </scene>
    </scenes>
</document>


================================================
FILE: ios/Runner/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleDisplayName</key>
	<string>Pixes</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>pixes</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(FLUTTER_BUILD_NAME)</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>$(FLUTTER_BUILD_NUMBER)</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>CADisableMinimumFrameDurationOnPhone</key>
	<true/>
	<key>UIApplicationSupportsIndirectInputEvents</key>
	<true/>
	<key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>pixiv</string>
            </array>
            <key>CFBundleURLName</key>
            <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
        </dict>
    </array>
	<key>NSPhotoLibraryAddUsageDescription</key>
	<string>photo</string>
	<key>NSPhotoLibraryUsageDescription</key>
	<string>photo</string>
</dict>
</plist>


================================================
FILE: ios/Runner/Runner-Bridging-Header.h
================================================
#import "GeneratedPluginRegistrant.h"


================================================
FILE: ios/Runner.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 54;
	objects = {

/* Begin PBXBuildFile section */
		1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
		331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
		3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
		74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
		97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
		97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
		97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = 97C146E61CF9000F007C117D /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = 97C146ED1CF9000F007C117D;
			remoteInfo = Runner;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
		9705A1C41CF9048500538489 /* Embed Frameworks */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 2147483647;
			dstPath = "";
			dstSubfolderSpec = 10;
			files = (
			);
			name = "Embed Frameworks";
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
		1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
		1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
		331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
		331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
		3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
		74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
		74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
		7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
		9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
		9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
		97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
		97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
		97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
		97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		97C146EB1CF9000F007C117D /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		331C8082294A63A400263BE5 /* RunnerTests */ = {
			isa = PBXGroup;
			children = (
				331C807B294A618700263BE5 /* RunnerTests.swift */,
			);
			path = RunnerTests;
			sourceTree = "<group>";
		};
		9740EEB11CF90186004384FC /* Flutter */ = {
			isa = PBXGroup;
			children = (
				3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
				9740EEB21CF90195004384FC /* Debug.xcconfig */,
				7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
				9740EEB31CF90195004384FC /* Generated.xcconfig */,
			);
			name = Flutter;
			sourceTree = "<group>";
		};
		97C146E51CF9000F007C117D = {
			isa = PBXGroup;
			children = (
				9740EEB11CF90186004384FC /* Flutter */,
				97C146F01CF9000F007C117D /* Runner */,
				97C146EF1CF9000F007C117D /* Products */,
				331C8082294A63A400263BE5 /* RunnerTests */,
			);
			sourceTree = "<group>";
		};
		97C146EF1CF9000F007C117D /* Products */ = {
			isa = PBXGroup;
			children = (
				97C146EE1CF9000F007C117D /* Runner.app */,
				331C8081294A63A400263BE5 /* RunnerTests.xctest */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		97C146F01CF9000F007C117D /* Runner */ = {
			isa = PBXGroup;
			children = (
				97C146FA1CF9000F007C117D /* Main.storyboard */,
				97C146FD1CF9000F007C117D /* Assets.xcassets */,
				97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
				97C147021CF9000F007C117D /* Info.plist */,
				1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
				1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
				74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
				74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
			);
			path = Runner;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		331C8080294A63A400263BE5 /* RunnerTests */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
			buildPhases = (
				331C807D294A63A400263BE5 /* Sources */,
				331C807F294A63A400263BE5 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
				331C8086294A63A400263BE5 /* PBXTargetDependency */,
			);
			name = RunnerTests;
			productName = RunnerTests;
			productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
			productType = "com.apple.product-type.bundle.unit-test";
		};
		97C146ED1CF9000F007C117D /* Runner */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
			buildPhases = (
				9740EEB61CF901F6004384FC /* Run Script */,
				97C146EA1CF9000F007C117D /* Sources */,
				97C146EB1CF9000F007C117D /* Frameworks */,
				97C146EC1CF9000F007C117D /* Resources */,
				9705A1C41CF9048500538489 /* Embed Frameworks */,
				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = Runner;
			productName = Runner;
			productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		97C146E61CF9000F007C117D /* Project object */ = {
			isa = PBXProject;
			attributes = {
				BuildIndependentTargetsInParallel = YES;
				LastUpgradeCheck = 1510;
				ORGANIZATIONNAME = "";
				TargetAttributes = {
					331C8080294A63A400263BE5 = {
						CreatedOnToolsVersion = 14.0;
						TestTargetID = 97C146ED1CF9000F007C117D;
					};
					97C146ED1CF9000F007C117D = {
						CreatedOnToolsVersion = 7.3.1;
						LastSwiftMigration = 1100;
					};
				};
			};
			buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
			compatibilityVersion = "Xcode 9.3";
			developmentRegion = en;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = 97C146E51CF9000F007C117D;
			productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				97C146ED1CF9000F007C117D /* Runner */,
				331C8080294A63A400263BE5 /* RunnerTests */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		331C807F294A63A400263BE5 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		97C146EC1CF9000F007C117D /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
		3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
			isa = PBXShellScriptBuildPhase;
			alwaysOutOfDate = 1;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
			);
			name = "Thin Binary";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
		};
		9740EEB61CF901F6004384FC /* Run Script */ = {
			isa = PBXShellScriptBuildPhase;
			alwaysOutOfDate = 1;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "Run Script";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
		};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		331C807D294A63A400263BE5 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		97C146EA1CF9000F007C117D /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
				1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
		331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = 97C146ED1CF9000F007C117D /* Runner */;
			targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
		};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
		97C146FA1CF9000F007C117D /* Main.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				97C146FB1CF9000F007C117D /* Base */,
			);
			name = Main.storyboard;
			sourceTree = "<group>";
		};
		97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				97C147001CF9000F007C117D /* Base */,
			);
			name = LaunchScreen.storyboard;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		249021D3217E4FDB00AE95B9 /* Profile */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_USER_SCRIPT_SANDBOXING = NO;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				SUPPORTED_PLATFORMS = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
				VALIDATE_PRODUCT = YES;
			};
			name = Profile;
		};
		249021D4217E4FDB00AE95B9 /* Profile */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CLANG_ENABLE_MODULES = YES;
				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
				ENABLE_BITCODE = NO;
				INFOPLIST_FILE = Runner/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.github.wgh136.pixes;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
				SWIFT_VERSION = 5.0;
				VERSIONING_SYSTEM = "apple-generic";
			};
			name = Profile;
		};
		331C8088294A63A400263BE5 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				BUNDLE_LOADER = "$(TEST_HOST)";
				CODE_SIGN_STYLE = Automatic;
				CURRENT_PROJECT_VERSION = 1;
				GENERATE_INFOPLIST_FILE = YES;
				MARKETING_VERSION = 1.0;
				PRODUCT_BUNDLE_IDENTIFIER = com.github.wgh136.pixes.RunnerTests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
				SWIFT_VERSION = 5.0;
				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
			};
			name = Debug;
		};
		331C8089294A63A400263BE5 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				BUNDLE_LOADER = "$(TEST_HOST)";
				CODE_SIGN_STYLE = Automatic;
				CURRENT_PROJECT_VERSION = 1;
				GENERATE_INFOPLIST_FILE = YES;
				MARKETING_VERSION = 1.0;
				PRODUCT_BUNDLE_IDENTIFIER = com.github.wgh136.pixes.RunnerTests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5.0;
				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
			};
			name = Release;
		};
		331C808A294A63A400263BE5 /* Profile */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				BUNDLE_LOADER = "$(TEST_HOST)";
				CODE_SIGN_STYLE = Automatic;
				CURRENT_PROJECT_VERSION = 1;
				GENERATE_INFOPLIST_FILE = YES;
				MARKETING_VERSION = 1.0;
				PRODUCT_BUNDLE_IDENTIFIER = com.github.wgh136.pixes.RunnerTests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5.0;
				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
			};
			name = Profile;
		};
		97C147031CF9000F007C117D /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				ENABLE_USER_SCRIPT_SANDBOXING = NO;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
				MTL_ENABLE_DEBUG_INFO = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		97C147041CF9000F007C117D /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_USER_SCRIPT_SANDBOXING = NO;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				SUPPORTED_PLATFORMS = iphoneos;
				SWIFT_COMPILATION_MODE = wholemodule;
				SWIFT_OPTIMIZATION_LEVEL = "-O";
				TARGETED_DEVICE_FAMILY = "1,2";
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		97C147061CF9000F007C117D /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CLANG_ENABLE_MODULES = YES;
				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
				ENABLE_BITCODE = NO;
				INFOPLIST_FILE = Runner/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.github.wgh136.pixes;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
				SWIFT_VERSION = 5.0;
				VERSIONING_SYSTEM = "apple-generic";
			};
			name = Debug;
		};
		97C147071CF9000F007C117D /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CLANG_ENABLE_MODULES = YES;
				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
				ENABLE_BITCODE = NO;
				INFOPLIST_FILE = Runner/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.github.wgh136.pixes;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
				SWIFT_VERSION = 5.0;
				VERSIONING_SYSTEM = "apple-generic";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				331C8088294A63A400263BE5 /* Debug */,
				331C8089294A63A400263BE5 /* Release */,
				331C808A294A63A400263BE5 /* Profile */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				97C147031CF9000F007C117D /* Debug */,
				97C147041CF9000F007C117D /* Release */,
				249021D3217E4FDB00AE95B9 /* Profile */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				97C147061CF9000F007C117D /* Debug */,
				97C147071CF9000F007C117D /* Release */,
				249021D4217E4FDB00AE95B9 /* Profile */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 97C146E61CF9000F007C117D /* Project object */;
}


================================================
FILE: ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:">
   </FileRef>
</Workspace>


================================================
FILE: ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IDEDidComputeMac32BitWarning</key>
	<true/>
</dict>
</plist>


================================================
FILE: ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>PreviewsEnabled</key>
	<false/>
</dict>
</plist>


================================================
FILE: ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "1510"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "97C146ED1CF9000F007C117D"
               BuildableName = "Runner.app"
               BlueprintName = "Runner"
               ReferencedContainer = "container:Runner.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
            BuildableName = "Runner.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <Testables>
         <TestableReference
            skipped = "NO"
            parallelizable = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "331C8080294A63A400263BE5"
               BuildableName = "RunnerTests.xctest"
               BlueprintName = "RunnerTests"
               ReferencedContainer = "container:Runner.xcodeproj">
            </BuildableReference>
         </TestableReference>
      </Testables>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
            BuildableName = "Runner.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Profile"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
            BuildableName = "Runner.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: ios/Runner.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "group:Runner.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IDEDidComputeMac32BitWarning</key>
	<true/>
</dict>
</plist>


================================================
FILE: ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>PreviewsEnabled</key>
	<false/>
</dict>
</plist>


================================================
FILE: ios/RunnerTests/RunnerTests.swift
================================================
import Flutter
import UIKit
import XCTest

class RunnerTests: XCTestCase {

  func testExample() {
    // If you add code to the Runner application, consider adding tests here.
    // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
  }

}


================================================
FILE: lib/appdata.dart
================================================
import 'dart:convert';
import 'dart:io';

import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pixes/utils/io.dart';

import 'foundation/app.dart';
import 'foundation/log.dart';
import 'network/models.dart';

class _Appdata {
  static const MethodChannel _macosDownloadPathChannel =
      MethodChannel("pixes/macos/download_path");

  Account? account;

  var searchOptions = SearchOptions();

  Map<String, dynamic> settings = {
    "downloadPath": null,
    "downloadSubPath": r"/${id}-p${index}.${ext}",
    "maxParallels": 3,
    "proxy": "",
    "darkMode": "System",
    "language": "System",
    "readingFontSize": 16.0,
    "readingLineHeight": 1.5,
    "readingParagraphSpacing": 8.0,
    "blockTags": [],
    "shortcuts": <int>[
      LogicalKeyboardKey.arrowDown.keyId,
      LogicalKeyboardKey.arrowUp.keyId,
      LogicalKeyboardKey.arrowRight.keyId,
      LogicalKeyboardKey.arrowLeft.keyId,
      LogicalKeyboardKey.enter.keyId,
      LogicalKeyboardKey.keyD.keyId,
      LogicalKeyboardKey.keyF.keyId,
      LogicalKeyboardKey.keyC.keyId,
      LogicalKeyboardKey.keyG.keyId,
    ],
    "showOriginalImage": false,
    "checkUpdate": true,
    "emphasizeArtworksFromFollowingArtists": true,
    "initialPage": 4,
  };

  bool lock = false;

  void writeData() async {
    while (lock) {
      await Future.delayed(const Duration(milliseconds: 20));
    }
    lock = true;
    await File("${App.dataPath}/account.json")
        .writeAsString(jsonEncode(account));
    await File("${App.dataPath}/settings.json")
        .writeAsString(jsonEncode(settings));
    lock = false;
  }

  void writeSettings() async {
    while (lock) {
      await Future.delayed(const Duration(milliseconds: 20));
    }
    lock = true;
    await File("${App.dataPath}/settings.json")
        .writeAsString(jsonEncode(settings));
    lock = false;
  }

  Future<void> readData() async {
    final file = File("${App.dataPath}/account.json");
    if (file.existsSync()) {
      var json = jsonDecode(await file.readAsString());
      if (json != null) {
        account = Account.fromJson(json);
      }
    }
    final settingsFile = File("${App.dataPath}/settings.json");
    if (settingsFile.existsSync()) {
      var json = jsonDecode(await settingsFile.readAsString());
      for (var key in json.keys) {
        if (json[key] != null) {
          if (json[key] is List && settings[key] is List) {
            for (int i = 0;
                i < json[key].length && i < settings[key].length;
                i++) {
              settings[key][i] = json[key][i];
            }
          } else {
            settings[key] = json[key];
          }
        }
      }
    }
    settings["downloadPath"] ??= await _defaultDownloadPath;
    if (App.isMacOS) {
      await _ensureMacOSDownloadPathPermission();
    }
  }

  Future<void> _ensureMacOSDownloadPathPermission() async {
    final defaultPath = await _defaultDownloadPath;
    final currentPath = settings["downloadPath"] as String? ?? defaultPath;
    if (_normalizePath(currentPath) == _normalizePath(defaultPath)) {
      settings["downloadPath"] = defaultPath;
      return;
    }

    final restoredPath = await _restoreMacOSDownloadPathAccess(currentPath);
    if (restoredPath != null) {
      settings["downloadPath"] = restoredPath;
      Log.info(
          "DownloadPath", "Restored macOS directory access: $restoredPath");
      return;
    }

    Log.warning(
      "DownloadPath",
      "Failed to restore macOS directory access for $currentPath, requesting permission again.",
    );
    final selectedPath = await _requestMacOSDownloadPathAccess(currentPath);
    if (selectedPath != null) {
      settings["downloadPath"] = selectedPath;
      writeSettings();
      Log.info(
        "DownloadPath",
        "Re-authorized macOS directory access: $selectedPath",
      );
      return;
    }

    settings["downloadPath"] = defaultPath;
    writeSettings();
    Log.warning(
      "DownloadPath",
      "macOS directory permission denied or canceled, fallback to default path: $defaultPath",
    );
  }

  Future<String?> _restoreMacOSDownloadPathAccess(String? expectedPath) async {
    try {
      return await _macosDownloadPathChannel.invokeMethod<String>(
        "restoreDownloadDirectoryAccess",
        {"path": expectedPath},
      );
    } catch (e) {
      Log.warning("DownloadPath", "restoreDownloadDirectoryAccess failed: $e");
      return null;
    }
  }

  Future<String?> _requestMacOSDownloadPathAccess(String? initialPath) async {
    try {
      return await _macosDownloadPathChannel.invokeMethod<String>(
        "selectDownloadDirectory",
        {"initialPath": initialPath},
      );
    } catch (e) {
      Log.warning("DownloadPath", "selectDownloadDirectory failed: $e");
      return null;
    }
  }

  String _normalizePath(String path) {
    if (!App.isMacOS) {
      return path;
    }
    final home = Platform.environment["HOME"];
    if (home != null && path.startsWith("~")) {
      return path.replaceFirst("~", home);
    }
    return path;
  }

  Future<String> get _defaultDownloadPath async {
    if (App.isAndroid) {
      String? downloadPath = "/storage/emulated/0/download";
      if (!Directory(downloadPath).havePermission()) {
        downloadPath = null;
      }
      var res = downloadPath;
      res ??= (await getExternalStorageDirectory())!.path;
      return "$res/pixes";
    } else if (App.isWindows) {
      var res =
          await const MethodChannel("pixes/picture_folder").invokeMethod("");
      if (res != "error") {
        return res + "/pixes";
      }
    } else if (App.isLinux) {
      var downloadPath = (await getDownloadsDirectory())?.path;
      if (downloadPath != null && Directory(downloadPath).havePermission()) {
        return "$downloadPath/pixes";
      }
    } else if (App.isMacOS) {
      if (Directory("~/Pictures").havePermission()) {
        return "~/Pictures/pixes";
      }
      try {
        Directory("~/Downloads/pixes").createSync(recursive: true);
        return "~/Downloads/pixes";
      } catch (e) {
        return "${App.dataPath}/download";
      }
    }

    return "${App.dataPath}/download";
  }
}

final appdata = _Appdata();


================================================
FILE: lib/components/animated_image.dart
================================================
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';

class AnimatedImage extends StatefulWidget {
  /// show animation when loading is complete.
  AnimatedImage({
    required ImageProvider image,
    super.key,
    double scale = 1.0,
    this.semanticLabel,
    this.excludeFromSemantics = false,
    this.width,
    this.height,
    this.color,
    this.opacity,
    this.colorBlendMode,
    this.fit,
    this.alignment = Alignment.center,
    this.repeat = ImageRepeat.noRepeat,
    this.centerSlice,
    this.matchTextDirection = false,
    this.gaplessPlayback = false,
    this.filterQuality = FilterQuality.low,
    this.isAntiAlias = false,
    Map<String, String>? headers,
    int? cacheWidth,
    int? cacheHeight,
  }
      ): image = ResizeImage.resizeIfNeeded(cacheWidth, cacheHeight, image),
        assert(cacheWidth == null || cacheWidth > 0),
        assert(cacheHeight == null || cacheHeight > 0);

  final ImageProvider image;

  final String? semanticLabel;

  final bool excludeFromSemantics;

  final double? width;

  final double? height;

  final bool gaplessPlayback;

  final bool matchTextDirection;

  final Rect? centerSlice;

  final ImageRepeat repeat;

  final AlignmentGeometry alignment;

  final BoxFit? fit;

  final BlendMode? colorBlendMode;

  final FilterQuality filterQuality;

  final Animation<double>? opacity;

  final Color? color;

  final bool isAntiAlias;

  static void clear() => _AnimatedImageState.clear();

  @override
  State<AnimatedImage> createState() => _AnimatedImageState();
}

class _AnimatedImageState extends State<AnimatedImage> with WidgetsBindingObserver {
  ImageStream? _imageStream;
  ImageInfo? _imageInfo;
  ImageChunkEvent? _loadingProgress;
  bool _isListeningToStream = false;
  late bool _invertColors;
  int? _frameNumber;
  bool _wasSynchronouslyLoaded = false;
  late DisposableBuildContext<State<AnimatedImage>> _scrollAwareContext;
  Object? _lastException;
  ImageStreamCompleterHandle? _completerHandle;

  static final Map<int, Size> _cache = {};

  static clear() => _cache.clear();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _scrollAwareContext = DisposableBuildContext<State<AnimatedImage>>(this);
  }

  @override
  void dispose() {
    assert(_imageStream != null);
    WidgetsBinding.instance.removeObserver(this);
    _stopListeningToStream();
    _completerHandle?.dispose();
    _scrollAwareContext.dispose();
    _replaceImage(info: null);
    super.dispose();
  }

  @override
  void didChangeDependencies() {
    _updateInvertColors();
    _resolveImage();

    if (TickerMode.of(context)) {
      _listenToStream();
    } else {
      _stopListeningToStream(keepStreamAlive: true);
    }

    super.didChangeDependencies();
  }

  @override
  void didUpdateWidget(AnimatedImage oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.image != oldWidget.image) {
      _resolveImage();
    }
  }

  @override
  void didChangeAccessibilityFeatures() {
    super.didChangeAccessibilityFeatures();
    setState(() {
      _updateInvertColors();
    });
  }

  @override
  void reassemble() {
    _resolveImage(); // in case the image cache was flushed
    super.reassemble();
  }

  void _updateInvertColors() {
    _invertColors = MediaQuery.maybeInvertColorsOf(context)
        ?? SemanticsBinding.instance.accessibilityFeatures.invertColors;
  }

  void _resolveImage() {
    final ScrollAwareImageProvider provider = ScrollAwareImageProvider<Object>(
      context: _scrollAwareContext,
      imageProvider: widget.image,
    );
    final ImageStream newStream =
    provider.resolve(createLocalImageConfiguration(
      context,
      size: widget.width != null && widget.height != null ? Size(widget.width!, widget.height!) : null,
    ));
    _updateSourceStream(newStream);
  }

  ImageStreamListener? _imageStreamListener;
  ImageStreamListener _getListener({bool recreateListener = false}) {
    if(_imageStreamListener == null || recreateListener) {
      _lastException = null;
      _imageStreamListener = ImageStreamListener(
        _handleImageFrame,
        onChunk: _handleImageChunk,
        onError: (Object error, StackTrace? stackTrace) {
          setState(() {
            _lastException = error;
          });
        },
      );
    }
    return _imageStreamListener!;
  }

  void _handleImageFrame(ImageInfo imageInfo, bool synchronousCall) {
    setState(() {
      _replaceImage(info: imageInfo);
      _loadingProgress = null;
      _lastException = null;
      _frameNumber = _frameNumber == null ? 0 : _frameNumber! + 1;
      _wasSynchronouslyLoaded = _wasSynchronouslyLoaded | synchronousCall;
    });
  }

  void _handleImageChunk(ImageChunkEvent event) {
    setState(() {
      _loadingProgress = event;
      _lastException = null;
    });
  }

  void _replaceImage({required ImageInfo? info}) {
    final ImageInfo? oldImageInfo = _imageInfo;
    SchedulerBinding.instance.addPostFrameCallback((_) => oldImageInfo?.dispose());
    _imageInfo = info;
  }

  // Updates _imageStream to newStream, and moves the stream listener
  // registration from the old stream to the new stream (if a listener was
  // registered).
  void _updateSourceStream(ImageStream newStream) {
    if (_imageStream?.key == newStream.key) {
      return;
    }

    if (_isListeningToStream) {
      _imageStream!.removeListener(_getListener());
    }

    if (!widget.gaplessPlayback) {
      setState(() { _replaceImage(info: null); });
    }

    setState(() {
      _loadingProgress = null;
      _frameNumber = null;
      _wasSynchronouslyLoaded = false;
    });

    _imageStream = newStream;
    if (_isListeningToStream) {
      _imageStream!.addListener(_getListener());
    }
  }

  void _listenToStream() {
    if (_isListeningToStream) {
      return;
    }

    _imageStream!.addListener(_getListener());
    _completerHandle?.dispose();
    _completerHandle = null;

    _isListeningToStream = true;
  }

  /// Stops listening to the image stream, if this state object has attached a
  /// listener.
  ///
  /// If the listener from this state is the last listener on the stream, the
  /// stream will be disposed. To keep the stream alive, set `keepStreamAlive`
  /// to true, which create [ImageStreamCompleterHandle] to keep the completer
  /// alive and is compatible with the [TickerMode] being off.
  void _stopListeningToStream({bool keepStreamAlive = false}) {
    if (!_isListeningToStream) {
      return;
    }

    if (keepStreamAlive && _completerHandle == null && _imageStream?.completer != null) {
      _completerHandle = _imageStream!.completer!.keepAlive();
    }

    _imageStream!.removeListener(_getListener());
    _isListeningToStream = false;
  }

  @override
  Widget build(BuildContext context) {
    Widget result;

    if(_imageInfo != null){
      // build image
      result = RawImage(
        // Do not clone the image, because RawImage is a stateless wrapper.
        // The image will be disposed by this state object when it is not needed
        // anymore, such as when it is unmounted or when the image stream pushes
        // a new image.
        image: _imageInfo?.image,
        width: widget.width,
        height: widget.height,
        debugImageLabel: _imageInfo?.debugLabel,
        scale: _imageInfo?.scale ?? 1.0,
        color: widget.color,
        opacity: widget.opacity,
        colorBlendMode: widget.colorBlendMode,
        alignment: widget.alignment,
        repeat: widget.repeat,
        centerSlice: widget.centerSlice,
        matchTextDirection: widget.matchTextDirection,
        invertColors: _invertColors,
        isAntiAlias: widget.isAntiAlias,
        filterQuality: widget.filterQuality,
        fit: widget.fit,
      );
    } else if (_lastException != null) {
      result = const Center(
        child: Icon(FluentIcons.error),
      );

      if (!widget.excludeFromSemantics) {
        result = Semantics(
          container: widget.semanticLabel != null,
          image: true,
          label: widget.semanticLabel ?? '',
          child: result,
        );
      }
    } else{
      result = const Center();
    }

    return AnimatedSwitcher(
      duration: const Duration(milliseconds: 200),
      reverseDuration: const Duration(milliseconds: 200),
      child: result,
    );
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder description) {
    super.debugFillProperties(description);
    description.add(DiagnosticsProperty<ImageStream>('stream', _imageStream));
    description.add(DiagnosticsProperty<ImageInfo>('pixels', _imageInfo));
    description.add(DiagnosticsProperty<ImageChunkEvent>('loadingProgress', _loadingProgress));
    description.add(DiagnosticsProperty<int>('frameNumber', _frameNumber));
    description.add(DiagnosticsProperty<bool>('wasSynchronouslyLoaded', _wasSynchronouslyLoaded));
  }
}


================================================
FILE: lib/components/batch_download.dart
================================================
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/components/md.dart';
import 'package:pixes/components/message.dart';
import 'package:pixes/foundation/app.dart';
import 'package:pixes/network/download.dart';
import 'package:pixes/utils/translation.dart';

import '../network/network.dart';

class BatchDownloadButton extends StatelessWidget {
  const BatchDownloadButton({super.key, required this.request});

  final Future<Res<List<Illust>>> Function() request;

  @override
  Widget build(BuildContext context) {
    return Button(
      child: const Icon(
        MdIcons.download,
        size: 20,
      ),
      onPressed: () {
        showDialog(
            context: context,
            barrierDismissible: false,
            barrierColor: Colors.transparent,
            useRootNavigator: false,
            builder: (context) => _DownloadDialog(request));
      },
    );
  }
}

class _DownloadDialog extends StatefulWidget {
  const _DownloadDialog(this.request);

  final Future<Res<List<Illust>>> Function() request;

  @override
  State<_DownloadDialog> createState() => _DownloadDialogState();
}

class _DownloadDialogState extends State<_DownloadDialog> {
  int maxCount = 30;

  int currentCount = 0;

  bool loading = false;

  bool cancel = false;

  @override
  Widget build(BuildContext context) {
    return ContentDialog(
      title: Text("Batch download".tl),
      content: SizedBox(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            if (!loading) Text('${"Maximum number of downloads".tl}:'),
            if (loading) Text("${"Current quantity".tl}: $currentCount"),
            const SizedBox(
              height: 16,
            ),
            SizedBox(
              height: 42,
              width: 196,
              child: NumberBox(
                value: maxCount,
                onChanged: (value) {
                  if (!loading) {
                    setState(() => maxCount = value ?? maxCount);
                  }
                },
                allowExpressions: true,
                mode: SpinButtonPlacementMode.inline,
                smallChange: 10,
                largeChange: 30,
                clearButton: false,
              ),
            ),
          ],
        ).paddingVertical(8),
      ),
      actions: [
        Button(
            child: Text("Cancel".tl),
            onPressed: () {
              cancel = true;
              context.pop();
            }),
        if (!loading)
          FilledButton(onPressed: load, child: Text("Continue".tl))
        else
          FilledButton(
              onPressed: () {},
              child: const SizedBox(
                height: 20,
                width: 64,
                child: Center(
                  child: SizedBox.square(
                    dimension: 18,
                    child: ProgressRing(
                      strokeWidth: 1.6,
                    ),
                  ),
                ),
              ))
      ],
    );
  }

  void load() async {
    setState(() {
      loading = true;
    });

    var request = widget.request();

    List<Illust> all = [];
    String? nextUrl;
    int retryCount = 0;
    while (nextUrl != "end" && all.length < maxCount) {
      if (nextUrl != null) {
        request = Network().getIllustsWithNextUrl(nextUrl);
      }
      var res = await request;
      if (cancel || !mounted) {
        return;
      }
      if (res.error) {
        retryCount++;
        if (retryCount > 3) {
          setState(() {
            loading = false;
          });
          showToast(context, message: "Error".tl);
          return;
        }
        await Future.delayed(Duration(seconds: 1 << retryCount));
        continue;
      }
      all.addAll(res.data);
      setState(() {
        currentCount = all.length;
      });
      nextUrl = res.subData ?? "end";
    }
    int i = 0;
    for (var illust in all) {
      if (i > maxCount) break;
      DownloadManager().addDownloadingTask(illust);
      i++;
    }
    context.pop();
  }
}


================================================
FILE: lib/components/button.dart
================================================
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/foundation/app.dart';

abstract class BaseButton extends StatelessWidget {
  const BaseButton({this.enabled = true, this.isLoading = false, super.key});

  final bool enabled;

  final bool isLoading;

  Widget buildNormal(BuildContext context);

  Widget buildLoading(BuildContext context);

  Widget buildDisabled(BuildContext context);

  @override
  Widget build(BuildContext context) {
    if (isLoading) {
      return buildLoading(context);
    } else if (enabled) {
      return buildNormal(context);
    } else {
      return buildDisabled(context);
    }
  }
}

class FluentButton extends BaseButton {
  const FluentButton({
    required this.onPressed,
    required this.child,
    this.width,
    super.enabled,
    super.isLoading,
    super.key,
  });

  final void Function() onPressed;

  final Widget child;

  final double? width;

  static const _kFluentButtonPadding = 12.0;

  @override
  Widget buildNormal(BuildContext context) {
    Widget child = this.child;
    if (width != null) {
      child = child.fixWidth(width! - _kFluentButtonPadding * 2);
    }
    return FilledButton(
      onPressed: onPressed,
      child: child,
    );
  }

  @override
  Widget buildLoading(BuildContext context) {
    Widget child = Center(
      widthFactor: 1,
      heightFactor: 1,
      child: const ProgressRing(
        strokeWidth: 1.6,
      ).fixWidth(14).fixHeight(14),
    );
    if (width != null) {
      child = child.fixWidth(width! - _kFluentButtonPadding * 2);
    }
    return Container(
      padding: const EdgeInsets.symmetric(
          horizontal: _kFluentButtonPadding, vertical: 6.5),
      decoration: BoxDecoration(
          color: FluentTheme.of(context).inactiveBackgroundColor,
          borderRadius: BorderRadius.circular(4)),
      child: child,
    );
  }

  @override
  Widget buildDisabled(BuildContext context) {
    Widget child = Center(
      widthFactor: 1,
      heightFactor: 1,
      child: this.child,
    );
    if (width != null) {
      child = child.fixWidth(width! - _kFluentButtonPadding * 2);
    }
    return Container(
      padding: const EdgeInsets.symmetric(
          horizontal: _kFluentButtonPadding, vertical: 6.5),
      decoration: BoxDecoration(
          color: FluentTheme.of(context).inactiveBackgroundColor,
          borderRadius: BorderRadius.circular(4)),
      child: child,
    );
  }
}


================================================
FILE: lib/components/grid.dart
================================================
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:pixes/foundation/app.dart';

class SliverGridViewWithFixedItemHeight extends StatelessWidget {
  const SliverGridViewWithFixedItemHeight(
      {required this.delegate,
      this.maxCrossAxisExtent = double.infinity,
      this.minCrossAxisExtent = 0,
      required this.itemHeight,
      super.key});

  final SliverChildDelegate delegate;

  final double maxCrossAxisExtent;

  final double minCrossAxisExtent;

  final double itemHeight;

  @override
  Widget build(BuildContext context) {
    return SliverGrid(
      delegate: delegate,
      gridDelegate: SliverGridDelegateWithFixedHeight(
          itemHeight: itemHeight,
          maxCrossAxisExtent: maxCrossAxisExtent,
          minCrossAxisExtent: minCrossAxisExtent),
    ).sliverPadding(EdgeInsets.only(bottom: context.padding.bottom));
  }
}

class GridViewWithFixedItemHeight extends StatelessWidget {
  const GridViewWithFixedItemHeight(
      {required this.builder,
      required this.itemCount,
      this.maxCrossAxisExtent = double.infinity,
      this.minCrossAxisExtent = 0,
      required this.itemHeight,
      super.key});

  final Widget Function(BuildContext, int) builder;

  final int itemCount;

  final double maxCrossAxisExtent;

  final double minCrossAxisExtent;

  final double itemHeight;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
        builder: ((context, constraints) => GridView.builder(
              gridDelegate: SliverGridDelegateWithFixedHeight(
                  itemHeight: itemHeight,
                  maxCrossAxisExtent: maxCrossAxisExtent,
                  minCrossAxisExtent: minCrossAxisExtent),
              itemBuilder: builder,
              itemCount: itemCount,
              padding: EdgeInsets.only(bottom: context.padding.bottom),
            )));
  }
}

class SliverGridDelegateWithFixedHeight extends SliverGridDelegate {
  const SliverGridDelegateWithFixedHeight({
    this.maxCrossAxisExtent = double.infinity,
    this.minCrossAxisExtent = 0,
    required this.itemHeight,
  });

  final double maxCrossAxisExtent;

  final double minCrossAxisExtent;

  final double itemHeight;

  @override
  SliverGridLayout getLayout(SliverConstraints constraints) {
    var crossItemsCount = calcCrossItemsCount(constraints.crossAxisExtent);
    return SliverGridRegularTileLayout(
        crossAxisCount: crossItemsCount,
        mainAxisStride: itemHeight,
        childMainAxisExtent: itemHeight,
        crossAxisStride: constraints.crossAxisExtent / crossItemsCount,
        childCrossAxisExtent: constraints.crossAxisExtent / crossItemsCount,
        reverseCrossAxis: false);
  }

  int calcCrossItemsCount(double width) {
    int count = 20;
    var itemWidth = width / 20;

    if(minCrossAxisExtent == 0) {
      count = 1;
      itemWidth = width;
      while(itemWidth > maxCrossAxisExtent) {
        count++;
        itemWidth = width / count;
      }
      return count;
    }

    while (
        !(itemWidth > minCrossAxisExtent && itemWidth < maxCrossAxisExtent)) {
      count--;
      itemWidth = width / count;
      if (count == 1) {
        return 1;
      }
    }
    return count;
  }

  @override
  bool shouldRelayout(covariant SliverGridDelegate oldDelegate) {
    return oldDelegate is! SliverGridDelegateWithFixedHeight ||
        oldDelegate.maxCrossAxisExtent != maxCrossAxisExtent ||
        oldDelegate.minCrossAxisExtent != minCrossAxisExtent ||
        oldDelegate.itemHeight != itemHeight;
  }
}


================================================
FILE: lib/components/illust_widget.dart
================================================
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/appdata.dart';
import 'package:pixes/components/animated_image.dart';
import 'package:pixes/foundation/app.dart';
import 'package:pixes/foundation/history.dart';
import 'package:pixes/foundation/image_provider.dart';
import 'package:pixes/network/download.dart';
import 'package:pixes/pages/related_page.dart';
import 'package:pixes/utils/translation.dart';

import '../network/network.dart';
import '../pages/illust_page.dart';
import 'md.dart';

typedef UpdateFavoriteFunc = void Function(bool v);

class IllustWidget extends StatefulWidget {
  const IllustWidget(this.illust, {this.onTap, super.key});

  final Illust illust;

  final void Function()? onTap;

  static Map<String, UpdateFavoriteFunc> favoriteCallbacks = {};

  @override
  State<IllustWidget> createState() => _IllustWidgetState();
}

class _IllustWidgetState extends State<IllustWidget> {
  bool isBookmarking = false;

  final contextController = FlyoutController();
  final contextAttachKey = GlobalKey();

  @override
  void initState() {
    IllustWidget.favoriteCallbacks[widget.illust.id.toString()] = (v) {
      setState(() {
        widget.illust.isBookmarked = v;
      });
    };
    super.initState();
  }

  @override
  void dispose() {
    IllustWidget.favoriteCallbacks.remove(widget.illust.id.toString());
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constrains) {
      final width = constrains.maxWidth;
      final height = widget.illust.height * width / widget.illust.width;
      return FlyoutTarget(
        controller: contextController,
        child: SizedBox(
          key: contextAttachKey,
          width: width,
          height: height,
          child: Stack(
            children: [
              Positioned.fill(
                child: Container(
                  width: width,
                  height: height,
                  padding: const EdgeInsets.symmetric(
                      horizontal: 8.0, vertical: 8.0),
                  child: Container(
                    width: double.infinity,
                    height: double.infinity,
                    padding: EdgeInsets.zero,
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(4.0),
                      color: FluentTheme.of(context).cardColor,
                      border: () {
                        var emphasis = widget.illust.author.isFollowed &&
                            appdata.settings[
                                'emphasizeArtworksFromFollowingArtists'];
                        var color = emphasis
                            ? ColorScheme.of(context).primary
                            : ColorScheme.of(context)
                                .outlineVariant
                                .toOpacity(0.64);
                        var width = emphasis ? 1.6 : 1.0;
                        return Border.all(color: color, width: width);
                      }(),
                    ),
                    margin: EdgeInsets.zero,
                    child: GestureDetector(
                      onTap: widget.onTap ??
                          () {
                            context.to(() => IllustPage(widget.illust));
                          },
                      onSecondaryTapUp: showMenu,
                      onLongPress: showMenu,
                      child: ClipRRect(
                        borderRadius: BorderRadius.circular(4.0),
                        child: AnimatedImage(
                          image: CachedImageProvider(
                              widget.illust.images.first.medium),
                          fit: BoxFit.cover,
                          width: width - 16.0,
                          height: height - 16.0,
                        ),
                      ),
                    ),
                  ),
                ),
              ),
              if (widget.illust.images.length > 1)
                Positioned(
                  top: 12,
                  left: 12,
                  child: Container(
                      width: 28,
                      height: 20,
                      decoration: BoxDecoration(
                        color: FluentTheme.of(context)
                            .micaBackgroundColor
                            .toOpacity(0.72),
                        borderRadius: BorderRadius.circular(4),
                        border: Border.all(
                            color: ColorScheme.of(context).outlineVariant,
                            width: 0.6),
                      ),
                      child: Center(
                        child: Text(
                          "${widget.illust.images.length}P",
                          style: const TextStyle(fontSize: 12),
                        ),
                      )),
                ),
              if (widget.illust.isAi)
                Positioned(
                  bottom: 12,
                  left: 12,
                  child: Container(
                      width: 28,
                      height: 20,
                      decoration: BoxDecoration(
                        color: ColorScheme.of(context)
                            .errorContainer
                            .toOpacity(0.8),
                        borderRadius: BorderRadius.circular(4),
                        border: Border.all(
                            color: ColorScheme.of(context).outlineVariant,
                            width: 0.6),
                      ),
                      child: const Center(
                        child: Text(
                          "AI",
                          style: TextStyle(fontSize: 12),
                        ),
                      )),
                ),
              if (widget.illust.isUgoira)
                Positioned(
                  bottom: 12,
                  left: 12,
                  child: Container(
                      width: 28,
                      height: 20,
                      decoration: BoxDecoration(
                        color: ColorScheme.of(context)
                            .primaryContainer
                            .toOpacity(0.8),
                        borderRadius: BorderRadius.circular(4),
                        border: Border.all(
                            color: ColorScheme.of(context).outlineVariant,
                            width: 0.6),
                      ),
                      child: const Center(
                        child: Text(
                          "GIF",
                          style: TextStyle(fontSize: 12),
                        ),
                      )),
                ),
              if (widget.illust.isR18)
                Positioned(
                  bottom: 12,
                  right: 12,
                  child: Container(
                      width: 28,
                      height: 20,
                      decoration: BoxDecoration(
                        color: ColorScheme.of(context).errorContainer,
                        borderRadius: BorderRadius.circular(4),
                        border: Border.all(
                            color: ColorScheme.of(context).outlineVariant,
                            width: 0.6),
                      ),
                      child: const Center(
                        child: Text(
                          "R18",
                          style: TextStyle(fontSize: 12),
                        ),
                      )),
                ),
              if (widget.illust.isR18G)
                Positioned(
                  bottom: 12,
                  right: 12,
                  child: Container(
                      width: 28,
                      height: 20,
                      decoration: BoxDecoration(
                        color: ColorScheme.of(context).errorContainer,
                        borderRadius: BorderRadius.circular(4),
                        border: Border.all(
                            color: ColorScheme.of(context).outlineVariant,
                            width: 0.6),
                      ),
                      child: const Center(
                        child: Text(
                          "R18G",
                          style: TextStyle(fontSize: 12),
                        ),
                      )),
                ),
              Positioned(
                top: 16,
                right: 16,
                child: buildButton(),
              )
            ],
          ),
        ),
      );
    });
  }

  void showMenu([TapUpDetails? details]) {
    // This calculates the position of the flyout according to the parent navigator
    final targetContext = contextAttachKey.currentContext;
    if (targetContext == null) return;
    final box = targetContext.findRenderObject() as RenderBox;
    Offset? position = box.localToGlobal(
      details?.localPosition ?? box.size.center(Offset.zero),
      ancestor: Navigator.of(context).context.findRenderObject(),
    );

    contextController.showFlyout(
      barrierColor: Colors.transparent,
      position: position,
      builder: (context) {
        return MenuFlyout(
          items: [
            MenuFlyoutItem(
                text: Text("View".tl),
                onPressed: () {
                  context.to(() => IllustPage(widget.illust));
                }),
            MenuFlyoutItem(
                text: Text("Private Favorite".tl),
                onPressed: () {
                  favorite("private");
                }),
            MenuFlyoutItem(
                text: Text("Download".tl),
                onPressed: () {
                  context.showToast(message: "Added");
                  DownloadManager().addDownloadingTask(widget.illust);
                }),
            MenuFlyoutItem(
                text: Text("Related Artworks".tl),
                onPressed: () {
                  context.to(
                      () => RelatedIllustsPage(widget.illust.id.toString()));
                }),
          ],
        );
      },
    );
  }

  void favorite([String type = "public"]) async {
    if (isBookmarking) return;
    setState(() {
      isBookmarking = true;
    });
    var method = widget.illust.isBookmarked ? "delete" : "add";
    var res =
        await Network().addBookmark(widget.illust.id.toString(), method, type);
    if (res.error) {
      if (mounted) {
        context.showToast(message: "Network Error");
      }
    } else {
      widget.illust.isBookmarked = !widget.illust.isBookmarked;
    }
    setState(() {
      isBookmarking = false;
    });
  }

  Widget buildButton() {
    Widget child;
    if (isBookmarking) {
      child = const SizedBox(
        width: 14,
        height: 14,
        child: ProgressRing(
          strokeWidth: 1.6,
        ),
      );
    } else if (widget.illust.isBookmarked) {
      child = Icon(
        MdIcons.favorite,
        color: Colors.red,
        size: 22,
      );
    } else {
      child = Icon(
        MdIcons.favorite,
        color: ColorScheme.of(context).outline,
        size: 22,
      );
    }

    return SizedBox(
      height: 24,
      width: 24,
      child: MouseRegion(
        cursor: SystemMouseCursors.click,
        child: GestureDetector(
          onTap: favorite,
          child: Center(
            child: child,
          ),
        ),
      ),
    );
  }
}

class IllustHistoryWidget extends StatelessWidget {
  const IllustHistoryWidget(this.illust, {super.key});

  final IllustHistory illust;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constrains) {
      final width = constrains.maxWidth;
      final height = illust.height * width / illust.width;
      return SizedBox(
        width: width,
        height: height,
        child: Stack(
          children: [
            Positioned.fill(
                child: Container(
              width: width,
              height: height,
              padding:
                  const EdgeInsets.symmetric(horizontal: 8.0, vertical: 8.0),
              child: Card(
                padding: EdgeInsets.zero,
                margin: EdgeInsets.zero,
                child: GestureDetector(
                  onTap: () {
                    context.to(() => IllustPageWithId(illust.id.toString()));
                  },
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(4.0),
                    child: AnimatedImage(
                      image: CachedImageProvider(illust.imgPath),
                      fit: BoxFit.cover,
                      width: width - 16.0,
                      height: height - 16.0,
                    ),
                  ),
                ),
              ),
            )),
            if (illust.imageCount > 1)
              Positioned(
                top: 12,
                left: 12,
                child: Container(
                    width: 28,
                    height: 20,
                    decoration: BoxDecoration(
                      color: FluentTheme.of(context)
                          .micaBackgroundColor
                          .toOpacity(0.72),
                      borderRadius: BorderRadius.circular(4),
                      border: Border.all(
                          color: ColorScheme.of(context).outlineVariant,
                          width: 0.6),
                    ),
                    child: Center(
                      child: Text(
                        "${illust.imageCount}P",
                        style: const TextStyle(fontSize: 12),
                      ),
                    )),
              ),
            if (illust.isAi)
              Positioned(
                bottom: 12,
                left: 12,
                child: Container(
                    width: 28,
                    height: 20,
                    decoration: BoxDecoration(
                      color: ColorScheme.of(context)
                          .errorContainer
                          .toOpacity(0.8),
                      borderRadius: BorderRadius.circular(4),
                      border: Border.all(
                          color: ColorScheme.of(context).outlineVariant,
                          width: 0.6),
                    ),
                    child: const Center(
                      child: Text(
                        "AI",
                        style: TextStyle(fontSize: 12),
                      ),
                    )),
              ),
            if (illust.isGif)
              Positioned(
                bottom: 12,
                left: 12,
                child: Container(
                    width: 28,
                    height: 20,
                    decoration: BoxDecoration(
                      color: ColorScheme.of(context)
                          .primaryContainer
                          .toOpacity(0.8),
                      borderRadius: BorderRadius.circular(4),
                      border: Border.all(
                          color: ColorScheme.of(context).outlineVariant,
                          width: 0.6),
                    ),
                    child: const Center(
                      child: Text(
                        "GIF",
                        style: TextStyle(fontSize: 12),
                      ),
                    )),
              ),
            if (illust.isR18)
              Positioned(
                bottom: 12,
                right: 12,
                child: Container(
                    width: 28,
                    height: 20,
                    decoration: BoxDecoration(
                      color: ColorScheme.of(context).errorContainer,
                      borderRadius: BorderRadius.circular(4),
                      border: Border.all(
                          color: ColorScheme.of(context).outlineVariant,
                          width: 0.6),
                    ),
                    child: const Center(
                      child: Text(
                        "R18",
                        style: TextStyle(fontSize: 12),
                      ),
                    )),
              ),
            if (illust.isR18G)
              Positioned(
                bottom: 12,
                right: 12,
                child: Container(
                    width: 28,
                    height: 20,
                    decoration: BoxDecoration(
                      color: ColorScheme.of(context).errorContainer,
                      borderRadius: BorderRadius.circular(4),
                      border: Border.all(
                          color: ColorScheme.of(context).outlineVariant,
                          width: 0.6),
                    ),
                    child: const Center(
                      child: Text(
                        "R18G",
                        style: TextStyle(fontSize: 12),
                      ),
                    )),
              ),
          ],
        ),
      );
    });
  }
}


================================================
FILE: lib/components/keyboard.dart
================================================
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pixes/foundation/app.dart';

typedef KeyEventHandler = void Function(LogicalKeyboardKey key);

class KeyEventListener extends StatefulWidget {
  const KeyEventListener({required this.child, super.key});

  final Widget child;

  static KeyEventListenerState? of(BuildContext context) {
    return context.findAncestorStateOfType<KeyEventListenerState>();
  }

  @override
  State<KeyEventListener> createState() => KeyEventListenerState();
}

class KeyEventListenerState extends State<KeyEventListener> {
  final focusNode = FocusNode();

  final List<KeyEventHandler> _handlers = [];

  void addHandler(KeyEventHandler handler) {
    _handlers.add(handler);
  }

  void removeHandler(KeyEventHandler handler) {
    _handlers.remove(handler);
  }

  void removeAll() {
    _handlers.clear();
  }

  @override
  Widget build(BuildContext context) {
    return Focus(
      focusNode: focusNode,
      autofocus: true,
      onKeyEvent: (node, event) {
        if (event is! KeyUpEvent) return KeyEventResult.ignored;
        if (event.logicalKey == LogicalKeyboardKey.escape) {
          if (App.rootNavigatorKey.currentState?.canPop() ?? false) {
            App.rootNavigatorKey.currentState?.pop();
          } else if (App.mainNavigatorKey?.currentState?.canPop() ?? false) {
            App.mainNavigatorKey?.currentState?.pop();
          }
          return KeyEventResult.handled;
        }
        for (var handler in _handlers) {
          handler(event.logicalKey);
        }
        return KeyEventResult.ignored;
      },
      child: widget.child,
    );
  }
}


================================================
FILE: lib/components/loading.dart
================================================
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/foundation/app.dart';
import 'package:pixes/network/res.dart';

abstract class LoadingState<T extends StatefulWidget, S extends Object> extends State<T>{
  bool isLoading = false;

  S? data;

  String? error;

  Future<Res<S>> loadData();

  Widget buildContent(BuildContext context, S data);

  Widget? buildFrame(BuildContext context, Widget child) => null;

  Widget buildLoading() {
    return const Center(
      child: ProgressRing(),
    );
  }

  void retry() {
    setState(() {
      isLoading = true;
      error = null;
    });
    loadData().then((value) {
      if(value.success) {
        setState(() {
          isLoading = false;
          data = value.data;
        });
      } else {
        setState(() {
          isLoading = false;
          error = value.errorMessage!;
        });
      }
    });
  }

  Widget buildError() {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(error!),
          const SizedBox(height: 12),
          Button(
            onPressed: retry,
            child: const Text("Retry"),
          )
        ],
      ),
    ).paddingHorizontal(16);
  }

  @override
  @mustCallSuper
  void initState() {
    isLoading = true;
    loadData().then((value) {
      if(value.success) {
        setState(() {
          isLoading = false;
          data = value.data;
        });
      } else {
        setState(() {
          isLoading = false;
          error = value.errorMessage!;
        });
      }
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    Widget child;

    if(isLoading){
      child = buildLoading();
    } else if (error != null){
      child = buildError();
    } else {
      child = buildContent(context, data!);
    }

    return buildFrame(context, child) ?? child;
  }
}

abstract class MultiPageLoadingState<T extends StatefulWidget, S extends Object> extends State<T>{
  bool _isFirstLoading = true;

  bool _isLoading = false;

  List<S>? _data;

  String? _error;

  int _page = 1;

  Future<Res<List<S>>> loadData(int page);

  Widget? buildFrame(BuildContext context, Widget child) => null;

  Widget buildContent(BuildContext context, List<S> data);

  bool get isLoading => _isLoading || _isFirstLoading;

  bool get isFirstLoading => _isFirstLoading;

  void nextPage() {
    if(_isLoading) return;
    _isLoading = true;
    loadData(_page).then((value) {
      _isLoading = false;
      if(value.success) {
        _page++;
        setState(() {
          _data!.addAll(value.data);
        });
      } else {
        var message = value.errorMessage ?? "Network Error";
        if(message == "No more data") {
          return;
        }
        if(message.length > 20) {
          message = "${message.substring(0, 20)}...";
        }
        if (mounted) {
          context.showToast(message: message);
        }
      }
    });
  }

  void reset() {
    setState(() {
      _isFirstLoading = true;
      _isLoading = false;
      _data = null;
      _error = null;
      _page = 1;
    });
    firstLoad();
  }

  void firstLoad() {
    loadData(_page).then((value) {
      if (!mounted) return;
      if(value.success) {
        _page++;
        setState(() {
          _isFirstLoading = false;
          _data = value.data;
        });
      } else {
        setState(() {
          _isFirstLoading = false;
          _error = value.errorMessage!;
        });
      }
    });
  }

  @override
  void initState() {
    firstLoad();
    super.initState();
  }

  Widget buildLoading(BuildContext context) {
    return const Center(
      child: ProgressRing(),
    );
  }

  Widget buildError(BuildContext context, String error) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(error),
          const SizedBox(height: 12),
          Button(
            onPressed: () {
              reset();
            },
            child: const Text("Retry"),
          )
        ],
      ),
    ).paddingHorizontal(16);
  }

  @override
  Widget build(BuildContext context) {
    Widget child;

    if(_isFirstLoading){
      child = buildLoading(context);
    } else if (_error != null){
      child = buildError(context, _error!);
    } else {
      child = buildContent(context, _data!);
    }

    return buildFrame(context, child) ?? child;
  }
}


================================================
FILE: lib/components/md.dart
================================================
import 'package:flutter/material.dart' as md;

typedef MdIcons = md.Icons;
typedef MdTheme = md.Theme;
typedef MdThemeData = md.ThemeData;
typedef MdColorScheme = md.ColorScheme;
typedef TextField = md.TextField;

class ColorScheme {
  static md.ColorScheme of(md.BuildContext context) {
    return md.Theme.of(context).colorScheme;
  }
}

================================================
FILE: lib/components/message.dart
================================================
import 'dart:async';

import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/components/md.dart';
import 'package:pixes/foundation/app.dart';

void showToast(BuildContext context, {required String message, IconData? icon}) {
  var newEntry = OverlayEntry(
      builder: (context) => ToastOverlay(message: message, icon: icon));

  var overlay = OverlayWidget.of(context);

  overlay?.addOverlay(newEntry);

  Timer(const Duration(seconds: 2), () => overlay?.remove(newEntry));
}

class ToastOverlay extends StatelessWidget {
  const ToastOverlay({required this.message, this.icon, super.key});

  final String message;

  final IconData? icon;

  @override
  Widget build(BuildContext context) {
    return Positioned(
      bottom: 24 + MediaQuery.of(context).viewInsets.bottom,
      left: 0,
      right: 0,
      child: Align(
        alignment: Alignment.bottomCenter,
        child: PhysicalModel(
          color: ColorScheme.of(context).surface.toOpacity(1),
          borderRadius: BorderRadius.circular(4),
          elevation: 1,
          child: Container(
            padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                if (icon != null) Icon(icon),
                if (icon != null)
                  const SizedBox(
                    width: 8,
                  ),
                Text(
                  message,
                  style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w500,
                      color: ColorScheme.of(context).onSurface
                  ),
                  maxLines: 3,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class OverlayWidget extends StatefulWidget {
  const OverlayWidget(this.child, {super.key});

  final Widget child;

  static OverlayWidgetState? of(BuildContext context) {
    return LookupBoundary.findAncestorStateOfType<OverlayWidgetState>(context);
  }

  @override
  State<OverlayWidget> createState() => OverlayWidgetState();
}

class OverlayWidgetState extends State<OverlayWidget> {
  var overlayKey = GlobalKey<OverlayState>();

  var entries = <OverlayEntry>[];

  void addOverlay(OverlayEntry entry) {
    if (overlayKey.currentState != null) {
      overlayKey.currentState!.insert(entry);
      entries.add(entry);
    }
  }

  void remove(OverlayEntry entry) {
    if (entries.remove(entry)) {
      entry.remove();
    }
  }

  void removeAll() {
    for (var entry in entries) {
      entry.remove();
    }
    entries.clear();
  }

  @override
  Widget build(BuildContext context) {
    return Overlay(
      key: overlayKey,
      initialEntries: [OverlayEntry(builder: (context) => widget.child)],
    );
  }
}


================================================
FILE: lib/components/novel.dart
================================================
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/components/animated_image.dart';
import 'package:pixes/components/md.dart';
import 'package:pixes/foundation/app.dart';
import 'package:pixes/foundation/image_provider.dart';
import 'package:pixes/network/network.dart';
import 'package:pixes/pages/novel_page.dart';

class NovelWidget extends StatefulWidget {
  const NovelWidget(this.novel, {super.key});

  final Novel novel;

  @override
  State<NovelWidget> createState() => _NovelWidgetState();
}

class _NovelWidgetState extends State<NovelWidget> {
  @override
  Widget build(BuildContext context) {
    return Card(
      margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      child: GestureDetector(
        onTap: () {
          context.to(() => NovelPage(widget.novel));
        },
        behavior: HitTestBehavior.opaque,
        child: Row(
          children: [
            Container(
              width: 96,
              height: double.infinity,
              decoration: BoxDecoration(
                color: ColorScheme.of(context).secondaryContainer,
                borderRadius: BorderRadius.circular(4),
              ),
              clipBehavior: Clip.antiAlias,
              child: AnimatedImage(
                fit: BoxFit.cover,
                filterQuality: FilterQuality.medium,
                width: double.infinity,
                height: double.infinity,
                image: CachedImageProvider(widget.novel.image),
              ),
            ),
            const SizedBox(
              width: 12,
            ),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    widget.novel.title,
                    maxLines: 2,
                    style: const TextStyle(
                        fontSize: 16, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(
                    height: 4,
                  ),
                  Expanded(
                    child: Text(
                      widget.novel.caption.trim().replaceAll('<br />', '\n'),
                      maxLines: 3,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                  const SizedBox(
                    height: 4,
                  ),
                  Text(
                    widget.novel.author.name,
                    style: const TextStyle(fontSize: 12),
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}


================================================
FILE: lib/components/page_route.dart
================================================
import 'dart:math';
import 'dart:ui';
import 'package:flutter/gestures.dart';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/material.dart' show PredictiveBackPageTransitionsBuilder;
import 'package:pixes/foundation/app.dart';

const double _kBackGestureWidth = 20.0;
const int _kMaxDroppedSwipePageForwardAnimationTime = 800;
const int _kMaxPageBackAnimationTime = 300;
const double _kMinFlingVelocity = 1.0;

class AppPageRoute<T> extends PageRoute<T> with _AppRouteTransitionMixin {
  /// Construct a MaterialPageRoute whose contents are defined by [builder].
  AppPageRoute({
    required this.builder,
    super.settings,
    this.maintainState = true,
    super.fullscreenDialog,
    super.allowSnapshotting = true,
    super.barrierDismissible = false,
    this.enableIOSGesture = true,
    this.preventRebuild = true,
    this.isRoot = false,
  }) {
    assert(opaque);
  }

  /// Builds the primary contents of the route.
  final WidgetBuilder builder;

  @override
  Widget buildContent(BuildContext context) {
    return builder(context);
  }

  @override
  final bool maintainState;

  @override
  String get debugLabel => '${super.debugLabel}(${settings.name})';

  @override
  final bool enableIOSGesture;

  @override
  final bool preventRebuild;

  @override
  final bool isRoot;

  static void updateBackButton() {
    Future.delayed(const Duration(milliseconds: 300), () {
      StateController.findOrNull(tag: "back_button")?.update();
    });
  }
}

mixin _AppRouteTransitionMixin<T> on PageRoute<T> {
  /// Builds the primary contents of the route.
  @protected
  Widget buildContent(BuildContext context);

  @override
  Duration get transitionDuration => const Duration(milliseconds: 300);

  @override
  Color? get barrierColor => null;

  @override
  String? get barrierLabel => null;

  @override
  bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
    // Don't perform outgoing animation if the next route is a fullscreen dialog.
    return nextRoute is PageRoute && !nextRoute.fullscreenDialog;
  }

  bool get enableIOSGesture;

  bool get preventRebuild;

  Widget? _child;

  bool get isRoot;

  @override
  Widget buildPage(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
  ) {
    Widget result;

    if (preventRebuild) {
      result = _child ?? (_child = buildContent(context));
    } else {
      result = buildContent(context);
    }

    return Semantics(
      scopesRoute: true,
      explicitChildNodes: true,
      child: result,
    );
  }

  static bool _isPopGestureEnabled<T>(PageRoute<T> route) {
    if (route.isFirst ||
        route.willHandlePopInternally ||
        route.popDisposition == RoutePopDisposition.doNotPop ||
        route.fullscreenDialog ||
        route.animation!.status != AnimationStatus.completed ||
        route.secondaryAnimation!.status != AnimationStatus.dismissed ||
        route.navigator!.userGestureInProgress) {
      return false;
    }

    return true;
  }

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation, Widget child) {
    child = ColoredBox(
      color: FluentTheme.of(context).micaBackgroundColor,
      child: child,
    );

    if (isRoot) {
      child = EntrancePageTransition(
        animation: CurvedAnimation(
          parent: animation,
          curve: FluentTheme.of(context).animationCurve,
        ),
        child: enableIOSGesture && App.isIOS
            ? IOSBackGestureDetector(
                gestureWidth: _kBackGestureWidth,
                enabledCallback: () => _isPopGestureEnabled<T>(this),
                onStartPopGesture: () => _startPopGesture(this),
                child: child)
            : child,
      );
    } else {
      if (App.isAndroid) {
        child = const PredictiveBackPageTransitionsBuilder().buildTransitions(
          this, 
          context, 
          animation, 
          secondaryAnimation, 
          child,
        );
      } else {
        child = DrillInPageTransition(
          animation: CurvedAnimation(
            parent: animation,
            curve: FluentTheme
                .of(context)
                .animationCurve,
          ),
          child: enableIOSGesture && App.isIOS
              ? IOSBackGestureDetector(
              gestureWidth: _kBackGestureWidth,
              enabledCallback: () => _isPopGestureEnabled<T>(this),
              onStartPopGesture: () => _startPopGesture(this),
              child: child)
              : child,
        );
      }
    }

    return child;
  }

  IOSBackGestureController _startPopGesture(PageRoute<T> route) {
    return IOSBackGestureController(route.controller!, route.navigator!);
  }
}

class IOSBackGestureController {
  final AnimationController controller;

  final NavigatorState navigator;

  IOSBackGestureController(this.controller, this.navigator) {
    navigator.didStartUserGesture();
  }

  void dragEnd(double velocity) {
    const Curve animationCurve = Curves.fastLinearToSlowEaseIn;
    final bool animateForward;

    if (velocity.abs() >= _kMinFlingVelocity) {
      animateForward = velocity <= 0;
    } else {
      animateForward = controller.value > 0.5;
    }

    if (animateForward) {
      final droppedPageForwardAnimationTime = min(
        lerpDouble(
                _kMaxDroppedSwipePageForwardAnimationTime, 0, controller.value)!
            .floor(),
        _kMaxPageBackAnimationTime,
      );
      controller.animateTo(1.0,
          duration: Duration(milliseconds: droppedPageForwardAnimationTime),
          curve: animationCurve);
    } else {
      navigator.pop();
      if (controller.isAnimating) {
        final droppedPageBackAnimationTime = lerpDouble(
                0, _kMaxDroppedSwipePageForwardAnimationTime, controller.value)!
            .floor();
        controller.animateBack(0.0,
            duration: Duration(milliseconds: droppedPageBackAnimationTime),
            curve: animationCurve);
      }
    }

    if (controller.isAnimating) {
      late AnimationStatusListener animationStatusCallback;
      animationStatusCallback = (status) {
        navigator.didStopUserGesture();
        controller.removeStatusListener(animationStatusCallback);
      };
      controller.addStatusListener(animationStatusCallback);
    } else {
      navigator.didStopUserGesture();
    }
  }

  void dragUpdate(double delta) {
    controller.value -= delta;
  }
}

class IOSBackGestureDetector extends StatefulWidget {
  const IOSBackGestureDetector(
      {required this.enabledCallback,
      required this.child,
      required this.gestureWidth,
      required this.onStartPopGesture,
      super.key});

  final double gestureWidth;

  final bool Function() enabledCallback;

  final IOSBackGestureController Function() onStartPopGesture;

  final Widget child;

  @override
  State<IOSBackGestureDetector> createState() => _IOSBackGestureDetectorState();
}

class _IOSBackGestureDetectorState extends State<IOSBackGestureDetector> {
  IOSBackGestureController? _backGestureController;

  late HorizontalDragGestureRecognizer _recognizer;

  @override
  void dispose() {
    _recognizer.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    _recognizer = HorizontalDragGestureRecognizer(debugOwner: this)
      ..onStart = _handleDragStart
      ..onUpdate = _handleDragUpdate
      ..onEnd = _handleDragEnd
      ..onCancel = _handleDragCancel;
  }

  @override
  Widget build(BuildContext context) {
    var dragAreaWidth = Directionality.of(context) == TextDirection.ltr
        ? MediaQuery.of(context).padding.left
        : MediaQuery.of(context).padding.right;
    dragAreaWidth = max(dragAreaWidth, widget.gestureWidth);
    return Stack(
      fit: StackFit.passthrough,
      children: <Widget>[
        widget.child,
        Positioned(
          width: dragAreaWidth,
          top: 0.0,
          bottom: 0.0,
          left: 0,
          child: Listener(
            onPointerDown: _handlePointerDown,
            behavior: HitTestBehavior.translucent,
          ),
        ),
      ],
    );
  }

  void _handlePointerDown(PointerDownEvent event) {
    if (widget.enabledCallback()) _recognizer.addPointer(event);
  }

  void _handleDragCancel() {
    assert(mounted);
    _backGestureController?.dragEnd(0.0);
    _backGestureController = null;
  }

  double _convertToLogical(double value) {
    switch (Directionality.of(context)) {
      case TextDirection.rtl:
        return -value;
      case TextDirection.ltr:
        return value;
    }
  }

  void _handleDragEnd(DragEndDetails details) {
    assert(mounted);
    assert(_backGestureController != null);
    _backGestureController!.dragEnd(_convertToLogical(
        details.velocity.pixelsPerSecond.dx / context.size!.width));
    _backGestureController = null;
  }

  void _handleDragStart(DragStartDetails details) {
    assert(mounted);
    assert(_backGestureController == null);
    _backGestureController = widget.onStartPopGesture();
  }

  void _handleDragUpdate(DragUpdateDetails details) {
    assert(mounted);
    assert(_backGestureController != null);
    _backGestureController!.dragUpdate(
        _convertToLogical(details.primaryDelta! / context.size!.width));
  }
}

const _kSideBarWidth = 420.0;

class SideBarRoute<T> extends PopupRoute<T> {
  SideBarRoute(this.child);

  final Widget child;

  @override
  Color? get barrierColor => Colors.transparent;

  @override
  bool get barrierDismissible => true;

  @override
  String? get barrierLabel => "side bar";

  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation) {
    return Align(
      alignment: Alignment.centerRight,
      child: Stack(
        children: [
          Positioned(
            right: 0,
            top: 0,
            bottom: 0,
            child: Container(
              decoration: BoxDecoration(
                  color: FluentTheme.of(context)
                      .micaBackgroundColor
                      .toOpacity(0.98),
                  borderRadius: const BorderRadius.only(
                      topLeft: Radius.circular(4),
                      bottomLeft: Radius.circular(4))),
              constraints: BoxConstraints(
                  maxWidth:
                      min(_kSideBarWidth, MediaQuery.of(context).size.width)),
              width: double.infinity,
              child: child,
            ),
          )
        ],
      ),
    );
  }

  @override
  Duration get transitionDuration => const Duration(milliseconds: 200);

  static bool _isPopGestureEnabled<T>(PopupRoute<T> route) {
    if (route.isFirst ||
        route.willHandlePopInternally ||
        route.popDisposition == RoutePopDisposition.doNotPop ||
        route.animation!.status != AnimationStatus.completed ||
        route.secondaryAnimation!.status != AnimationStatus.dismissed ||
        route.navigator!.userGestureInProgress) {
      return false;
    }

    return true;
  }

  bool get enableIOSGesture => true;

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation, Widget child) {
    var offset =
        Tween<Offset>(begin: const Offset(1, 0), end: const Offset(0, 0));
    return SlideTransition(
      position: offset.animate(CurvedAnimation(
        parent: animation,
        curve: Curves.fastOutSlowIn,
      )),
      child: enableIOSGesture
          ? IOSBackGestureDetector(
              gestureWidth: _kBackGestureWidth,
              enabledCallback: () => _isPopGestureEnabled<T>(this),
              onStartPopGesture: () => _startPopGesture(this),
              child: child)
          : child,
    );
  }

  IOSBackGestureController _startPopGesture(PopupRoute<T> route) {
    return IOSBackGestureController(route.controller!, route.navigator!);
  }
}

class EntrancePageTransition extends StatelessWidget {
  /// Creates an entrance page transition
  const EntrancePageTransition({
    super.key,
    required this.child,
    required this.animation,
  });

  /// The widget to be animated
  final Widget child;

  /// The animation to drive this transition
  final Animation<double> animation;

  @override
  Widget build(BuildContext context) {
    return SlideTransition(
      position: Tween<Offset>(
        begin: const Offset(0, 0.1),
        end: Offset.zero,
      ).animate(animation),
      child: FadeTransition(
        opacity: animation,
        child: child,
      ),
    );
  }
}


================================================
FILE: lib/components/search_field.dart
================================================
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/foundation/app.dart';

class AutoCompleteItem {
  final String title;
  final String? subtitle;
  final VoidCallback onTap;

  const AutoCompleteItem({
    required this.title,
    this.subtitle,
    required this.onTap,
  });
}

class AutoCompleteData {
  final List<AutoCompleteItem> items;
  final bool isLoading;

  const AutoCompleteData({
    this.items = const <AutoCompleteItem>[],
    this.isLoading = false,
  });
}

class SearchField extends StatefulWidget {
  const SearchField({
    super.key,
    this.autoCompleteItems = const <AutoCompleteItem>[],
    this.isLoadingAutoCompleteItems = false,
    this.enableAutoComplete = true,
    this.textEditingController,
    this.placeholder,
    this.leading,
    this.trailing,
    this.foregroundDecoration,
    this.onChanged,
    this.onSubmitted,
    this.padding,
    this.focusNode,
    this.autoCompleteNoResultsText,
  });

  final List<AutoCompleteItem> autoCompleteItems;

  final bool isLoadingAutoCompleteItems;

  final bool enableAutoComplete;

  final TextEditingController? textEditingController;

  final String? placeholder;

  final Widget? leading;

  final Widget? trailing;

  final WidgetStatePropertyAll<BoxDecoration>? foregroundDecoration;

  final void Function(String)? onChanged;

  final void Function(String)? onSubmitted;

  final EdgeInsets? padding;

  final FocusNode? focusNode;

  final String? autoCompleteNoResultsText;

  @override
  State<SearchField> createState() => _SearchFieldState();
}

class _SearchFieldState extends State<SearchField> with TickerProviderStateMixin {
  late final ValueNotifier<AutoCompleteData> autoCompleteItems;

  late final FocusNode focusNode;

  final boxKey = GlobalKey();

  OverlayEntry? _overlayEntry;

  AnimationController? _animationController;
  Animation<double>? _fadeAnimation;

  @override
  void initState() {
    autoCompleteItems = ValueNotifier(AutoCompleteData(
      items: widget.autoCompleteItems,
      isLoading: widget.isLoadingAutoCompleteItems,
    ));
    focusNode = widget.focusNode ?? FocusNode();
    focusNode.addListener(onfocusChange);
    super.initState();
  }

  @override
  void dispose() {
    _animationController?.dispose();
    focusNode.removeListener(onfocusChange);
    if (widget.focusNode == null) {
      focusNode.dispose();
    }
    super.dispose();
  }

  @override
  void didUpdateWidget(covariant SearchField oldWidget) {
    if (widget.autoCompleteItems != oldWidget.autoCompleteItems ||
        widget.isLoadingAutoCompleteItems !=
            oldWidget.isLoadingAutoCompleteItems) {
      Future.microtask(() {
        autoCompleteItems.value = AutoCompleteData(
          items: widget.autoCompleteItems,
          isLoading: widget.isLoadingAutoCompleteItems,
        );
      });
    }
    super.didUpdateWidget(oldWidget);
  }

  void onfocusChange() {
    if (focusNode.hasFocus && widget.enableAutoComplete) {
      final box = context.findRenderObject() as RenderBox?;
      if (box == null) return;
      final overlay = Overlay.of(context);
      final position = box.localToGlobal(
        Offset.zero,
        ancestor: overlay.context.findRenderObject(),
      );

      if (_overlayEntry != null) {
        _removeOverlayWithAnimation();
      }

      _animationController = AnimationController(
        duration: const Duration(milliseconds: 200),
        vsync: this,
      );

      _fadeAnimation = Tween<double>(
        begin: 0.0,
        end: 1.0,
      ).animate(CurvedAnimation(
        parent: _animationController!,
        curve: Curves.easeOut,
      ));

      _overlayEntry = OverlayEntry(
        builder: (context) {
          return Positioned(
            left: position.dx,
            width: box.size.width,
            top: position.dy + box.size.height,
            child: _AnimatedOverlayWrapper(
              animation: _fadeAnimation!,
              child: _AutoCompleteOverlay(
                data: autoCompleteItems,
                noResultsText: widget.autoCompleteNoResultsText,
              ),
            ),
          );
        },
      );

      overlay.insert(_overlayEntry!);
      _animationController!.forward();
    } else {
      _removeOverlayWithAnimation();
    }
  }

  void _removeOverlayWithAnimation() {
    if (_overlayEntry != null && _animationController != null) {
      _animationController!.reverse().then((_) {
        _overlayEntry?.remove();
        _overlayEntry = null;
        _animationController?.dispose();
        _animationController = null;
        _fadeAnimation = null;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return TextBox(
      controller: widget.textEditingController,
      key: boxKey,
      focusNode: focusNode,
      padding: const EdgeInsets.symmetric(horizontal: 12),
      placeholder: widget.placeholder,
      onChanged: widget.onChanged,
      onSubmitted: widget.onSubmitted,
      foregroundDecoration: widget.foregroundDecoration,
      prefix: widget.leading,
      suffix: widget.trailing,
    );
  }
}

class _AutoCompleteOverlay extends StatefulWidget {
  const _AutoCompleteOverlay({required this.data, this.noResultsText});

  final ValueNotifier<AutoCompleteData> data;

  final String? noResultsText;

  @override
  State<_AutoCompleteOverlay> createState() => _AutoCompleteOverlayState();
}

class _AutoCompleteOverlayState extends State<_AutoCompleteOverlay> {
  late final notifier = widget.data;

  var items = <AutoCompleteItem>[];

  var isLoading = false;

  @override
  void initState() {
    items = notifier.value.items;
    isLoading = notifier.value.isLoading;
    notifier.addListener(onItemsChanged);
    super.initState();
  }

  @override
  void dispose() {
    notifier.removeListener(onItemsChanged);
    super.dispose();
  }

  void onItemsChanged() {
    setState(() {
      items = notifier.value.items;
      isLoading = notifier.value.isLoading;
    });
  }

  @override
  Widget build(BuildContext context) {
    var items = List<AutoCompleteItem>.from(this.items);

    Widget? content;

    if (isLoading) {
      content = SizedBox(
        height: 44,
        child: Center(
          child: ProgressRing(
            activeColor: FluentTheme.of(context).accentColor,
            strokeWidth: 2,
          ).fixWidth(24).fixHeight(24),
        ),
      );
    } else if (items.isEmpty) {
      content = ListTile(
        title: Text(widget.noResultsText ?? 'No results found'),
        onPressed: () {},
      );
    } else {
      if (items.length > 8) {
        items = items.sublist(0, 8);
      }
      content = Column(
        mainAxisSize: MainAxisSize.min,
        children: items.map((item) {
          return ListTile(
            title: Text(item.title),
            subtitle: item.subtitle != null ? Text(item.subtitle!) : null,
            onPressed: item.onTap,
          );
        }).toList(),
      );
    }

    return Card(
      backgroundColor: FluentTheme.of(context).micaBackgroundColor,
      child: AnimatedSize(
        alignment: Alignment.topCenter,
        duration: const Duration(milliseconds: 160),
        child: content,
      ),
    );
  }
}

class _AnimatedOverlayWrapper extends StatelessWidget {
  const _AnimatedOverlayWrapper({
    required this.animation,
    required this.child,
  });

  final Animation<double> animation;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: animation,
      builder: (context, child) {
        return FadeTransition(
          opacity: animation,
          child: Transform.scale(
            scale: 0.9 + (0.1 * animation.value),
            alignment: Alignment.topCenter,
            child: child,
          ),
        );
      },
      child: child,
    );
  }
}


================================================
FILE: lib/components/segmented_button.dart
================================================
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/foundation/app.dart';

import 'md.dart';

class SegmentedButton<T> extends StatelessWidget {
  const SegmentedButton(
      {required this.options,
      required this.value,
      required this.onPressed,
      super.key});

  final List<SegmentedButtonOption<T>> options;

  final T value;

  final void Function(T key) onPressed;

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.centerLeft,
      child: Card(
        padding: EdgeInsets.zero,
        child: SizedBox(
          height: 28,
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: options.map((e) => buildButton(e)).toList(),
          ),
        ),
      ),
    );
  }

  Widget buildButton(SegmentedButtonOption<T> e) {
    bool active = value == e.key;
    return HoverButton(
        cursor: active ? MouseCursor.defer : SystemMouseCursors.click,
        onPressed: () => onPressed(e.key),
        builder: (context, states) {
          var textColor = active ? null : ColorScheme.of(context).outline;
          var backgroundColor = active ? null : WidgetStateProperty.resolveWith((states) {
            return ButtonThemeData.buttonColor(context, states);
          }).resolve(states);

          return Container(
            decoration: BoxDecoration(
                color: backgroundColor,
                border: e != options.last
                    ? Border(
                        right: BorderSide(
                            width: 0.6,
                            color: ColorScheme.of(context).outlineVariant))
                    : null),
            child: Center(
              child: Text(e.text,
                      style: TextStyle(
                          color: textColor, fontWeight: FontWeight.w500))
                  .paddingHorizontal(12),
            ),
          );
        });
  }
}

class SegmentedButtonOption<T> {
  final T key;
  final String text;

  const SegmentedButtonOption(this.key, this.text);
}


================================================
FILE: lib/components/title_bar.dart
================================================
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/foundation/app.dart';

class TitleBar extends StatelessWidget {
  const TitleBar({required this.title, this.action, super.key});

  final String title;

  final Widget? action;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      child: Row(
        children: [
          Text(title,
            style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
          const Spacer(),
          if(action != null)
            action!
        ],
      ).paddingHorizontal(16).paddingVertical(8),
    );
  }
}

class SliverTitleBar extends StatelessWidget {
  const SliverTitleBar({required this.title, this.action, super.key});

  final String title;

  final Widget? action;


  @override
  Widget build(BuildContext context) {
    return SliverToBoxAdapter(
      child: SizedBox(
        child: Row(
          children: [
            Text(title,
              style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
            const Spacer(),
            if(action != null)
              action!
          ],
        ).paddingHorizontal(16).paddingVertical(8),
      ),
    );
  }
}


================================================
FILE: lib/components/ugoira.dart
================================================
import 'dart:convert';
import 'dart:io';
import 'package:archive/archive_io.dart';

import 'package:crypto/crypto.dart';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:intl/intl.dart';
import 'package:pixes/components/md.dart';
import 'package:pixes/network/network.dart';

import '../foundation/cache_manager.dart';
import '../network/app_dio.dart';
import 'dart:ui' as ui;

class UgoiraWidget extends StatefulWidget {
  const UgoiraWidget({super.key, required this.id, required this.previewImage,
    required this.width, required this.height});

  final String id;

  final ImageProvider previewImage;

  final double width;

  final double height;

  @override
  State<UgoiraWidget> createState() => _UgoiraWidgetState();
}

class _UgoiraWidgetState extends State<UgoiraWidget> {
  _UgoiraMetadata? _metadata;

  bool _loading = false;

  bool _finished = false;

  bool _error = false;

  int expectedBytes = 1;

  int receivedBytes = 0;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: widget.width,
      height: widget.height,
      child: !_finished
        ? buildPreview()
        : _UgoiraAnimation(metadata: _metadata!, key: Key(widget.id),),
    );
  }

  Widget buildPreview() {
    return Stack(
      children: [
        Positioned.fill(
          child: ClipRRect(
            borderRadius: BorderRadius.circular(4),
            child: Image(
              image: widget.previewImage,
              fit: BoxFit.cover,
            ),
          ),
        ),
        if(_error)
          const Positioned.fill(
            child: Center(
              child: Icon(
                MdIcons.error_outline,
                size: 36,
              ),
            )),
        if(!_loading)
          Positioned.fill(
            child: GestureDetector(
              onTap: load,
              child: const Center(
                child: Icon(
                  MdIcons.play_circle_outline,
                  size: 36,
                ),
              ),
            ),
          )
        else
          Center(
            child: ProgressRing(value: (receivedBytes / expectedBytes) * 100,),
          ),
      ],
    );
  }

  void load() async {
    setState(() {
      _loading = true;
    });
    var res0 = await Network().apiGet('/v1/ugoira/metadata?illust_id=${widget.id}');
    if(res0.error) {
      setState(() {
        _error = true;
        _loading = false;
      });
      return;
    }
    var json = res0.data;
    _metadata = _UgoiraMetadata(
      url: json["ugoira_metadata"]["zip_urls"]["medium"],
      frames: (json["ugoira_metadata"]["frames"] as List).map<_UgoiraFrame>((e) => _UgoiraFrame(
        delay: e["delay"],
        fileName: e["file"],
      )).toList(),
    );
    try {
      var key = "ugoira_${widget.id}";
      var cached = await CacheManager().findCache(key);
      if(cached != null) {
        await extract(cached);
        return;
      }
      var dio = AppDio();
      final time = DateFormat("yyyy-MM-dd'T'HH:mm:ss'+00:00'").format(DateTime.now());
      final hash = md5.convert(utf8.encode(time + Network.hashSalt)).toString();
      var res = await dio.get<ResponseBody>(
          _metadata!.url,
          options: Options(
              responseType: ResponseType.stream,
              validateStatus: (status) => status != null && status < 500,
              headers: {
                "referer": "https://app-api.pixiv.net/",
                "user-agent": "PixivAndroidApp/5.0.234 (Android 14; Pixes)",
                "x-client-time": time,
                "x-client-hash": hash,
                "accept-enconding": "gzip",
              }
          )
      );
      if(res.statusCode != 200) {
        throw "Failed to load image: ${res.statusCode}";
      }
      expectedBytes = int.parse(res.headers.value("content-length") ?? "1");
      var cachingFile = await CacheManager().openWrite(key);
      await for (var chunk in res.data!.stream) {
        await cachingFile.writeBytes(chunk);
        setState(() {
          receivedBytes += chunk.length;
          if(receivedBytes > expectedBytes) {
            expectedBytes = receivedBytes + 1;
          }
        });
      }
      await cachingFile.close();
      await extract(cachingFile.file.path);
    }
    catch(e) {
      setState(() {
        _error = true;
        _loading = false;
      });
      return;
    }
  }

  Future<void> extract(String filePath) async{
    var zip = ZipDecoder().decodeBytes(await File(filePath).readAsBytes());
    for(var file in zip) {
      if(file.isFile) {
        var frame = _metadata!.frames.firstWhere((element) => element.fileName == file.name);
        frame.data = await decodeImageFromList(file.content);
      }
    }
    zip.clear();
    setState(() {
      _loading = false;
      _finished = true;
    });
  }
}


class _UgoiraAnimation extends StatefulWidget {
  const _UgoiraAnimation({super.key, required this.metadata});

  final _UgoiraMetadata metadata;

  @override
  State<_UgoiraAnimation> createState() => _UgoiraAnimationState();
}

class _UgoiraAnimationState extends State<_UgoiraAnimation> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    final totalDuration = widget.metadata.frames.fold<int>(
        0, (previousValue, element) => previousValue + element.delay);
    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: totalDuration),
      value: 0,
      lowerBound: 0,
      upperBound: widget.metadata.frames.length.toDouble(),
    );
    _controller.repeat();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        final frame = widget.metadata.frames[_controller.value.toInt()];
        return CustomPaint(
          painter: _ImagePainter(frame.data!),
        );
      },
    );
  }
}

class _UgoiraMetadata {
  final String url;
  final List<_UgoiraFrame> frames;

  _UgoiraMetadata({required this.url, required this.frames});
}

class _UgoiraFrame {
  final int delay;
  final String fileName;
  ui.Image? data;

  _UgoiraFrame({required this.delay, required this.fileName});
}

class _ImagePainter extends CustomPainter {
  final ui.Image data;

  _ImagePainter(this.data);

  @override
  void paint(Canvas canvas, Size size) {
    // 覆盖整个画布
    Rect rect = Offset.zero & size;
    canvas.drawImageRect(
      data,
      Rect.fromLTRB(0, 0, data.width.toDouble(), data.height.toDouble()),
      rect,
      Paint()..filterQuality = FilterQuality.medium
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return data != (oldDelegate as _ImagePainter).data;
  }
}


================================================
FILE: lib/components/user_preview.dart
================================================
import 'dart:math';

import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/components/animated_image.dart';
import 'package:pixes/foundation/app.dart';
import 'package:pixes/foundation/image_provider.dart';
import 'package:pixes/pages/illust_page.dart';
import 'package:pixes/pages/user_info_page.dart';
import 'package:pixes/utils/translation.dart';

import '../network/network.dart';
import 'md.dart';

typedef UpdateFollowCallback = void Function(bool isFollowed);

class UserPreviewWidget extends StatefulWidget {
  const UserPreviewWidget(this.user, {super.key});

  final UserPreview user;

  static Map<String, UpdateFollowCallback> followCallbacks = {};

  @override
  State<UserPreviewWidget> createState() => _UserPreviewWidgetState();
}

class _UserPreviewWidgetState extends State<UserPreviewWidget> {
  @override
  void initState() {
    UserPreviewWidget.followCallbacks[widget.user.id.toString()] = (v) {
      setState(() {
        widget.user.isFollowed = v;
      });
    };
    super.initState();
  }

  @override
  void dispose() {
    UserPreviewWidget.followCallbacks.remove(widget.user.id.toString());
    super.dispose();
  }

  bool isFollowing = false;

  void follow() async {
    if (isFollowing) return;
    setState(() {
      isFollowing = true;
    });
    var method = widget.user.isFollowed ? "delete" : "add";
    var res = await Network().follow(widget.user.id.toString(), method);
    if (res.error) {
      if (mounted) {
        context.showToast(message: "Network Error");
      }
    } else {
      widget.user.isFollowed = !widget.user.isFollowed;
    }
    setState(() {
      isFollowing = false;
    });
    UserInfoPage.followCallbacks[widget.user.id.toString()]
        ?.call(widget.user.isFollowed);
    IllustPage.updateFollow(widget.user.id.toString(), widget.user.isFollowed);
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      margin: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
      child: GestureDetector(
        onTap: () => context.to(() => UserInfoPage(widget.user.id.toString())),
        behavior: HitTestBehavior.translucent,
        child: SizedBox.expand(
          child: Row(
            children: [
              SizedBox(
                width: 64,
                height: 64,
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(64),
                  child: ColoredBox(
                    color: ColorScheme.of(context).secondaryContainer,
                    child: AnimatedImage(
                      image: CachedImageProvider(widget.user.avatar),
                      fit: BoxFit.cover,
                      filterQuality: FilterQuality.medium,
                    ),
                  ),
                ),
              ),
              const SizedBox(
                width: 12,
              ),
              SizedBox(
                width: 96,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Spacer(),
                    Text(widget.user.name,
                        maxLines: 1,
                        style: const TextStyle(
                            fontSize: 16, fontWeight: FontWeight.bold)),
                    const SizedBox(
                      height: 12,
                    ),
                    Row(
                      children: [
                        if (isFollowing)
                          Button(
                              onPressed: follow,
                              child: const SizedBox(
                                width: 42,
                                height: 24,
                                child: Center(
                                  child: SizedBox.square(
                                    dimension: 18,
                                    child: ProgressRing(
                                      strokeWidth: 2,
                                    ),
                                  ),
                                ),
                              ))
                        else if (!widget.user.isFollowed)
                          Button(onPressed: follow, child: Text("Follow".tl))
                        else
                          Button(
                            onPressed: follow,
                            child: Text(
                              "Unfollow".tl,
                              style: TextStyle(
                                  color: ColorScheme.of(context).error),
                            ),
                          ),
                      ],
                    ),
                    const Spacer(),
                  ],
                ),
              ),
              Expanded(
                child: LayoutBuilder(
                  builder: (context, constraints) {
                    var count = constraints.maxWidth.toInt() ~/ 96;
                    var images = List.generate(
                        min(count, widget.user.artworks.length),
                        (index) => buildIllust(widget.user.artworks[index]));
                    return Row(
                      children: images,
                    );
                  },
                ),
              ),
              const Icon(
                FluentIcons.chevron_right,
                size: 14,
              )
            ],
          ),
        ),
      ),
    );
  }

  Widget buildIllust(Illust illust) {
    return SizedBox(
      width: 96,
      height: double.infinity,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 8),
        child: ClipRRect(
          borderRadius: BorderRadius.circular(4),
          child: ColoredBox(
            color: ColorScheme.of(context).secondaryContainer,
            child: AnimatedImage(
              width: double.infinity,
              height: double.infinity,
              fit: BoxFit.cover,
              filterQuality: FilterQuality.medium,
              image: CachedImageProvider(illust.images.first.medium),
            ),
          ),
        ),
      ),
    );
  }
}


================================================
FILE: lib/foundation/app.dart
================================================
import 'dart:io';
import 'dart:ui';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:path_provider/path_provider.dart';

import '../appdata.dart';

export "widget_utils.dart";
export "state_controller.dart";
export "navigation.dart";

class _App {
  final version = "1.2.1";

  bool get isAndroid => Platform.isAndroid;
  bool get isIOS => Platform.isIOS;
  bool get isWindows => Platform.isWindows;
  int? _windowsVersion;
  int get windowsVersion => _windowsVersion!;
  bool get isLinux => Platform.isLinux;
  bool get isMacOS => Platform.isMacOS;
  bool get isDesktop =>
      Platform.isWindows || Platform.isLinux || Platform.isMacOS;
  bool get isMobile => Platform.isAndroid || Platform.isIOS;

  Locale get locale {
    if (appdata.settings["language"] != "System") {
      return switch (appdata.settings["language"]) {
        "English" => const Locale("en"),
        "简体中文" => const Locale("zh", "CN"),
        "繁體中文" => const Locale("zh", "TW"),
        _ => const Locale("en"),
      };
    }
    Locale deviceLocale = PlatformDispatcher.instance.locale;
    if (deviceLocale.languageCode == "zh" &&
        deviceLocale.scriptCode == "Hant") {
      deviceLocale = const Locale("zh", "TW");
    }
    return deviceLocale;
  }

  late String dataPath;
  late String cachePath;

  init() async {
    cachePath = (await getApplicationCacheDirectory()).path;
    dataPath = (await getApplicationSupportDirectory()).path;
    if (App.isWindows) {
      final deviceInfoPlugin = DeviceInfoPlugin();
      final deviceInfo = await deviceInfoPlugin.windowsInfo;
      if (deviceInfo.majorVersion <= 6) {
        if (deviceInfo.minorVersion < 2) {
          _windowsVersion = 7;
        } else {
          _windowsVersion = 8;
        }
      } else if (deviceInfo.buildNumber < 22000) {
        _windowsVersion = 10;
      } else {
        _windowsVersion = 11;
      }
    }
  }

  final rootNavigatorKey = GlobalKey<NavigatorState>();

  GlobalKey<NavigatorState>? mainNavigatorKey;
}

// ignore: non_constant_identifier_names
final App = _App();


================================================
FILE: lib/foundation/cache_manager.dart
================================================
import 'dart:io';

import 'package:crypto/crypto.dart';
import 'package:flutter/foundation.dart';
import 'package:pixes/utils/io.dart';
import 'package:sqlite3/sqlite3.dart';

import 'app.dart';

class CacheManager {
  static String get cachePath => '${App.cachePath}/cache';

  static CacheManager? instance;

  late Database _db;

  int? _currentSize;

  /// size in bytes
  int get currentSize => _currentSize ?? 0;

  int dir = 0;

  int _limitSize = 2 * 1024 * 1024 * 1024;

  CacheManager._create(){
    Directory(cachePath).createSync(recursive: true);
    _db = sqlite3.open('${App.dataPath}/cache.db');
    _db.execute('''
      CREATE TABLE IF NOT EXISTS cache (
        key TEXT PRIMARY KEY NOT NULL,
        dir TEXT NOT NULL,
        name TEXT NOT NULL,
        expires INTEGER NOT NULL
      )
    ''');
    compute((path) => Directory(path).size, cachePath)
        .then((value) => _currentSize = value);
  }

  factory CacheManager() => instance ??= CacheManager._create();

  /// set cache size limit in bytes
  void setLimitSize(int size){
    _limitSize = size;
  }

  Future<void> writeCache(String key, Uint8List data, [int duration = 7 * 24 * 60 * 60 * 1000]) async{
    this.dir++;
    this.dir %= 100;
    var dir = this.dir;
    var name = md5.convert(Uint8List.fromList(key.codeUnits)).toString();
    var file = File('$cachePath/$dir/$name');
    while(await file.exists()){
      name = md5.convert(Uint8List.fromList(name.codeUnits)).toString();
      file = File('$cachePath/$dir/$name');
    }
    await file.create(recursive: true);
    await file.writeAsBytes(data);
    var expires = DateTime.now().millisecondsSinceEpoch + duration;
    _db.execute('
Download .txt
gitextract_i0cj6x04/

├── .github/
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .metadata
├── .vscode/
│   └── settings.json
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android/
│   ├── .gitignore
│   ├── app/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── debug/
│   │       │   └── AndroidManifest.xml
│   │       ├── main/
│   │       │   ├── AndroidManifest.xml
│   │       │   ├── kotlin/
│   │       │   │   └── com/
│   │       │   │       └── github/
│   │       │   │           └── wgh136/
│   │       │   │               └── pixes/
│   │       │   │                   └── MainActivity.kt
│   │       │   └── res/
│   │       │       ├── drawable/
│   │       │       │   └── launch_background.xml
│   │       │       ├── drawable-v21/
│   │       │       │   └── launch_background.xml
│   │       │       ├── mipmap-anydpi-v26/
│   │       │       │   └── ic_launcher.xml
│   │       │       ├── values/
│   │       │       │   └── styles.xml
│   │       │       └── values-night/
│   │       │           └── styles.xml
│   │       └── profile/
│   │           └── AndroidManifest.xml
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       └── gradle-wrapper.properties
│   ├── gradle.properties
│   └── settings.gradle
├── assets/
│   └── tr.json
├── debian/
│   ├── build.py
│   ├── debian.yaml
│   └── gui/
│       └── pixes.desktop
├── ios/
│   ├── .gitignore
│   ├── Flutter/
│   │   ├── AppFrameworkInfo.plist
│   │   ├── Debug.xcconfig
│   │   └── Release.xcconfig
│   ├── Podfile
│   ├── Runner/
│   │   ├── AppDelegate.swift
│   │   ├── Assets.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   └── LaunchImage.imageset/
│   │   │       ├── Contents.json
│   │   │       └── README.md
│   │   ├── Base.lproj/
│   │   │   ├── LaunchScreen.storyboard
│   │   │   └── Main.storyboard
│   │   ├── Info.plist
│   │   └── Runner-Bridging-Header.h
│   ├── 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
│   └── RunnerTests/
│       └── RunnerTests.swift
├── lib/
│   ├── appdata.dart
│   ├── components/
│   │   ├── animated_image.dart
│   │   ├── batch_download.dart
│   │   ├── button.dart
│   │   ├── grid.dart
│   │   ├── illust_widget.dart
│   │   ├── keyboard.dart
│   │   ├── loading.dart
│   │   ├── md.dart
│   │   ├── message.dart
│   │   ├── novel.dart
│   │   ├── page_route.dart
│   │   ├── search_field.dart
│   │   ├── segmented_button.dart
│   │   ├── title_bar.dart
│   │   ├── ugoira.dart
│   │   └── user_preview.dart
│   ├── foundation/
│   │   ├── app.dart
│   │   ├── cache_manager.dart
│   │   ├── history.dart
│   │   ├── image_provider.dart
│   │   ├── log.dart
│   │   ├── navigation.dart
│   │   ├── pair.dart
│   │   ├── state_controller.dart
│   │   └── widget_utils.dart
│   ├── main.dart
│   ├── network/
│   │   ├── app_dio.dart
│   │   ├── download.dart
│   │   ├── models.dart
│   │   ├── network.dart
│   │   ├── novel.dart
│   │   ├── res.dart
│   │   └── translator.dart
│   ├── pages/
│   │   ├── bookmarks.dart
│   │   ├── comments_page.dart
│   │   ├── downloaded_page.dart
│   │   ├── downloading_page.dart
│   │   ├── following_artworks.dart
│   │   ├── following_novels_page.dart
│   │   ├── following_users_page.dart
│   │   ├── history.dart
│   │   ├── illust_page.dart
│   │   ├── image_page.dart
│   │   ├── login_page.dart
│   │   ├── logs.dart
│   │   ├── main_page.dart
│   │   ├── novel_bookmarks_page.dart
│   │   ├── novel_page.dart
│   │   ├── novel_ranking_page.dart
│   │   ├── novel_reading_page.dart
│   │   ├── novel_recommendation_page.dart
│   │   ├── ranking.dart
│   │   ├── recommendation_page.dart
│   │   ├── related_page.dart
│   │   ├── search_page.dart
│   │   ├── settings_page.dart
│   │   ├── user_info_page.dart
│   │   └── webview_page.dart
│   └── utils/
│       ├── app_links.dart
│       ├── block.dart
│       ├── debounce.dart
│       ├── debug.dart
│       ├── ext.dart
│       ├── io.dart
│       ├── loop.dart
│       ├── mouse_listener.dart
│       ├── translation.dart
│       ├── update.dart
│       └── window.dart
├── linux/
│   ├── .gitignore
│   ├── CMakeLists.txt
│   ├── flutter/
│   │   ├── CMakeLists.txt
│   │   ├── generated_plugin_registrant.cc
│   │   ├── generated_plugin_registrant.h
│   │   └── generated_plugins.cmake
│   ├── main.cc
│   ├── my_application.cc
│   └── my_application.h
├── macos/
│   ├── .gitignore
│   ├── Flutter/
│   │   ├── Flutter-Debug.xcconfig
│   │   ├── Flutter-Release.xcconfig
│   │   └── GeneratedPluginRegistrant.swift
│   ├── Podfile
│   ├── Runner/
│   │   ├── AppDelegate.swift
│   │   ├── Assets.xcassets/
│   │   │   └── AppIcon.appiconset/
│   │   │       └── Contents.json
│   │   ├── Base.lproj/
│   │   │   └── MainMenu.xib
│   │   ├── Configs/
│   │   │   ├── AppInfo.xcconfig
│   │   │   ├── Debug.xcconfig
│   │   │   ├── Release.xcconfig
│   │   │   └── Warnings.xcconfig
│   │   ├── DebugProfile.entitlements
│   │   ├── Info.plist
│   │   ├── MainFlutterWindow.swift
│   │   └── Release.entitlements
│   ├── Runner.xcodeproj/
│   │   ├── project.pbxproj
│   │   ├── project.xcworkspace/
│   │   │   └── xcshareddata/
│   │   │       └── IDEWorkspaceChecks.plist
│   │   └── xcshareddata/
│   │       └── xcschemes/
│   │           └── Runner.xcscheme
│   ├── Runner.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcshareddata/
│   │       └── IDEWorkspaceChecks.plist
│   └── RunnerTests/
│       └── RunnerTests.swift
├── pubspec.yaml
├── test/
│   └── widget_test.dart
└── windows/
    ├── .gitignore
    ├── CMakeLists.txt
    ├── build.iss
    ├── build.py
    ├── flutter/
    │   ├── CMakeLists.txt
    │   ├── generated_plugin_registrant.cc
    │   ├── generated_plugin_registrant.h
    │   └── generated_plugins.cmake
    └── runner/
        ├── CMakeLists.txt
        ├── RCa14464
        ├── RCa18972
        ├── Runner.aps
        ├── Runner.rc
        ├── flutter_window.cpp
        ├── flutter_window.h
        ├── main.cpp
        ├── resource.h
        ├── runner.exe.manifest
        ├── utils.cpp
        ├── utils.h
        ├── win32_window.cpp
        └── win32_window.h
Download .txt
SYMBOL INDEX (932 symbols across 81 files)

FILE: lib/appdata.dart
  class _Appdata (line 12) | class _Appdata {
    method writeData (line 50) | void writeData()
    method writeSettings (line 62) | void writeSettings()
    method readData (line 72) | Future<void> readData()
    method _ensureMacOSDownloadPathPermission (line 103) | Future<void> _ensureMacOSDownloadPathPermission()
    method _restoreMacOSDownloadPathAccess (line 142) | Future<String?> _restoreMacOSDownloadPathAccess(String? expectedPath)
    method _requestMacOSDownloadPathAccess (line 154) | Future<String?> _requestMacOSDownloadPathAccess(String? initialPath)
    method _normalizePath (line 166) | String _normalizePath(String path)

FILE: lib/components/animated_image.dart
  class AnimatedImage (line 5) | class AnimatedImage extends StatefulWidget {
    method clear (line 66) | void clear()
    method createState (line 69) | State<AnimatedImage> createState()
  class _AnimatedImageState (line 72) | class _AnimatedImageState extends State<AnimatedImage> with WidgetsBindi...
    method clear (line 86) | clear()
    method initState (line 89) | void initState()
    method dispose (line 96) | void dispose()
    method didChangeDependencies (line 107) | void didChangeDependencies()
    method didUpdateWidget (line 121) | void didUpdateWidget(AnimatedImage oldWidget)
    method didChangeAccessibilityFeatures (line 129) | void didChangeAccessibilityFeatures()
    method reassemble (line 137) | void reassemble()
    method _updateInvertColors (line 142) | void _updateInvertColors()
    method _resolveImage (line 147) | void _resolveImage()
    method _getListener (line 161) | ImageStreamListener _getListener({bool recreateListener = false})
    method _handleImageFrame (line 177) | void _handleImageFrame(ImageInfo imageInfo, bool synchronousCall)
    method _handleImageChunk (line 187) | void _handleImageChunk(ImageChunkEvent event)
    method _replaceImage (line 194) | void _replaceImage({required ImageInfo? info})
    method _updateSourceStream (line 203) | void _updateSourceStream(ImageStream newStream)
    method _listenToStream (line 228) | void _listenToStream()
    method _stopListeningToStream (line 247) | void _stopListeningToStream({bool keepStreamAlive = false})
    method build (line 261) | Widget build(BuildContext context)
    method debugFillProperties (line 313) | void debugFillProperties(DiagnosticPropertiesBuilder description)

FILE: lib/components/batch_download.dart
  class BatchDownloadButton (line 10) | class BatchDownloadButton extends StatelessWidget {
    method build (line 16) | Widget build(BuildContext context)
  class _DownloadDialog (line 34) | class _DownloadDialog extends StatefulWidget {
    method createState (line 40) | State<_DownloadDialog> createState()
  class _DownloadDialogState (line 43) | class _DownloadDialogState extends State<_DownloadDialog> {
    method build (line 53) | Widget build(BuildContext context)
    method load (line 114) | void load()

FILE: lib/components/button.dart
  class BaseButton (line 4) | abstract class BaseButton extends StatelessWidget {
    method buildNormal (line 11) | Widget buildNormal(BuildContext context)
    method buildLoading (line 13) | Widget buildLoading(BuildContext context)
    method buildDisabled (line 15) | Widget buildDisabled(BuildContext context)
    method build (line 18) | Widget build(BuildContext context)
  class FluentButton (line 29) | class FluentButton extends BaseButton {
    method buildNormal (line 48) | Widget buildNormal(BuildContext context)
    method buildLoading (line 60) | Widget buildLoading(BuildContext context)
    method buildDisabled (line 82) | Widget buildDisabled(BuildContext context)

FILE: lib/components/grid.dart
  class SliverGridViewWithFixedItemHeight (line 5) | class SliverGridViewWithFixedItemHeight extends StatelessWidget {
    method build (line 22) | Widget build(BuildContext context)
  class GridViewWithFixedItemHeight (line 33) | class GridViewWithFixedItemHeight extends StatelessWidget {
    method build (line 53) | Widget build(BuildContext context)
  class SliverGridDelegateWithFixedHeight (line 67) | class SliverGridDelegateWithFixedHeight extends SliverGridDelegate {
    method getLayout (line 81) | SliverGridLayout getLayout(SliverConstraints constraints)
    method calcCrossItemsCount (line 92) | int calcCrossItemsCount(double width)
    method shouldRelayout (line 118) | bool shouldRelayout(covariant SliverGridDelegate oldDelegate)

FILE: lib/components/illust_widget.dart
  type UpdateFavoriteFunc (line 15) | typedef UpdateFavoriteFunc = void Function(bool v);
  class IllustWidget (line 17) | class IllustWidget extends StatefulWidget {
    method createState (line 27) | State<IllustWidget> createState()
  class _IllustWidgetState (line 30) | class _IllustWidgetState extends State<IllustWidget> {
    method initState (line 37) | void initState()
    method dispose (line 47) | void dispose()
    method build (line 53) | Widget build(BuildContext context)
    method showMenu (line 236) | void showMenu([TapUpDetails? details])
    method favorite (line 280) | void favorite([String type = "public"])
    method buildButton (line 300) | Widget buildButton()
  class IllustHistoryWidget (line 340) | class IllustHistoryWidget extends StatelessWidget {
    method build (line 346) | Widget build(BuildContext context)

FILE: lib/components/keyboard.dart
  type KeyEventHandler (line 5) | typedef KeyEventHandler = void Function(LogicalKeyboardKey key);
  class KeyEventListener (line 7) | class KeyEventListener extends StatefulWidget {
    method of (line 12) | KeyEventListenerState? of(BuildContext context)
    method createState (line 17) | State<KeyEventListener> createState()
  class KeyEventListenerState (line 20) | class KeyEventListenerState extends State<KeyEventListener> {
    method addHandler (line 25) | void addHandler(KeyEventHandler handler)
    method removeHandler (line 29) | void removeHandler(KeyEventHandler handler)
    method removeAll (line 33) | void removeAll()
    method build (line 38) | Widget build(BuildContext context)

FILE: lib/components/loading.dart
  class LoadingState (line 5) | abstract class LoadingState<T extends StatefulWidget, S extends Object> ...
    method loadData (line 12) | Future<Res<S>> loadData()
    method buildContent (line 14) | Widget buildContent(BuildContext context, S data)
    method buildFrame (line 16) | Widget? buildFrame(BuildContext context, Widget child)
    method buildLoading (line 18) | Widget buildLoading()
    method retry (line 24) | void retry()
    method buildError (line 44) | Widget buildError()
    method initState (line 62) | void initState()
    method build (line 81) | Widget build(BuildContext context)
  class MultiPageLoadingState (line 96) | abstract class MultiPageLoadingState<T extends StatefulWidget, S extends...
    method loadData (line 107) | Future<Res<List<S>>> loadData(int page)
    method buildFrame (line 109) | Widget? buildFrame(BuildContext context, Widget child)
    method buildContent (line 111) | Widget buildContent(BuildContext context, List<S> data)
    method nextPage (line 117) | void nextPage()
    method reset (line 142) | void reset()
    method firstLoad (line 153) | void firstLoad()
    method initState (line 172) | void initState()
    method buildLoading (line 177) | Widget buildLoading(BuildContext context)
    method buildError (line 183) | Widget buildError(BuildContext context, String error)
    method build (line 202) | Widget build(BuildContext context)

FILE: lib/components/md.dart
  type MdIcons (line 3) | typedef MdIcons = md.Icons;
  type MdTheme (line 4) | typedef MdTheme = md.Theme;
  type MdThemeData (line 5) | typedef MdThemeData = md.ThemeData;
  type MdColorScheme (line 6) | typedef MdColorScheme = md.ColorScheme;
  type TextField (line 7) | typedef TextField = md.TextField;
  class ColorScheme (line 9) | class ColorScheme {
    method of (line 10) | md.ColorScheme of(md.BuildContext context)

FILE: lib/components/message.dart
  function showToast (line 7) | void showToast(BuildContext context, {required String message, IconData?...
  class ToastOverlay (line 18) | class ToastOverlay extends StatelessWidget {
    method build (line 26) | Widget build(BuildContext context)
  class OverlayWidget (line 65) | class OverlayWidget extends StatefulWidget {
    method of (line 70) | OverlayWidgetState? of(BuildContext context)
    method createState (line 75) | State<OverlayWidget> createState()
  class OverlayWidgetState (line 78) | class OverlayWidgetState extends State<OverlayWidget> {
    method addOverlay (line 83) | void addOverlay(OverlayEntry entry)
    method remove (line 90) | void remove(OverlayEntry entry)
    method removeAll (line 96) | void removeAll()
    method build (line 104) | Widget build(BuildContext context)

FILE: lib/components/novel.dart
  class NovelWidget (line 9) | class NovelWidget extends StatefulWidget {
    method createState (line 15) | State<NovelWidget> createState()
  class _NovelWidgetState (line 18) | class _NovelWidgetState extends State<NovelWidget> {
    method build (line 20) | Widget build(BuildContext context)

FILE: lib/components/page_route.dart
  class AppPageRoute (line 13) | class AppPageRoute<T> extends PageRoute<T> with _AppRouteTransitionMixin {
    method buildContent (line 33) | Widget buildContent(BuildContext context)
    method updateBackButton (line 52) | void updateBackButton()
  function buildContent (line 62) | Widget buildContent(BuildContext context)
  function canTransitionTo (line 74) | bool canTransitionTo(TransitionRoute<dynamic> nextRoute)
  function buildPage (line 88) | Widget buildPage(
  function _isPopGestureEnabled (line 108) | bool _isPopGestureEnabled<T>(PageRoute<T> route)
  function buildTransitions (line 123) | Widget buildTransitions(BuildContext context, Animation<double> animation,
  function _startPopGesture (line 175) | IOSBackGestureController _startPopGesture(PageRoute<T> route)
  class IOSBackGestureController (line 180) | class IOSBackGestureController {
    method dragEnd (line 189) | void dragEnd(double velocity)
    method dragUpdate (line 233) | void dragUpdate(double delta)
  class IOSBackGestureDetector (line 238) | class IOSBackGestureDetector extends StatefulWidget {
    method createState (line 255) | State<IOSBackGestureDetector> createState()
  class _IOSBackGestureDetectorState (line 258) | class _IOSBackGestureDetectorState extends State<IOSBackGestureDetector> {
    method dispose (line 264) | void dispose()
    method initState (line 270) | void initState()
    method build (line 280) | Widget build(BuildContext context)
    method _handlePointerDown (line 303) | void _handlePointerDown(PointerDownEvent event)
    method _handleDragCancel (line 307) | void _handleDragCancel()
    method _convertToLogical (line 313) | double _convertToLogical(double value)
    method _handleDragEnd (line 322) | void _handleDragEnd(DragEndDetails details)
    method _handleDragStart (line 330) | void _handleDragStart(DragStartDetails details)
    method _handleDragUpdate (line 336) | void _handleDragUpdate(DragUpdateDetails details)
  class SideBarRoute (line 346) | class SideBarRoute<T> extends PopupRoute<T> {
    method buildPage (line 361) | Widget buildPage(BuildContext context, Animation<double> animation,
    method _isPopGestureEnabled (line 394) | bool _isPopGestureEnabled<T>(PopupRoute<T> route)
    method buildTransitions (line 410) | Widget buildTransitions(BuildContext context, Animation<double> animat...
    method _startPopGesture (line 429) | IOSBackGestureController _startPopGesture(PopupRoute<T> route)
  class EntrancePageTransition (line 434) | class EntrancePageTransition extends StatelessWidget {
    method build (line 449) | Widget build(BuildContext context)

FILE: lib/components/search_field.dart
  class AutoCompleteItem (line 4) | class AutoCompleteItem {
  class AutoCompleteData (line 16) | class AutoCompleteData {
  class SearchField (line 26) | class SearchField extends StatefulWidget {
    method createState (line 71) | State<SearchField> createState()
  class _SearchFieldState (line 74) | class _SearchFieldState extends State<SearchField> with TickerProviderSt...
    method initState (line 87) | void initState()
    method dispose (line 98) | void dispose()
    method didUpdateWidget (line 108) | void didUpdateWidget(covariant SearchField oldWidget)
    method onfocusChange (line 122) | void onfocusChange()
    method _removeOverlayWithAnimation (line 173) | void _removeOverlayWithAnimation()
    method build (line 186) | Widget build(BuildContext context)
  class _AutoCompleteOverlay (line 202) | class _AutoCompleteOverlay extends StatefulWidget {
    method createState (line 210) | State<_AutoCompleteOverlay> createState()
  class _AutoCompleteOverlayState (line 213) | class _AutoCompleteOverlayState extends State<_AutoCompleteOverlay> {
    method initState (line 221) | void initState()
    method dispose (line 229) | void dispose()
    method onItemsChanged (line 234) | void onItemsChanged()
    method build (line 242) | Widget build(BuildContext context)
  class _AnimatedOverlayWrapper (line 289) | class _AnimatedOverlayWrapper extends StatelessWidget {
    method build (line 299) | Widget build(BuildContext context)

FILE: lib/components/segmented_button.dart
  class SegmentedButton (line 6) | class SegmentedButton<T> extends StatelessWidget {
    method build (line 20) | Widget build(BuildContext context)
    method buildButton (line 36) | Widget buildButton(SegmentedButtonOption<T> e)
  class SegmentedButtonOption (line 67) | class SegmentedButtonOption<T> {

FILE: lib/components/title_bar.dart
  class TitleBar (line 4) | class TitleBar extends StatelessWidget {
    method build (line 12) | Widget build(BuildContext context)
  class SliverTitleBar (line 27) | class SliverTitleBar extends StatelessWidget {
    method build (line 36) | Widget build(BuildContext context)

FILE: lib/components/ugoira.dart
  class UgoiraWidget (line 15) | class UgoiraWidget extends StatefulWidget {
    method createState (line 28) | State<UgoiraWidget> createState()
  class _UgoiraWidgetState (line 31) | class _UgoiraWidgetState extends State<UgoiraWidget> {
    method build (line 45) | Widget build(BuildContext context)
    method buildPreview (line 55) | Widget buildPreview()
    method load (line 95) | void load()
    method extract (line 165) | Future<void> extract(String filePath)
  class _UgoiraAnimation (line 182) | class _UgoiraAnimation extends StatefulWidget {
    method createState (line 188) | State<_UgoiraAnimation> createState()
  class _UgoiraAnimationState (line 191) | class _UgoiraAnimationState extends State<_UgoiraAnimation> with SingleT...
    method initState (line 195) | void initState()
    method dispose (line 210) | void dispose()
    method build (line 216) | Widget build(BuildContext context)
  class _UgoiraMetadata (line 229) | class _UgoiraMetadata {
  class _UgoiraFrame (line 236) | class _UgoiraFrame {
  class _ImagePainter (line 244) | class _ImagePainter extends CustomPainter {
    method paint (line 250) | void paint(Canvas canvas, Size size)
    method shouldRepaint (line 262) | bool shouldRepaint(covariant CustomPainter oldDelegate)

FILE: lib/components/user_preview.dart
  type UpdateFollowCallback (line 14) | typedef UpdateFollowCallback = void Function(bool isFollowed);
  class UserPreviewWidget (line 16) | class UserPreviewWidget extends StatefulWidget {
    method createState (line 24) | State<UserPreviewWidget> createState()
  class _UserPreviewWidgetState (line 27) | class _UserPreviewWidgetState extends State<UserPreviewWidget> {
    method initState (line 29) | void initState()
    method dispose (line 39) | void dispose()
    method follow (line 46) | void follow()
    method build (line 69) | Widget build(BuildContext context)
    method buildIllust (line 167) | Widget buildIllust(Illust illust)

FILE: lib/foundation/app.dart
  class _App (line 14) | class _App {

FILE: lib/foundation/cache_manager.dart
  class CacheManager (line 10) | class CacheManager {
    method setLimitSize (line 44) | void setLimitSize(int size)
    method writeCache (line 48) | Future<void> writeCache(String key, Uint8List data, [int duration = 7 ...
    method openWrite (line 72) | Future<CachingFile> openWrite(String key)
    method findCache (line 86) | Future<String?> findCache(String key)
    method checkCache (line 106) | Future<void> checkCache()
    method delete (line 161) | Future<void> delete(String key)
    method clear (line 187) | Future<void> clear()
    method deleteKeyword (line 196) | Future<void> deleteKeyword(String keyword)
  class CachingFile (line 222) | class CachingFile{
    method writeBytes (line 235) | Future<void> writeBytes(List<int> data)
    method close (line 243) | Future<void> close()
    method cancel (line 252) | Future<void> cancel()

FILE: lib/foundation/history.dart
  class IllustHistory (line 5) | class IllustHistory {
  class HistoryManager (line 21) | class HistoryManager {
    method addHistory (line 48) | void addHistory(Illust illust)
    method getHistories (line 74) | List<IllustHistory> getHistories(int page)

FILE: lib/foundation/image_provider.dart
  class BadRequestException (line 15) | class BadRequestException implements Exception {
    method toString (line 21) | String toString()
  class BaseImageProvider (line 26) | abstract class BaseImageProvider<T extends BaseImageProvider<T>>
    method loadImage (line 31) | ImageStreamCompleter loadImage(T key, ImageDecoderCallback decode)
    method _loadBufferAsync (line 47) | Future<ui.Codec> _loadBufferAsync(
    method load (line 121) | Future<Uint8List> load(StreamController<ImageChunkEvent> chunkEvents)
    method toString (line 134) | String toString()
  type FileDecoderCallback (line 139) | typedef FileDecoderCallback = Future<ui.Codec> Function(Uint8List);
  class CachedImageProvider (line 141) | class CachedImageProvider extends BaseImageProvider<CachedImageProvider> {
    method load (line 150) | Future<Uint8List> load(StreamController<ImageChunkEvent> chunkEvents)
    method obtainKey (line 200) | Future<CachedImageProvider> obtainKey(ImageConfiguration configuration)
  class CachedNovelImageProvider (line 205) | class CachedNovelImageProvider
    method load (line 216) | Future<Uint8List> load(StreamController<ImageChunkEvent> chunkEvents)
    method obtainKey (line 268) | Future<CachedNovelImageProvider> obtainKey(ImageConfiguration configur...

FILE: lib/foundation/log.dart
  class LogItem (line 6) | class LogItem {
  type LogLevel (line 18) | enum LogLevel { error, warning, info }
  class Log (line 20) | class Log {
    method printWarning (line 34) | void printWarning(String text)
    method printError (line 38) | void printError(String text)
    method addLog (line 42) | void addLog(LogLevel level, String title, String content)
    method info (line 75) | info(String title, String content)
    method warning (line 79) | warning(String title, String content)
    method error (line 83) | error(String title, String content)
    method clear (line 87) | void clear()
    method toString (line 90) | String toString()

FILE: lib/foundation/navigation.dart
  function pop (line 7) | void pop<T>([T? result])
  function to (line 11) | Future<T?> to<T>(Widget Function() builder)
  function showToast (line 16) | void showToast({required String message, IconData? icon})

FILE: lib/foundation/pair.dart
  class Pair (line 1) | class Pair<M, V>{

FILE: lib/foundation/state_controller.dart
  class SimpleController (line 4) | class SimpleController extends StateController{
    method refresh (line 10) | void refresh()
  class StateController (line 15) | abstract class StateController{
    method put (line 18) | T put<T extends StateController>(T controller, {Object? tag, bool auto...
    method putIfNotExists (line 23) | T putIfNotExists<T extends StateController>(T controller, {Object? tag...
    method find (line 27) | T find<T extends StateController>({Object? tag})
    method findOrNull (line 38) | T? findOrNull<T extends StateController>({Object? tag})
    method remove (line 49) | void remove<T>([Object? tag, bool check = false])
    method putSimpleController (line 62) | SimpleController putSimpleController(void Function() onUpdate, Object?...
    method update (line 71) | void update([List<Object>? ids])
    method dispose (line 85) | void dispose()
    method refresh (line 89) | void refresh()
  class StateControllerWrapped (line 94) | class StateControllerWrapped{
  class StateBuilder (line 103) | class StateBuilder<T extends StateController> extends StatefulWidget {
    method builderWrapped (line 117) | Widget builderWrapped(StateController controller)
    method initStateWrapped (line 121) | void initStateWrapped(StateController controller)
    method disposeWrapped (line 125) | void disposeWrapped(StateController controller)
    method createState (line 132) | State<StateBuilder> createState()
  class _StateBuilderState (line 135) | class _StateBuilderState<T extends StateController> extends State<StateB...
    method initState (line 139) | void initState()
    method dispose (line 159) | void dispose()
    method build (line 166) | Widget build(BuildContext context)
  class StateWithController (line 169) | abstract class StateWithController<T extends StatefulWidget> extends Sta...
    method refresh (line 172) | void refresh()
    method initState (line 178) | void initState()
    method dispose (line 185) | void dispose()
    method update (line 190) | void update()

FILE: lib/foundation/widget_utils.dart
  function padding (line 4) | Widget padding(EdgeInsetsGeometry padding)
  function paddingLeft (line 8) | Widget paddingLeft(double padding)
  function paddingRight (line 12) | Widget paddingRight(double padding)
  function paddingTop (line 16) | Widget paddingTop(double padding)
  function paddingBottom (line 20) | Widget paddingBottom(double padding)
  function paddingVertical (line 24) | Widget paddingVertical(double padding)
  function paddingHorizontal (line 28) | Widget paddingHorizontal(double padding)
  function paddingAll (line 32) | Widget paddingAll(double padding)
  function toCenter (line 36) | Widget toCenter()
  function toAlign (line 40) | Widget toAlign(AlignmentGeometry alignment)
  function sliverPadding (line 44) | Widget sliverPadding(EdgeInsetsGeometry padding)
  function sliverPaddingAll (line 48) | Widget sliverPaddingAll(double padding)
  function sliverPaddingVertical (line 52) | Widget sliverPaddingVertical(double padding)
  function sliverPaddingHorizontal (line 56) | Widget sliverPaddingHorizontal(double padding)
  function fixWidth (line 60) | Widget fixWidth(double width)
  function fixHeight (line 64) | Widget fixHeight(double height)
  function toOpacity (line 70) | Color toOpacity(double opacity)

FILE: lib/main.dart
  function main (line 25) | void main()
  class MyApp (line 69) | class MyApp extends StatelessWidget {
    method build (line 73) | Widget build(BuildContext context)
  function _floatToInt8 (line 174) | int _floatToInt8(double x)
  function darken (line 178) | Color darken(Color c, [int percent = 10])
  function lighten (line 189) | Color lighten(Color c, [int percent = 10])

FILE: lib/network/app_dio.dart
  class MyLogInterceptor (line 14) | class MyLogInterceptor implements Interceptor {
    method onError (line 16) | void onError(DioException err, ErrorInterceptorHandler handler)
    method _getStatusCodeInfo (line 58) | String _getStatusCodeInfo(int? statusCode)
    method onResponse (line 68) | void onResponse(
    method onRequest (line 90) | void onRequest(RequestOptions options, RequestInterceptorHandler handler)
  class AppDio (line 103) | class AppDio extends DioForNative {
    method request (line 107) | Future<Response<T>> request<T>(String path,
  function setSystemProxy (line 169) | void setSystemProxy()
  class _ProxyHttpOverrides (line 173) | class _ProxyHttpOverrides extends HttpOverrides {
    method findProxy (line 176) | String findProxy(Uri uri)
    method createHttpClient (line 216) | HttpClient createHttpClient(SecurityContext? context)

FILE: lib/network/download.dart
  class DownloadedIllust (line 22) | class DownloadedIllust {
  class DownloadingTask (line 36) | class DownloadingTask {
    method start (line 55) | void start()
    method cancel (line 62) | void cancel()
    method _download (line 72) | void _download()
    method _handleError (line 116) | void _handleError(Object error)
    method _generateFilePath (line 127) | String _generateFilePath(Illust illust, int index, String ext)
    method extractTags (line 138) | List<String> extractTags(String input)
    method _cleanFilePath (line 152) | String _cleanFilePath(String filePath)
    method retry (line 163) | void retry()
    method pause (line 169) | void pause()
  class DownloadManager (line 174) | class DownloadManager {
    method registerUiUpdater (line 196) | void registerUiUpdater(void Function() callback)
    method removeUiUpdater (line 200) | void removeUiUpdater()
    method init (line 204) | void init()
    method saveInfo (line 224) | void saveInfo(Illust illust, List<String> imagePaths)
    method getImage (line 237) | File? getImage(int illustId, int index)
    method checkDownloaded (line 248) | bool checkDownloaded(int illustId)
    method listAll (line 256) | List<DownloadedIllust> listAll()
    method addDownloadingTask (line 269) | void addDownloadingTask(Illust illust)
    method receiveBytes (line 279) | void receiveBytes(int bytes)
    method pause (line 289) | void pause()
    method run (line 296) | void run()
    method delete (line 317) | void delete(DownloadedIllust illust)
    method getImagePaths (line 335) | List<String> getImagePaths(int illustId)
    method batchDownload (line 343) | Future<void> batchDownload(Future<Res<List<Illust>>> request, int maxC...
    method checkAndClearInvalidItems (line 371) | Future<void> checkAndClearInvalidItems()
    method resume (line 391) | void resume()

FILE: lib/network/models.dart
  class Account (line 3) | class Account {
    method toJson (line 15) | Map<String, dynamic> toJson()
  class User (line 22) | class User {
    method toJson (line 41) | Map<String, dynamic> toJson()
  class UserDetails (line 51) | class UserDetails {
  class Author (line 124) | class Author {
  class Tag (line 134) | class Tag {
    method toString (line 141) | String toString()
    method fromJson (line 156) | Tag fromJson(Map<String, dynamic> json)
  class IllustImage (line 161) | class IllustImage {
  class Illust (line 170) | class Illust {
  class TrendingTag (line 239) | class TrendingTag {
  type KeywordMatchType (line 246) | enum KeywordMatchType {
  type FavoriteNumber (line 265) | enum FavoriteNumber {
  type SearchSort (line 288) | enum SearchSort {
  type AgeLimit (line 329) | enum AgeLimit {
  class SearchOptions (line 348) | class SearchOptions {
  class UserPreview (line 370) | class UserPreview {
  class Comment (line 413) | class Comment {
  class Novel (line 486) | class Novel {
  class MuteList (line 535) | class MuteList {
    method fromJson (line 544) | MuteList? fromJson(Map<String, dynamic> data)

FILE: lib/network/network.dart
  class Network (line 19) | class Network {
    method generateWebviewUrl (line 58) | Future<String> generateWebviewUrl()
    method loginWithCode (line 70) | Future<Res<bool>> loginWithCode(String code)
    method refreshToken (line 99) | Future<Res<bool>> refreshToken()
    method apiGet (line 129) | Future<Res<Map<String, dynamic>>> apiGet(String path,
    method apiGetPlain (line 163) | Future<Res<String>> apiGetPlain(String path,
    method encodeFormData (line 194) | String? encodeFormData(Map<String, dynamic>? data)
    method apiPost (line 209) | Future<Res<Map<String, dynamic>>> apiPost(String path,
    method getUserDetails (line 248) | Future<Res<UserDetails>> getUserDetails(Object userId)
    method getRecommendedIllusts (line 261) | Future<Res<List<Illust>>> getRecommendedIllusts()
    method getBookmarkedIllusts (line 272) | Future<Res<List<Illust>>> getBookmarkedIllusts(String restrict,
    method getUserBookmarks (line 285) | Future<Res<List<Illust>>> getUserBookmarks(String uid,
    method addBookmark (line 298) | Future<Res<bool>> addBookmark(String id, String method,
    method follow (line 313) | Future<Res<bool>> follow(String uid, String method,
    method getHotTags (line 328) | Future<Res<List<TrendingTag>>> getHotTags()
    method search (line 339) | Future<Res<List<Illust>>> search(
    method getIllustsWithNextUrl (line 363) | Future<Res<List<Illust>>> getIllustsWithNextUrl(String nextUrl)
    method searchUsers (line 374) | Future<Res<List<UserPreview>>> searchUsers(String keyword,
    method getUserIllusts (line 390) | Future<Res<List<Illust>>> getUserIllusts(String uid, String? type)
    method getFollowing (line 402) | Future<Res<List<UserPreview>>> getFollowing(String uid, String type,
    method getFollowingArtworks (line 418) | Future<Res<List<Illust>>> getFollowingArtworks(String restrict,
    method getRecommendationUsers (line 430) | Future<Res<List<UserPreview>>> getRecommendationUsers()
    method getRanking (line 444) | Future<Res<List<Illust>>> getRanking(String mode, [String? nextUrl])
    method getComments (line 456) | Future<Res<List<Comment>>> getComments(String id, [String? nextUrl])
    method comment (line 469) | Future<Res<bool>> comment(String id, String content)
    method getIllustByID (line 479) | Future<Res<Illust>> getIllustByID(String id)
    method getRecommendedMangas (line 488) | Future<Res<List<Illust>>> getRecommendedMangas()
    method getHistory (line 500) | Future<Res<List<Illust>>> getHistory(int page)
    method getMuteList (line 515) | Future<Res<MuteList>> getMuteList()
    method editMute (line 524) | Future<Res<bool>> editMute(List<String> addTags, List<String> addUsers,
    method relatedUsers (line 540) | Future<Res<List<UserPreview>>> relatedUsers(String id)
    method relatedIllusts (line 552) | Future<Res<List<Illust>>> relatedIllusts(String id)
    method getNovelImage (line 564) | Future<Res<String>> getNovelImage(String novelId, String imageId)
    method sendHistory (line 577) | Future<Res<bool>> sendHistory(List<int> ids)
    method getAutoCompleteTags (line 587) | Future<Res<List<Tag>>> getAutoCompleteTags(String keyword)

FILE: lib/network/novel.dart
  function getRecommendNovels (line 4) | Future<Res<List<Novel>>> getRecommendNovels()
  function getNovelsWithNextUrl (line 8) | Future<Res<List<Novel>>> getNovelsWithNextUrl(String nextUrl)
  function searchNovels (line 18) | Future<Res<List<Novel>>> searchNovels(String keyword, SearchOptions opti...
  function getNovelRanking (line 30) | Future<Res<List<Novel>>> getNovelRanking(String mode, DateTime? date)
  function getBookmarkedNovels (line 38) | Future<Res<List<Novel>>> getBookmarkedNovels(String uid, bool public)
  function favoriteNovel (line 43) | Future<Res<bool>> favoriteNovel(String id, bool public)
  function deleteFavoriteNovel (line 54) | Future<Res<bool>> deleteFavoriteNovel(String id)
  function getNovelContent (line 64) | Future<Res<String>> getNovelContent(String id)
  function relatedNovels (line 98) | Future<Res<List<Novel>>> relatedNovels(String id)
  function getUserNovels (line 109) | Future<Res<List<Novel>>> getUserNovels(String uid)
  function getNovelSeries (line 113) | Future<Res<List<Novel>>> getNovelSeries(String id, [String? nextUrl])
  function getNovelComments (line 123) | Future<Res<List<Comment>>> getNovelComments(String id,
  function commentNovel (line 134) | Future<Res<bool>> commentNovel(String id, String content)
  function getNovelDetail (line 145) | Future<Res<Novel>> getNovelDetail(String id)
  function getFollowingNovels (line 153) | Future<Res<List<Novel>>> getFollowingNovels(String restrict,

FILE: lib/network/res.dart
  class Res (line 3) | @immutable
    method toString (line 30) | String toString()

FILE: lib/network/translator.dart
  class Translator (line 3) | abstract class Translator {
    method init (line 13) | void init()
    method translate (line 18) | Future<String> translate(String text, String to)
  class GoogleTranslator (line 21) | class GoogleTranslator implements Translator {
    method buildBody (line 26) | Map<String, dynamic> buildBody(String text, String to)
    method translatePart (line 39) | Future<String> translatePart(String part, String to)
    method translate (line 57) | Future<String> translate(String text, String to)

FILE: lib/pages/bookmarks.dart
  class BookMarkedArtworkPage (line 14) | class BookMarkedArtworkPage extends StatefulWidget {
    method createState (line 18) | State<BookMarkedArtworkPage> createState()
  class _BookMarkedArtworkPageState (line 21) | class _BookMarkedArtworkPageState extends State<BookMarkedArtworkPage>{
    method build (line 25) | Widget build(BuildContext context)
    method buildTab (line 36) | Widget buildTab()
  class _OneBookmarkedPage (line 63) | class _OneBookmarkedPage extends StatefulWidget {
    method createState (line 69) | State<_OneBookmarkedPage> createState()
  class _OneBookmarkedPageState (line 72) | class _OneBookmarkedPageState extends MultiPageLoadingState<_OneBookmark...
    method buildContent (line 74) | Widget buildContent(BuildContext context, final List<Illust> data)
    method loadData (line 102) | Future<Res<List<Illust>>> loadData(page)

FILE: lib/pages/comments_page.dart
  class CommentsPage (line 14) | class CommentsPage extends StatefulWidget {
    method show (line 21) | void show(BuildContext context, String id, {bool isNovel = false})
    method createState (line 27) | State<CommentsPage> createState()
  class _CommentsPageState (line 30) | class _CommentsPageState extends MultiPageLoadingState<CommentsPage, Com...
    method buildContent (line 34) | Widget buildContent(BuildContext context, List<Comment> data)
    method buildBody (line 48) | Widget buildBody(BuildContext context, List<Comment> data)
    method buildBottom (line 142) | Widget buildBottom(BuildContext context)
    method loadData (line 201) | Future<Res<List<Comment>>> loadData(int page)

FILE: lib/pages/downloaded_page.dart
  class DownloadedPage (line 21) | class DownloadedPage extends StatefulWidget {
    method createState (line 25) | State<DownloadedPage> createState()
  class _DownloadedPageState (line 28) | class _DownloadedPageState extends State<DownloadedPage> {
    method loadData (line 32) | void loadData()
    method initState (line 39) | void initState()
    method build (line 45) | Widget build(BuildContext context)
    method buildBody (line 67) | Widget buildBody()
  class _DownloadedIllustViewPage (line 200) | class _DownloadedIllustViewPage extends StatefulWidget {
    method createState (line 206) | State<_DownloadedIllustViewPage> createState()
  class _DownloadedIllustViewPageState (line 210) | class _DownloadedIllustViewPageState extends State<_DownloadedIllustView...
    method initState (line 215) | void initState()
    method dispose (line 221) | void dispose()
    method onWindowMaximize (line 227) | void onWindowMaximize()
    method onWindowUnmaximize (line 234) | void onWindowUnmaximize()
    method getFile (line 246) | Future<File?> getFile()
    method showMenu (line 254) | void showMenu()
    method build (line 292) | Widget build(BuildContext context)
    method buildActions (line 403) | Widget buildActions()

FILE: lib/pages/downloading_page.dart
  class DownloadingPage (line 11) | class DownloadingPage extends StatefulWidget {
    method createState (line 15) | State<DownloadingPage> createState()
  class _DownloadingPageState (line 18) | class _DownloadingPageState extends State<DownloadingPage> {
    method initState (line 20) | void initState()
    method dispose (line 26) | void dispose()
    method build (line 34) | Widget build(BuildContext context)
    method buildTop (line 47) | Widget buildTop()
    method buildContent (line 84) | Widget buildContent()
    method buildItem (line 96) | Widget buildItem(DownloadingTask task)

FILE: lib/pages/following_artworks.dart
  class FollowingArtworksPage (line 15) | class FollowingArtworksPage extends StatefulWidget {
    method createState (line 19) | State<FollowingArtworksPage> createState()
  class _FollowingArtworksPageState (line 22) | class _FollowingArtworksPageState extends State<FollowingArtworksPage> {
    method build (line 26) | Widget build(BuildContext context)
    method buildTab (line 40) | Widget buildTab()
  class _OneFollowingPage (line 71) | class _OneFollowingPage extends StatefulWidget {
    method createState (line 77) | State<_OneFollowingPage> createState()
  class _OneFollowingPageState (line 80) | class _OneFollowingPageState
    method buildContent (line 83) | Widget buildContent(BuildContext context, List<Illust> data)
    method loadData (line 109) | Future<Res<List<Illust>>> loadData(page)

FILE: lib/pages/following_novels_page.dart
  class FollowingNovelsPage (line 11) | class FollowingNovelsPage extends StatefulWidget {
    method createState (line 15) | State<FollowingNovelsPage> createState()
  class _FollowingNovelsPageState (line 18) | class _FollowingNovelsPageState
    method buildFrame (line 23) | Widget? buildFrame(BuildContext context, Widget child)
    method buildContent (line 52) | Widget buildContent(BuildContext context, List<Novel> data)
    method loadData (line 75) | Future<Res<List<Novel>>> loadData(int page)

FILE: lib/pages/following_users_page.dart
  class FollowingUsersPage (line 12) | class FollowingUsersPage extends StatefulWidget {
    method createState (line 18) | State<FollowingUsersPage> createState()
  class _FollowingUsersPageState (line 21) | class _FollowingUsersPageState
    method buildContent (line 26) | Widget buildContent(BuildContext context, final List<UserPreview> data)
    method loadData (line 73) | Future<Res<List<UserPreview>>> loadData(page)

FILE: lib/pages/history.dart
  class HistoryPage (line 15) | class HistoryPage extends StatefulWidget {
    method createState (line 19) | State<HistoryPage> createState()
  class _HistoryPageState (line 22) | class _HistoryPageState extends State<HistoryPage> {
    method build (line 26) | Widget build(BuildContext context)
  class LocalHistoryPage (line 54) | class LocalHistoryPage extends StatefulWidget {
    method createState (line 58) | State<LocalHistoryPage> createState()
  class _LocalHistoryPageState (line 61) | class _LocalHistoryPageState extends State<LocalHistoryPage> {
    method build (line 67) | Widget build(BuildContext context)
  class NetworkHistoryPage (line 88) | class NetworkHistoryPage extends StatefulWidget {
    method createState (line 92) | State<NetworkHistoryPage> createState()
  class _NetworkHistoryPageState (line 95) | class _NetworkHistoryPageState
    method buildContent (line 98) | Widget buildContent(BuildContext context, final List<Illust> data)
    method loadData (line 123) | Future<Res<List<Illust>>> loadData(page)

FILE: lib/pages/illust_page.dart
  class IllustGalleryPage (line 35) | class IllustGalleryPage extends StatefulWidget {
    method createState (line 51) | State<IllustGalleryPage> createState()
  class _IllustGalleryPageState (line 54) | class _IllustGalleryPageState extends State<IllustGalleryPage> {
    method initState (line 66) | void initState()
    method dispose (line 77) | void dispose()
    method nextPage (line 86) | void nextPage()
    method previousPage (line 93) | void previousPage()
    method build (line 100) | Widget build(BuildContext context)
    method buildLast (line 154) | Widget buildLast()
    method load (line 164) | void load()
  class IllustPage (line 182) | class IllustPage extends StatefulWidget {
    method updateFollow (line 193) | void updateFollow(String uid, bool isFollowed)
    method createState (line 202) | State<IllustPage> createState()
  class _IllustPageState (line 205) | class _IllustPageState extends State<IllustPage> {
    method initState (line 213) | void initState()
    method dispose (line 230) | void dispose()
    method build (line 237) | Widget build(BuildContext context)
    method handleKey (line 281) | void handleKey(LogicalKeyboardKey key)
    method buildBody (line 333) | Widget buildBody(double width, double height)
    method openImage (line 343) | void openImage(int index)
    method buildHeader (line 356) | Widget buildHeader()
    method buildImage (line 416) | Widget buildImage(double width, double height, int index)
  class _BottomBarController (line 497) | class _BottomBarController {
    method isOpen (line 504) | bool isOpen()
  class _BottomBar (line 519) | class _BottomBar extends StatefulWidget {
    method createState (line 534) | State<_BottomBar> createState()
  class _BottomBarState (line 537) | class _BottomBarState extends State<_BottomBar> with TickerProviderState...
    method initState (line 555) | void initState()
    method dispose (line 589) | void dispose()
    method _handlePointerDown (line 595) | void _handlePointerDown(DragStartDetails details)
    method _handlePointerMove (line 596) | void _handlePointerMove(DragUpdateDetails details)
    method _handlePointerUp (line 605) | void _handlePointerUp(DragEndDetails details)
    method _handlePointerCancel (line 617) | void _handlePointerCancel()
    method didUpdateWidget (line 629) | void didUpdateWidget(covariant _BottomBar oldWidget)
    method build (line 651) | Widget build(BuildContext context)
    method buildTop (line 710) | Widget buildTop()
    method follow (line 740) | void follow()
    method buildAuthor (line 764) | Widget buildAuthor()
    method favorite (line 841) | void favorite([String type = "public"])
    method buildActions (line 863) | Iterable<Widget> buildActions(double width)
    method download (line 868) | void download()
    method buildMoreActions (line 992) | Widget buildMoreActions()
  class _BlockingPage (line 1116) | class _BlockingPage extends StatefulWidget {
    method createState (line 1122) | State<_BlockingPage> createState()
  class __BlockingPageState (line 1125) | class __BlockingPageState extends State<_BlockingPage> {
    method build (line 1129) | Widget build(BuildContext context)
    method buildSubmit (line 1185) | Widget buildSubmit()
  class IllustPageWithId (line 1272) | class IllustPageWithId extends StatefulWidget {
    method createState (line 1278) | State<IllustPageWithId> createState()
  class _IllustPageWithIdState (line 1281) | class _IllustPageWithIdState extends LoadingState<IllustPageWithId, Illu...
    method buildContent (line 1283) | Widget buildContent(BuildContext context, Illust data)
    method loadData (line 1288) | Future<Res<Illust>> loadData()

FILE: lib/pages/image_page.dart
  class ImagePage (line 20) | class ImagePage extends StatefulWidget {
    method show (line 27) | show(List<String> urls, {int initialPage = 0})
    method createState (line 33) | State<ImagePage> createState()
  class _ImagePageState (line 36) | class _ImagePageState extends State<ImagePage> with WindowListener {
    method initState (line 40) | void initState()
    method dispose (line 46) | void dispose()
    method onWindowMaximize (line 52) | void onWindowMaximize()
    method onWindowUnmaximize (line 59) | void onWindowUnmaximize()
    method getFile (line 71) | Future<File?> getFile()
    method getExtensionName (line 84) | String getExtensionName()
    method showMenu (line 92) | void showMenu()
    method build (line 160) | Widget build(BuildContext context)
    method buildActions (line 280) | Widget buildActions()
    method getImageProvider (line 308) | ImageProvider getImageProvider(String url)

FILE: lib/pages/login_page.dart
  class LoginPage (line 10) | class LoginPage extends StatefulWidget {
    method createState (line 16) | State<LoginPage> createState()
  class _LoginPageState (line 19) | class _LoginPageState extends State<LoginPage> {
    method build (line 27) | Widget build(BuildContext context)
    method buildLogin (line 37) | Widget buildLogin(BuildContext context)
    method buildWaiting (line 102) | Widget buildWaiting(BuildContext context)
    method buildLoading (line 150) | Widget buildLoading(BuildContext context)
    method onContinue (line 180) | void onContinue()
    method onFinished (line 243) | void onFinished(String code)

FILE: lib/pages/logs.dart
  class LogsPage (line 7) | class LogsPage extends StatefulWidget {
    method createState (line 11) | State<LogsPage> createState()
  class _LogsPageState (line 14) | class _LogsPageState extends State<LogsPage> {
    method build (line 16) | Widget build(BuildContext context)

FILE: lib/pages/main_page.dart
  class TitleBarAction (line 36) | class TitleBarAction {
  class TitleBarController (line 44) | class TitleBarController extends StateController {
    method addAction (line 51) | void addAction(TitleBarAction action)
    method removeAction (line 56) | void removeAction(TitleBarAction action)
  class MainPage (line 62) | class MainPage extends StatefulWidget {
    method createState (line 66) | State<MainPage> createState()
  class _MainPageState (line 69) | class _MainPageState extends State<MainPage>
    method initState (line 81) | void initState()
    method didChangeDependencies (line 91) | void didChangeDependencies()
    method dispose (line 102) | void dispose()
    method onWindowMaximize (line 110) | void onWindowMaximize()
    method onWindowUnmaximize (line 117) | void onWindowUnmaximize()
    method build (line 126) | Widget build(BuildContext context)
    method navigate (line 269) | void navigate(int index)
    method buildAppBar (line 283) | NavigationAppBar buildAppBar(
    method onPopInvokedWithResult (line 379) | void onPopInvokedWithResult(bool didPop, result)
    method onPopInvoked (line 390) | void onPopInvoked(bool didPop)
  class _BackButton (line 393) | class _BackButton extends StatefulWidget {
    method createState (line 399) | State<_BackButton> createState()
  class _BackButtonState (line 402) | class _BackButtonState extends State<_BackButton> {
    method initState (line 410) | void initState()
    method loop (line 416) | void loop()
    method dispose (line 426) | void dispose()
    method build (line 432) | Widget build(BuildContext context)
    method onPressed (line 433) | void onPressed()
  class _MacosBackButton (line 470) | class _MacosBackButton extends StatefulWidget {
    method createState (line 476) | State<_MacosBackButton> createState()
  class __MacosBackButtonState (line 479) | class __MacosBackButtonState extends State<_MacosBackButton> {
    method initState (line 486) | void initState()
    method loop (line 492) | void loop()
    method dispose (line 502) | void dispose()
    method build (line 508) | Widget build(BuildContext context)
  class WindowButtons (line 547) | class WindowButtons extends StatelessWidget {
    method build (line 551) | Widget build(BuildContext context)
  class WindowButton (line 618) | class WindowButton extends StatefulWidget {
    method createState (line 635) | State<WindowButton> createState()
  class _WindowButtonState (line 638) | class _WindowButtonState extends State<WindowButton> {
    method build (line 642) | Widget build(BuildContext context)
  class UserPane (line 664) | class UserPane extends PaneItem {
    method build (line 668) | Widget build(BuildContext context, bool selected, VoidCallback? onPres...
  class CloseIcon (line 806) | class CloseIcon extends StatelessWidget {
    method build (line 812) | Widget build(BuildContext context)
  class _ClosePainter (line 815) | class _ClosePainter extends _IconPainter {
    method paint (line 819) | void paint(Canvas canvas, Size size)
  class MaximizeIcon (line 827) | class MaximizeIcon extends StatelessWidget {
    method build (line 833) | Widget build(BuildContext context)
  class _MaximizePainter (line 836) | class _MaximizePainter extends _IconPainter {
    method paint (line 840) | void paint(Canvas canvas, Size size)
  class RestoreIcon (line 847) | class RestoreIcon extends StatelessWidget {
    method build (line 856) | Widget build(BuildContext context)
  class _RestorePainter (line 859) | class _RestorePainter extends _IconPainter {
    method paint (line 863) | void paint(Canvas canvas, Size size)
  class MinimizeIcon (line 876) | class MinimizeIcon extends StatelessWidget {
    method build (line 882) | Widget build(BuildContext context)
  class _MinimizePainter (line 885) | class _MinimizePainter extends _IconPainter {
    method paint (line 889) | void paint(Canvas canvas, Size size)
  class _IconPainter (line 897) | abstract class _IconPainter extends CustomPainter {
    method shouldRepaint (line 903) | bool shouldRepaint(covariant CustomPainter oldDelegate)
  class _AlignedPaint (line 906) | class _AlignedPaint extends StatelessWidget {
    method build (line 912) | Widget build(BuildContext context)
  function getPaint (line 919) | Paint getPaint(Color color, [bool isAntiAlias = false])

FILE: lib/pages/novel_bookmarks_page.dart
  class NovelBookmarksPage (line 12) | class NovelBookmarksPage extends StatefulWidget {
    method createState (line 16) | State<NovelBookmarksPage> createState()
  class _NovelBookmarksPageState (line 19) | class _NovelBookmarksPageState
    method buildFrame (line 24) | Widget? buildFrame(BuildContext context, Widget child)
    method buildContent (line 53) | Widget buildContent(BuildContext context, List<Novel> data)
    method loadData (line 76) | Future<Res<List<Novel>>> loadData(int page)

FILE: lib/pages/novel_page.dart
  class NovelPage (line 24) | class NovelPage extends StatefulWidget {
    method createState (line 30) | State<NovelPage> createState()
  class _NovelPageState (line 33) | class _NovelPageState extends State<NovelPage> {
    method build (line 37) | Widget build(BuildContext context)
    method buildTop (line 65) | Widget buildTop()
    method buildStats (line 117) | Widget buildStats()
    method buildAuthor (line 209) | Widget buildAuthor()
    method buildActions (line 278) | Widget buildActions()
    method favorite (line 279) | void favorite()
    method buildDescription (line 443) | Widget buildDescription()
    method buildDescriptionText (line 507) | Iterable<TextSpan> buildDescriptionText()
  class NovelSeriesWidget (line 572) | class NovelSeriesWidget extends StatefulWidget {
    method createState (line 580) | State<NovelSeriesWidget> createState()
  class _NovelSeriesWidgetState (line 583) | class _NovelSeriesWidgetState
    method buildFrame (line 586) | Widget? buildFrame(BuildContext context, Widget child)
    method buildLoading (line 610) | Widget buildLoading(BuildContext context)
    method buildError (line 619) | Widget buildError(BuildContext context, String error)
    method buildContent (line 628) | Widget buildContent(BuildContext context, final List<Novel> data)
    method loadData (line 647) | Future<Res<List<Novel>>> loadData(page)
  class NovelPageWithId (line 661) | class NovelPageWithId extends StatefulWidget {
    method createState (line 667) | State<NovelPageWithId> createState()
  class _NovelPageWithIdState (line 670) | class _NovelPageWithIdState extends LoadingState<NovelPageWithId, Novel> {
    method loadData (line 672) | Future<Res<Novel>> loadData()
    method buildContent (line 677) | Widget buildContent(BuildContext context, Novel data)
  class _RelatedNovelsPage (line 682) | class _RelatedNovelsPage extends StatefulWidget {
    method createState (line 688) | State<_RelatedNovelsPage> createState()
  class __RelatedNovelsPageState (line 691) | class __RelatedNovelsPageState
    method buildContent (line 694) | Widget buildContent(BuildContext context, List<Novel> data)
    method loadData (line 712) | Future<Res<List<Novel>>> loadData()

FILE: lib/pages/novel_ranking_page.dart
  class NovelRankingPage (line 11) | class NovelRankingPage extends StatefulWidget {
    method createState (line 15) | State<NovelRankingPage> createState()
  class _NovelRankingPageState (line 18) | class _NovelRankingPageState extends State<NovelRankingPage> {
    method build (line 31) | Widget build(BuildContext context)
    method buildHeader (line 45) | Widget buildHeader()
  class _OneRankingPage (line 63) | class _OneRankingPage extends StatefulWidget {
    method createState (line 69) | State<_OneRankingPage> createState()
  class _OneRankingPageState (line 72) | class _OneRankingPageState extends MultiPageLoadingState<_OneRankingPage...
    method buildContent (line 74) | Widget buildContent(BuildContext context, final List<Novel> data)
    method loadData (line 91) | Future<Res<List<Novel>>> loadData(page)

FILE: lib/pages/novel_reading_page.dart
  class NovelReadingPage (line 18) | class NovelReadingPage extends StatefulWidget {
    method createState (line 24) | State<NovelReadingPage> createState()
  class _NovelReadingPageState (line 27) | class _NovelReadingPageState extends LoadingState<NovelReadingPage, Stri...
    method initState (line 35) | void initState()
    method dispose (line 74) | void dispose()
    method buildContent (line 82) | Widget buildContent(BuildContext context, String data)
    method loadData (line 101) | Future<Res<String>> loadData()
    method buildList (line 105) | Iterable<Widget> buildList(BuildContext context)
  class TranslationController (line 158) | class TranslationController {
  class _NovelReadingSettings (line 175) | class _NovelReadingSettings extends StatefulWidget {
    method show (line 182) | Future show(
    method createState (line 193) | State<_NovelReadingSettings> createState()
  class __NovelReadingSettingsState (line 196) | class __NovelReadingSettingsState extends State<_NovelReadingSettings> {
    method build (line 198) | Widget build(BuildContext context)
    method translate (line 345) | void translate()

FILE: lib/pages/novel_recommendation_page.dart
  class NovelRecommendationPage (line 10) | class NovelRecommendationPage extends StatefulWidget {
    method createState (line 14) | State<NovelRecommendationPage> createState()
  class _NovelRecommendationPageState (line 18) | class _NovelRecommendationPageState
    method buildContent (line 21) | Widget buildContent(BuildContext context, List<Novel> data)
    method loadData (line 43) | Future<Res<List<Novel>>> loadData(int page)

FILE: lib/pages/ranking.dart
  class RankingPage (line 14) | class RankingPage extends StatefulWidget {
    method createState (line 18) | State<RankingPage> createState()
  class _RankingPageState (line 21) | class _RankingPageState extends State<RankingPage> {
    method build (line 40) | Widget build(BuildContext context)
    method buildHeader (line 54) | Widget buildHeader()
  class _OneRankingPage (line 78) | class _OneRankingPage extends StatefulWidget {
    method createState (line 84) | State<_OneRankingPage> createState()
  class _OneRankingPageState (line 87) | class _OneRankingPageState extends MultiPageLoadingState<_OneRankingPage...
    method buildContent (line 89) | Widget buildContent(BuildContext context, final List<Illust> data)
    method loadData (line 118) | Future<Res<List<Illust>>> loadData(page)

FILE: lib/pages/recommendation_page.dart
  class RecommendationPage (line 16) | class RecommendationPage extends StatefulWidget {
    method createState (line 20) | State<RecommendationPage> createState()
  class _RecommendationPageState (line 23) | class _RecommendationPageState extends State<RecommendationPage> {
    method build (line 27) | Widget build(BuildContext context)
    method buildTab (line 43) | Widget buildTab()
  class _RecommendationArtworksPage (line 65) | class _RecommendationArtworksPage extends StatefulWidget {
    method createState (line 71) | State<_RecommendationArtworksPage> createState()
  class _RecommendationArtworksPageState (line 75) | class _RecommendationArtworksPageState
    method buildContent (line 78) | Widget buildContent(BuildContext context, final List<Illust> data)
    method loadData (line 108) | Future<Res<List<Illust>>> loadData(page)
  class _RecommendationUsersPage (line 115) | class _RecommendationUsersPage extends StatefulWidget {
    method createState (line 119) | State<_RecommendationUsersPage> createState()
  class _RecommendationUsersPageState (line 123) | class _RecommendationUsersPageState
    method buildContent (line 126) | Widget buildContent(BuildContext context, List<UserPreview> data)
    method loadData (line 144) | Future<Res<List<UserPreview>>> loadData(page)

FILE: lib/pages/related_page.dart
  class RelatedIllustsPage (line 10) | class RelatedIllustsPage extends StatefulWidget {
    method createState (line 16) | State<RelatedIllustsPage> createState()
  class _RelatedIllustsPageState (line 19) | class _RelatedIllustsPageState
    method buildFrame (line 22) | Widget? buildFrame(BuildContext context, Widget child)
    method buildContent (line 34) | Widget buildContent(BuildContext context, final List<Illust> data)
    method loadData (line 56) | Future<Res<List<Illust>>> loadData(page)

FILE: lib/pages/search_page.dart
  class SearchPage (line 35) | class SearchPage extends StatefulWidget {
    method createState (line 39) | State<SearchPage> createState()
  class _SearchPageState (line 42) | class _SearchPageState extends State<SearchPage> {
    method search (line 45) | void search(String text)
    method build (line 69) | Widget build(BuildContext context)
  class _TrendingTagsView (line 97) | class _TrendingTagsView extends StatefulWidget {
    method createState (line 101) | State<_TrendingTagsView> createState()
  class _TrendingTagsViewState (line 104) | class _TrendingTagsViewState
    method buildContent (line 107) | Widget buildContent(BuildContext context, List<TrendingTag> data)
    method buildItem (line 121) | Widget buildItem(TrendingTag tag)
    method loadData (line 183) | Future<Res<List<TrendingTag>>> loadData()
  class SearchSettings (line 188) | class SearchSettings extends StatefulWidget {
    method createState (line 196) | State<SearchSettings> createState()
  class _SearchSettingsState (line 199) | class _SearchSettingsState extends State<SearchSettings> {
    method build (line 201) | Widget build(BuildContext context)
    method buildItem (line 358) | Widget buildItem({required String title, required Widget child})
  class SearchResultPage (line 370) | class SearchResultPage extends StatefulWidget {
    method createState (line 376) | State<SearchResultPage> createState()
  class _SearchResultPageState (line 379) | class _SearchResultPageState
    method reset (line 388) | void reset()
    method search (line 393) | void search()
    method buildContent (line 401) | Widget buildContent(BuildContext context, final List<Illust> data)
    method buildSearchBar (line 433) | Widget buildSearchBar()
    method loadData (line 511) | Future<Res<List<Illust>>> loadData(page)
  class SearchUserResultPage (line 526) | class SearchUserResultPage extends StatefulWidget {
    method createState (line 532) | State<SearchUserResultPage> createState()
  class _SearchUserResultPageState (line 535) | class _SearchUserResultPageState
    method buildContent (line 538) | Widget buildContent(BuildContext context, final List<UserPreview> data)
    method loadData (line 567) | Future<Res<List<UserPreview>>> loadData(page)
  class SearchNovelResultPage (line 580) | class SearchNovelResultPage extends StatefulWidget {
    method createState (line 586) | State<SearchNovelResultPage> createState()
  class _SearchNovelResultPageState (line 589) | class _SearchNovelResultPageState
    method search (line 597) | void search()
    method buildContent (line 605) | Widget buildContent(BuildContext context, final List<Novel> data)
    method buildSearchBar (line 629) | Widget buildSearchBar()
    method loadData (line 706) | Future<Res<List<Novel>>> loadData(page)
  class _SearchBar (line 721) | class _SearchBar extends StatefulWidget {
    method createState (line 735) | State<_SearchBar> createState()
  class _SearchBarState (line 738) | class _SearchBarState extends State<_SearchBar> {
    method buildSearchOption (line 751) | Widget buildSearchOption(BuildContext context)
    method onTextChanged (line 763) | void onTextChanged(String text)
    method build (line 810) | Widget build(BuildContext context)

FILE: lib/pages/settings_page.dart
  class SettingsPage (line 19) | class SettingsPage extends StatefulWidget {
    method createState (line 23) | State<SettingsPage> createState()
  class _SettingsPageState (line 26) | class _SettingsPageState extends State<SettingsPage> {
    method build (line 28) | Widget build(BuildContext context)
    method buildHeader (line 51) | Widget buildHeader(String text)
    method buildItem (line 61) | Widget buildItem({required String title, String? subtitle, Widget? act...
    method buildAccount (line 73) | Widget buildAccount()
    method buildDownload (line 122) | Widget buildDownload()
    method buildAbout (line 187) | Widget buildAbout()
    method buildBrowse (line 234) | Widget buildBrowse()
    method buildAppearance (line 309) | Widget buildAppearance()
  class _SetSingleFieldPage (line 394) | class _SetSingleFieldPage extends StatefulWidget {
    method createState (line 404) | State<_SetSingleFieldPage> createState()
  class _SetSingleFieldPageState (line 407) | class _SetSingleFieldPageState extends State<_SetSingleFieldPage> {
    method build (line 412) | Widget build(BuildContext context)
  class _SetDownloadSubPathPage (line 442) | class _SetDownloadSubPathPage extends StatefulWidget {
    method createState (line 446) | State<_SetDownloadSubPathPage> createState()
  class __SetDownloadSubPathPageState (line 450) | class __SetDownloadSubPathPageState extends State<_SetDownloadSubPathPag...
    method build (line 455) | Widget build(BuildContext context)
    method check (line 491) | bool check(String text)
  class _BlockTagsPage (line 516) | class _BlockTagsPage extends StatefulWidget {
    method createState (line 520) | State<_BlockTagsPage> createState()
  class __BlockTagsPageState (line 523) | class __BlockTagsPageState extends State<_BlockTagsPage> {
    method build (line 525) | Widget build(BuildContext context)
    method finish (line 535) | void finish(BuildContext context)
  class ShortcutsSettings (line 601) | class ShortcutsSettings extends StatefulWidget {
    method createState (line 605) | State<ShortcutsSettings> createState()
  class _ShortcutsSettingsState (line 608) | class _ShortcutsSettingsState extends State<ShortcutsSettings> {
    method initState (line 614) | void initState()
    method dispose (line 620) | void dispose()
    method build (line 638) | Widget build(BuildContext context)
    method buildItem (line 647) | Widget buildItem(String text, int index)
  class _SetInitialPageWidget (line 681) | class _SetInitialPageWidget extends StatefulWidget {
    method createState (line 685) | State<_SetInitialPageWidget> createState()
  class _SetInitialPageWidgetState (line 688) | class _SetInitialPageWidgetState extends State<_SetInitialPageWidget> {
    method build (line 707) | Widget build(BuildContext context)
  class _MacosDownloadPathSelectButton (line 749) | class _MacosDownloadPathSelectButton extends StatefulWidget {
    method createState (line 755) | State<_MacosDownloadPathSelectButton> createState()
  class _MacosDownloadPathSelectButtonState (line 759) | class _MacosDownloadPathSelectButtonState
    method build (line 766) | Widget build(BuildContext context)

FILE: lib/pages/user_info_page.dart
  class UserInfoPage (line 23) | class UserInfoPage extends StatefulWidget {
    method createState (line 31) | State<UserInfoPage> createState()
  class _UserInfoPageState (line 34) | class _UserInfoPageState extends LoadingState<UserInfoPage, UserDetails> {
    method initState (line 36) | void initState()
    method dispose (line 47) | void dispose()
    method buildContent (line 55) | Widget buildContent(BuildContext context, UserDetails data)
    method follow (line 83) | void follow()
    method buildUser (line 125) | Widget buildUser()
    method buildHeader (line 204) | Widget buildHeader(String title, {Widget? action})
    method buildArtworkHeader (line 221) | Widget buildArtworkHeader()
    method buildInformation (line 270) | Widget buildInformation()
    method buildItem (line 271) | Widget buildItem(
    method loadData (line 346) | Future<Res<UserDetails>> loadData()
  class _UserArtworks (line 351) | class _UserArtworks extends StatefulWidget {
    method createState (line 359) | State<_UserArtworks> createState()
  class _UserArtworksState (line 362) | class _UserArtworksState extends MultiPageLoadingState<_UserArtworks, Il...
    method buildLoading (line 364) | Widget buildLoading(BuildContext context)
    method buildError (line 375) | Widget buildError(context, error)
    method buildContent (line 394) | Widget buildContent(BuildContext context, List<Illust> data)
    method loadData (line 418) | Future<Res<List<Illust>>> loadData(page)
  class _UserNovels (line 436) | class _UserNovels extends StatefulWidget {
    method createState (line 442) | State<_UserNovels> createState()
  class _UserNovelsState (line 445) | class _UserNovelsState extends MultiPageLoadingState<_UserNovels, Novel> {
    method buildLoading (line 447) | Widget buildLoading(BuildContext context)
    method buildError (line 458) | Widget buildError(context, error)
    method buildContent (line 477) | Widget buildContent(BuildContext context, List<Novel> data)
    method loadData (line 496) | Future<Res<List<Novel>>> loadData(page)
  class _RelatedUsers (line 511) | class _RelatedUsers extends StatefulWidget {
    method createState (line 517) | State<_RelatedUsers> createState()
  class _RelatedUsersState (line 520) | class _RelatedUsersState
    method buildFrame (line 523) | Widget buildFrame(BuildContext context, Widget child)
    method buildContent (line 536) | Widget buildContent(BuildContext context, List<UserPreview> data)
    method loadData (line 579) | Future<Res<List<UserPreview>>> loadData()

FILE: lib/pages/webview_page.dart
  class WebviewPage (line 10) | class WebviewPage extends StatefulWidget {
    method createState (line 18) | State<WebviewPage> createState()
  class _WebviewPageState (line 21) | class _WebviewPageState extends State<WebviewPage> {
    method initState (line 25) | void initState()
    method handleNavigation (line 29) | NavigationDecision handleNavigation(NavigationRequest req)
    method build (line 39) | Widget build(BuildContext context)

FILE: lib/utils/app_links.dart
  function _register (line 15) | Future<void> _register(String scheme)
  function _registerPixiv (line 34) | void _registerPixiv()
  function handleLinks (line 65) | void handleLinks()
  function handleLink (line 82) | bool handleLink(Uri uri)

FILE: lib/utils/block.dart
  function checkIllusts (line 4) | List<Illust> checkIllusts(List<Illust> illusts)

FILE: lib/utils/debounce.dart
  class Debounce (line 4) | class Debounce {
    method call (line 11) | void call(VoidCallback action)
    method _execute (line 17) | void _execute()
    method cancel (line 24) | void cancel()

FILE: lib/utils/debug.dart
  function debug (line 2) | void debug()

FILE: lib/utils/ext.dart
  function getNoBlankList (line 3) | List<T> getNoBlankList()
  function firstWhereOrNull (line 13) | T? firstWhereOrNull(bool Function(T element) test)
  function addIfNotNull (line 22) | void addIfNotNull(T? value)
  function toList (line 34) | List<String> toList()
  function _nums (line 36) | String _nums()
  function setValueAt (line 46) | String setValueAt(String value, int index)
  function subStringOrNull (line 50) | String? subStringOrNull(int start, [int? end])
  function replaceLast (line 57) | String replaceLast(String from, String to)
  function hasMatch (line 72) | bool hasMatch(String? value, String pattern)
  function _isURL (line 76) | bool _isURL()

FILE: lib/utils/io.dart
  function deleteIfExists (line 9) | Future<void> deleteIfExists()
  function deleteIgnoreError (line 15) | Future<void> deleteIgnoreError()
  function havePermission (line 38) | bool havePermission()
  function bytesToText (line 52) | String bytesToText(int bytes)
  function saveFile (line 64) | void saveFile(File file, [String? name])

FILE: lib/utils/loop.dart
  class Loop (line 3) | class Loop {
    method start (line 6) | void start()
    method register (line 14) | void register(void Function() func)
    method remove (line 18) | void remove(void Function() func)

FILE: lib/utils/mouse_listener.dart
  function mouseSideButtonCallback (line 5) | void mouseSideButtonCallback(GlobalKey<NavigatorState> key)
  function listenMouseSideButtonToBack (line 16) | void listenMouseSideButtonToBack(GlobalKey<NavigatorState> key)

FILE: lib/utils/translation.dart
  function init (line 15) | Future<void> init()

FILE: lib/utils/update.dart
  function getLatestVersion (line 8) | Future<String> getLatestVersion()
  function compareVersion (line 23) | bool compareVersion(String a, String b)
  function checkUpdate (line 36) | Future<void> checkUpdate()

FILE: lib/utils/window.dart
  class WindowPlacement (line 8) | class WindowPlacement {
    method applyToWindow (line 15) | Future<void> applyToWindow()
    method writeToFile (line 27) | Future<void> writeToFile()
    method loadFromFile (line 38) | Future<WindowPlacement> loadFromFile()
    method loop (line 60) | void loop()
    method validate (line 72) | bool validate(Rect rect)

FILE: linux/flutter/generated_plugin_registrant.cc
  function fl_register_plugins (line 17) | void fl_register_plugins(FlPluginRegistry* registry) {

FILE: linux/main.cc
  function main (line 3) | int main(int argc, char** argv) {

FILE: linux/my_application.cc
  type _MyApplication (line 10) | struct _MyApplication {
  function my_application_activate (line 18) | static void my_application_activate(GApplication* application) {
  function gboolean (line 73) | static gboolean my_application_local_command_line(GApplication* applicat...
  function my_application_startup (line 92) | static void my_application_startup(GApplication* application) {
  function my_application_shutdown (line 101) | static void my_application_shutdown(GApplication* application) {
  function my_application_dispose (line 110) | static void my_application_dispose(GObject* object) {
  function my_application_class_init (line 116) | static void my_application_class_init(MyApplicationClass* klass) {
  function my_application_init (line 124) | static void my_application_init(MyApplication* self) {}
  function MyApplication (line 126) | MyApplication* my_application_new() {

FILE: test/widget_test.dart
  function main (line 13) | void main()

FILE: windows/flutter/generated_plugin_registrant.cc
  function RegisterPlugins (line 18) | void RegisterPlugins(flutter::PluginRegistry* registry) {

FILE: windows/runner/flutter_window.cpp
  function getProxy (line 16) | static std::string getProxy() {
  function getPicturePath (line 31) | static std::string getPicturePath() {
  function mouse_side_button_listener (line 127) | void mouse_side_button_listener(unsigned int input)
  function LRESULT (line 135) | LRESULT

FILE: windows/runner/flutter_window.h
  function class (line 12) | class FlutterWindow : public Win32Window {

FILE: windows/runner/main.cpp
  function SendAppLinkToInstance (line 9) | bool SendAppLinkToInstance(const std::wstring& title) {
  function wWinMain (line 44) | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,

FILE: windows/runner/utils.cpp
  function CreateAndAttachConsole (line 10) | void CreateAndAttachConsole() {
  function GetCommandLineArguments (line 24) | std::vector<std::string> GetCommandLineArguments() {
  function Utf8FromUtf16 (line 44) | std::string Utf8FromUtf16(const wchar_t* utf16_string) {

FILE: windows/runner/win32_window.cpp
  function Scale (line 36) | int Scale(int source, double scale_factor) {
  function EnableFullDpiSupportIfAvailable (line 42) | void EnableFullDpiSupportIfAvailable(HWND hwnd) {
  class WindowClassRegistrar (line 59) | class WindowClassRegistrar {
    method WindowClassRegistrar (line 64) | static WindowClassRegistrar* GetInstance() {
    method WindowClassRegistrar (line 80) | WindowClassRegistrar() = default;
  function wchar_t (line 89) | const wchar_t* WindowClassRegistrar::GetWindowClass() {
  function LRESULT (line 157) | LRESULT CALLBACK Win32Window::WndProc(HWND const window,
  function LRESULT (line 176) | LRESULT
  function Win32Window (line 236) | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
  function RECT (line 252) | RECT Win32Window::GetClientArea() {
  function HWND (line 258) | HWND Win32Window::GetHandle() {

FILE: windows/runner/win32_window.h
  type Size (line 21) | struct Size {
Condensed preview — 173 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (747K chars).
[
  {
    "path": ".github/workflows/main.yml",
    "chars": 9009,
    "preview": "name: Build ALL\nrun-name: Build ALL\non:\n  workflow_dispatch:\n    inputs:\n      # macOS build disabled: the macOS job fre"
  },
  {
    "path": ".gitignore",
    "chars": 715,
    "preview": "# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.build/\n.buildlog/\n.history\n.svn/\n.swiftpm/\nmigrate_working_d"
  },
  {
    "path": ".metadata",
    "chars": 1560,
    "preview": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrade"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 239,
    "preview": "{\n    \"cSpell.words\": [\n        \"appdata\",\n        \"Bungo\",\n        \"gjzr\",\n        \"microtask\",\n        \"mypixiv\",\n    "
  },
  {
    "path": "LICENSE",
    "chars": 1061,
    "preview": "MIT License\n\nCopyright (c) 2024 nyne\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof th"
  },
  {
    "path": "README.md",
    "chars": 1404,
    "preview": "# pixes\n\n[![flutter](https://img.shields.io/badge/flutter-3.32.5-blue)](https://flutter.dev/) \n[![License](https://img.s"
  },
  {
    "path": "analysis_options.yaml",
    "chars": 1420,
    "preview": "# This file configures the analyzer, which statically analyzes Dart code to\n# check for errors, warnings, and lints.\n#\n#"
  },
  {
    "path": "android/.gitignore",
    "chars": 285,
    "preview": "gradle-wrapper.jar\n/.gradle\n/captures/\n/gradlew\n/gradlew.bat\n/local.properties\nGeneratedPluginRegistrant.java\n\n# Remembe"
  },
  {
    "path": "android/app/build.gradle",
    "chars": 3622,
    "preview": "plugins {\n    id \"com.android.application\"\n    id \"kotlin-android\"\n    id \"dev.flutter.flutter-gradle-plugin\"\n}\n\next.abi"
  },
  {
    "path": "android/app/src/debug/AndroidManifest.xml",
    "chars": 378,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <!-- The INTERNET permission is required for d"
  },
  {
    "path": "android/app/src/main/AndroidManifest.xml",
    "chars": 3657,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <uses-permission android:name=\"android.permiss"
  },
  {
    "path": "android/app/src/main/kotlin/com/github/wgh136/pixes/MainActivity.kt",
    "chars": 899,
    "preview": "package com.github.wgh136.pixes\n\nimport io.flutter.embedding.android.FlutterActivity\nimport io.flutter.plugins.Generated"
  },
  {
    "path": "android/app/src/main/res/drawable/launch_background.xml",
    "chars": 434,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmln"
  },
  {
    "path": "android/app/src/main/res/drawable-v21/launch_background.xml",
    "chars": 438,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmln"
  },
  {
    "path": "android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 328,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <bac"
  },
  {
    "path": "android/app/src/main/res/values/styles.xml",
    "chars": 1157,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is sta"
  },
  {
    "path": "android/app/src/main/res/values-night/styles.xml",
    "chars": 1156,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is sta"
  },
  {
    "path": "android/app/src/profile/AndroidManifest.xml",
    "chars": 378,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <!-- The INTERNET permission is required for d"
  },
  {
    "path": "android/build.gradle",
    "chars": 322,
    "preview": "allprojects {\n    repositories {\n        google()\n        mavenCentral()\n    }\n}\n\nrootProject.buildDir = '../build'\nsubp"
  },
  {
    "path": "android/gradle/wrapper/gradle-wrapper.properties",
    "chars": 200,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dist"
  },
  {
    "path": "android/gradle.properties",
    "chars": 79,
    "preview": "org.gradle.jvmargs=-Xmx4G\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n"
  },
  {
    "path": "android/settings.gradle",
    "chars": 791,
    "preview": "pluginManagement {\n    def flutterSdkPath = {\n        def properties = new Properties()\n        file(\"local.properties\")"
  },
  {
    "path": "assets/tr.json",
    "chars": 21751,
    "preview": "{\n    \"zh_CN\": {\n        \"Search\": \"搜索\",\n        \"Downloading\": \"下载中\",\n        \"Downloaded\": \"已下载\",\n        \"Artwork\": \""
  },
  {
    "path": "debian/build.py",
    "chars": 1142,
    "preview": "import subprocess\nimport sys\n\narch = sys.argv[1]\ndebianContent = ''\ndesktopContent = ''\nversion = ''\n\nwith open('debian/"
  },
  {
    "path": "debian/debian.yaml",
    "chars": 372,
    "preview": "flutter_app: \n  command: pixes\n  arch: {{Arch}}\n  parent: /usr/local/lib\n  nonInteractive: true\n  execFieldCodes: u\n\ncon"
  },
  {
    "path": "debian/gui/pixes.desktop",
    "chars": 207,
    "preview": "[Desktop Entry]\nName=Pixes\nGenericName=Pixes\nComment=Unofficial pixiv application\nTerminal=false\nType=Application\nCatego"
  },
  {
    "path": "ios/.gitignore",
    "chars": 569,
    "preview": "**/dgph\n*.mode1v3\n*.mode2v3\n*.moved-aside\n*.pbxuser\n*.perspectivev3\n**/*sync/\n.sconsign.dblite\n.tags*\n**/.vagrant/\n**/De"
  },
  {
    "path": "ios/Flutter/AppFrameworkInfo.plist",
    "chars": 774,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "ios/Flutter/Debug.xcconfig",
    "chars": 107,
    "preview": "#include? \"Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"\n#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "ios/Flutter/Release.xcconfig",
    "chars": 109,
    "preview": "#include? \"Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"\n#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "ios/Podfile",
    "chars": 1391,
    "preview": "# Uncomment this line to define a global platform for your project\n# platform :ios, '13.0'\n\n# CocoaPods analytics sends "
  },
  {
    "path": "ios/Runner/AppDelegate.swift",
    "chars": 1245,
    "preview": "import UIKit\nimport Flutter\n\n@UIApplicationMain\n@objc class AppDelegate: FlutterAppDelegate {\n  override func applicatio"
  },
  {
    "path": "ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 2630,
    "preview": "{\n  \"images\": [\n    {\n      \"filename\": \"AppIcon@2x.png\",\n      \"idiom\": \"iphone\",\n      \"scale\": \"2x\",\n      \"size\": \"6"
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
    "chars": 391,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage.png\",\n      \"scale\" : \"1x\"\n    },\n  "
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md",
    "chars": 336,
    "preview": "# Launch Screen Assets\n\nYou can customize the launch screen with your own desired assets by replacing the image files in"
  },
  {
    "path": "ios/Runner/Base.lproj/LaunchScreen.storyboard",
    "chars": 2377,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "ios/Runner/Base.lproj/Main.storyboard",
    "chars": 1605,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "ios/Runner/Info.plist",
    "chars": 2078,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "ios/Runner/Runner-Bridging-Header.h",
    "chars": 38,
    "preview": "#import \"GeneratedPluginRegistrant.h\"\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.pbxproj",
    "chars": 23672,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 54;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "chars": 226,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "chars": 3647,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1510\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "ios/Runner.xcworkspace/contents.xcworkspacedata",
    "chars": 152,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodepr"
  },
  {
    "path": "ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "chars": 226,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "ios/RunnerTests/RunnerTests.swift",
    "chars": 285,
    "preview": "import Flutter\nimport UIKit\nimport XCTest\n\nclass RunnerTests: XCTestCase {\n\n  func testExample() {\n    // If you add cod"
  },
  {
    "path": "lib/appdata.dart",
    "chars": 6262,
    "preview": "import 'dart:convert';\nimport 'dart:io';\n\nimport 'package:flutter/services.dart';\nimport 'package:path_provider/path_pro"
  },
  {
    "path": "lib/components/animated_image.dart",
    "chars": 8998,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter/rendering.dart';\nimport 'package:flutter/scheduler.da"
  },
  {
    "path": "lib/components/batch_download.dart",
    "chars": 4134,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/md.dart';\nimport 'package:pixes/components/m"
  },
  {
    "path": "lib/components/button.dart",
    "chars": 2437,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/foundation/app.dart';\n\nabstract class BaseButton extend"
  },
  {
    "path": "lib/components/grid.dart",
    "chars": 3577,
    "preview": "import 'package:flutter/rendering.dart';\nimport 'package:flutter/widgets.dart';\nimport 'package:pixes/foundation/app.dar"
  },
  {
    "path": "lib/components/illust_widget.dart",
    "chars": 17132,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/appdata.dart';\nimport 'package:pixes/components/animate"
  },
  {
    "path": "lib/components/keyboard.dart",
    "chars": 1669,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:pixes/foundation/app.dar"
  },
  {
    "path": "lib/components/loading.dart",
    "chars": 4463,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/foundation/app.dart';\nimport 'package:pixes/network/res"
  },
  {
    "path": "lib/components/md.dart",
    "chars": 338,
    "preview": "import 'package:flutter/material.dart' as md;\n\ntypedef MdIcons = md.Icons;\ntypedef MdTheme = md.Theme;\ntypedef MdThemeDa"
  },
  {
    "path": "lib/components/message.dart",
    "chars": 2834,
    "preview": "import 'dart:async';\n\nimport 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/md.dart';\nimport 'pack"
  },
  {
    "path": "lib/components/novel.dart",
    "chars": 2648,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/animated_image.dart';\nimport 'package:pixes/"
  },
  {
    "path": "lib/components/page_route.dart",
    "chars": 12646,
    "preview": "import 'dart:math';\nimport 'dart:ui';\nimport 'package:flutter/gestures.dart';\nimport 'package:fluent_ui/fluent_ui.dart';"
  },
  {
    "path": "lib/components/search_field.dart",
    "chars": 7841,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/foundation/app.dart';\n\nclass AutoCompleteItem {\n  final"
  },
  {
    "path": "lib/components/segmented_button.dart",
    "chars": 2062,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/foundation/app.dart';\n\nimport 'md.dart';\n\nclass Segment"
  },
  {
    "path": "lib/components/title_bar.dart",
    "chars": 1196,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/foundation/app.dart';\n\nclass TitleBar extends Stateless"
  },
  {
    "path": "lib/components/ugoira.dart",
    "chars": 6875,
    "preview": "import 'dart:convert';\nimport 'dart:io';\nimport 'package:archive/archive_io.dart';\n\nimport 'package:crypto/crypto.dart';"
  },
  {
    "path": "lib/components/user_preview.dart",
    "chars": 6137,
    "preview": "import 'dart:math';\n\nimport 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/animated_image.dart';\ni"
  },
  {
    "path": "lib/foundation/app.dart",
    "chars": 2123,
    "preview": "import 'dart:io';\nimport 'dart:ui';\n\nimport 'package:device_info_plus/device_info_plus.dart';\nimport 'package:fluent_ui/"
  },
  {
    "path": "lib/foundation/cache_manager.dart",
    "chars": 6735,
    "preview": "import 'dart:io';\n\nimport 'package:crypto/crypto.dart';\nimport 'package:flutter/foundation.dart';\nimport 'package:pixes/"
  },
  {
    "path": "lib/foundation/history.dart",
    "chars": 2621,
    "preview": "import 'package:pixes/foundation/app.dart';\nimport 'package:sqlite3/sqlite3.dart';\nimport 'package:pixes/network/models."
  },
  {
    "path": "lib/foundation/image_provider.dart",
    "chars": 7863,
    "preview": "import 'dart:async' show Future, StreamController, scheduleMicrotask;\nimport 'dart:convert';\nimport 'dart:io';\nimport 'd"
  },
  {
    "path": "lib/foundation/log.dart",
    "chars": 2176,
    "preview": "import 'dart:io';\n\nimport 'package:flutter/foundation.dart';\nimport 'package:pixes/utils/ext.dart';\n\nclass LogItem {\n  f"
  },
  {
    "path": "lib/foundation/navigation.dart",
    "chars": 685,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\n\nimport '../components/message.dart' as overlay;\nimport '../components/page_r"
  },
  {
    "path": "lib/foundation/pair.dart",
    "chars": 186,
    "preview": "class Pair<M, V>{\n  M left;\n  V right;\n\n  Pair(this.left, this.right);\n\n  Pair.fromMap(Map<M, V> map, M key): left = key"
  },
  {
    "path": "lib/foundation/state_controller.dart",
    "chars": 4760,
    "preview": "import 'package:flutter/material.dart';\nimport 'pair.dart';\n\nclass SimpleController extends StateController{\n  final voi"
  },
  {
    "path": "lib/foundation/widget_utils.dart",
    "chars": 2001,
    "preview": "import 'package:flutter/widgets.dart';\n\nextension WidgetExtension on Widget{\n  Widget padding(EdgeInsetsGeometry padding"
  },
  {
    "path": "lib/main.dart",
    "chars": 7305,
    "preview": "import \"dart:async\";\nimport \"dart:ui\";\n\nimport \"package:dynamic_color/dynamic_color.dart\";\nimport \"package:fluent_ui/flu"
  },
  {
    "path": "lib/network/app_dio.dart",
    "chars": 7267,
    "preview": "import 'dart:convert';\nimport 'dart:io';\n\nimport 'package:dio/dio.dart';\nimport 'package:dio/io.dart';\nimport 'package:f"
  },
  {
    "path": "lib/network/download.dart",
    "chars": 10494,
    "preview": "import 'dart:async';\nimport 'dart:convert';\nimport 'dart:io';\n\nimport 'package:crypto/crypto.dart';\nimport 'package:intl"
  },
  {
    "path": "lib/network/models.dart",
    "chars": 15962,
    "preview": "import 'package:pixes/appdata.dart';\n\nclass Account {\n  String accessToken;\n  String refreshToken;\n  final User user;\n\n "
  },
  {
    "path": "lib/network/network.dart",
    "chars": 19653,
    "preview": "import 'dart:convert';\nimport 'dart:math';\n\nimport 'package:crypto/crypto.dart';\nimport 'package:intl/intl.dart';\nimport"
  },
  {
    "path": "lib/network/novel.dart",
    "chars": 5119,
    "preview": "part of \"network.dart\";\n\nextension NovelExt on Network {\n  Future<Res<List<Novel>>> getRecommendNovels() {\n    return ge"
  },
  {
    "path": "lib/network/res.dart",
    "chars": 922,
    "preview": "import 'package:flutter/cupertino.dart';\n\n@immutable\nclass Res<T>{\n  ///error info\n  final String? errorMessage;\n\n  Stri"
  },
  {
    "path": "lib/network/translator.dart",
    "chars": 1778,
    "preview": "import 'package:pixes/network/app_dio.dart';\n\nabstract class Translator {\n  static Translator? _instance;\n\n  static Tran"
  },
  {
    "path": "lib/pages/bookmarks.dart",
    "chars": 3227,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'"
  },
  {
    "path": "lib/pages/comments_page.dart",
    "chars": 7228,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/animated_image.dart';\nimport 'package:pixes/"
  },
  {
    "path": "lib/pages/downloaded_page.dart",
    "chars": 15125,
    "preview": "import 'dart:io';\n\nimport 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter/gestures.dart';\nimport 'package:fl"
  },
  {
    "path": "lib/pages/downloading_page.dart",
    "chars": 6632,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/md.dart';\nimport 'package:pixes/components/t"
  },
  {
    "path": "lib/pages/following_artworks.dart",
    "chars": 3323,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'"
  },
  {
    "path": "lib/pages/following_novels_page.dart",
    "chars": 2386,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/grid.dart';\nimport 'package:pixes/components"
  },
  {
    "path": "lib/pages/following_users_page.dart",
    "chars": 2475,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/appdata.dart';\nimport 'package:pixes/components/loading"
  },
  {
    "path": "lib/pages/history.dart",
    "chars": 3737,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'"
  },
  {
    "path": "lib/pages/illust_page.dart",
    "chars": 37491,
    "preview": "import 'dart:io';\n\nimport 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter/gestures.dart';\nimport 'package:fl"
  },
  {
    "path": "lib/pages/image_page.dart",
    "chars": 10867,
    "preview": "import 'dart:io';\n\nimport 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter/gestures.dart';\nimport 'package:fl"
  },
  {
    "path": "lib/pages/login_page.dart",
    "chars": 7952,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/button.dart';\nimport 'package:pixes/foundati"
  },
  {
    "path": "lib/pages/logs.dart",
    "chars": 3205,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter/services.dart';\nimport 'package:pixes/components/md.d"
  },
  {
    "path": "lib/pages/main_page.dart",
    "chars": 27308,
    "preview": "import \"dart:async\";\n\nimport \"package:fluent_ui/fluent_ui.dart\";\nimport \"package:flutter/foundation.dart\";\nimport \"packa"
  },
  {
    "path": "lib/pages/novel_bookmarks_page.dart",
    "chars": 2421,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/appdata.dart';\nimport 'package:pixes/components/grid.da"
  },
  {
    "path": "lib/pages/novel_page.dart",
    "chars": 23795,
    "preview": "import 'dart:collection';\n\nimport 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter/gestures.dart';\nimport 'pa"
  },
  {
    "path": "lib/pages/novel_ranking_page.dart",
    "chars": 2631,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/loading.dart';\nimport 'package:pixes/compone"
  },
  {
    "path": "lib/pages/novel_reading_page.dart",
    "chars": 11875,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/appdata.dart';\nimport 'package:pixes/components/animate"
  },
  {
    "path": "lib/pages/novel_recommendation_page.dart",
    "chars": 1370,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/grid.dart';\nimport 'package:pixes/components"
  },
  {
    "path": "lib/pages/ranking.dart",
    "chars": 3556,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'"
  },
  {
    "path": "lib/pages/recommendation_page.dart",
    "chars": 4198,
    "preview": "import 'package:flutter/widgets.dart';\nimport 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';\nim"
  },
  {
    "path": "lib/pages/related_page.dart",
    "chars": 1996,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'"
  },
  {
    "path": "lib/pages/search_page.dart",
    "chars": 28987,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'"
  },
  {
    "path": "lib/pages/settings_page.dart",
    "chars": 25442,
    "preview": "import 'dart:io';\n\nimport 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter/services.dart';\nimport 'package:pi"
  },
  {
    "path": "lib/pages/user_info_page.dart",
    "chars": 17181,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:flutter/gestures.dart';\nimport 'package:flutter_staggered_gri"
  },
  {
    "path": "lib/pages/webview_page.dart",
    "chars": 2311,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/components/md.dart';\nimport 'package:url_launcher/url_l"
  },
  {
    "path": "lib/utils/app_links.dart",
    "chars": 3957,
    "preview": "import 'dart:io';\n\nimport 'package:app_links/app_links.dart';\nimport 'package:fluent_ui/fluent_ui.dart';\nimport 'package"
  },
  {
    "path": "lib/utils/block.dart",
    "chars": 582,
    "preview": "import 'package:pixes/appdata.dart';\nimport 'package:pixes/network/models.dart';\n\nList<Illust> checkIllusts(List<Illust>"
  },
  {
    "path": "lib/utils/debounce.dart",
    "chars": 444,
    "preview": "import 'dart:async';\nimport 'dart:ui';\n\nclass Debounce {\n  final Duration delay;\n  VoidCallback? _action;\n  Timer? _time"
  },
  {
    "path": "lib/utils/debug.dart",
    "chars": 45,
    "preview": "/// function used for debug\nvoid debug() {\n\n}"
  },
  {
    "path": "lib/utils/ext.dart",
    "chars": 1974,
    "preview": "extension ListExt<T> on List<T>{\n  /// Remove all blank value and return the list.\n  List<T> getNoBlankList(){\n    List<"
  },
  {
    "path": "lib/utils/io.dart",
    "chars": 2009,
    "preview": "import 'dart:io';\nimport 'dart:typed_data';\n\nimport 'package:file_selector/file_selector.dart';\nimport 'package:flutter_"
  },
  {
    "path": "lib/utils/loop.dart",
    "chars": 413,
    "preview": "import 'dart:async';\n\nclass Loop {\n  static final List<void Function()> _callbacks = [];\n\n  static void start() {\n    Ti"
  },
  {
    "path": "lib/utils/mouse_listener.dart",
    "chars": 678,
    "preview": "import 'package:flutter/services.dart';\nimport 'package:flutter/widgets.dart';\nimport '../foundation/app.dart';\n\nvoid mo"
  },
  {
    "path": "lib/utils/translation.dart",
    "chars": 538,
    "preview": "import 'dart:convert';\n\nimport 'package:flutter/services.dart';\nimport 'package:pixes/foundation/app.dart';\n\nextension T"
  },
  {
    "path": "lib/utils/update.dart",
    "chars": 2224,
    "preview": "import 'package:fluent_ui/fluent_ui.dart';\nimport 'package:pixes/appdata.dart';\nimport 'package:pixes/foundation/app.dar"
  },
  {
    "path": "lib/utils/window.dart",
    "chars": 1945,
    "preview": "import 'dart:convert';\nimport 'dart:ui';\nimport 'dart:io';\n\nimport 'package:pixes/foundation/app.dart';\nimport 'package:"
  },
  {
    "path": "linux/.gitignore",
    "chars": 18,
    "preview": "flutter/ephemeral\n"
  },
  {
    "path": "linux/CMakeLists.txt",
    "chars": 5429,
    "preview": "# Project-level configuration.\ncmake_minimum_required(VERSION 3.10)\nproject(runner LANGUAGES CXX)\n\n# The name of the exe"
  },
  {
    "path": "linux/flutter/CMakeLists.txt",
    "chars": 2815,
    "preview": "# This file controls Flutter-level build steps. It should not be edited.\ncmake_minimum_required(VERSION 3.10)\n\nset(EPHEM"
  },
  {
    "path": "linux/flutter/generated_plugin_registrant.cc",
    "chars": 2059,
    "preview": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#include \"generated_plugin_registrant.h\"\n\n#include <dynamic"
  },
  {
    "path": "linux/flutter/generated_plugin_registrant.h",
    "chars": 303,
    "preview": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#ifndef GENERATED_PLUGIN_REGISTRANT_\n#define GENERATED_PLUG"
  },
  {
    "path": "linux/flutter/generated_plugins.cmake",
    "chars": 869,
    "preview": "#\n# Generated file, do not edit.\n#\n\nlist(APPEND FLUTTER_PLUGIN_LIST\n  dynamic_color\n  file_selector_linux\n  gtk\n  screen"
  },
  {
    "path": "linux/main.cc",
    "chars": 180,
    "preview": "#include \"my_application.h\"\n\nint main(int argc, char** argv) {\n  g_autoptr(MyApplication) app = my_application_new();\n  "
  },
  {
    "path": "linux/my_application.cc",
    "chars": 4622,
    "preview": "#include \"my_application.h\"\n\n#include <flutter_linux/flutter_linux.h>\n#ifdef GDK_WINDOWING_X11\n#include <gdk/gdkx.h>\n#en"
  },
  {
    "path": "linux/my_application.h",
    "chars": 388,
    "preview": "#ifndef FLUTTER_MY_APPLICATION_H_\n#define FLUTTER_MY_APPLICATION_H_\n\n#include <gtk/gtk.h>\n\nG_DECLARE_FINAL_TYPE(MyApplic"
  },
  {
    "path": "macos/.gitignore",
    "chars": 89,
    "preview": "# Flutter-related\n**/Flutter/ephemeral/\n**/Pods/\n\n# Xcode-related\n**/dgph\n**/xcuserdata/\n"
  },
  {
    "path": "macos/Flutter/Flutter-Debug.xcconfig",
    "chars": 125,
    "preview": "#include? \"Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"\n#include \"ephemeral/Flutter-Generated.xccon"
  },
  {
    "path": "macos/Flutter/Flutter-Release.xcconfig",
    "chars": 127,
    "preview": "#include? \"Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"\n#include \"ephemeral/Flutter-Generated.xcc"
  },
  {
    "path": "macos/Flutter/GeneratedPluginRegistrant.swift",
    "chars": 1456,
    "preview": "//\n//  Generated file. Do not edit.\n//\n\nimport FlutterMacOS\nimport Foundation\n\nimport app_links\nimport device_info_plus\n"
  },
  {
    "path": "macos/Podfile",
    "chars": 1513,
    "preview": "platform :osx, '14.0'\n\n# CocoaPods analytics sends network stats synchronously affecting flutter build latency.\nENV['COC"
  },
  {
    "path": "macos/Runner/AppDelegate.swift",
    "chars": 311,
    "preview": "import Cocoa\nimport FlutterMacOS\n\n@main\nclass AppDelegate: FlutterAppDelegate {\n  override func applicationShouldTermina"
  },
  {
    "path": "macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1291,
    "preview": "{\n  \"images\" : [\n    {\n      \"size\" : \"16x16\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"app_icon_16.png\",\n      \"scale"
  },
  {
    "path": "macos/Runner/Base.lproj/MainMenu.xib",
    "chars": 23723,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion"
  },
  {
    "path": "macos/Runner/Configs/AppInfo.xcconfig",
    "chars": 590,
    "preview": "// Application-level settings for the Runner target.\n//\n// This may be replaced with something auto-generated from metad"
  },
  {
    "path": "macos/Runner/Configs/Debug.xcconfig",
    "chars": 77,
    "preview": "#include \"../../Flutter/Flutter-Debug.xcconfig\"\n#include \"Warnings.xcconfig\"\n"
  },
  {
    "path": "macos/Runner/Configs/Release.xcconfig",
    "chars": 79,
    "preview": "#include \"../../Flutter/Flutter-Release.xcconfig\"\n#include \"Warnings.xcconfig\"\n"
  },
  {
    "path": "macos/Runner/Configs/Warnings.xcconfig",
    "chars": 580,
    "preview": "WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverl"
  },
  {
    "path": "macos/Runner/DebugProfile.entitlements",
    "chars": 483,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "macos/Runner/Info.plist",
    "chars": 1337,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "macos/Runner/MainFlutterWindow.swift",
    "chars": 6047,
    "preview": "import Cocoa\nimport FlutterMacOS\nimport IOKit.ps\n\nclass MainFlutterWindow: NSWindow {\n  private static let downloadPathB"
  },
  {
    "path": "macos/Runner/Release.entitlements",
    "chars": 436,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "macos/Runner.xcodeproj/project.pbxproj",
    "chars": 30393,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 54;\n\tobjects = {\n\n/* Begin PBXAggregateTarget sec"
  },
  {
    "path": "macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "chars": 3679,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1510\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "macos/Runner.xcworkspace/contents.xcworkspacedata",
    "chars": 224,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodepr"
  },
  {
    "path": "macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "macos/RunnerTests/RunnerTests.swift",
    "chars": 290,
    "preview": "import FlutterMacOS\nimport Cocoa\nimport XCTest\n\nclass RunnerTests: XCTestCase {\n\n  func testExample() {\n    // If you ad"
  },
  {
    "path": "pubspec.yaml",
    "chars": 3910,
    "preview": "name: pixes\ndescription: \"A new Flutter project.\"\n# The following line prevents the package from being accidentally publ"
  },
  {
    "path": "test/widget_test.dart",
    "chars": 1056,
    "preview": "// This is a basic Flutter widget test.\n//\n// To perform an interaction with a widget in your test, use the WidgetTester"
  },
  {
    "path": "windows/.gitignore",
    "chars": 291,
    "preview": "flutter/ephemeral/\n\n# Visual Studio user-specific files.\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# Visual Studio bu"
  },
  {
    "path": "windows/CMakeLists.txt",
    "chars": 4146,
    "preview": "# Project-level configuration.\ncmake_minimum_required(VERSION 3.14)\nproject(pixes LANGUAGES CXX)\n\n# The name of the exec"
  },
  {
    "path": "windows/build.iss",
    "chars": 3573,
    "preview": "; Script generated by the Inno Setup Script Wizard.\n; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FI"
  },
  {
    "path": "windows/build.py",
    "chars": 1197,
    "preview": "import subprocess\nimport os\nimport httpx\n\nfile = open('pubspec.yaml', 'r')\ncontent = file.read()\nfile.close()\n\nsubproces"
  },
  {
    "path": "windows/flutter/CMakeLists.txt",
    "chars": 3742,
    "preview": "# This file controls Flutter-level build steps. It should not be edited.\ncmake_minimum_required(VERSION 3.14)\n\nset(EPHEM"
  },
  {
    "path": "windows/flutter/generated_plugin_registrant.cc",
    "chars": 1528,
    "preview": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#include \"generated_plugin_registrant.h\"\n\n#include <app_lin"
  },
  {
    "path": "windows/flutter/generated_plugin_registrant.h",
    "chars": 302,
    "preview": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#ifndef GENERATED_PLUGIN_REGISTRANT_\n#define GENERATED_PLUG"
  },
  {
    "path": "windows/flutter/generated_plugins.cmake",
    "chars": 898,
    "preview": "#\n# Generated file, do not edit.\n#\n\nlist(APPEND FLUTTER_PLUGIN_LIST\n  app_links\n  dynamic_color\n  file_selector_windows\n"
  },
  {
    "path": "windows/runner/CMakeLists.txt",
    "chars": 1796,
    "preview": "cmake_minimum_required(VERSION 3.14)\nproject(runner LANGUAGES CXX)\n\n# Define the application target. To change its name,"
  },
  {
    "path": "windows/runner/Runner.rc",
    "chars": 3029,
    "preview": "// Microsoft Visual C++ generated resource script.\n//\n#pragma code_page(65001)\n#include \"resource.h\"\n\n#define APSTUDIO_R"
  },
  {
    "path": "windows/runner/flutter_window.cpp",
    "chars": 5208,
    "preview": "#pragma comment(lib, \"winhttp.lib\")\n#include \"flutter_window.h\"\n#include <flutter/method_channel.h>\n#include <flutter/ev"
  },
  {
    "path": "windows/runner/flutter_window.h",
    "chars": 928,
    "preview": "#ifndef RUNNER_FLUTTER_WINDOW_H_\n#define RUNNER_FLUTTER_WINDOW_H_\n\n#include <flutter/dart_project.h>\n#include <flutter/f"
  },
  {
    "path": "windows/runner/main.cpp",
    "chars": 2289,
    "preview": "#include <flutter/dart_project.h>\n#include <flutter/flutter_view_controller.h>\n#include <windows.h>\n\n#include \"flutter_w"
  },
  {
    "path": "windows/runner/resource.h",
    "chars": 432,
    "preview": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by Runner.rc\n//\n#define IDI_APP_ICON      "
  },
  {
    "path": "windows/runner/runner.exe.manifest",
    "chars": 874,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersi"
  },
  {
    "path": "windows/runner/utils.cpp",
    "chars": 1788,
    "preview": "#include \"utils.h\"\n\n#include <flutter_windows.h>\n#include <io.h>\n#include <stdio.h>\n#include <windows.h>\n\n#include <iost"
  },
  {
    "path": "windows/runner/utils.h",
    "chars": 672,
    "preview": "#ifndef RUNNER_UTILS_H_\n#define RUNNER_UTILS_H_\n\n#include <string>\n#include <vector>\n\n// Creates a console for the proce"
  },
  {
    "path": "windows/runner/win32_window.cpp",
    "chars": 8534,
    "preview": "#include \"win32_window.h\"\n\n#include <dwmapi.h>\n#include <flutter_windows.h>\n\n#include \"resource.h\"\n\nnamespace {\n\n/// Win"
  },
  {
    "path": "windows/runner/win32_window.h",
    "chars": 3522,
    "preview": "#ifndef RUNNER_WIN32_WINDOW_H_\n#define RUNNER_WIN32_WINDOW_H_\n\n#include <windows.h>\n\n#include <functional>\n#include <mem"
  }
]

// ... and 3 more files (download for full content)

About this extraction

This page contains the full source code of the wgh136/pixes GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 173 files (679.3 KB), approximately 166.0k tokens, and a symbol index with 932 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!