├── android
├── .idea
│ ├── .name
│ ├── misc.xml
│ ├── gradle.xml
│ └── codeStyles
│ │ └── Project.xml
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── ic_launcher-web.png
│ │ │ ├── res
│ │ │ │ ├── xml
│ │ │ │ │ └── file_paths.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── values-zh
│ │ │ │ │ └── strings.xml
│ │ │ │ ├── values
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ │ ├── ic_launcher.xml
│ │ │ │ │ └── ic_launcher_round.xml
│ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ └── drawable-night
│ │ │ │ │ └── launch_background.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── yaerin
│ │ │ │ │ └── dailypics
│ │ │ │ │ ├── MainActivity.kt
│ │ │ │ │ ├── PlatformPluginImpl.kt
│ │ │ │ │ ├── PlatformPluginApi24Impl.kt
│ │ │ │ │ ├── UseAsWallpaperActivity.kt
│ │ │ │ │ └── PlatformPlugin.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── signingConfigs.gradle.example
│ └── build.gradle
├── gradle.properties
├── .gitignore
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── settings.gradle
└── build.gradle
├── README.md
├── ios
├── Runner
│ ├── Runner-Bridging-Header.h
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ └── Contents.json
│ ├── Runner.entitlements
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ ├── Info.plist
│ └── AppDelegate.swift
├── Flutter
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── AppFrameworkInfo.plist
├── Runner.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── TodayExtension
│ ├── TodayExtension.entitlements
│ ├── Info.plist
│ ├── TodayViewController.swift
│ └── Base.lproj
│ │ └── MainInterface.storyboard
├── .gitignore
├── Podfile
└── Podfile.lock
├── res
├── ic_launcher.png
├── placeholder.jpg
├── ionicons-v5.5.1.ttf
├── placeholder-night.jpg
└── contributors.json
├── windows
├── runner
│ ├── resources
│ │ └── app_icon.ico
│ ├── resource.h
│ ├── CMakeLists.txt
│ ├── utils.h
│ ├── runner.exe.manifest
│ ├── run_loop.h
│ ├── flutter_window.h
│ ├── main.cpp
│ ├── utils.cpp
│ ├── flutter_window.cpp
│ ├── run_loop.cpp
│ ├── Runner.rc
│ └── win32_window.h
├── .gitignore
├── flutter
│ ├── generated_plugin_registrant.h
│ ├── generated_plugin_registrant.cc
│ ├── generated_plugins.cmake
│ └── CMakeLists.txt
└── CMakeLists.txt
├── lib
├── misc
│ ├── config.g.dart
│ ├── bean.g.dart
│ └── bean.dart
├── utils
│ ├── http.dart
│ ├── windows.dart
│ ├── api.dart
│ └── utils.dart
├── widget
│ ├── error.dart
│ ├── buttons.dart
│ ├── qrcode.dart
│ ├── optimized_image.dart
│ ├── hightlight.dart
│ ├── adaptive_scaffold.dart
│ ├── animated_transform.dart
│ ├── slivers.dart
│ ├── search.dart
│ ├── toast.dart
│ ├── photo_card.dart
│ └── panel_view.dart
├── extension.dart
├── components
│ ├── settings.dart
│ └── suggest.dart
├── model
│ └── app.dart
├── main.dart
└── pages
│ ├── splash.dart
│ ├── home.dart
│ └── search.dart
├── .idea
├── vcs.xml
├── encodings.xml
├── statistic.xml
├── dictionaries
│ └── KagurazakaHanabi.xml
├── codeStyles
│ └── Project.xml
└── misc.xml
├── .metadata
├── .github
└── no-response.yml
├── .gitignore
├── .gitattributes
├── pubspec.yaml
└── analysis_options.yaml
/android/.idea/.name:
--------------------------------------------------------------------------------
1 | _android
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 图鉴日图 - 精选壁纸推荐
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/res/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/res/ic_launcher.png
--------------------------------------------------------------------------------
/res/placeholder.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/res/placeholder.jpg
--------------------------------------------------------------------------------
/res/ionicons-v5.5.1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/res/ionicons-v5.5.1.ttf
--------------------------------------------------------------------------------
/res/placeholder-night.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/res/placeholder-night.jpg
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/windows/runner/resources/app_icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/windows/runner/resources/app_icon.ico
--------------------------------------------------------------------------------
/android/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/android/app/src/main/res/xml/file_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /app/signingConfigs.gradle
4 | /captures/
5 | /gradlew
6 | /gradlew.bat
7 | /local.properties
8 | GeneratedPluginRegistrant.java
9 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/lib/misc/config.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | class Config {
4 | static const int buildNumber = 200220;
5 |
6 | static const String version = '2.1.1';
7 | }
8 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KagurazakaHanabi/dailypics/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/statistic.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-zh/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 图鉴日图
4 | 用作壁纸
5 |
6 |
--------------------------------------------------------------------------------
/android/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Daily Pics
4 | Use As Wallpaper
5 |
6 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/signingConfigs.gradle.example:
--------------------------------------------------------------------------------
1 | android {
2 | signingConfigs {
3 | release {
4 | storeFile file("")
5 | keyAlias ""
6 | storePassword ""
7 | keyPassword ""
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 740fb2a8bb6d43a475ce76f7fe3e5fc10bbe24ff
8 | channel: master
9 |
10 | project_type: app
11 |
12 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/TodayExtension/TodayExtension.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.application-groups
6 |
7 | group.dailypics.Today
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/windows/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral/
2 |
3 | # Visual Studio user-specific files.
4 | *.suo
5 | *.user
6 | *.userosscache
7 | *.sln.docstates
8 |
9 | # Visual Studio build-related files.
10 | x64/
11 | x86/
12 |
13 | # Visual Studio cache files
14 | # files ending in .cache can be ignored
15 | *.[Cc]ache
16 | # but keep track of directories ending in .cache
17 | !*.[Cc]ache/
18 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.github/no-response.yml:
--------------------------------------------------------------------------------
1 | # Configuration for probot-no-response - https://github.com/probot/no-response
2 |
3 | # Number of days of inactivity before an Issue is closed for lack of response
4 | daysUntilClose: 7
5 | # Label requiring a response
6 | responseRequiredLabel: "waiting for customer response"
7 | # Comment to post when closing an Issue for lack of response. Set to `false` to disable
8 | closeComment: false
9 |
--------------------------------------------------------------------------------
/windows/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
8 | #define GENERATED_PLUGIN_REGISTRANT_
9 |
10 | #include
11 |
12 | // Registers Flutter plugins.
13 | void RegisterPlugins(flutter::PluginRegistry* registry);
14 |
15 | #endif // GENERATED_PLUGIN_REGISTRANT_
16 |
--------------------------------------------------------------------------------
/windows/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #include "generated_plugin_registrant.h"
8 |
9 | #include
10 |
11 | void RegisterPlugins(flutter::PluginRegistry* registry) {
12 | UrlLauncherPluginRegisterWithRegistrar(
13 | registry->GetRegistrarForPlugin("UrlLauncherPlugin"));
14 | }
15 |
--------------------------------------------------------------------------------
/.idea/dictionaries/KagurazakaHanabi.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | cerasus
5 | chimon
6 | cupertino
7 | dailypics
8 | hanabi
9 | hitokoto
10 | ionicons
11 | kagurazaka
12 | recents
13 | tujian
14 | vsync
15 | yaerin
16 |
17 |
18 |
--------------------------------------------------------------------------------
/windows/runner/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by Runner.rc
4 | //
5 | #define IDI_APP_ICON 101
6 |
7 | // Next default values for new objects
8 | //
9 | #ifdef APSTUDIO_INVOKED
10 | #ifndef APSTUDIO_READONLY_SYMBOLS
11 | #define _APS_NEXT_RESOURCE_VALUE 102
12 | #define _APS_NEXT_COMMAND_VALUE 40001
13 | #define _APS_NEXT_CONTROL_VALUE 1001
14 | #define _APS_NEXT_SYMED_VALUE 101
15 | #endif
16 | #endif
17 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/ios/Runner/Runner.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.developer.associated-domains
6 |
7 | applinks:dailypics.cn
8 | applinks:www.dailypics.cn
9 |
10 | com.apple.security.application-groups
11 |
12 | group.dailypics.Today
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/windows/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 |
5 | list(APPEND FLUTTER_PLUGIN_LIST
6 | url_launcher_windows
7 | )
8 |
9 | set(PLUGIN_BUNDLED_LIBRARIES)
10 |
11 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
12 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
13 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
14 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
15 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
16 | endforeach(plugin)
17 |
--------------------------------------------------------------------------------
/windows/runner/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.15)
2 | project(runner LANGUAGES CXX)
3 |
4 | add_executable(${BINARY_NAME} WIN32
5 | "flutter_window.cpp"
6 | "main.cpp"
7 | "run_loop.cpp"
8 | "utils.cpp"
9 | "win32_window.cpp"
10 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
11 | "Runner.rc"
12 | "runner.exe.manifest"
13 | )
14 | apply_standard_settings(${BINARY_NAME})
15 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
16 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
17 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
18 | add_dependencies(${BINARY_NAME} flutter_assemble)
19 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = "1.3.50"
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.3'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = "../build"
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(":app")
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/windows/runner/utils.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_UTILS_H_
2 | #define RUNNER_UTILS_H_
3 |
4 | #include
5 | #include
6 |
7 | // Creates a console for the process, and redirects stdout and stderr to
8 | // it for both the runner and the Flutter library.
9 | void CreateAndAttachConsole();
10 |
11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
12 | // encoded in UTF-8. Returns an empty std::string on failure.
13 | std::string Utf8FromUtf16(const wchar_t* utf16_string);
14 |
15 | // Gets the command line arguments passed in as a std::vector,
16 | // encoded in UTF-8. Returns an empty std::vector on failure.
17 | std::vector GetCommandLineArguments();
18 |
19 | #endif // RUNNER_UTILS_H_
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .idea/
11 | .svn/
12 | .vscode/
13 | test/
14 |
15 | # IntelliJ related
16 | *.iml
17 | *.ipr
18 | *.iws
19 | **/.idea/caches
20 | **/.idea/libraries
21 | **/.idea/misc.xml
22 | **/.idea/modules.xml
23 | **/.idea/workspace.xml
24 | **/.idea/navEditor.xml
25 | **/.idea/assetWizardSettings.xml
26 |
27 | # Flutter/Dart/Pub related
28 | **/doc/api/
29 | .dart_tool/
30 | .flutter-plugins
31 | .flutter-plugins-dependencies
32 | .packages
33 | .packages.generated
34 | .pub-cache/
35 | .pub/
36 | /build/
37 |
38 | # Web related
39 | lib/generated_plugin_registrant.dart
40 |
41 | # Exceptions to above rules.
42 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
43 |
--------------------------------------------------------------------------------
/lib/utils/http.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:dailypics/misc/config.g.dart';
16 | import 'package:dio/dio.dart';
17 |
18 | Dio http = Dio(BaseOptions(
19 | headers: {
20 | 'user-agent': 'Dailypics/${Config.version} Version/${Config.buildNumber}',
21 | },
22 | ));
23 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/windows/runner/runner.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PerMonitorV2
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Always perform LF normalization on these files
5 | *.dart text
6 | *.gradle text
7 | *.html text
8 | *.java text
9 | *.json text
10 | *.md text
11 | *.py text
12 | *.sh text
13 | *.txt text
14 | *.xml text
15 | *.yaml text
16 |
17 | # Make sure that these Windows files always have CRLF line endings in checkout
18 | *.bat text eol=crlf
19 | *.ps1 text eol=crlf
20 | *.rc text eol=crlf
21 | *.sln text eol=crlf
22 | *.props text eol=crlf
23 | *.vcxproj text eol=crlf
24 | *.vcxproj.filters text eol=crlf
25 |
26 | # Never perform LF normalization on these files
27 | *.ico binary
28 | *.jar binary
29 | *.png binary
30 | *.zip binary
31 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: dailypics
2 | description: A new Flutter application.
3 | version: 2.2.7+200325
4 | publish_to: none
5 |
6 | environment:
7 | sdk: ">=2.6.0 <3.0.0"
8 | flutter: ">=2.0.0 <3.0.0"
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 | flutter_localizations:
14 | sdk: flutter
15 | flutter_markdown:
16 | git: https://github.com/KagurazakaHanabi/flutter_markdown.git
17 | cached_network_image: ^2.0.0
18 | cupertino_icons: ^0.1.3
19 | dio: ^3.0.9
20 | flutter_staggered_grid_view: ^0.3.0
21 | image_picker: ^0.6.3+1
22 | json_annotation: ^3.0.1
23 | package_info: ^0.4.0+13
24 | palette_generator: ^0.2.0
25 | path_provider: ^1.5.1
26 | photo_view: ^0.9.1
27 | qr: ^1.2.0
28 | scoped_model: ^1.0.1
29 | shared_preferences: ^0.5.6
30 | uni_links: ^0.2.0
31 | url_launcher: ^5.4.1
32 | win32: ^2.0.5
33 |
34 | dev_dependencies:
35 | build_runner: ^1.7.4
36 | json_serializable: ^3.2.5
37 |
38 | flutter:
39 | uses-material-design: true
40 | assets:
41 | - res/
42 | fonts:
43 | - family: Ionicons
44 | fonts:
45 | - asset: res/Ionicons-v5.5.1.ttf
46 |
--------------------------------------------------------------------------------
/ios/TodayExtension/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | 图鉴日图 Today
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | NSExtension
24 |
25 | NSExtensionMainStoryboard
26 | MainInterface
27 | NSExtensionPointIdentifier
28 | com.apple.widget-extension
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/windows/runner/run_loop.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_RUN_LOOP_H_
2 | #define RUNNER_RUN_LOOP_H_
3 |
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | // A runloop that will service events for Flutter instances as well
10 | // as native messages.
11 | class RunLoop {
12 | public:
13 | RunLoop();
14 | ~RunLoop();
15 |
16 | // Prevent copying
17 | RunLoop(RunLoop const&) = delete;
18 | RunLoop& operator=(RunLoop const&) = delete;
19 |
20 | // Runs the run loop until the application quits.
21 | void Run();
22 |
23 | // Registers the given Flutter instance for event servicing.
24 | void RegisterFlutterInstance(
25 | flutter::FlutterEngine* flutter_instance);
26 |
27 | // Unregisters the given Flutter instance from event servicing.
28 | void UnregisterFlutterInstance(
29 | flutter::FlutterEngine* flutter_instance);
30 |
31 | private:
32 | using TimePoint = std::chrono::steady_clock::time_point;
33 |
34 | // Processes all currently pending messages for registered Flutter instances.
35 | TimePoint ProcessFlutterMessages();
36 |
37 | std::set flutter_instances_;
38 | };
39 |
40 | #endif // RUNNER_RUN_LOOP_H_
41 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/yaerin/dailypics/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2021 KagurazakaHanabi
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.yaerin.dailypics
18 |
19 | import androidx.annotation.NonNull
20 | import io.flutter.embedding.android.FlutterActivity
21 | import io.flutter.embedding.engine.FlutterEngine
22 | import io.flutter.plugins.GeneratedPluginRegistrant
23 |
24 | class MainActivity : FlutterActivity() {
25 | override fun configureFlutterEngine(@NonNull engine: FlutterEngine) {
26 | GeneratedPluginRegistrant.registerWith(engine)
27 | engine.plugins.add(PlatformPlugin())
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/windows/runner/flutter_window.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_FLUTTER_WINDOW_H_
2 | #define RUNNER_FLUTTER_WINDOW_H_
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | #include "run_loop.h"
10 | #include "win32_window.h"
11 |
12 | // A window that does nothing but host a Flutter view.
13 | class FlutterWindow : public Win32Window {
14 | public:
15 | // Creates a new FlutterWindow driven by the |run_loop|, hosting a
16 | // Flutter view running |project|.
17 | explicit FlutterWindow(RunLoop* run_loop,
18 | const flutter::DartProject& project);
19 | virtual ~FlutterWindow();
20 |
21 | protected:
22 | // Win32Window:
23 | bool OnCreate() override;
24 | void OnDestroy() override;
25 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
26 | LPARAM const lparam) noexcept override;
27 |
28 | private:
29 | // The run loop driving events for this window.
30 | RunLoop* run_loop_;
31 |
32 | // The project to run.
33 | flutter::DartProject project_;
34 |
35 | // The Flutter instance hosted by this window.
36 | std::unique_ptr flutter_controller_;
37 | };
38 |
39 | #endif // RUNNER_FLUTTER_WINDOW_H_
40 |
--------------------------------------------------------------------------------
/lib/utils/windows.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2021 chimon89
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:ffi';
16 | import 'dart:io';
17 |
18 | import 'package:ffi/ffi.dart';
19 | import 'package:win32/win32.dart';
20 |
21 | class Windows {
22 | static void useAsWallpaper(File wallpaperFile) {
23 | final hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
24 | if (FAILED(hr)) throw WindowsException(hr);
25 |
26 | final wallpaper = DesktopWallpaper.createInstance();
27 |
28 | final pathPtr = TEXT(wallpaperFile.path);
29 | wallpaper.SetWallpaper(nullptr, pathPtr);
30 | if (FAILED(hr)) throw WindowsException(hr);
31 |
32 | calloc.free(pathPtr);
33 | calloc.free(wallpaper.ptr);
34 |
35 | CoUninitialize();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/windows/runner/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #pragma execution_character_set("utf-8")
5 |
6 | #include "flutter_window.h"
7 | #include "run_loop.h"
8 | #include "utils.h"
9 |
10 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
11 | _In_ wchar_t *command_line, _In_ int show_command) {
12 | // Attach to console when present (e.g., 'flutter run') or create a
13 | // new console when running with a debugger.
14 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
15 | CreateAndAttachConsole();
16 | }
17 |
18 | // Initialize COM, so that it is available for use in the library and/or
19 | // plugins.
20 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
21 |
22 | RunLoop run_loop;
23 |
24 | flutter::DartProject project(L"data");
25 |
26 | std::vector command_line_arguments =
27 | GetCommandLineArguments();
28 |
29 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
30 |
31 | FlutterWindow window(&run_loop, project);
32 | Win32Window::Point origin(10, 10);
33 | Win32Window::Size size(480, 800);
34 | if (!window.CreateAndShow(L"Dailypics Desktop", origin, size)) {
35 | return EXIT_FAILURE;
36 | }
37 | window.SetQuitOnClose(true);
38 |
39 | run_loop.Run();
40 |
41 | ::CoUninitialize();
42 | return EXIT_SUCCESS;
43 | }
44 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/yaerin/dailypics/PlatformPluginImpl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2021 KagurazakaHanabi
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.yaerin.dailypics
18 |
19 | import io.flutter.plugin.common.MethodCall
20 | import io.flutter.plugin.common.MethodChannel.Result
21 | import java.io.IOException
22 |
23 | internal interface PlatformPluginImpl {
24 | companion object {
25 | const val PROVIDER_AUTHORITY = BuildConfig.APPLICATION_ID + ".file_provider"
26 | }
27 |
28 | @Throws(IOException::class)
29 | fun share(path: String, result: Result?)
30 |
31 | fun useAsWallpaper(file: String, result: Result?)
32 |
33 | fun requestReview(result: Result?)
34 |
35 | fun isAlbumAuthorized(result: Result?)
36 |
37 | fun openAppSettings(result: Result?)
38 |
39 | @Throws(IOException::class)
40 | fun syncAlbum(call: MethodCall, result: Result)
41 | }
42 |
--------------------------------------------------------------------------------
/lib/widget/error.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/cupertino.dart';
16 | import 'package:flutter/material.dart' show Colors;
17 |
18 | class CustomErrorWidget extends StatelessWidget {
19 | const CustomErrorWidget(
20 | this.details, {
21 | Key key,
22 | }) : super(key: key);
23 |
24 | final FlutterErrorDetails details;
25 |
26 | @override
27 | Widget build(BuildContext context) {
28 | return Container(
29 | color: CupertinoTheme.of(context).scaffoldBackgroundColor,
30 | alignment: Alignment.center,
31 | padding: const EdgeInsets.all(16),
32 | child: Text(
33 | details.exceptionAsString(),
34 | style: TextStyle(
35 | color: const CupertinoDynamicColor.withBrightness(
36 | color: Colors.black54,
37 | darkColor: Colors.white70,
38 | ).resolveFrom(context),
39 | ),
40 | ),
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/extension.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/widgets.dart';
16 |
17 | extension ColorX on Color {
18 | static Color fromHexString(String source) {
19 | String s = source.toUpperCase().replaceAll('#', '');
20 | if (s.length == 6) {
21 | s = 'FF$s';
22 | } else if (s.length == 3) {
23 | s = 'FF${s[0] * 2}${s[1] * 2}${s[2] * 2}';
24 | }
25 | return Color(int.parse(s, radix: 16));
26 | }
27 |
28 | String get hexString {
29 | return '#${value.toRadixString(16).padLeft(8, '0')}';
30 | }
31 |
32 | bool get isDark {
33 | // See https://github.com/FooStudio/tinycolor
34 | return (red * 299 + green * 587 + blue * 114) / 1000 < 128;
35 | }
36 | }
37 |
38 | extension StringX on String {
39 | bool get isUuid {
40 | if (isEmpty) return false;
41 | return RegExp(
42 | r'^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$',
43 | caseSensitive: false,
44 | ).hasMatch(this);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/components/settings.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:dailypics/pages/upload.dart';
16 | import 'package:flutter/cupertino.dart';
17 |
18 | class SettingsComponent extends StatefulWidget {
19 | @override
20 | _SettingsComponentState createState() => _SettingsComponentState();
21 | }
22 |
23 | class _SettingsComponentState extends State {
24 | @override
25 | Widget build(BuildContext context) {
26 | return CupertinoPageScaffold(
27 | navigationBar: CupertinoNavigationBar(
28 | middle: const Text('更多'),
29 | trailing: CupertinoButton(
30 | padding: EdgeInsets.zero,
31 | child: const Text('投稿'),
32 | onPressed: () {
33 | Navigator.of(context, rootNavigator: true).push(
34 | CupertinoPageRoute(builder: (_) => UploadPage()),
35 | );
36 | },
37 | ),
38 | ),
39 | child: ListView(
40 | children: [],
41 | ),
42 | );
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | linter:
2 | rules:
3 | - avoid_empty_else
4 | - avoid_init_to_null
5 | - avoid_relative_lib_imports
6 | - avoid_return_types_on_setters
7 | - avoid_shadowing_type_parameters
8 | - avoid_types_as_parameter_names
9 | - avoid_unused_constructor_parameters
10 | - avoid_print
11 | - always_declare_return_types
12 | - await_only_futures
13 | - camel_case_types
14 | - cancel_subscriptions
15 | - close_sinks
16 | - curly_braces_in_flow_control_structures
17 | - empty_catches
18 | - empty_constructor_bodies
19 | - empty_statements
20 | - file_names
21 | - hash_and_equals
22 | - implementation_imports
23 | - library_names
24 | - library_prefixes
25 | - literal_only_boolean_expressions
26 | - no_adjacent_strings_in_list
27 | - no_duplicate_case_values
28 | - non_constant_identifier_names
29 | - null_closures
30 | - prefer_const_constructors
31 | - prefer_const_declarations
32 | - prefer_contains
33 | - prefer_equal_for_default_values
34 | - prefer_is_empty
35 | - prefer_is_not_empty
36 | - prefer_is_not_operator
37 | - prefer_iterable_whereType
38 | - recursive_getters
39 | - slash_for_doc_comments
40 | - sort_constructors_first
41 | - sort_unnamed_constructors_first
42 | - type_init_formals
43 | - unnecessary_const
44 | - unnecessary_getters_setters
45 | - unnecessary_new
46 | - unnecessary_null_in_if_null_operators
47 | - unnecessary_parenthesis
48 | - unnecessary_statements
49 | - unnecessary_this
50 | - unrelated_type_equality_checks
51 | - use_rethrow_when_possible
52 | - valid_regexps
53 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/yaerin/dailypics/PlatformPluginApi24Impl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2021 KagurazakaHanabi
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.yaerin.dailypics
18 |
19 | import android.content.Context
20 | import android.content.Intent
21 | import android.net.Uri
22 | import androidx.core.content.FileProvider
23 | import com.yaerin.dailypics.PlatformPluginImpl.Companion.PROVIDER_AUTHORITY
24 | import io.flutter.plugin.common.MethodChannel
25 | import java.io.File
26 |
27 | class PlatformPluginApi24Impl(context: Context) : PlatformPluginBaseImpl(context) {
28 | override fun share(path: String, result: MethodChannel.Result?) {
29 | val uri: Uri = FileProvider.getUriForFile(context, PROVIDER_AUTHORITY, File(path))
30 | val intent = Intent(Intent.ACTION_SEND)
31 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
32 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
33 | intent.putExtra(Intent.EXTRA_STREAM, uri)
34 | context.startActivity(Intent.createChooser(intent, null))
35 | result?.success(null)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/widget/buttons.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/cupertino.dart';
16 |
17 | class Button extends StatelessWidget {
18 | const Button({
19 | Key key,
20 | @required this.child,
21 | this.color,
22 | @required this.onPressed,
23 | }) : super(key: key);
24 |
25 | final Widget child;
26 |
27 | final Color color;
28 |
29 | final GestureTapCallback onPressed;
30 |
31 | @override
32 | Widget build(BuildContext context) {
33 | return GestureDetector(
34 | onTap: onPressed,
35 | child: Container(
36 | margin: const EdgeInsets.all(8),
37 | padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 20),
38 | decoration: BoxDecoration(
39 | color: color ?? CupertinoTheme.of(context).primaryColor,
40 | borderRadius: BorderRadius.circular(46),
41 | ),
42 | child: DefaultTextStyle(
43 | child: child,
44 | style: TextStyle(
45 | fontSize: 14,
46 | color: CupertinoTheme.of(context).primaryContrastingColor,
47 | ),
48 | ),
49 | ),
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/yaerin/dailypics/UseAsWallpaperActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2021 KagurazakaHanabi
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.yaerin.dailypics
18 |
19 | import android.app.Activity
20 | import android.app.WallpaperManager
21 | import android.content.Intent
22 | import android.net.Uri
23 | import android.os.Bundle
24 | import java.io.IOException
25 |
26 | class UseAsWallpaperActivity : Activity() {
27 | override fun onCreate(savedInstanceState: Bundle?) {
28 | super.onCreate(savedInstanceState)
29 | val data: String? = intent?.extras?.getString(Intent.EXTRA_STREAM)
30 | if (data == null) {
31 | finish()
32 | }
33 |
34 | val uri = Uri.parse(data)
35 | try {
36 | val intent: Intent? = PlatformPluginBaseImpl.getCropAndSetWallpaperIntent(this, uri)
37 | startActivity(Intent.createChooser(intent, "设置为壁纸"))
38 | } catch (e: Exception) {
39 | val wm = WallpaperManager.getInstance(this)
40 | try {
41 | wm.setStream(contentResolver.openInputStream(uri))
42 | } catch (ex: IOException) {
43 | }
44 | }
45 | finish()
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/model/app.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:dailypics/misc/bean.dart';
16 | import 'package:flutter/cupertino.dart';
17 | import 'package:scoped_model/scoped_model.dart';
18 |
19 | class AppModel extends Model {
20 | Map _types;
21 | Map get types => _types;
22 | set types(Map data) {
23 | _types = data;
24 | notifyListeners();
25 | }
26 |
27 | List _today = [];
28 | List get today => _today;
29 | set today(List data) {
30 | _today = data;
31 | notifyListeners();
32 | }
33 |
34 | List _recent = [];
35 | List get recent => _recent;
36 | set recent(List data) {
37 | _recent = data;
38 | notifyListeners();
39 | }
40 |
41 | List _collections = [];
42 | List get collections => _collections;
43 | set collections(List data) {
44 | _collections = data;
45 | notifyListeners();
46 | }
47 |
48 | @override
49 | void notifyListeners() {
50 | super.notifyListeners();
51 | }
52 |
53 | static AppModel of(BuildContext context) {
54 | return ScopedModel.of(context, rebuildOnChange: true);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file("local.properties")
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader("UTF-8") { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty("flutter.sdk")
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = "1"
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty("flutter.versionName")
20 | if (flutterVersionName == null) {
21 | flutterVersionName = "1.0"
22 | }
23 |
24 | apply plugin: "com.android.application"
25 | apply plugin: "kotlin-android"
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 | apply from: "signingConfigs.gradle"
28 |
29 | android {
30 | compileSdkVersion 29
31 |
32 | sourceSets {
33 | main.java.srcDirs += "src/main/kotlin"
34 | }
35 |
36 | lintOptions {
37 | disable "InvalidPackage"
38 | }
39 |
40 | defaultConfig {
41 | applicationId "cn.dailypics.android"
42 | minSdkVersion 16
43 | targetSdkVersion 29
44 | versionCode flutterVersionCode.toInteger()
45 | versionName flutterVersionName
46 | }
47 |
48 | buildTypes {
49 | release {
50 | signingConfig signingConfigs.release
51 | }
52 | }
53 | }
54 |
55 | flutter {
56 | source "../.."
57 | }
58 |
59 | dependencies {
60 | implementation "androidx.legacy:legacy-support-v4:1.0.0"
61 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
62 | }
63 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/windows/runner/utils.cpp:
--------------------------------------------------------------------------------
1 | #include "utils.h"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | void CreateAndAttachConsole() {
11 | if (::AllocConsole()) {
12 | FILE *unused;
13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
14 | _dup2(_fileno(stdout), 1);
15 | }
16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
17 | _dup2(_fileno(stdout), 2);
18 | }
19 | std::ios::sync_with_stdio();
20 | FlutterDesktopResyncOutputStreams();
21 | }
22 | }
23 |
24 | std::vector GetCommandLineArguments() {
25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
26 | int argc;
27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
28 | if (argv == nullptr) {
29 | return std::vector();
30 | }
31 |
32 | std::vector command_line_arguments;
33 |
34 | // Skip the first argument as it's the binary name.
35 | for (int i = 1; i < argc; i++) {
36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
37 | }
38 |
39 | ::LocalFree(argv);
40 |
41 | return command_line_arguments;
42 | }
43 |
44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) {
45 | if (utf16_string == nullptr) {
46 | return std::string();
47 | }
48 | int target_length = ::WideCharToMultiByte(
49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
50 | -1, nullptr, 0, nullptr, nullptr);
51 | if (target_length == 0) {
52 | return std::string();
53 | }
54 | std::string utf8_string;
55 | utf8_string.resize(target_length);
56 | int converted_length = ::WideCharToMultiByte(
57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
58 | -1, utf8_string.data(),
59 | target_length, nullptr, nullptr);
60 | if (converted_length == 0) {
61 | return std::string();
62 | }
63 | return utf8_string;
64 | }
65 |
--------------------------------------------------------------------------------
/res/contributors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "avatar": "https://qlogo1.store.qq.com/qzone/1461397456/1461397456/100",
4 | "name": "Chimon",
5 | "position": "执行 / 开发",
6 | "url": "mailto:Chimon@Chimon.me"
7 | },
8 | {
9 | "avatar": "https://qlogo1.store.qq.com/qzone/3314176520/3314176520/100",
10 | "name": "Createlite",
11 | "position": "执行",
12 | "url": "https://github.com/Createlite"
13 | },
14 | {
15 | "avatar": "https://qlogo1.store.qq.com/qzone/2598136787/2598136787/100",
16 | "name": "Copyright³",
17 | "position": "后端开发",
18 | "url": "https://github.com/unstartdev"
19 | },
20 | {
21 | "avatar": "https://qlogo1.store.qq.com/qzone/2433146453/2433146453/100",
22 | "name": "神楽坂花火",
23 | "position": "iOS 开发",
24 | "url": "https://github.com/KagurazakaHanabi"
25 | },
26 | {
27 | "avatar": "https://qlogo1.store.qq.com/qzone/2331490629/2331490629/100",
28 | "name": "Gadgetry",
29 | "position": "Python 开发",
30 | "url": "https://github.com/gggxbbb"
31 | },
32 | {
33 | "avatar": "https://qlogo1.store.qq.com/qzone/727526713/727526713/100",
34 | "name": "Kiyoi Bread",
35 | "position": "UI 设计",
36 | "url": null
37 | },
38 | {
39 | "avatar": "https://dl.chimon.work/head/galentwww_20210414_094622.png",
40 | "name": "Galentwww",
41 | "position": "运营",
42 | "url": "mailto:galentwww@mail.dailypics.cn"
43 | },
44 | {
45 | "avatar": "https://qlogo1.store.qq.com/qzone/2838925057/2838925057/100",
46 | "name": "Night Glow.",
47 | "position": "运营",
48 | "url": null
49 | },
50 | {
51 | "avatar": "https://qlogo1.store.qq.com/qzone/2289582155/2289582155/100",
52 | "name": "Delsart",
53 | "position": "小程序",
54 | "url": null
55 | },
56 | {
57 | "avatar": "https://qlogo1.store.qq.com/qzone/2598487949/2598487949/100",
58 | "name": "Recheast",
59 | "position": "公关",
60 | "url": null
61 | }
62 | ]
63 |
--------------------------------------------------------------------------------
/windows/runner/flutter_window.cpp:
--------------------------------------------------------------------------------
1 | #include "flutter_window.h"
2 |
3 | #include
4 |
5 | #include "flutter/generated_plugin_registrant.h"
6 |
7 | FlutterWindow::FlutterWindow(RunLoop* run_loop,
8 | const flutter::DartProject& project)
9 | : run_loop_(run_loop), project_(project) {}
10 |
11 | FlutterWindow::~FlutterWindow() {}
12 |
13 | bool FlutterWindow::OnCreate() {
14 | if (!Win32Window::OnCreate()) {
15 | return false;
16 | }
17 |
18 | RECT frame = GetClientArea();
19 |
20 | // The size here must match the window dimensions to avoid unnecessary surface
21 | // creation / destruction in the startup path.
22 | flutter_controller_ = std::make_unique(
23 | frame.right - frame.left, frame.bottom - frame.top, project_);
24 | // Ensure that basic setup of the controller was successful.
25 | if (!flutter_controller_->engine() || !flutter_controller_->view()) {
26 | return false;
27 | }
28 | RegisterPlugins(flutter_controller_->engine());
29 | run_loop_->RegisterFlutterInstance(flutter_controller_->engine());
30 | SetChildContent(flutter_controller_->view()->GetNativeWindow());
31 | return true;
32 | }
33 |
34 | void FlutterWindow::OnDestroy() {
35 | if (flutter_controller_) {
36 | run_loop_->UnregisterFlutterInstance(flutter_controller_->engine());
37 | flutter_controller_ = nullptr;
38 | }
39 |
40 | Win32Window::OnDestroy();
41 | }
42 |
43 | LRESULT
44 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
45 | WPARAM const wparam,
46 | LPARAM const lparam) noexcept {
47 | // Give Flutter, including plugins, an opporutunity to handle window messages.
48 | if (flutter_controller_) {
49 | std::optional result =
50 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
51 | lparam);
52 | if (result) {
53 | return *result;
54 | }
55 | }
56 |
57 | switch (message) {
58 | case WM_FONTCHANGE:
59 | flutter_controller_->engine()->ReloadSystemFonts();
60 | break;
61 | }
62 |
63 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
64 | }
65 |
--------------------------------------------------------------------------------
/lib/widget/qrcode.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/cupertino.dart';
16 | import 'package:qr/qr.dart';
17 |
18 | class QrCodeView extends StatefulWidget {
19 | const QrCodeView(this.data);
20 |
21 | final String data;
22 |
23 | @override
24 | _QrCodeViewState createState() => _QrCodeViewState();
25 | }
26 |
27 | class _QrCodeViewState extends State {
28 | QrCode code;
29 |
30 | @override
31 | void initState() {
32 | super.initState();
33 | code = QrCode.fromData(
34 | data: widget.data,
35 | errorCorrectLevel: QrErrorCorrectLevel.L,
36 | );
37 | code.make();
38 | }
39 |
40 | @override
41 | Widget build(BuildContext context) {
42 | double width = (code.moduleCount * 1.5 + 3).toDouble();
43 | return CustomPaint(
44 | size: Size(width, width),
45 | painter: _QrCodePainter(code),
46 | );
47 | }
48 | }
49 |
50 | class _QrCodePainter extends CustomPainter {
51 | _QrCodePainter(this.code);
52 |
53 | final QrCode code;
54 |
55 | @override
56 | void paint(Canvas canvas, Size size) {
57 | canvas.drawRect(
58 | Rect.fromLTWH(0, 0, size.width, size.height),
59 | Paint()..color = const Color(0xFFFFFFFF),
60 | );
61 | canvas.translate(1.5, 1.5);
62 | for (int x = 0; x < code.moduleCount; x++) {
63 | for (int y = 0; y < code.moduleCount; y++) {
64 | if (code.isDark(y, x)) {
65 | canvas.drawRect(
66 | Rect.fromLTWH(x * 1.5, y * 1.5, 1.5, 1.5),
67 | Paint()..color = const Color(0xFF000000),
68 | );
69 | }
70 | }
71 | }
72 | }
73 |
74 | @override
75 | bool shouldRepaint(CustomPainter oldDelegate) => true;
76 | }
77 |
--------------------------------------------------------------------------------
/lib/widget/optimized_image.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:cached_network_image/cached_network_image.dart';
16 | import 'package:flutter/cupertino.dart';
17 |
18 | class OptimizedImage extends StatelessWidget {
19 | OptimizedImage(
20 | this.imageUrl, {
21 | Key key,
22 | this.fit = BoxFit.cover,
23 | this.borderRadius = BorderRadius.zero,
24 | this.heroTag,
25 | }) : assert(imageUrl != null),
26 | assert(borderRadius != null),
27 | super(key: key);
28 |
29 | final String imageUrl;
30 |
31 | final BoxFit fit;
32 |
33 | final BorderRadius borderRadius;
34 |
35 | final Object heroTag;
36 |
37 | @override
38 | Widget build(BuildContext context) {
39 | bool isDark = CupertinoTheme.of(context).brightness == Brightness.dark;
40 | Widget result = ClipRRect(
41 | borderRadius: borderRadius,
42 | child: CachedNetworkImage(
43 | imageUrl: imageUrl,
44 | fit: fit,
45 | placeholderFadeInDuration: Duration.zero,
46 | fadeInDuration: const Duration(milliseconds: 700),
47 | fadeInCurve: Curves.easeIn,
48 | fadeOutDuration: const Duration(milliseconds: 300),
49 | fadeOutCurve: Curves.easeOut,
50 | placeholder: (_, __) {
51 | return Container(
52 | alignment: Alignment.center,
53 | color: isDark ? const Color(0xFF1F1F1F) : const Color(0xFFE0E0E0),
54 | child: Image.asset('res/placeholder${isDark ? '-night' : ''}.jpg'),
55 | );
56 | },
57 | ),
58 | );
59 | if (heroTag != null) {
60 | result = Hero(
61 | tag: heroTag,
62 | transitionOnUserGestures: true,
63 | child: result,
64 | );
65 | }
66 | return result;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | 图鉴日图
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | dailypics
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleURLTypes
24 |
25 |
26 | CFBundleURLName
27 | $(PRODUCT_BUNDLE_IDENTIFIER)
28 | CFBundleURLSchemes
29 |
30 | dailypics
31 |
32 |
33 |
34 | CFBundleURLName
35 | $(PRODUCT_BUNDLE_IDENTIFIER)
36 | CFBundleURLSchemes
37 |
38 | https
39 |
40 |
41 |
42 | CFBundleVersion
43 | $(FLUTTER_BUILD_NUMBER)
44 | ITSAppUsesNonExemptEncryption
45 |
46 | LSRequiresIPhoneOS
47 |
48 | NSPhotoLibraryUsageDescription
49 | 需要访问相册以保存图片
50 | UILaunchStoryboardName
51 | LaunchScreen
52 | UIMainStoryboardFile
53 | Main
54 | UISupportedInterfaceOrientations
55 |
56 | UIInterfaceOrientationLandscapeLeft
57 | UIInterfaceOrientationLandscapeRight
58 | UIInterfaceOrientationPortrait
59 |
60 | UISupportedInterfaceOrientations~ipad
61 |
62 | UIInterfaceOrientationLandscapeLeft
63 | UIInterfaceOrientationPortraitUpsideDown
64 | UIInterfaceOrientationLandscapeRight
65 | UIInterfaceOrientationPortrait
66 |
67 | UIViewControllerBasedStatusBarAppearance
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:dailypics/model/app.dart';
16 | import 'package:dailypics/pages/splash.dart';
17 | import 'package:dailypics/widget/error.dart';
18 | import 'package:flutter/cupertino.dart';
19 | import 'package:flutter_localizations/flutter_localizations.dart';
20 | import 'package:scoped_model/scoped_model.dart';
21 |
22 | void main() async {
23 | ErrorWidget.builder = (FlutterErrorDetails details) {
24 | return CustomErrorWidget(details);
25 | };
26 | runApp(TujianApp());
27 | }
28 |
29 | class TujianApp extends StatelessWidget {
30 | final AppModel model = AppModel();
31 |
32 | @override
33 | Widget build(BuildContext context) {
34 | return ScopedModel(
35 | model: model,
36 | child: CupertinoApp(
37 | title: '图鉴日图',
38 | home: SplashPage(),
39 | debugShowCheckedModeBanner: false,
40 | builder: (BuildContext context, Widget child) {
41 | CupertinoThemeData theme = CupertinoTheme.of(context).copyWith(
42 | brightness: MediaQuery.platformBrightnessOf(context),
43 | );
44 | CupertinoTextThemeData textTheme = theme.textTheme;
45 | return CupertinoTheme(
46 | data: theme,
47 | child: DefaultTextStyle(
48 | style: textTheme.textStyle,
49 | child: child,
50 | ),
51 | );
52 | },
53 | supportedLocales: const [
54 | Locale('zh'),
55 | Locale('ja'),
56 | Locale('en'),
57 | ],
58 | localizationsDelegates: [
59 | GlobalCupertinoLocalizations.delegate,
60 | GlobalMaterialLocalizations.delegate,
61 | GlobalWidgetsLocalizations.delegate,
62 | ],
63 | ),
64 | );
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/windows/runner/run_loop.cpp:
--------------------------------------------------------------------------------
1 | #include "run_loop.h"
2 |
3 | #include
4 |
5 | #include
6 |
7 | RunLoop::RunLoop() {}
8 |
9 | RunLoop::~RunLoop() {}
10 |
11 | void RunLoop::Run() {
12 | bool keep_running = true;
13 | TimePoint next_flutter_event_time = TimePoint::clock::now();
14 | while (keep_running) {
15 | std::chrono::nanoseconds wait_duration =
16 | std::max(std::chrono::nanoseconds(0),
17 | next_flutter_event_time - TimePoint::clock::now());
18 | ::MsgWaitForMultipleObjects(
19 | 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000),
20 | QS_ALLINPUT);
21 | bool processed_events = false;
22 | MSG message;
23 | // All pending Windows messages must be processed; MsgWaitForMultipleObjects
24 | // won't return again for items left in the queue after PeekMessage.
25 | while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) {
26 | processed_events = true;
27 | if (message.message == WM_QUIT) {
28 | keep_running = false;
29 | break;
30 | }
31 | ::TranslateMessage(&message);
32 | ::DispatchMessage(&message);
33 | // Allow Flutter to process messages each time a Windows message is
34 | // processed, to prevent starvation.
35 | next_flutter_event_time =
36 | std::min(next_flutter_event_time, ProcessFlutterMessages());
37 | }
38 | // If the PeekMessage loop didn't run, process Flutter messages.
39 | if (!processed_events) {
40 | next_flutter_event_time =
41 | std::min(next_flutter_event_time, ProcessFlutterMessages());
42 | }
43 | }
44 | }
45 |
46 | void RunLoop::RegisterFlutterInstance(
47 | flutter::FlutterEngine* flutter_instance) {
48 | flutter_instances_.insert(flutter_instance);
49 | }
50 |
51 | void RunLoop::UnregisterFlutterInstance(
52 | flutter::FlutterEngine* flutter_instance) {
53 | flutter_instances_.erase(flutter_instance);
54 | }
55 |
56 | RunLoop::TimePoint RunLoop::ProcessFlutterMessages() {
57 | TimePoint next_event_time = TimePoint::max();
58 | for (auto instance : flutter_instances_) {
59 | std::chrono::nanoseconds wait_duration = instance->ProcessMessages();
60 | if (wait_duration != std::chrono::nanoseconds::max()) {
61 | next_event_time =
62 | std::min(next_event_time, TimePoint::clock::now() + wait_duration);
63 | }
64 | }
65 | return next_event_time;
66 | }
67 |
--------------------------------------------------------------------------------
/lib/components/suggest.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:dailypics/misc/bean.dart';
16 | import 'package:dailypics/utils/api.dart';
17 | import 'package:dailypics/widget/slivers.dart';
18 | import 'package:flutter/cupertino.dart';
19 |
20 | class SuggestComponent extends StatefulWidget {
21 | @override
22 | _SuggestComponentState createState() => _SuggestComponentState();
23 | }
24 |
25 | class _SuggestComponentState extends State with AutomaticKeepAliveClientMixin {
26 | ScrollController controller = ScrollController();
27 |
28 | List data;
29 |
30 | @override
31 | void initState() {
32 | super.initState();
33 | _fetchData();
34 | }
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | super.build(context);
39 | if (data == null) {
40 | return const Center(
41 | child: CupertinoActivityIndicator(),
42 | );
43 | } else {
44 | return CupertinoScrollbar(
45 | controller: controller,
46 | child: CustomScrollView(
47 | controller: controller,
48 | physics: const AlwaysScrollableScrollPhysics(),
49 | slivers: [
50 | const CupertinoSliverNavigationBar(
51 | largeTitle: Text('推荐'),
52 | ),
53 | CupertinoSliverRefreshControl(onRefresh: _fetchData),
54 | SliverSafeArea(
55 | top: false,
56 | sliver: SliverImageCardList(
57 | tagBuilder: (i) => '$i-${data[i].id}',
58 | data: data,
59 | ),
60 | ),
61 | ],
62 | ),
63 | );
64 | }
65 | }
66 |
67 | Future _fetchData() async {
68 | data = await TujianApi.getRandom(count: 20);
69 | setState(() {});
70 | }
71 |
72 | @override
73 | void dispose() {
74 | controller.dispose();
75 | super.dispose();
76 | }
77 |
78 | @override
79 | bool get wantKeepAlive => data != null;
80 | }
81 |
--------------------------------------------------------------------------------
/lib/widget/hightlight.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/cupertino.dart';
16 | import 'package:flutter/gestures.dart';
17 |
18 | typedef RecognizerBuilder = GestureRecognizer Function(String match);
19 |
20 | class HighlightedText {
21 | const HighlightedText({this.recognizer, this.style});
22 |
23 | final RecognizerBuilder recognizer;
24 |
25 | final TextStyle style;
26 | }
27 |
28 | class _LinkSpec {
29 | _LinkSpec(this.pattern, this.origin, this.text, this.start, this.end);
30 |
31 | final HighlightedText pattern;
32 |
33 | final RegExpMatch origin;
34 |
35 | final String text;
36 |
37 | final int start;
38 |
39 | final int end;
40 |
41 | @override
42 | String toString() {
43 | return '_LinkSpec { text: $text, start: $start, end: $end }';
44 | }
45 | }
46 |
47 | class Highlight extends StatelessWidget {
48 | const Highlight({
49 | Key key,
50 | @required this.text,
51 | @required this.defaultStyle,
52 | @required this.style,
53 | @required this.patterns,
54 | }) : super(key: key);
55 |
56 | final String text;
57 |
58 | final TextStyle defaultStyle;
59 |
60 | final TextStyle style;
61 |
62 | final Map patterns;
63 |
64 | @override
65 | Widget build(BuildContext context) {
66 | List<_LinkSpec> links = [];
67 | patterns.forEach((Pattern p, HighlightedText h) {
68 | p.allMatches(text).forEach((Match e) {
69 | int start = e.start, end = e.end;
70 | links.add(_LinkSpec(h, e, e.input.substring(start, end), start, end));
71 | });
72 | });
73 | links.sort((a, b) => a.start - b.start);
74 | return Text.rich(
75 | TextSpan(
76 | text: links.isEmpty ? text : text.substring(0, links[0].start),
77 | style: defaultStyle,
78 | children: links.map((_LinkSpec e) {
79 | HighlightedText p = e.pattern;
80 | int i = links.indexOf(e);
81 | bool last = i == links.length - 1;
82 | return TextSpan(
83 | text: e.text,
84 | recognizer: p.recognizer != null ? p.recognizer(e.text) : null,
85 | style: p.style ?? style,
86 | children: [
87 | TextSpan(
88 | style: defaultStyle,
89 | text: text.substring(e.end, last ? null : links[i + 1].start),
90 | )
91 | ],
92 | );
93 | }).toList(),
94 | ),
95 | );
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/lib/widget/adaptive_scaffold.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:ui';
16 |
17 | import 'package:dailypics/utils/utils.dart';
18 | import 'package:flutter/cupertino.dart';
19 |
20 | class AdaptiveScaffold extends StatelessWidget {
21 | const AdaptiveScaffold({
22 | Key key,
23 | this.navigationBar,
24 | this.backgroundColor,
25 | this.resizeToAvoidBottomInset = true,
26 | this.padding = const EdgeInsets.fromLTRB(80, 48, 80, 0),
27 | @required this.child,
28 | }) : assert(child != null),
29 | assert(resizeToAvoidBottomInset != null),
30 | super(key: key);
31 |
32 | final ObstructingPreferredSizeWidget navigationBar;
33 |
34 | final Widget child;
35 |
36 | final Color backgroundColor;
37 |
38 | final bool resizeToAvoidBottomInset;
39 |
40 | final EdgeInsets padding;
41 |
42 | @override
43 | Widget build(BuildContext context) {
44 | Widget result = CupertinoPageScaffold(
45 | child: child,
46 | navigationBar: navigationBar,
47 | backgroundColor: backgroundColor,
48 | resizeToAvoidBottomInset: resizeToAvoidBottomInset,
49 | );
50 | if (SystemUtils.isIPad(context)) {
51 | Size size = MediaQuery.of(context).size;
52 | double left = padding.left, right = padding.right;
53 | if (!SystemUtils.isPortrait(context)) {
54 | left = (size.width - size.height) / 2;
55 | right = (size.width - size.height) / 2;
56 | }
57 | if (SystemUtils.isIPad(context, true)) {
58 | left += left / 3;
59 | right += right / 3;
60 | }
61 | result = BackdropFilter(
62 | filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
63 | child: Stack(
64 | children: [
65 | GestureDetector(
66 | behavior: HitTestBehavior.opaque,
67 | onTap: () => Navigator.of(context).pop(),
68 | child: Container(),
69 | ),
70 | Padding(
71 | padding: EdgeInsets.only(
72 | left: left,
73 | top: padding.top,
74 | right: right,
75 | bottom: padding.bottom,
76 | ),
77 | child: ClipRRect(
78 | borderRadius: const BorderRadius.vertical(
79 | top: Radius.circular(16),
80 | ),
81 | child: result,
82 | ),
83 | )
84 | ],
85 | ),
86 | );
87 | }
88 | return result;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/TodayExtension/TodayViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2019-2021 KagurazakaHanabi
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 | //
16 |
17 | import Alamofire
18 | import AlamofireImage
19 | import UIKit
20 | import NotificationCenter
21 |
22 | class TodayViewController: UIViewController, NCWidgetProviding {
23 | @IBOutlet weak var imageView: UIImageView!
24 |
25 | var current: Picture?
26 |
27 | override func viewDidLoad() {
28 | super.viewDidLoad()
29 | self.extensionContext?.widgetLargestAvailableDisplayMode = .expanded
30 | }
31 |
32 | func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
33 | AF.request("https://v2.api.dailypics.cn/today").responseJSON { response in
34 | switch response.result {
35 | case .success:
36 | if let data = response.value as? Array {
37 | let random = data[Int.random(in: 0.., with event: UIEvent?) {
62 | if self.current != nil {
63 | let uri = URL.init(string: "dailypics://p/\(current!.id)")
64 | self.extensionContext?.open(uri!, completionHandler: nil)
65 | }
66 | }
67 | }
68 |
69 | struct Picture {
70 | let id: String
71 | let url: String
72 |
73 | init?(source: [String: Any]) {
74 | guard let id = source["PID"] as? String,
75 | let path = source["nativePath"] as? String
76 | else {
77 | return nil
78 | }
79 |
80 | self.id = id
81 | self.url = "https://s1.images.dailypics.cn/\(path)!w1080_jpg"
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
19 |
20 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
43 |
44 |
48 |
49 |
50 |
51 |
52 |
53 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
71 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/android/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
39 |
40 |
--------------------------------------------------------------------------------
/lib/widget/animated_transform.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/cupertino.dart';
16 |
17 | class AnimatedTransform extends ImplicitlyAnimatedWidget {
18 | const AnimatedTransform({
19 | Key key,
20 | this.child,
21 | @required this.transform,
22 | this.alignment = Alignment.center,
23 | this.transformHitTests = true,
24 | Curve curve = Curves.linear,
25 | @required Duration duration,
26 | }) : assert(transform != null),
27 | super(key: key, curve: curve, duration: duration);
28 |
29 | AnimatedTransform.rotate({
30 | Key key,
31 | this.child,
32 | @required double angle,
33 | this.alignment = Alignment.center,
34 | this.transformHitTests = true,
35 | Curve curve = Curves.linear,
36 | @required Duration duration,
37 | }) : transform = Matrix4.rotationZ(angle),
38 | super(key: key, curve: curve, duration: duration);
39 |
40 | AnimatedTransform.translate({
41 | Key key,
42 | this.child,
43 | @required Offset offset,
44 | this.transformHitTests = true,
45 | Curve curve = Curves.linear,
46 | @required Duration duration,
47 | }) : transform = Matrix4.translationValues(offset.dx, offset.dy, 0.0),
48 | alignment = null,
49 | super(key: key, curve: curve, duration: duration);
50 |
51 | AnimatedTransform.scale({
52 | Key key,
53 | this.child,
54 | @required double scale,
55 | this.alignment = Alignment.center,
56 | this.transformHitTests = true,
57 | Curve curve = Curves.linear,
58 | @required Duration duration,
59 | }) : transform = Matrix4.diagonal3Values(scale, scale, 1),
60 | super(key: key, curve: curve, duration: duration);
61 |
62 | final Widget child;
63 |
64 | final Matrix4 transform;
65 |
66 | final AlignmentGeometry alignment;
67 |
68 | final bool transformHitTests;
69 |
70 | @override
71 | _AnimatedTransformState createState() => _AnimatedTransformState();
72 | }
73 |
74 | class _AnimatedTransformState extends AnimatedWidgetBaseState {
75 | AlignmentGeometryTween _alignment;
76 | Matrix4Tween _transform;
77 |
78 | @override
79 | void forEachTween(TweenVisitor visitor) {
80 | _alignment = visitor(_alignment, widget.alignment, (dynamic value) => AlignmentGeometryTween(begin: value));
81 | _transform = visitor(_transform, widget.transform, (dynamic value) => Matrix4Tween(begin: value));
82 | }
83 |
84 | @override
85 | Widget build(BuildContext context) {
86 | return Transform(
87 | child: widget.child,
88 | transform: _transform.evaluate(animation),
89 | alignment: _alignment?.evaluate(animation),
90 | transformHitTests: widget.transformHitTests,
91 | );
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/lib/widget/slivers.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:dailypics/misc/bean.dart';
16 | import 'package:dailypics/utils/utils.dart';
17 | import 'package:flutter/cupertino.dart';
18 | import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
19 |
20 | import 'photo_card.dart';
21 |
22 | class SliverImageCardList extends StatelessWidget {
23 | const SliverImageCardList({
24 | Key key,
25 | this.header,
26 | this.footer,
27 | @required this.data,
28 | this.tagBuilder,
29 | this.adaptiveTablet = false,
30 | }) : assert(data != null),
31 | assert(adaptiveTablet != null),
32 | super(key: key);
33 |
34 | final Widget header;
35 |
36 | final Widget footer;
37 |
38 | final List data;
39 |
40 | final String Function(int index) tagBuilder;
41 |
42 | final bool adaptiveTablet;
43 |
44 | @override
45 | Widget build(BuildContext context) {
46 | bool iPad = SystemUtils.isIPad(context, true);
47 | bool portrait = SystemUtils.isPortrait(context);
48 | int cnt = SystemUtils.isIPad(context) ? iPad && !portrait && adaptiveTablet ? 6 : 2 : 1;
49 | return SliverPadding(
50 | padding: SystemUtils.isIPad(context, true)
51 | ? const EdgeInsets.fromLTRB(12, 12, 12, 0)
52 | : const EdgeInsets.only(left: 4, top: 15, right: 4),
53 | sliver: SliverStaggeredGrid.countBuilder(
54 | crossAxisCount: cnt,
55 | itemCount: data.length + 2,
56 | staggeredTileBuilder: (i) {
57 | if (i == 0 || i == data.length + 1) {
58 | return StaggeredTile.fit(cnt);
59 | } else if (iPad && !portrait && adaptiveTablet) {
60 | if (_needWiden(i)) {
61 | return const StaggeredTile.count(4, 3);
62 | } else {
63 | return const StaggeredTile.count(2, 3);
64 | }
65 | } else {
66 | return const StaggeredTile.fit(1);
67 | }
68 | },
69 | itemBuilder: (_, int i) {
70 | if (i == 0) {
71 | return header ?? Container();
72 | } else if (i == data.length + 1) {
73 | return footer ?? Container();
74 | } else if (iPad && !portrait && adaptiveTablet) {
75 | return PhotoCard(
76 | data[i - 1],
77 | tagBuilder != null ? tagBuilder(i - 1) : '#$i',
78 | aspectRatio: _needWiden(i) ? 4 / 3 : 2 / 3.15,
79 | );
80 | } else {
81 | return PhotoCard(
82 | data[i - 1],
83 | tagBuilder != null ? tagBuilder(i - 1) : '#$i',
84 | );
85 | }
86 | },
87 | ),
88 | );
89 | }
90 |
91 | bool _needWiden(int index) {
92 | return index % 4 == 1 || index % 4 == 0;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/ios/TodayExtension/Base.lproj/MainInterface.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/windows/runner/Runner.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #pragma code_page(65001)
4 | #include "resource.h"
5 |
6 | #define APSTUDIO_READONLY_SYMBOLS
7 | /////////////////////////////////////////////////////////////////////////////
8 | //
9 | // Generated from the TEXTINCLUDE 2 resource.
10 | //
11 | #include "winres.h"
12 |
13 | /////////////////////////////////////////////////////////////////////////////
14 | #undef APSTUDIO_READONLY_SYMBOLS
15 |
16 | /////////////////////////////////////////////////////////////////////////////
17 | // English (United States) resources
18 |
19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21 |
22 | #ifdef APSTUDIO_INVOKED
23 | /////////////////////////////////////////////////////////////////////////////
24 | //
25 | // TEXTINCLUDE
26 | //
27 |
28 | 1 TEXTINCLUDE
29 | BEGIN
30 | "resource.h\0"
31 | END
32 |
33 | 2 TEXTINCLUDE
34 | BEGIN
35 | "#include ""winres.h""\r\n"
36 | "\0"
37 | END
38 |
39 | 3 TEXTINCLUDE
40 | BEGIN
41 | "\r\n"
42 | "\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Icon
51 | //
52 |
53 | // Icon with lowest ID value placed first to ensure application icon
54 | // remains consistent on all systems.
55 | IDI_APP_ICON ICON "resources\\app_icon.ico"
56 |
57 |
58 | /////////////////////////////////////////////////////////////////////////////
59 | //
60 | // Version
61 | //
62 |
63 | #ifdef FLUTTER_BUILD_NUMBER
64 | #define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER
65 | #else
66 | #define VERSION_AS_NUMBER 1,0,0
67 | #endif
68 |
69 | #ifdef FLUTTER_BUILD_NAME
70 | #define VERSION_AS_STRING #FLUTTER_BUILD_NAME
71 | #else
72 | #define VERSION_AS_STRING "1.0.0"
73 | #endif
74 |
75 | VS_VERSION_INFO VERSIONINFO
76 | FILEVERSION VERSION_AS_NUMBER
77 | PRODUCTVERSION VERSION_AS_NUMBER
78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
79 | #ifdef _DEBUG
80 | FILEFLAGS VS_FF_DEBUG
81 | #else
82 | FILEFLAGS 0x0L
83 | #endif
84 | FILEOS VOS__WINDOWS32
85 | FILETYPE VFT_APP
86 | FILESUBTYPE 0x0L
87 | BEGIN
88 | BLOCK "StringFileInfo"
89 | BEGIN
90 | BLOCK "040904e4"
91 | BEGIN
92 | VALUE "CompanyName", "cn.dailypics" "\0"
93 | VALUE "FileDescription", "Dailypics Desktop" "\0"
94 | VALUE "FileVersion", VERSION_AS_STRING "\0"
95 | VALUE "InternalName", "dailypics" "\0"
96 | VALUE "LegalCopyright", "Copyright (C) 2021 图鉴事务所 All rights reserved." "\0"
97 | VALUE "OriginalFilename", "dailypics.exe" "\0"
98 | VALUE "ProductName", "dailypics" "\0"
99 | VALUE "ProductVersion", VERSION_AS_STRING "\0"
100 | END
101 | END
102 | BLOCK "VarFileInfo"
103 | BEGIN
104 | VALUE "Translation", 0x409, 1252
105 | END
106 | END
107 |
108 | #endif // English (United States) resources
109 | /////////////////////////////////////////////////////////////////////////////
110 |
111 |
112 |
113 | #ifndef APSTUDIO_INVOKED
114 | /////////////////////////////////////////////////////////////////////////////
115 | //
116 | // Generated from the TEXTINCLUDE 3 resource.
117 | //
118 |
119 |
120 | /////////////////////////////////////////////////////////////////////////////
121 | #endif // not APSTUDIO_INVOKED
122 |
--------------------------------------------------------------------------------
/lib/widget/search.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/cupertino.dart';
16 |
17 | const CupertinoDynamicColor _kClearColor = CupertinoDynamicColor.withBrightness(
18 | color: Color(0xFF636366),
19 | darkColor: Color(0xFFAEAEB2),
20 | );
21 |
22 | class CupertinoSearchBar extends StatelessWidget {
23 | CupertinoSearchBar({
24 | Key key,
25 | this.controller,
26 | this.padding = const EdgeInsets.fromLTRB(16, 10, 16, 10),
27 | this.readOnly = false,
28 | this.autofocus = false,
29 | this.showCancelButton = false,
30 | this.onChanged,
31 | this.onSubmitted,
32 | this.onTap,
33 | }) : super(key: key);
34 |
35 | final TextEditingController controller;
36 |
37 | final EdgeInsets padding;
38 |
39 | final bool readOnly;
40 |
41 | final bool autofocus;
42 |
43 | final bool showCancelButton;
44 |
45 | final ValueChanged onChanged;
46 |
47 | final ValueChanged onSubmitted;
48 |
49 | final GestureTapCallback onTap;
50 |
51 | @override
52 | Widget build(BuildContext context) {
53 | return Container(
54 | color: CupertinoTheme.of(context).barBackgroundColor,
55 | padding: padding,
56 | child: Row(
57 | children: [
58 | Expanded(
59 | child: Hero(
60 | tag: 'CupertinoSearchBar',
61 | child: CupertinoTextField(
62 | controller: controller,
63 | readOnly: readOnly,
64 | autofocus: autofocus,
65 | onChanged: onChanged,
66 | onSubmitted: onSubmitted,
67 | onTap: onTap,
68 | clearButtonMode: OverlayVisibilityMode.editing,
69 | textInputAction: TextInputAction.search,
70 | keyboardAppearance: CupertinoTheme.of(context).brightness,
71 | placeholder: '搜索',
72 | decoration: BoxDecoration(
73 | borderRadius: BorderRadius.circular(10),
74 | color: CupertinoColors.tertiarySystemFill,
75 | ),
76 | prefix: Padding(
77 | padding: const EdgeInsets.only(left: 8),
78 | child: Icon(
79 | CupertinoIcons.search,
80 | color: _kClearColor.resolveFrom(context),
81 | size: 22,
82 | ),
83 | ),
84 | ),
85 | ),
86 | ),
87 | Hero(
88 | tag: 'CupertinoSearchBar.showCancelButton',
89 | child: Offstage(
90 | offstage: !showCancelButton,
91 | child: CupertinoButton(
92 | padding: const EdgeInsets.only(left: 16),
93 | child: const Text('取消', softWrap: false),
94 | onPressed: () => Navigator.of(context).pop(),
95 | ),
96 | ),
97 | ),
98 | ],
99 | ),
100 | );
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/windows/runner/win32_window.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_WIN32_WINDOW_H_
2 | #define RUNNER_WIN32_WINDOW_H_
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be
11 | // inherited from by classes that wish to specialize with custom
12 | // rendering and input handling
13 | class Win32Window {
14 | public:
15 | struct Point {
16 | unsigned int x;
17 | unsigned int y;
18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {}
19 | };
20 |
21 | struct Size {
22 | unsigned int width;
23 | unsigned int height;
24 | Size(unsigned int width, unsigned int height)
25 | : width(width), height(height) {}
26 | };
27 |
28 | Win32Window();
29 | virtual ~Win32Window();
30 |
31 | // Creates and shows a win32 window with |title| and position and size using
32 | // |origin| and |size|. New windows are created on the default monitor. Window
33 | // sizes are specified to the OS in physical pixels, hence to ensure a
34 | // consistent size to will treat the width height passed in to this function
35 | // as logical pixels and scale to appropriate for the default monitor. Returns
36 | // true if the window was created successfully.
37 | bool CreateAndShow(const std::wstring& title,
38 | const Point& origin,
39 | const Size& size);
40 |
41 | // Release OS resources associated with window.
42 | void Destroy();
43 |
44 | // Inserts |content| into the window tree.
45 | void SetChildContent(HWND content);
46 |
47 | // Returns the backing Window handle to enable clients to set icon and other
48 | // window properties. Returns nullptr if the window has been destroyed.
49 | HWND GetHandle();
50 |
51 | // If true, closing this window will quit the application.
52 | void SetQuitOnClose(bool quit_on_close);
53 |
54 | // Return a RECT representing the bounds of the current client area.
55 | RECT GetClientArea();
56 |
57 | protected:
58 | // Processes and route salient window messages for mouse handling,
59 | // size change and DPI. Delegates handling of these to member overloads that
60 | // inheriting classes can handle.
61 | virtual LRESULT MessageHandler(HWND window,
62 | UINT const message,
63 | WPARAM const wparam,
64 | LPARAM const lparam) noexcept;
65 |
66 | // Called when CreateAndShow is called, allowing subclass window-related
67 | // setup. Subclasses should return false if setup fails.
68 | virtual bool OnCreate();
69 |
70 | // Called when Destroy is called.
71 | virtual void OnDestroy();
72 |
73 | private:
74 | friend class WindowClassRegistrar;
75 |
76 | // OS callback called by message pump. Handles the WM_NCCREATE message which
77 | // is passed when the non-client area is being created and enables automatic
78 | // non-client DPI scaling so that the non-client area automatically
79 | // responsponds to changes in DPI. All other messages are handled by
80 | // MessageHandler.
81 | static LRESULT CALLBACK WndProc(HWND const window,
82 | UINT const message,
83 | WPARAM const wparam,
84 | LPARAM const lparam) noexcept;
85 |
86 | // Retrieves a class instance pointer for |window|
87 | static Win32Window* GetThisFromHandle(HWND const window) noexcept;
88 |
89 | bool quit_on_close_ = false;
90 |
91 | // window handle for top level window.
92 | HWND window_handle_ = nullptr;
93 |
94 | // window handle for hosted content.
95 | HWND child_content_ = nullptr;
96 | };
97 |
98 | #endif // RUNNER_WIN32_WINDOW_H_
99 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | xmlns:android
11 |
12 | ^$
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | xmlns:.*
22 |
23 | ^$
24 |
25 |
26 | BY_NAME
27 |
28 |
29 |
30 |
31 |
32 |
33 | .*:id
34 |
35 | http://schemas.android.com/apk/res/android
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | .*:name
45 |
46 | http://schemas.android.com/apk/res/android
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | name
56 |
57 | ^$
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | style
67 |
68 | ^$
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | .*
78 |
79 | ^$
80 |
81 |
82 | BY_NAME
83 |
84 |
85 |
86 |
87 |
88 |
89 | .*
90 |
91 | http://schemas.android.com/apk/res/android
92 |
93 |
94 | ANDROID_ATTRIBUTE_ORDER
95 |
96 |
97 |
98 |
99 |
100 |
101 | .*
102 |
103 | .*
104 |
105 |
106 | BY_NAME
107 |
108 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/windows/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.15)
2 | project(dailypics LANGUAGES CXX)
3 |
4 | set(BINARY_NAME "dailypics")
5 |
6 | cmake_policy(SET CMP0063 NEW)
7 |
8 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
9 |
10 | # Configure build options.
11 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
12 | if(IS_MULTICONFIG)
13 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
14 | CACHE STRING "" FORCE)
15 | else()
16 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
17 | set(CMAKE_BUILD_TYPE "Debug" CACHE
18 | STRING "Flutter build mode" FORCE)
19 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
20 | "Debug" "Profile" "Release")
21 | endif()
22 | endif()
23 |
24 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
25 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
26 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
27 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
28 |
29 | # Use Unicode for all projects.
30 | add_definitions(-DUNICODE -D_UNICODE)
31 |
32 | # Compilation settings that should be applied to most targets.
33 | function(APPLY_STANDARD_SETTINGS TARGET)
34 | target_compile_features(${TARGET} PUBLIC cxx_std_17)
35 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
36 | target_compile_options(${TARGET} PRIVATE /EHsc)
37 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
38 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>")
39 | endfunction()
40 |
41 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
42 |
43 | # Flutter library and tool build rules.
44 | add_subdirectory(${FLUTTER_MANAGED_DIR})
45 |
46 | # Application build
47 | add_subdirectory("runner")
48 |
49 | # Generated plugin build rules, which manage building the plugins and adding
50 | # them to the application.
51 | include(flutter/generated_plugins.cmake)
52 |
53 |
54 | # === Installation ===
55 | # Support files are copied into place next to the executable, so that it can
56 | # run in place. This is done instead of making a separate bundle (as on Linux)
57 | # so that building and running from within Visual Studio will work.
58 | set(BUILD_BUNDLE_DIR "$")
59 | # Make the "install" step default, as it's required to run.
60 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
61 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
62 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
63 | endif()
64 |
65 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
66 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
67 |
68 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
69 | COMPONENT Runtime)
70 |
71 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
72 | COMPONENT Runtime)
73 |
74 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
75 | COMPONENT Runtime)
76 |
77 | if(PLUGIN_BUNDLED_LIBRARIES)
78 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
79 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
80 | COMPONENT Runtime)
81 | endif()
82 |
83 | # Fully re-copy the assets directory on each build to avoid having stale files
84 | # from a previous install.
85 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
86 | install(CODE "
87 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
88 | " COMPONENT Runtime)
89 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
90 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
91 |
92 | # Install the AOT library on non-Debug builds only.
93 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
94 | CONFIGURATIONS Profile;Release
95 | COMPONENT Runtime)
96 |
--------------------------------------------------------------------------------
/lib/widget/toast.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:async';
16 | import 'dart:collection';
17 |
18 | import 'package:flutter/material.dart';
19 |
20 | class Toast extends StatelessWidget {
21 | Toast(
22 | this.context,
23 | this.text, {
24 | this.duration = length_short,
25 | this.alignment = const Alignment(0, 0.75),
26 | }) : assert(context != null),
27 | assert(duration != null),
28 | assert(alignment != null);
29 |
30 | static const Duration length_short = Duration(seconds: 4);
31 |
32 | static const Duration length_long = Duration(seconds: 7);
33 |
34 | static const Duration _animationDuration = Duration(milliseconds: 500);
35 |
36 | static Queue _toasts = Queue();
37 |
38 | static Timer _toastTimer;
39 |
40 | final BuildContext context;
41 |
42 | final String text;
43 |
44 | final Duration duration;
45 |
46 | final Alignment alignment;
47 |
48 | @override
49 | Widget build(BuildContext context) {
50 | TextStyle textStyle = const TextStyle(
51 | color: Color(0xDE000000),
52 | fontSize: 14,
53 | );
54 | return Container(
55 | width: MediaQuery.of(context).size.width,
56 | height: MediaQuery.of(context).size.height,
57 | padding: MediaQuery.of(context).padding,
58 | alignment: alignment,
59 | child: DefaultTextStyle(
60 | style: Theme.of(context).textTheme.subtitle1.merge(textStyle),
61 | child: AnimatedOpacity(
62 | opacity: _toasts.contains(this) ? 1 : 0,
63 | duration: const Duration(milliseconds: 500),
64 | curve: Curves.easeInOut,
65 | child: Container(
66 | margin: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
67 | padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
68 | decoration: BoxDecoration(
69 | borderRadius: BorderRadius.circular(22),
70 | color: const Color(0xE6EEEEEE),
71 | ),
72 | child: Text(text ?? 'null'),
73 | ),
74 | ),
75 | ),
76 | );
77 | }
78 |
79 | void show() async {
80 | if (_toasts.isNotEmpty) {
81 | _toasts.addLast(this);
82 | return;
83 | }
84 | _toasts.addLast(this);
85 | OverlayState overlay = Overlay.of(context);
86 | OverlayEntry entry = OverlayEntry(builder: (_) => this);
87 | overlay.insert(entry);
88 | entry.markNeedsBuild();
89 | await Future.delayed(_animationDuration);
90 | _toastTimer = Timer.periodic(duration, (_) async {
91 | _toasts.removeFirst();
92 | entry.markNeedsBuild();
93 | await Future.delayed(_animationDuration);
94 | entry.remove();
95 | if (_toasts.isNotEmpty) {
96 | entry = OverlayEntry(builder: (_) => _toasts.first);
97 | overlay.insert(entry);
98 | entry.markNeedsBuild();
99 | await Future.delayed(_animationDuration);
100 | } else {
101 | _toastTimer.cancel();
102 | _toastTimer = null;
103 | }
104 | });
105 | }
106 |
107 | void cancel() => _toasts.remove(this);
108 | }
109 |
--------------------------------------------------------------------------------
/android/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | xmlns:android
14 |
15 | ^$
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | xmlns:.*
25 |
26 | ^$
27 |
28 |
29 | BY_NAME
30 |
31 |
32 |
33 |
34 |
35 |
36 | .*:id
37 |
38 | http://schemas.android.com/apk/res/android
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | .*:name
48 |
49 | http://schemas.android.com/apk/res/android
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | name
59 |
60 | ^$
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | style
70 |
71 | ^$
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | .*
81 |
82 | ^$
83 |
84 |
85 | BY_NAME
86 |
87 |
88 |
89 |
90 |
91 |
92 | .*
93 |
94 | http://schemas.android.com/apk/res/android
95 |
96 |
97 | ANDROID_ATTRIBUTE_ORDER
98 |
99 |
100 |
101 |
102 |
103 |
104 | .*
105 |
106 | .*
107 |
108 |
109 | BY_NAME
110 |
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | platform :ios, '10.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def parse_KV_file(file, separator='=')
14 | file_abs_path = File.expand_path(file)
15 | if !File.exists? file_abs_path
16 | return [];
17 | end
18 | generated_key_values = {}
19 | skip_line_start_symbols = ["#", "/"]
20 | File.foreach(file_abs_path) do |line|
21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
22 | plugin = line.split(pattern=separator)
23 | if plugin.length == 2
24 | podname = plugin[0].strip()
25 | path = plugin[1].strip()
26 | podpath = File.expand_path("#{path}", file_abs_path)
27 | generated_key_values[podname] = podpath
28 | else
29 | puts "Invalid plugin specification: #{line}"
30 | end
31 | end
32 | generated_key_values
33 | end
34 |
35 | target 'Runner' do
36 | use_frameworks!
37 | use_modular_headers!
38 |
39 | # Flutter Pod
40 |
41 | copied_flutter_dir = File.join(__dir__, 'Flutter')
42 | copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
43 | copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
44 | unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
45 | # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
46 | # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
47 | # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
48 |
49 | generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
50 | unless File.exist?(generated_xcode_build_settings_path)
51 | raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
52 | end
53 | generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
54 | cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
55 |
56 | unless File.exist?(copied_framework_path)
57 | FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
58 | end
59 | unless File.exist?(copied_podspec_path)
60 | FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
61 | end
62 | end
63 |
64 | # Keep pod path relative so it can be checked into Podfile.lock.
65 | pod 'Flutter', :path => 'Flutter'
66 |
67 | # Plugin Pods
68 |
69 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
70 | # referring to absolute paths on developers' machines.
71 | system('rm -rf .symlinks')
72 | system('mkdir -p .symlinks/plugins')
73 | plugin_pods = parse_KV_file('../.flutter-plugins')
74 | plugin_pods.each do |name, path|
75 | symlink = File.join('.symlinks', 'plugins', name)
76 | File.symlink(path, symlink)
77 | pod name, :path => File.join(symlink, 'ios')
78 | end
79 | end
80 |
81 | target 'TodayExtension' do
82 | use_frameworks!
83 |
84 | pod 'Alamofire', '~> 5.0'
85 | pod 'AlamofireImage', '~> 4.0'
86 | end
87 |
88 | # Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
89 | install! 'cocoapods', :disable_input_output_paths => true
90 |
91 | post_install do |installer|
92 | installer.pods_project.targets.each do |target|
93 | target.build_configurations.each do |config|
94 | config.build_settings['ENABLE_BITCODE'] = 'NO'
95 | end
96 | end
97 | end
98 |
99 |
--------------------------------------------------------------------------------
/lib/pages/splash.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:async';
16 | import 'dart:io';
17 | import 'dart:ui';
18 |
19 | import 'package:dailypics/misc/bean.dart';
20 | import 'package:dailypics/model/app.dart';
21 | import 'package:dailypics/pages/home.dart';
22 | import 'package:dailypics/utils/api.dart';
23 | import 'package:dailypics/utils/utils.dart';
24 | import 'package:flutter/cupertino.dart';
25 | import 'package:flutter_cache_manager/flutter_cache_manager.dart';
26 |
27 | class SplashPage extends StatefulWidget {
28 | @override
29 | _SplashPageState createState() => _SplashPageState();
30 | }
31 |
32 | class _SplashPageState extends State {
33 | ImageFrameBuilder _frameBuilder = (_, Widget child, int frame, bool loaded) {
34 | if (loaded) return child;
35 | return AnimatedOpacity(
36 | child: child,
37 | curve: Curves.easeOut,
38 | opacity: frame == null ? 0 : 1,
39 | duration: const Duration(milliseconds: 300),
40 | );
41 | };
42 |
43 | File _file;
44 | Timer _timer;
45 |
46 | @override
47 | void initState() {
48 | super.initState();
49 | _initialize();
50 | }
51 |
52 | Future _initialize() async {
53 | _timer = Timer(const Duration(seconds: 3), () => HomePage.push(context));
54 | List results = await Future.wait([
55 | TujianApi.getTypes(),
56 | Settings.initialize(),
57 | _fetchOrShowSplash(),
58 | ]);
59 | AppModel.of(context).types = results[0];
60 | if (_file == null) {
61 | _timer.cancel();
62 | HomePage.push(context);
63 | }
64 | }
65 |
66 | Future _fetchOrShowSplash() async {
67 | Splash splash = await TujianApi.getSplash();
68 | String url = splash.imageUrl;
69 | DateTime now = DateTime.now();
70 | if (now.isAfter(splash.effectiveAt) && now.isBefore(splash.expiresAt)) {
71 | DefaultCacheManager manager = DefaultCacheManager();
72 | FileInfo info = await manager.getFileFromCache(url);
73 | if (info != null) {
74 | return setState(() => _file = info.file);
75 | } else {
76 | manager.downloadFile(url);
77 | }
78 | }
79 | }
80 |
81 | @override
82 | Widget build(BuildContext context) {
83 | if (_file == null) {
84 | return CupertinoPageScaffold(
85 | child: Container(),
86 | );
87 | }
88 | return CupertinoPageScaffold(
89 | child: Stack(
90 | fit: StackFit.expand,
91 | alignment: Alignment.center,
92 | children: [
93 | Image.file(
94 | _file,
95 | fit: BoxFit.cover,
96 | frameBuilder: _frameBuilder,
97 | ),
98 | if (SystemUtils.isIPad(context))
99 | ClipRect(
100 | child: BackdropFilter(
101 | filter: ImageFilter.blur(sigmaX: 32, sigmaY: 32),
102 | child: Image.file(
103 | _file,
104 | fit: BoxFit.contain,
105 | frameBuilder: _frameBuilder,
106 | ),
107 | ),
108 | ),
109 | ],
110 | ),
111 | );
112 | }
113 |
114 | @override
115 | void dispose() {
116 | _timer?.cancel();
117 | super.dispose();
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/windows/flutter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.15)
2 |
3 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
4 |
5 | # Configuration provided via flutter tool.
6 | include(${EPHEMERAL_DIR}/generated_config.cmake)
7 |
8 | # TODO: Move the rest of this into files in ephemeral. See
9 | # https://github.com/flutter/flutter/issues/57146.
10 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
11 |
12 | # === Flutter Library ===
13 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
14 |
15 | # Published to parent scope for install step.
16 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
17 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
18 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
19 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
20 |
21 | list(APPEND FLUTTER_LIBRARY_HEADERS
22 | "flutter_export.h"
23 | "flutter_windows.h"
24 | "flutter_messenger.h"
25 | "flutter_plugin_registrar.h"
26 | "flutter_texture_registrar.h"
27 | )
28 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
29 | add_library(flutter INTERFACE)
30 | target_include_directories(flutter INTERFACE
31 | "${EPHEMERAL_DIR}"
32 | )
33 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
34 | add_dependencies(flutter flutter_assemble)
35 |
36 | # === Wrapper ===
37 | list(APPEND CPP_WRAPPER_SOURCES_CORE
38 | "core_implementations.cc"
39 | "standard_codec.cc"
40 | )
41 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
42 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
43 | "plugin_registrar.cc"
44 | )
45 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
46 | list(APPEND CPP_WRAPPER_SOURCES_APP
47 | "flutter_engine.cc"
48 | "flutter_view_controller.cc"
49 | )
50 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
51 |
52 | # Wrapper sources needed for a plugin.
53 | add_library(flutter_wrapper_plugin STATIC
54 | ${CPP_WRAPPER_SOURCES_CORE}
55 | ${CPP_WRAPPER_SOURCES_PLUGIN}
56 | )
57 | apply_standard_settings(flutter_wrapper_plugin)
58 | set_target_properties(flutter_wrapper_plugin PROPERTIES
59 | POSITION_INDEPENDENT_CODE ON)
60 | set_target_properties(flutter_wrapper_plugin PROPERTIES
61 | CXX_VISIBILITY_PRESET hidden)
62 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
63 | target_include_directories(flutter_wrapper_plugin PUBLIC
64 | "${WRAPPER_ROOT}/include"
65 | )
66 | add_dependencies(flutter_wrapper_plugin flutter_assemble)
67 |
68 | # Wrapper sources needed for the runner.
69 | add_library(flutter_wrapper_app STATIC
70 | ${CPP_WRAPPER_SOURCES_CORE}
71 | ${CPP_WRAPPER_SOURCES_APP}
72 | )
73 | apply_standard_settings(flutter_wrapper_app)
74 | target_link_libraries(flutter_wrapper_app PUBLIC flutter)
75 | target_include_directories(flutter_wrapper_app PUBLIC
76 | "${WRAPPER_ROOT}/include"
77 | )
78 | add_dependencies(flutter_wrapper_app flutter_assemble)
79 |
80 | # === Flutter tool backend ===
81 | # _phony_ is a non-existent file to force this command to run every time,
82 | # since currently there's no way to get a full input/output list from the
83 | # flutter tool.
84 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
85 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
86 | add_custom_command(
87 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
88 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
89 | ${CPP_WRAPPER_SOURCES_APP}
90 | ${PHONY_OUTPUT}
91 | COMMAND ${CMAKE_COMMAND} -E env
92 | ${FLUTTER_TOOL_ENVIRONMENT}
93 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
94 | windows-x64 $
95 | VERBATIM
96 | )
97 | add_custom_target(flutter_assemble DEPENDS
98 | "${FLUTTER_LIBRARY}"
99 | ${FLUTTER_LIBRARY_HEADERS}
100 | ${CPP_WRAPPER_SOURCES_CORE}
101 | ${CPP_WRAPPER_SOURCES_PLUGIN}
102 | ${CPP_WRAPPER_SOURCES_APP}
103 | )
104 |
--------------------------------------------------------------------------------
/lib/pages/home.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:async';
16 |
17 | import 'package:dailypics/extension.dart';
18 | import 'package:dailypics/components/suggest.dart';
19 | import 'package:dailypics/components/today.dart';
20 | import 'package:dailypics/misc/ionicons.dart';
21 | import 'package:dailypics/pages/about.dart';
22 | import 'package:dailypics/pages/details.dart';
23 | import 'package:dailypics/pages/recent.dart';
24 | import 'package:flutter/cupertino.dart';
25 | import 'package:flutter/services.dart';
26 | import 'package:uni_links/uni_links.dart';
27 |
28 | class HomePage extends StatefulWidget {
29 | @override
30 | _HomePageState createState() => _HomePageState();
31 |
32 | static void push(BuildContext context) {
33 | Navigator.of(context).pushReplacement(
34 | PageRouteBuilder(pageBuilder: (_, Animation animation, __) {
35 | return FadeTransition(
36 | opacity: animation,
37 | child: HomePage(),
38 | );
39 | }),
40 | );
41 | }
42 | }
43 |
44 | class _HomePageState extends State {
45 | StreamSubscription _subscription;
46 |
47 | @override
48 | void initState() {
49 | super.initState();
50 | _subscription = getUriLinksStream().listen(_handleUniLink);
51 | getInitialUri().then(_handleUniLink);
52 | }
53 |
54 | @override
55 | Widget build(BuildContext context) {
56 | return AnnotatedRegion(
57 | value: CupertinoTheme.of(context).barBackgroundColor.isDark
58 | ? SystemUiOverlayStyle.light
59 | : SystemUiOverlayStyle.dark,
60 | child: CupertinoTabScaffold(
61 | resizeToAvoidBottomInset: false,
62 | tabBar: CupertinoTabBar(
63 | items: [
64 | _buildNavigationItem(Ionicons.today_outline, 'Today'),
65 | _buildNavigationItem(Ionicons.time_outline, '以往'),
66 | _buildNavigationItem(Ionicons.flame_outline, '推荐 '),
67 | _buildNavigationItem(Ionicons.settings_outline, '更多'),
68 | ],
69 | ),
70 | tabBuilder: (_, index) {
71 | switch (index) {
72 | case 0:
73 | return CupertinoTabView(builder: (_) => TodayComponent());
74 | case 1:
75 | return CupertinoTabView(builder: (_) => RecentPage());
76 | case 2:
77 | return CupertinoTabView(builder: (_) => SuggestComponent());
78 | case 3:
79 | return CupertinoTabView(builder: (_) => AboutPage());
80 | default:
81 | return null;
82 | }
83 | },
84 | ),
85 | );
86 | }
87 |
88 | @override
89 | void dispose() {
90 | _subscription.cancel();
91 | super.dispose();
92 | }
93 |
94 | BottomNavigationBarItem _buildNavigationItem(IconData icon, String title) {
95 | return BottomNavigationBarItem(icon: Icon(icon), label: title);
96 | }
97 |
98 | void _handleUniLink(Uri uri) {
99 | if (uri == null) return;
100 | if ((uri.scheme == 'dailypics' && uri.host == 'p') ||
101 | ((uri.scheme == 'https' && uri.host.contains('dailypics.cn')) &&
102 | (uri.path.startsWith('/p/') || uri.path.startsWith('/member/id/')))) {
103 | DetailsPage.push(context, pid: uri.pathSegments.last);
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/lib/misc/bean.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'bean.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | Picture _$PictureFromJson(Map json) {
10 | return Picture(
11 | id: json['PID'] as String,
12 | tid: json['TID'] as String,
13 | user: json['username'] as String,
14 | title: json['p_title'] as String,
15 | content: json['p_content'] as String,
16 | width: json['width'] as int,
17 | height: json['height'] as int,
18 | cdnUrl: Picture._urlFromJson(json['nativePath'] as String),
19 | color: Picture._colorFromHex(json['theme_color'] as String),
20 | date: json['p_date'] as String,
21 | marked: json['marked'] as bool ?? false,
22 | );
23 | }
24 |
25 | Map _$PictureToJson(Picture instance) => {
26 | 'PID': instance.id,
27 | 'TID': instance.tid,
28 | 'username': instance.user,
29 | 'p_title': instance.title,
30 | 'p_content': instance.content,
31 | 'width': instance.width,
32 | 'height': instance.height,
33 | 'nativePath': instance.cdnUrl,
34 | 'theme_color': Picture._colorToHex(instance.color),
35 | 'p_date': instance.date,
36 | 'marked': instance.marked,
37 | };
38 |
39 | Recents _$RecentsFromJson(Map json) {
40 | return Recents(
41 | current: json['page'] as int,
42 | maximum: json['maxpage'] as int,
43 | option: json['op'] as String,
44 | data: (json['result'] as List)
45 | ?.map((e) =>
46 | e == null ? null : Picture.fromJson(e as Map))
47 | ?.toList(),
48 | );
49 | }
50 |
51 | Map _$RecentsToJson(Recents instance) => {
52 | 'page': instance.current,
53 | 'maxpage': instance.maximum,
54 | 'op': instance.option,
55 | 'result': instance.data,
56 | };
57 |
58 | Splash _$SplashFromJson(Map json) {
59 | return Splash(
60 | title: json['splash_title'] as String,
61 | imageUrl: json['splash_image'] as String,
62 | effectiveAt: Splash._parseDateTime(json['effective_at'] as String),
63 | expiresAt: Splash._parseDateTime(json['expires_at'] as String),
64 | );
65 | }
66 |
67 | Map _$SplashToJson(Splash instance) => {
68 | 'splash_title': instance.title,
69 | 'splash_image': instance.imageUrl,
70 | 'effective_at': instance.effectiveAt?.toIso8601String(),
71 | 'expires_at': instance.expiresAt?.toIso8601String(),
72 | };
73 |
74 | Hitokoto _$HitokotoFromJson(Map json) {
75 | return Hitokoto(
76 | source: json['source'] as String,
77 | content: json['hitokoto'] as String,
78 | );
79 | }
80 |
81 | Map _$HitokotoToJson(Hitokoto instance) => {
82 | 'source': instance.source,
83 | 'hitokoto': instance.content,
84 | };
85 |
86 | Contributor _$ContributorFromJson(Map json) {
87 | return Contributor(
88 | avatar: json['avatar'] as String,
89 | name: json['name'] as String,
90 | position: json['position'] as String,
91 | url: json['url'] as String,
92 | );
93 | }
94 |
95 | Map _$ContributorToJson(Contributor instance) =>
96 | {
97 | 'avatar': instance.avatar,
98 | 'name': instance.name,
99 | 'position': instance.position,
100 | 'url': instance.url,
101 | };
102 |
103 | User _$UserFromJson(Map json) {
104 | return User(
105 | nickname: json['nickname'] as String,
106 | username: json['username'] as String,
107 | );
108 | }
109 |
110 | Map _$UserToJson(User instance) => {
111 | 'nickname': instance.nickname,
112 | 'username': instance.username,
113 | };
114 |
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Alamofire (5.0.2)
3 | - AlamofireImage (4.0.2):
4 | - Alamofire (< 6.0.0, >= 5.0.2)
5 | - Flutter (1.0.0)
6 | - flutter_plugin_android_lifecycle (0.0.1):
7 | - Flutter
8 | - FMDB (2.7.5):
9 | - FMDB/standard (= 2.7.5)
10 | - FMDB/standard (2.7.5)
11 | - image_picker (0.0.1):
12 | - Flutter
13 | - package_info (0.0.1):
14 | - Flutter
15 | - path_provider (0.0.1):
16 | - Flutter
17 | - path_provider_macos (0.0.1):
18 | - Flutter
19 | - shared_preferences (0.0.1):
20 | - Flutter
21 | - shared_preferences_macos (0.0.1):
22 | - Flutter
23 | - shared_preferences_web (0.0.1):
24 | - Flutter
25 | - sqflite (0.0.1):
26 | - Flutter
27 | - FMDB (~> 2.7.2)
28 | - uni_links (0.0.1):
29 | - Flutter
30 | - url_launcher (0.0.1):
31 | - Flutter
32 | - url_launcher_macos (0.0.1):
33 | - Flutter
34 | - url_launcher_web (0.0.1):
35 | - Flutter
36 |
37 | DEPENDENCIES:
38 | - Alamofire (~> 5.0)
39 | - AlamofireImage (~> 4.0)
40 | - Flutter (from `Flutter`)
41 | - flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`)
42 | - image_picker (from `.symlinks/plugins/image_picker/ios`)
43 | - package_info (from `.symlinks/plugins/package_info/ios`)
44 | - path_provider (from `.symlinks/plugins/path_provider/ios`)
45 | - path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`)
46 | - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
47 | - shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`)
48 | - shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`)
49 | - sqflite (from `.symlinks/plugins/sqflite/ios`)
50 | - uni_links (from `.symlinks/plugins/uni_links/ios`)
51 | - url_launcher (from `.symlinks/plugins/url_launcher/ios`)
52 | - url_launcher_macos (from `.symlinks/plugins/url_launcher_macos/ios`)
53 | - url_launcher_web (from `.symlinks/plugins/url_launcher_web/ios`)
54 |
55 | SPEC REPOS:
56 | trunk:
57 | - Alamofire
58 | - AlamofireImage
59 | - FMDB
60 |
61 | EXTERNAL SOURCES:
62 | Flutter:
63 | :path: Flutter
64 | flutter_plugin_android_lifecycle:
65 | :path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios"
66 | image_picker:
67 | :path: ".symlinks/plugins/image_picker/ios"
68 | package_info:
69 | :path: ".symlinks/plugins/package_info/ios"
70 | path_provider:
71 | :path: ".symlinks/plugins/path_provider/ios"
72 | path_provider_macos:
73 | :path: ".symlinks/plugins/path_provider_macos/ios"
74 | shared_preferences:
75 | :path: ".symlinks/plugins/shared_preferences/ios"
76 | shared_preferences_macos:
77 | :path: ".symlinks/plugins/shared_preferences_macos/ios"
78 | shared_preferences_web:
79 | :path: ".symlinks/plugins/shared_preferences_web/ios"
80 | sqflite:
81 | :path: ".symlinks/plugins/sqflite/ios"
82 | uni_links:
83 | :path: ".symlinks/plugins/uni_links/ios"
84 | url_launcher:
85 | :path: ".symlinks/plugins/url_launcher/ios"
86 | url_launcher_macos:
87 | :path: ".symlinks/plugins/url_launcher_macos/ios"
88 | url_launcher_web:
89 | :path: ".symlinks/plugins/url_launcher_web/ios"
90 |
91 | SPEC CHECKSUMS:
92 | Alamofire: 3ba7a4db18b4f62c4a1c0e1cb39d7f3d52e10ada
93 | AlamofireImage: ca7325440303d041a80b7caa55066ba945522378
94 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
95 | flutter_plugin_android_lifecycle: 47de533a02850f070f5696a623995e93eddcdb9b
96 | FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
97 | image_picker: e3eacd46b94694dde7cf2705955cece853aa1a8f
98 | package_info: 48b108e75b8802c2d5e126f208ef540561c98aef
99 | path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d
100 | path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0
101 | shared_preferences: 430726339841afefe5142b9c1f50cb6bd7793e01
102 | shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087
103 | shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9
104 | sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0
105 | uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
106 | url_launcher: a1c0cc845906122c4784c542523d8cacbded5626
107 | url_launcher_macos: fd7894421cd39320dce5f292fc99ea9270b2a313
108 | url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c
109 |
110 | PODFILE CHECKSUM: aacc89576a3f3fb06a06647bd0e510aba02fc626
111 |
112 | COCOAPODS: 1.8.4
113 |
--------------------------------------------------------------------------------
/lib/utils/api.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2021 KagurazakaHanabi
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:async';
16 | import 'dart:convert';
17 | import 'dart:io';
18 |
19 | import 'package:dailypics/misc/bean.dart';
20 | import 'package:dailypics/utils/http.dart';
21 | import 'package:dio/dio.dart';
22 | import 'package:flutter/cupertino.dart';
23 |
24 | class TujianApiException implements Exception {
25 | const TujianApiException(this.message);
26 |
27 | final String message;
28 |
29 | @override
30 | String toString() => 'TujianApiException: $message';
31 | }
32 |
33 | class TujianApi {
34 | static const String _kBaseUrl = 'https://v2.api.dailypics.cn';
35 |
36 | static Future