diff --git a/01-advanced-navigation/01-starter/.gitignore b/01-advanced-navigation/01-starter/.gitignore index a8e938c..221b422 100644 --- a/01-advanced-navigation/01-starter/.gitignore +++ b/01-advanced-navigation/01-starter/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/01-advanced-navigation/01-starter/android/gradle/wrapper/gradle-wrapper.properties b/01-advanced-navigation/01-starter/android/gradle/wrapper/gradle-wrapper.properties index afa1e8e..ac3b479 100644 --- a/01-advanced-navigation/01-starter/android/gradle/wrapper/gradle-wrapper.properties +++ b/01-advanced-navigation/01-starter/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/01-advanced-navigation/01-starter/android/settings.gradle.kts b/01-advanced-navigation/01-starter/android/settings.gradle.kts index a439442..43394ed 100644 --- a/01-advanced-navigation/01-starter/android/settings.gradle.kts +++ b/01-advanced-navigation/01-starter/android/settings.gradle.kts @@ -18,8 +18,8 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.7.0" apply false - id("org.jetbrains.kotlin.android") version "1.8.22" apply false + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false } include(":app") diff --git a/01-advanced-navigation/01-starter/ios/Flutter/AppFrameworkInfo.plist b/01-advanced-navigation/01-starter/ios/Flutter/AppFrameworkInfo.plist index 7c56964..1dc6cf7 100644 --- a/01-advanced-navigation/01-starter/ios/Flutter/AppFrameworkInfo.plist +++ b/01-advanced-navigation/01-starter/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/01-advanced-navigation/01-starter/ios/Runner.xcodeproj/project.pbxproj b/01-advanced-navigation/01-starter/ios/Runner.xcodeproj/project.pbxproj index 866b376..fee6cdd 100644 --- a/01-advanced-navigation/01-starter/ios/Runner.xcodeproj/project.pbxproj +++ b/01-advanced-navigation/01-starter/ios/Runner.xcodeproj/project.pbxproj @@ -346,7 +346,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -473,7 +473,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -524,7 +524,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/01-advanced-navigation/01-starter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/01-advanced-navigation/01-starter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15cada4..e3773d4 100644 --- a/01-advanced-navigation/01-starter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/01-advanced-navigation/01-starter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> =3.7.0-0 <4.0.0" + dart: ">=3.9.2 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/01-advanced-navigation/01-starter/pubspec.yaml b/01-advanced-navigation/01-starter/pubspec.yaml index 9fd0ee3..39aba6f 100644 --- a/01-advanced-navigation/01-starter/pubspec.yaml +++ b/01-advanced-navigation/01-starter/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ^3.7.0 + sdk: ^3.9.2 dependencies: flutter: diff --git a/01-advanced-navigation/02-01-page-api/.gitignore b/01-advanced-navigation/02-01-page-api/.gitignore index a8e938c..221b422 100644 --- a/01-advanced-navigation/02-01-page-api/.gitignore +++ b/01-advanced-navigation/02-01-page-api/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/01-advanced-navigation/02-01-page-api/android/gradle/wrapper/gradle-wrapper.properties b/01-advanced-navigation/02-01-page-api/android/gradle/wrapper/gradle-wrapper.properties index afa1e8e..ac3b479 100644 --- a/01-advanced-navigation/02-01-page-api/android/gradle/wrapper/gradle-wrapper.properties +++ b/01-advanced-navigation/02-01-page-api/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/01-advanced-navigation/02-01-page-api/android/settings.gradle.kts b/01-advanced-navigation/02-01-page-api/android/settings.gradle.kts index a439442..43394ed 100644 --- a/01-advanced-navigation/02-01-page-api/android/settings.gradle.kts +++ b/01-advanced-navigation/02-01-page-api/android/settings.gradle.kts @@ -18,8 +18,8 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.7.0" apply false - id("org.jetbrains.kotlin.android") version "1.8.22" apply false + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false } include(":app") diff --git a/01-advanced-navigation/02-01-page-api/ios/Flutter/AppFrameworkInfo.plist b/01-advanced-navigation/02-01-page-api/ios/Flutter/AppFrameworkInfo.plist index 7c56964..1dc6cf7 100644 --- a/01-advanced-navigation/02-01-page-api/ios/Flutter/AppFrameworkInfo.plist +++ b/01-advanced-navigation/02-01-page-api/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/01-advanced-navigation/02-01-page-api/ios/Runner.xcodeproj/project.pbxproj b/01-advanced-navigation/02-01-page-api/ios/Runner.xcodeproj/project.pbxproj index 866b376..fee6cdd 100644 --- a/01-advanced-navigation/02-01-page-api/ios/Runner.xcodeproj/project.pbxproj +++ b/01-advanced-navigation/02-01-page-api/ios/Runner.xcodeproj/project.pbxproj @@ -346,7 +346,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -473,7 +473,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -524,7 +524,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/01-advanced-navigation/02-01-page-api/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/01-advanced-navigation/02-01-page-api/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15cada4..e3773d4 100644 --- a/01-advanced-navigation/02-01-page-api/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/01-advanced-navigation/02-01-page-api/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> =3.7.0-0 <4.0.0" + dart: ">=3.9.2 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/01-advanced-navigation/02-01-page-api/pubspec.yaml b/01-advanced-navigation/02-01-page-api/pubspec.yaml index 9fd0ee3..39aba6f 100644 --- a/01-advanced-navigation/02-01-page-api/pubspec.yaml +++ b/01-advanced-navigation/02-01-page-api/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ^3.7.0 + sdk: ^3.9.2 dependencies: flutter: diff --git a/01-advanced-navigation/02-02-router-api/.gitignore b/01-advanced-navigation/02-02-router-api/.gitignore index a8e938c..221b422 100644 --- a/01-advanced-navigation/02-02-router-api/.gitignore +++ b/01-advanced-navigation/02-02-router-api/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/01-advanced-navigation/02-02-router-api/android/gradle/wrapper/gradle-wrapper.properties b/01-advanced-navigation/02-02-router-api/android/gradle/wrapper/gradle-wrapper.properties index afa1e8e..ac3b479 100644 --- a/01-advanced-navigation/02-02-router-api/android/gradle/wrapper/gradle-wrapper.properties +++ b/01-advanced-navigation/02-02-router-api/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/01-advanced-navigation/02-02-router-api/android/settings.gradle.kts b/01-advanced-navigation/02-02-router-api/android/settings.gradle.kts index a439442..43394ed 100644 --- a/01-advanced-navigation/02-02-router-api/android/settings.gradle.kts +++ b/01-advanced-navigation/02-02-router-api/android/settings.gradle.kts @@ -18,8 +18,8 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.7.0" apply false - id("org.jetbrains.kotlin.android") version "1.8.22" apply false + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false } include(":app") diff --git a/01-advanced-navigation/02-02-router-api/ios/Flutter/AppFrameworkInfo.plist b/01-advanced-navigation/02-02-router-api/ios/Flutter/AppFrameworkInfo.plist index 7c56964..1dc6cf7 100644 --- a/01-advanced-navigation/02-02-router-api/ios/Flutter/AppFrameworkInfo.plist +++ b/01-advanced-navigation/02-02-router-api/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/01-advanced-navigation/02-02-router-api/ios/Runner.xcodeproj/project.pbxproj b/01-advanced-navigation/02-02-router-api/ios/Runner.xcodeproj/project.pbxproj index 866b376..fee6cdd 100644 --- a/01-advanced-navigation/02-02-router-api/ios/Runner.xcodeproj/project.pbxproj +++ b/01-advanced-navigation/02-02-router-api/ios/Runner.xcodeproj/project.pbxproj @@ -346,7 +346,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -473,7 +473,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -524,7 +524,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/01-advanced-navigation/02-02-router-api/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/01-advanced-navigation/02-02-router-api/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15cada4..e3773d4 100644 --- a/01-advanced-navigation/02-02-router-api/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/01-advanced-navigation/02-02-router-api/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> =3.7.0 <4.0.0" + dart: ">=3.9.2 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/01-advanced-navigation/02-02-router-api/pubspec.yaml b/01-advanced-navigation/02-02-router-api/pubspec.yaml index 9fd0ee3..39aba6f 100644 --- a/01-advanced-navigation/02-02-router-api/pubspec.yaml +++ b/01-advanced-navigation/02-02-router-api/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ^3.7.0 + sdk: ^3.9.2 dependencies: flutter: diff --git a/01-advanced-navigation/02-03-return-data/.gitignore b/01-advanced-navigation/02-03-return-data/.gitignore index a8e938c..221b422 100644 --- a/01-advanced-navigation/02-03-return-data/.gitignore +++ b/01-advanced-navigation/02-03-return-data/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/01-advanced-navigation/02-03-return-data/android/gradle/wrapper/gradle-wrapper.properties b/01-advanced-navigation/02-03-return-data/android/gradle/wrapper/gradle-wrapper.properties index afa1e8e..ac3b479 100644 --- a/01-advanced-navigation/02-03-return-data/android/gradle/wrapper/gradle-wrapper.properties +++ b/01-advanced-navigation/02-03-return-data/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/01-advanced-navigation/02-03-return-data/android/settings.gradle.kts b/01-advanced-navigation/02-03-return-data/android/settings.gradle.kts index a439442..43394ed 100644 --- a/01-advanced-navigation/02-03-return-data/android/settings.gradle.kts +++ b/01-advanced-navigation/02-03-return-data/android/settings.gradle.kts @@ -18,8 +18,8 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.7.0" apply false - id("org.jetbrains.kotlin.android") version "1.8.22" apply false + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false } include(":app") diff --git a/01-advanced-navigation/02-03-return-data/ios/Flutter/AppFrameworkInfo.plist b/01-advanced-navigation/02-03-return-data/ios/Flutter/AppFrameworkInfo.plist index 7c56964..1dc6cf7 100644 --- a/01-advanced-navigation/02-03-return-data/ios/Flutter/AppFrameworkInfo.plist +++ b/01-advanced-navigation/02-03-return-data/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/01-advanced-navigation/02-03-return-data/ios/Runner.xcodeproj/project.pbxproj b/01-advanced-navigation/02-03-return-data/ios/Runner.xcodeproj/project.pbxproj index 866b376..fee6cdd 100644 --- a/01-advanced-navigation/02-03-return-data/ios/Runner.xcodeproj/project.pbxproj +++ b/01-advanced-navigation/02-03-return-data/ios/Runner.xcodeproj/project.pbxproj @@ -346,7 +346,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -473,7 +473,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -524,7 +524,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/01-advanced-navigation/02-03-return-data/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/01-advanced-navigation/02-03-return-data/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15cada4..e3773d4 100644 --- a/01-advanced-navigation/02-03-return-data/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/01-advanced-navigation/02-03-return-data/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> =3.7.0 <4.0.0" + dart: ">=3.9.2 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/01-advanced-navigation/02-03-return-data/pubspec.yaml b/01-advanced-navigation/02-03-return-data/pubspec.yaml index 779e55b..40048b3 100644 --- a/01-advanced-navigation/02-03-return-data/pubspec.yaml +++ b/01-advanced-navigation/02-03-return-data/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ^3.7.0 + sdk: ^3.9.2 dependencies: flutter: diff --git a/01-advanced-navigation/03-redirection/.gitignore b/01-advanced-navigation/03-redirection/.gitignore index a8e938c..221b422 100644 --- a/01-advanced-navigation/03-redirection/.gitignore +++ b/01-advanced-navigation/03-redirection/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/01-advanced-navigation/03-redirection/android/gradle/wrapper/gradle-wrapper.properties b/01-advanced-navigation/03-redirection/android/gradle/wrapper/gradle-wrapper.properties index afa1e8e..ac3b479 100644 --- a/01-advanced-navigation/03-redirection/android/gradle/wrapper/gradle-wrapper.properties +++ b/01-advanced-navigation/03-redirection/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/01-advanced-navigation/03-redirection/android/settings.gradle.kts b/01-advanced-navigation/03-redirection/android/settings.gradle.kts index a439442..43394ed 100644 --- a/01-advanced-navigation/03-redirection/android/settings.gradle.kts +++ b/01-advanced-navigation/03-redirection/android/settings.gradle.kts @@ -18,8 +18,8 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.7.0" apply false - id("org.jetbrains.kotlin.android") version "1.8.22" apply false + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false } include(":app") diff --git a/01-advanced-navigation/03-redirection/ios/Flutter/AppFrameworkInfo.plist b/01-advanced-navigation/03-redirection/ios/Flutter/AppFrameworkInfo.plist index 7c56964..1dc6cf7 100644 --- a/01-advanced-navigation/03-redirection/ios/Flutter/AppFrameworkInfo.plist +++ b/01-advanced-navigation/03-redirection/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/01-advanced-navigation/03-redirection/ios/Podfile b/01-advanced-navigation/03-redirection/ios/Podfile index e549ee2..620e46e 100644 --- a/01-advanced-navigation/03-redirection/ios/Podfile +++ b/01-advanced-navigation/03-redirection/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '12.0' +# platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/01-advanced-navigation/03-redirection/ios/Podfile.lock b/01-advanced-navigation/03-redirection/ios/Podfile.lock new file mode 100644 index 0000000..952bce6 --- /dev/null +++ b/01-advanced-navigation/03-redirection/ios/Podfile.lock @@ -0,0 +1,23 @@ +PODS: + - Flutter (1.0.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - Flutter (from `Flutter`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + +SPEC CHECKSUMS: + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + +PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e + +COCOAPODS: 1.16.2 diff --git a/01-advanced-navigation/03-redirection/ios/Runner.xcodeproj/project.pbxproj b/01-advanced-navigation/03-redirection/ios/Runner.xcodeproj/project.pbxproj index 866b376..b541186 100644 --- a/01-advanced-navigation/03-redirection/ios/Runner.xcodeproj/project.pbxproj +++ b/01-advanced-navigation/03-redirection/ios/Runner.xcodeproj/project.pbxproj @@ -14,6 +14,8 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + BCF09B75B9C68E37A30F24BA /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 930914D7DA20712C630E24E8 /* Pods_RunnerTests.framework */; }; + F553CFCC9ECF959565A35AC8 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DB4D74838BAC6EEC3AD6841 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -40,14 +42,20 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0A169CBD9A0782A4CE873DC7 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2E65D3B4EA0BB7A61D7F5F6E /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 74D8DD3C1E66CFEA9FB4008C /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 870211AD99D988B88755DEAF /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 8DB4D74838BAC6EEC3AD6841 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 930914D7DA20712C630E24E8 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -55,13 +63,24 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + F1D830D517B5F8E319208804 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + FAD5611EABED42B669634DD9 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 23511686B71217080FD64429 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BCF09B75B9C68E37A30F24BA /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F553CFCC9ECF959565A35AC8 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -76,6 +95,20 @@ path = RunnerTests; sourceTree = ""; }; + 6C94985C3F7C914E2352FAC1 /* Pods */ = { + isa = PBXGroup; + children = ( + 2E65D3B4EA0BB7A61D7F5F6E /* Pods-Runner.debug.xcconfig */, + F1D830D517B5F8E319208804 /* Pods-Runner.release.xcconfig */, + 0A169CBD9A0782A4CE873DC7 /* Pods-Runner.profile.xcconfig */, + 74D8DD3C1E66CFEA9FB4008C /* Pods-RunnerTests.debug.xcconfig */, + 870211AD99D988B88755DEAF /* Pods-RunnerTests.release.xcconfig */, + FAD5611EABED42B669634DD9 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -94,6 +127,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + 6C94985C3F7C914E2352FAC1 /* Pods */, + CC939316E66B82DFB3894B3E /* Frameworks */, ); sourceTree = ""; }; @@ -121,6 +156,15 @@ path = Runner; sourceTree = ""; }; + CC939316E66B82DFB3894B3E /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8DB4D74838BAC6EEC3AD6841 /* Pods_Runner.framework */, + 930914D7DA20712C630E24E8 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -128,8 +172,10 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 973A0C8C659B61879E0A79A8 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + 23511686B71217080FD64429 /* Frameworks */, ); buildRules = ( ); @@ -145,12 +191,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 794DF0B8D9FE5C707F16F5F7 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + B0B959DCADA5846DBF98A6C8 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -238,6 +286,50 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 794DF0B8D9FE5C707F16F5F7 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 973A0C8C659B61879E0A79A8 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -253,6 +345,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + B0B959DCADA5846DBF98A6C8 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -346,7 +455,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -379,6 +488,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 74D8DD3C1E66CFEA9FB4008C /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -396,6 +506,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 870211AD99D988B88755DEAF /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -411,6 +522,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = FAD5611EABED42B669634DD9 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -473,7 +585,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -524,7 +636,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/01-advanced-navigation/03-redirection/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/01-advanced-navigation/03-redirection/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15cada4..e3773d4 100644 --- a/01-advanced-navigation/03-redirection/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/01-advanced-navigation/03-redirection/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> + + diff --git a/01-advanced-navigation/03-redirection/lib/routes/router_delegate.dart b/01-advanced-navigation/03-redirection/lib/routes/router_delegate.dart index 89345c3..60c6e25 100644 --- a/01-advanced-navigation/03-redirection/lib/routes/router_delegate.dart +++ b/01-advanced-navigation/03-redirection/lib/routes/router_delegate.dart @@ -13,9 +13,8 @@ class MyRouterDelegate extends RouterDelegate final GlobalKey _navigatorKey; final AuthRepository authRepository; - MyRouterDelegate( - this.authRepository, - ) : _navigatorKey = GlobalKey() { + MyRouterDelegate(this.authRepository) + : _navigatorKey = GlobalKey() { /// todo 9: create initial function to check user logged in. _init(); } @@ -55,10 +54,6 @@ class MyRouterDelegate extends RouterDelegate selectedQuote = null; notifyListeners(); } - if (page.key == const ValueKey("RegisterPage")) { - isRegister = false; - notifyListeners(); - } }, ); } @@ -70,67 +65,62 @@ class MyRouterDelegate extends RouterDelegate /// todo 12: add these variable to support history stack List get _splashStack => const [ - MaterialPage( - key: ValueKey("SplashScreen"), - child: SplashScreen(), - ), - ]; + MaterialPage(key: ValueKey("SplashScreen"), child: SplashScreen()), + ]; List get _loggedOutStack => [ - MaterialPage( - key: const ValueKey("LoginPage"), - child: LoginScreen( - /// todo 17: add onLogin and onRegister method to update the state - onLogin: () { - isLoggedIn = true; - notifyListeners(); - }, - onRegister: () { - isRegister = true; - notifyListeners(); - }, - ), + MaterialPage( + key: const ValueKey("LoginPage"), + child: LoginScreen( + /// todo 17: add onLogin and onRegister method to update the state + onLogin: () { + isLoggedIn = true; + notifyListeners(); + }, + onRegister: () { + isRegister = true; + notifyListeners(); + }, + ), + ), + if (isRegister == true) + MaterialPage( + key: const ValueKey("RegisterPage"), + child: RegisterScreen( + onRegister: () { + isRegister = false; + notifyListeners(); + }, + onLogin: () { + isRegister = false; + notifyListeners(); + }, ), - if (isRegister == true) - MaterialPage( - key: const ValueKey("RegisterPage"), - child: RegisterScreen( - onRegister: () { - isRegister = false; - notifyListeners(); - }, - onLogin: () { - isRegister = false; - notifyListeners(); - }, - ), - ), - ]; + ), + ]; List get _loggedInStack => [ - MaterialPage( - key: const ValueKey("QuotesListPage"), - child: QuotesListScreen( - quotes: quotes, - onTapped: (String quoteId) { - selectedQuote = quoteId; - notifyListeners(); - }, + MaterialPage( + key: const ValueKey("QuotesListPage"), + child: QuotesListScreen( + quotes: quotes, + onTapped: (String quoteId) { + selectedQuote = quoteId; + notifyListeners(); + }, - /// todo 21: add onLogout method to update the state and - /// create a logout button - onLogout: () { - isLoggedIn = false; - notifyListeners(); - }, - ), - ), - if (selectedQuote != null) - MaterialPage( - key: ValueKey(selectedQuote), - child: QuoteDetailsScreen( - quoteId: selectedQuote!, - ), - ), - ]; + /// todo 21: add onLogout method to update the state and + /// create a logout button + onLogout: () { + isLoggedIn = false; + notifyListeners(); + }, + ), + ), + if (selectedQuote != null) + MaterialPage( + key: ValueKey(selectedQuote), + child: QuoteDetailsScreen(quoteId: selectedQuote!), + ), + ]; } diff --git a/01-advanced-navigation/03-redirection/pubspec.lock b/01-advanced-navigation/03-redirection/pubspec.lock index 4e5c917..588f687 100644 --- a/01-advanced-navigation/03-redirection/pubspec.lock +++ b/01-advanced-navigation/03-redirection/pubspec.lock @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" ffi: dependency: transitive description: @@ -100,26 +100,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -329,18 +329,18 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -374,5 +374,5 @@ packages: source: hosted version: "0.2.0+2" sdks: - dart: ">=3.7.0 <4.0.0" + dart: ">=3.9.2 <4.0.0" flutter: ">=3.27.0" diff --git a/01-advanced-navigation/03-redirection/pubspec.yaml b/01-advanced-navigation/03-redirection/pubspec.yaml index 256cb18..2b3e427 100644 --- a/01-advanced-navigation/03-redirection/pubspec.yaml +++ b/01-advanced-navigation/03-redirection/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ^3.7.0 + sdk: ^3.9.2 dependencies: flutter: diff --git a/01-advanced-navigation/04-01-use-parameter/.gitignore b/01-advanced-navigation/04-01-use-parameter/.gitignore index a8e938c..221b422 100644 --- a/01-advanced-navigation/04-01-use-parameter/.gitignore +++ b/01-advanced-navigation/04-01-use-parameter/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/01-advanced-navigation/04-01-use-parameter/android/gradle/wrapper/gradle-wrapper.properties b/01-advanced-navigation/04-01-use-parameter/android/gradle/wrapper/gradle-wrapper.properties index afa1e8e..ac3b479 100644 --- a/01-advanced-navigation/04-01-use-parameter/android/gradle/wrapper/gradle-wrapper.properties +++ b/01-advanced-navigation/04-01-use-parameter/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/01-advanced-navigation/04-01-use-parameter/android/settings.gradle.kts b/01-advanced-navigation/04-01-use-parameter/android/settings.gradle.kts index a439442..43394ed 100644 --- a/01-advanced-navigation/04-01-use-parameter/android/settings.gradle.kts +++ b/01-advanced-navigation/04-01-use-parameter/android/settings.gradle.kts @@ -18,8 +18,8 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.7.0" apply false - id("org.jetbrains.kotlin.android") version "1.8.22" apply false + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false } include(":app") diff --git a/01-advanced-navigation/04-01-use-parameter/ios/Flutter/AppFrameworkInfo.plist b/01-advanced-navigation/04-01-use-parameter/ios/Flutter/AppFrameworkInfo.plist index 7c56964..1dc6cf7 100644 --- a/01-advanced-navigation/04-01-use-parameter/ios/Flutter/AppFrameworkInfo.plist +++ b/01-advanced-navigation/04-01-use-parameter/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/01-advanced-navigation/04-01-use-parameter/ios/Podfile b/01-advanced-navigation/04-01-use-parameter/ios/Podfile index e549ee2..620e46e 100644 --- a/01-advanced-navigation/04-01-use-parameter/ios/Podfile +++ b/01-advanced-navigation/04-01-use-parameter/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '12.0' +# platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/01-advanced-navigation/04-01-use-parameter/ios/Podfile.lock b/01-advanced-navigation/04-01-use-parameter/ios/Podfile.lock new file mode 100644 index 0000000..952bce6 --- /dev/null +++ b/01-advanced-navigation/04-01-use-parameter/ios/Podfile.lock @@ -0,0 +1,23 @@ +PODS: + - Flutter (1.0.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - Flutter (from `Flutter`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + +SPEC CHECKSUMS: + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + +PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e + +COCOAPODS: 1.16.2 diff --git a/01-advanced-navigation/04-01-use-parameter/ios/Runner.xcodeproj/project.pbxproj b/01-advanced-navigation/04-01-use-parameter/ios/Runner.xcodeproj/project.pbxproj index 866b376..3bc5646 100644 --- a/01-advanced-navigation/04-01-use-parameter/ios/Runner.xcodeproj/project.pbxproj +++ b/01-advanced-navigation/04-01-use-parameter/ios/Runner.xcodeproj/project.pbxproj @@ -10,6 +10,8 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 61A0AEA950BFD856F01D2DAF /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C5CD49EEBC8F2196CAE669A /* Pods_RunnerTests.framework */; }; + 6AF2BC197B76591E4389B464 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08915E54EAD55589CD237A93 /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; @@ -40,14 +42,21 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 01F6D9EF5A9B5A940797E148 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 08915E54EAD55589CD237A93 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3AD3D771BF23C22D52534C70 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 668C39052109BA5347857C91 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 68EB211DA5284B65E679DEAC /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 77EBCC9093874AF5BAA1D3DE /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 8C5CD49EEBC8F2196CAE669A /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -55,6 +64,7 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + F61C82B4620770765F731C0F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,6 +72,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 6AF2BC197B76591E4389B464 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D36D109436E1CA92629FFD57 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 61A0AEA950BFD856F01D2DAF /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -76,6 +95,29 @@ path = RunnerTests; sourceTree = ""; }; + 43F9F41F55BD0C942467CE6D /* Frameworks */ = { + isa = PBXGroup; + children = ( + 08915E54EAD55589CD237A93 /* Pods_Runner.framework */, + 8C5CD49EEBC8F2196CAE669A /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 8131077993529A94D9F281A2 /* Pods */ = { + isa = PBXGroup; + children = ( + 68EB211DA5284B65E679DEAC /* Pods-Runner.debug.xcconfig */, + 668C39052109BA5347857C91 /* Pods-Runner.release.xcconfig */, + F61C82B4620770765F731C0F /* Pods-Runner.profile.xcconfig */, + 3AD3D771BF23C22D52534C70 /* Pods-RunnerTests.debug.xcconfig */, + 01F6D9EF5A9B5A940797E148 /* Pods-RunnerTests.release.xcconfig */, + 77EBCC9093874AF5BAA1D3DE /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -94,6 +136,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + 8131077993529A94D9F281A2 /* Pods */, + 43F9F41F55BD0C942467CE6D /* Frameworks */, ); sourceTree = ""; }; @@ -128,8 +172,10 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + DC3F0CA7D8404ED750BA030F /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + D36D109436E1CA92629FFD57 /* Frameworks */, ); buildRules = ( ); @@ -145,12 +191,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 61C0BA536E80E786BC4A0AA9 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + A46A17A8ED969FFC8ADF2423 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -238,6 +286,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 61C0BA536E80E786BC4A0AA9 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -253,6 +323,45 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + A46A17A8ED969FFC8ADF2423 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + DC3F0CA7D8404ED750BA030F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -346,7 +455,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -379,6 +488,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 3AD3D771BF23C22D52534C70 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -396,6 +506,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 01F6D9EF5A9B5A940797E148 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -411,6 +522,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 77EBCC9093874AF5BAA1D3DE /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -473,7 +585,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -524,7 +636,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/01-advanced-navigation/04-01-use-parameter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/01-advanced-navigation/04-01-use-parameter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15cada4..e3773d4 100644 --- a/01-advanced-navigation/04-01-use-parameter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/01-advanced-navigation/04-01-use-parameter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> + + diff --git a/01-advanced-navigation/04-01-use-parameter/lib/routes/router_delegate.dart b/01-advanced-navigation/04-01-use-parameter/lib/routes/router_delegate.dart index cb78e0f..669ad43 100644 --- a/01-advanced-navigation/04-01-use-parameter/lib/routes/router_delegate.dart +++ b/01-advanced-navigation/04-01-use-parameter/lib/routes/router_delegate.dart @@ -58,10 +58,6 @@ class MyRouterDelegate extends RouterDelegate selectedQuote = null; notifyListeners(); } - if (page.key == const ValueKey("RegisterPage")) { - isRegister = false; - notifyListeners(); - } }, ); } diff --git a/01-advanced-navigation/04-01-use-parameter/pubspec.lock b/01-advanced-navigation/04-01-use-parameter/pubspec.lock index 1ecedb7..557590f 100644 --- a/01-advanced-navigation/04-01-use-parameter/pubspec.lock +++ b/01-advanced-navigation/04-01-use-parameter/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" ffi: dependency: transitive description: @@ -92,26 +92,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -321,18 +321,18 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -366,5 +366,5 @@ packages: source: hosted version: "0.2.0+2" sdks: - dart: ">=3.7.0 <4.0.0" + dart: ">=3.9.2 <4.0.0" flutter: ">=3.27.0" diff --git a/01-advanced-navigation/04-01-use-parameter/pubspec.yaml b/01-advanced-navigation/04-01-use-parameter/pubspec.yaml index 3e1de7f..935c07f 100644 --- a/01-advanced-navigation/04-01-use-parameter/pubspec.yaml +++ b/01-advanced-navigation/04-01-use-parameter/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ^3.7.0 + sdk: ^3.9.2 dependencies: flutter: diff --git a/01-advanced-navigation/04-02-url-path-strategy/.gitignore b/01-advanced-navigation/04-02-url-path-strategy/.gitignore index a8e938c..221b422 100644 --- a/01-advanced-navigation/04-02-url-path-strategy/.gitignore +++ b/01-advanced-navigation/04-02-url-path-strategy/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/01-advanced-navigation/04-02-url-path-strategy/android/gradle/wrapper/gradle-wrapper.properties b/01-advanced-navigation/04-02-url-path-strategy/android/gradle/wrapper/gradle-wrapper.properties index afa1e8e..ac3b479 100644 --- a/01-advanced-navigation/04-02-url-path-strategy/android/gradle/wrapper/gradle-wrapper.properties +++ b/01-advanced-navigation/04-02-url-path-strategy/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/01-advanced-navigation/04-02-url-path-strategy/android/settings.gradle.kts b/01-advanced-navigation/04-02-url-path-strategy/android/settings.gradle.kts index a439442..43394ed 100644 --- a/01-advanced-navigation/04-02-url-path-strategy/android/settings.gradle.kts +++ b/01-advanced-navigation/04-02-url-path-strategy/android/settings.gradle.kts @@ -18,8 +18,8 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.7.0" apply false - id("org.jetbrains.kotlin.android") version "1.8.22" apply false + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false } include(":app") diff --git a/01-advanced-navigation/04-02-url-path-strategy/ios/Flutter/AppFrameworkInfo.plist b/01-advanced-navigation/04-02-url-path-strategy/ios/Flutter/AppFrameworkInfo.plist index 7c56964..1dc6cf7 100644 --- a/01-advanced-navigation/04-02-url-path-strategy/ios/Flutter/AppFrameworkInfo.plist +++ b/01-advanced-navigation/04-02-url-path-strategy/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/01-advanced-navigation/04-02-url-path-strategy/ios/Podfile b/01-advanced-navigation/04-02-url-path-strategy/ios/Podfile index e549ee2..620e46e 100644 --- a/01-advanced-navigation/04-02-url-path-strategy/ios/Podfile +++ b/01-advanced-navigation/04-02-url-path-strategy/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '12.0' +# platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/01-advanced-navigation/04-02-url-path-strategy/ios/Podfile.lock b/01-advanced-navigation/04-02-url-path-strategy/ios/Podfile.lock new file mode 100644 index 0000000..952bce6 --- /dev/null +++ b/01-advanced-navigation/04-02-url-path-strategy/ios/Podfile.lock @@ -0,0 +1,23 @@ +PODS: + - Flutter (1.0.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - Flutter (from `Flutter`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + +SPEC CHECKSUMS: + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + +PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e + +COCOAPODS: 1.16.2 diff --git a/01-advanced-navigation/04-02-url-path-strategy/ios/Runner.xcodeproj/project.pbxproj b/01-advanced-navigation/04-02-url-path-strategy/ios/Runner.xcodeproj/project.pbxproj index 866b376..f14420f 100644 --- a/01-advanced-navigation/04-02-url-path-strategy/ios/Runner.xcodeproj/project.pbxproj +++ b/01-advanced-navigation/04-02-url-path-strategy/ios/Runner.xcodeproj/project.pbxproj @@ -14,6 +14,8 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + D77D08DCA40A01F179097372 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A180C25C865690F2A145184 /* Pods_RunnerTests.framework */; }; + E7E2B26B2CCFCB7CD53C444D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDCE67885AEF7FC0BD33FDF8 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -40,11 +42,17 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 01173065708CEA2B15CFD175 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 0AEC1137B7912D2FE885CFF8 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 0E5DB62967352D1A987F872A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2C7B470CA384639CBCCE9D6B /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 5A180C25C865690F2A145184 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5C35EDE9A6D3BF2E0AEED19D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -55,6 +63,8 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D0B156F17EC8BA5A063B55A2 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + EDCE67885AEF7FC0BD33FDF8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,12 +72,35 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E7E2B26B2CCFCB7CD53C444D /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9B969CD57050A27E0EE98180 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D77D08DCA40A01F179097372 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 05AF1BE960B75792F9968786 /* Pods */ = { + isa = PBXGroup; + children = ( + 5C35EDE9A6D3BF2E0AEED19D /* Pods-Runner.debug.xcconfig */, + 0E5DB62967352D1A987F872A /* Pods-Runner.release.xcconfig */, + 0AEC1137B7912D2FE885CFF8 /* Pods-Runner.profile.xcconfig */, + 01173065708CEA2B15CFD175 /* Pods-RunnerTests.debug.xcconfig */, + 2C7B470CA384639CBCCE9D6B /* Pods-RunnerTests.release.xcconfig */, + D0B156F17EC8BA5A063B55A2 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 331C8082294A63A400263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( @@ -76,6 +109,15 @@ path = RunnerTests; sourceTree = ""; }; + 51324E61778A67CC2F1F4A71 /* Frameworks */ = { + isa = PBXGroup; + children = ( + EDCE67885AEF7FC0BD33FDF8 /* Pods_Runner.framework */, + 5A180C25C865690F2A145184 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -94,6 +136,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + 05AF1BE960B75792F9968786 /* Pods */, + 51324E61778A67CC2F1F4A71 /* Frameworks */, ); sourceTree = ""; }; @@ -128,8 +172,10 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 8942EE3A88481511EAA554A5 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + 9B969CD57050A27E0EE98180 /* Frameworks */, ); buildRules = ( ); @@ -145,12 +191,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + E5FA844761827DDF95D3AE8B /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + D0A354A1E26A3E62410B9706 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -238,6 +286,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 8942EE3A88481511EAA554A5 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -253,6 +323,45 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + D0A354A1E26A3E62410B9706 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E5FA844761827DDF95D3AE8B /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -346,7 +455,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -379,6 +488,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 01173065708CEA2B15CFD175 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -396,6 +506,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 2C7B470CA384639CBCCE9D6B /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -411,6 +522,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = D0B156F17EC8BA5A063B55A2 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -473,7 +585,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -524,7 +636,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/01-advanced-navigation/04-02-url-path-strategy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/01-advanced-navigation/04-02-url-path-strategy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15cada4..e3773d4 100644 --- a/01-advanced-navigation/04-02-url-path-strategy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/01-advanced-navigation/04-02-url-path-strategy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> + + diff --git a/01-advanced-navigation/04-02-url-path-strategy/lib/routes/router_delegate.dart b/01-advanced-navigation/04-02-url-path-strategy/lib/routes/router_delegate.dart index 2896502..2ba3da3 100644 --- a/01-advanced-navigation/04-02-url-path-strategy/lib/routes/router_delegate.dart +++ b/01-advanced-navigation/04-02-url-path-strategy/lib/routes/router_delegate.dart @@ -55,10 +55,6 @@ class MyRouterDelegate extends RouterDelegate selectedQuote = null; notifyListeners(); } - if (isRegister) { - isRegister = false; - notifyListeners(); - } }, ); } diff --git a/01-advanced-navigation/04-02-url-path-strategy/pubspec.lock b/01-advanced-navigation/04-02-url-path-strategy/pubspec.lock index 5096601..e4b4ee0 100644 --- a/01-advanced-navigation/04-02-url-path-strategy/pubspec.lock +++ b/01-advanced-navigation/04-02-url-path-strategy/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" ffi: dependency: transitive description: @@ -92,26 +92,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -321,18 +321,18 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -366,5 +366,5 @@ packages: source: hosted version: "0.2.0+2" sdks: - dart: ">=3.7.0 <4.0.0" + dart: ">=3.9.2 <4.0.0" flutter: ">=3.27.0" diff --git a/01-advanced-navigation/04-02-url-path-strategy/pubspec.yaml b/01-advanced-navigation/04-02-url-path-strategy/pubspec.yaml index 3e7a25e..f6b8f81 100644 --- a/01-advanced-navigation/04-02-url-path-strategy/pubspec.yaml +++ b/01-advanced-navigation/04-02-url-path-strategy/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ^3.7.0 + sdk: ^3.9.2 dependencies: flutter: diff --git a/05-advanced-widget/01-animated_list_project/.gitignore b/05-advanced-widget/01-animated_list_project/.gitignore index 24476c5..6c31954 100644 --- a/05-advanced-widget/01-animated_list_project/.gitignore +++ b/05-advanced-widget/01-animated_list_project/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/05-advanced-widget/01-animated_list_project/.metadata b/05-advanced-widget/01-animated_list_project/.metadata index e1179a6..b11d65d 100644 --- a/05-advanced-widget/01-animated_list_project/.metadata +++ b/05-advanced-widget/01-animated_list_project/.metadata @@ -1,11 +1,11 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled. +# This file should be version controlled and should not be manually edited. version: - revision: 18a827f3933c19f51862dde3fa472197683249d6 - channel: stable + revision: "ac4e799d237041cf905519190471f657b657155a" + channel: "stable" project_type: app @@ -13,26 +13,26 @@ project_type: app migration: platforms: - platform: root - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: android - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: ios - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: linux - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: macos - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: web - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: windows - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a # User provided section diff --git a/05-advanced-widget/01-animated_list_project/android/.gitignore b/05-advanced-widget/01-animated_list_project/android/.gitignore index 6f56801..be3943c 100644 --- a/05-advanced-widget/01-animated_list_project/android/.gitignore +++ b/05-advanced-widget/01-animated_list_project/android/.gitignore @@ -5,9 +5,10 @@ gradle-wrapper.jar /gradlew.bat /local.properties GeneratedPluginRegistrant.java +.cxx/ # Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +# See https://flutter.dev/to/reference-keystore key.properties **/*.keystore **/*.jks diff --git a/05-advanced-widget/01-animated_list_project/android/app/build.gradle b/05-advanced-widget/01-animated_list_project/android/app/build.gradle deleted file mode 100644 index 19566f4..0000000 --- a/05-advanced-widget/01-animated_list_project/android/app/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion flutter.compileSdkVersion - ndkVersion flutter.ndkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.dicoding.animated_list_project" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion - targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/05-advanced-widget/01-animated_list_project/android/app/build.gradle.kts b/05-advanced-widget/01-animated_list_project/android/app/build.gradle.kts new file mode 100644 index 0000000..f360dc3 --- /dev/null +++ b/05-advanced-widget/01-animated_list_project/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.dicoding.animated_list_project" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.dicoding.animated_list_project" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/05-advanced-widget/01-animated_list_project/android/app/src/debug/AndroidManifest.xml b/05-advanced-widget/01-animated_list_project/android/app/src/debug/AndroidManifest.xml index 3d4e612..399f698 100644 --- a/05-advanced-widget/01-animated_list_project/android/app/src/debug/AndroidManifest.xml +++ b/05-advanced-widget/01-animated_list_project/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,4 @@ - + + + + + + + diff --git a/05-advanced-widget/01-animated_list_project/android/app/src/main/kotlin/com/dicoding/animated_list_project/MainActivity.kt b/05-advanced-widget/01-animated_list_project/android/app/src/main/kotlin/com/dicoding/animated_list_project/MainActivity.kt index 3b3adae..9327dc1 100644 --- a/05-advanced-widget/01-animated_list_project/android/app/src/main/kotlin/com/dicoding/animated_list_project/MainActivity.kt +++ b/05-advanced-widget/01-animated_list_project/android/app/src/main/kotlin/com/dicoding/animated_list_project/MainActivity.kt @@ -2,5 +2,4 @@ package com.dicoding.animated_list_project import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() { -} +class MainActivity : FlutterActivity() diff --git a/05-advanced-widget/01-animated_list_project/android/app/src/profile/AndroidManifest.xml b/05-advanced-widget/01-animated_list_project/android/app/src/profile/AndroidManifest.xml index 3d4e612..399f698 100644 --- a/05-advanced-widget/01-animated_list_project/android/app/src/profile/AndroidManifest.xml +++ b/05-advanced-widget/01-animated_list_project/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,4 @@ - + - + @@ -31,28 +31,8 @@ animated_list_project - - - - - + diff --git a/05-advanced-widget/01-animated_list_project/windows/CMakeLists.txt b/05-advanced-widget/01-animated_list_project/windows/CMakeLists.txt index 565bdca..e281ec6 100644 --- a/05-advanced-widget/01-animated_list_project/windows/CMakeLists.txt +++ b/05-advanced-widget/01-animated_list_project/windows/CMakeLists.txt @@ -8,7 +8,7 @@ set(BINARY_NAME "animated_list_project") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. -cmake_policy(SET CMP0063 NEW) +cmake_policy(VERSION 3.14...3.25) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -52,6 +52,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) # Application build; see runner/CMakeLists.txt. add_subdirectory("runner") + # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) @@ -86,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") diff --git a/05-advanced-widget/01-animated_list_project/windows/flutter/CMakeLists.txt b/05-advanced-widget/01-animated_list_project/windows/flutter/CMakeLists.txt index 930d207..903f489 100644 --- a/05-advanced-widget/01-animated_list_project/windows/flutter/CMakeLists.txt +++ b/05-advanced-widget/01-animated_list_project/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/05-advanced-widget/01-animated_list_project/windows/runner/CMakeLists.txt b/05-advanced-widget/01-animated_list_project/windows/runner/CMakeLists.txt index 17411a8..394917c 100644 --- a/05-advanced-widget/01-animated_list_project/windows/runner/CMakeLists.txt +++ b/05-advanced-widget/01-animated_list_project/windows/runner/CMakeLists.txt @@ -33,6 +33,7 @@ target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") # Add dependency libraries and include directories. Add any application-specific # dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") # Run the Flutter tool portions of the build. This must not be removed. diff --git a/05-advanced-widget/01-animated_list_project/windows/runner/Runner.rc b/05-advanced-widget/01-animated_list_project/windows/runner/Runner.rc index 506d38d..b843de0 100644 --- a/05-advanced-widget/01-animated_list_project/windows/runner/Runner.rc +++ b/05-advanced-widget/01-animated_list_project/windows/runner/Runner.rc @@ -93,7 +93,7 @@ BEGIN VALUE "FileDescription", "animated_list_project" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "animated_list_project" "\0" - VALUE "LegalCopyright", "Copyright (C) 2022 com.dicoding. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2025 com.dicoding. All rights reserved." "\0" VALUE "OriginalFilename", "animated_list_project.exe" "\0" VALUE "ProductName", "animated_list_project" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/05-advanced-widget/01-animated_list_project/windows/runner/flutter_window.cpp b/05-advanced-widget/01-animated_list_project/windows/runner/flutter_window.cpp index b43b909..955ee30 100644 --- a/05-advanced-widget/01-animated_list_project/windows/runner/flutter_window.cpp +++ b/05-advanced-widget/01-animated_list_project/windows/runner/flutter_window.cpp @@ -26,6 +26,16 @@ bool FlutterWindow::OnCreate() { } RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } diff --git a/05-advanced-widget/01-animated_list_project/windows/runner/main.cpp b/05-advanced-widget/01-animated_list_project/windows/runner/main.cpp index 8a89298..65c6e36 100644 --- a/05-advanced-widget/01-animated_list_project/windows/runner/main.cpp +++ b/05-advanced-widget/01-animated_list_project/windows/runner/main.cpp @@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"animated_list_project", origin, size)) { + if (!window.Create(L"animated_list_project", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/05-advanced-widget/01-animated_list_project/windows/runner/runner.exe.manifest b/05-advanced-widget/01-animated_list_project/windows/runner/runner.exe.manifest index a42ea76..153653e 100644 --- a/05-advanced-widget/01-animated_list_project/windows/runner/runner.exe.manifest +++ b/05-advanced-widget/01-animated_list_project/windows/runner/runner.exe.manifest @@ -9,12 +9,6 @@ - - - - - - diff --git a/05-advanced-widget/01-animated_list_project/windows/runner/utils.cpp b/05-advanced-widget/01-animated_list_project/windows/runner/utils.cpp index f5bf9fa..3a0b465 100644 --- a/05-advanced-widget/01-animated_list_project/windows/runner/utils.cpp +++ b/05-advanced-widget/01-animated_list_project/windows/runner/utils.cpp @@ -45,9 +45,11 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { if (utf16_string == nullptr) { return std::string(); } - int target_length = ::WideCharToMultiByte( + unsigned int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); std::string utf8_string; if (target_length == 0 || target_length > utf8_string.max_size()) { return utf8_string; @@ -55,8 +57,7 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, utf8_string.data(), - target_length, nullptr, nullptr); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/05-advanced-widget/01-animated_list_project/windows/runner/win32_window.cpp b/05-advanced-widget/01-animated_list_project/windows/runner/win32_window.cpp index c10f08d..60608d0 100644 --- a/05-advanced-widget/01-animated_list_project/windows/runner/win32_window.cpp +++ b/05-advanced-widget/01-animated_list_project/windows/runner/win32_window.cpp @@ -1,13 +1,31 @@ #include "win32_window.h" +#include #include #include "resource.h" namespace { +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + // The number of Win32Window objects that currently exist. static int g_active_window_count = 0; @@ -31,8 +49,8 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { GetProcAddress(user32_module, "EnableNonClientDpiScaling")); if (enable_non_client_dpi_scaling != nullptr) { enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); } + FreeLibrary(user32_module); } } // namespace @@ -42,7 +60,7 @@ class WindowClassRegistrar { public: ~WindowClassRegistrar() = default; - // Returns the singleton registar instance. + // Returns the singleton registrar instance. static WindowClassRegistrar* GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); @@ -102,9 +120,9 @@ Win32Window::~Win32Window() { Destroy(); } -bool Win32Window::CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size) { +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { Destroy(); const wchar_t* window_class = @@ -117,7 +135,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title, double scale_factor = dpi / 96.0; HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), Scale(size.width, scale_factor), Scale(size.height, scale_factor), nullptr, nullptr, GetModuleHandle(nullptr), this); @@ -126,9 +144,15 @@ bool Win32Window::CreateAndShow(const std::wstring& title, return false; } + UpdateTheme(window); + return OnCreate(); } +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + // static LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, @@ -188,6 +212,10 @@ Win32Window::MessageHandler(HWND hwnd, SetFocus(child_content_); } return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -243,3 +271,18 @@ bool Win32Window::OnCreate() { void Win32Window::OnDestroy() { // No-op; provided for subclasses. } + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/05-advanced-widget/01-animated_list_project/windows/runner/win32_window.h b/05-advanced-widget/01-animated_list_project/windows/runner/win32_window.h index 17ba431..e901dde 100644 --- a/05-advanced-widget/01-animated_list_project/windows/runner/win32_window.h +++ b/05-advanced-widget/01-animated_list_project/windows/runner/win32_window.h @@ -28,15 +28,16 @@ class Win32Window { Win32Window(); virtual ~Win32Window(); - // Creates and shows a win32 window with |title| and position and size using + // Creates a win32 window with |title| that is positioned and sized using // |origin| and |size|. New windows are created on the default monitor. Window // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size); + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); // Release OS resources associated with window. void Destroy(); @@ -76,7 +77,7 @@ class Win32Window { // OS callback called by message pump. Handles the WM_NCCREATE message which // is passed when the non-client area is being created and enables automatic // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by + // responds to changes in DPI. All other messages are handled by // MessageHandler. static LRESULT CALLBACK WndProc(HWND const window, UINT const message, @@ -86,6 +87,9 @@ class Win32Window { // Retrieves a class instance pointer for |window| static Win32Window* GetThisFromHandle(HWND const window) noexcept; + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + bool quit_on_close_ = false; // window handle for top level window. diff --git a/05-advanced-widget/02-animated_button_final/.gitignore b/05-advanced-widget/02-animated_button_final/.gitignore index 24476c5..6c31954 100644 --- a/05-advanced-widget/02-animated_button_final/.gitignore +++ b/05-advanced-widget/02-animated_button_final/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/05-advanced-widget/02-animated_button_final/.metadata b/05-advanced-widget/02-animated_button_final/.metadata index e1179a6..b11d65d 100644 --- a/05-advanced-widget/02-animated_button_final/.metadata +++ b/05-advanced-widget/02-animated_button_final/.metadata @@ -1,11 +1,11 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled. +# This file should be version controlled and should not be manually edited. version: - revision: 18a827f3933c19f51862dde3fa472197683249d6 - channel: stable + revision: "ac4e799d237041cf905519190471f657b657155a" + channel: "stable" project_type: app @@ -13,26 +13,26 @@ project_type: app migration: platforms: - platform: root - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: android - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: ios - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: linux - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: macos - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: web - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: windows - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a # User provided section diff --git a/05-advanced-widget/02-animated_button_final/android/.gitignore b/05-advanced-widget/02-animated_button_final/android/.gitignore index 6f56801..be3943c 100644 --- a/05-advanced-widget/02-animated_button_final/android/.gitignore +++ b/05-advanced-widget/02-animated_button_final/android/.gitignore @@ -5,9 +5,10 @@ gradle-wrapper.jar /gradlew.bat /local.properties GeneratedPluginRegistrant.java +.cxx/ # Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +# See https://flutter.dev/to/reference-keystore key.properties **/*.keystore **/*.jks diff --git a/05-advanced-widget/02-animated_button_final/android/app/build.gradle b/05-advanced-widget/02-animated_button_final/android/app/build.gradle deleted file mode 100644 index 6998b3e..0000000 --- a/05-advanced-widget/02-animated_button_final/android/app/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion flutter.compileSdkVersion - ndkVersion flutter.ndkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.animated_button" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion - targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/05-advanced-widget/02-animated_button_final/android/app/build.gradle.kts b/05-advanced-widget/02-animated_button_final/android/app/build.gradle.kts new file mode 100644 index 0000000..2ed6efb --- /dev/null +++ b/05-advanced-widget/02-animated_button_final/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.dicoding.animated_button" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.dicoding.animated_button" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/05-advanced-widget/02-animated_button_final/android/app/src/debug/AndroidManifest.xml b/05-advanced-widget/02-animated_button_final/android/app/src/debug/AndroidManifest.xml index 39825d1..399f698 100644 --- a/05-advanced-widget/02-animated_button_final/android/app/src/debug/AndroidManifest.xml +++ b/05-advanced-widget/02-animated_button_final/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,4 @@ - + + + + + + + diff --git a/05-advanced-widget/02-animated_button_final/android/app/src/main/kotlin/com/dicoding/animated_button/MainActivity.kt b/05-advanced-widget/02-animated_button_final/android/app/src/main/kotlin/com/dicoding/animated_button/MainActivity.kt new file mode 100644 index 0000000..72714cf --- /dev/null +++ b/05-advanced-widget/02-animated_button_final/android/app/src/main/kotlin/com/dicoding/animated_button/MainActivity.kt @@ -0,0 +1,5 @@ +package com.dicoding.animated_button + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/05-advanced-widget/02-animated_button_final/android/app/src/main/kotlin/com/example/animated_button/MainActivity.kt b/05-advanced-widget/02-animated_button_final/android/app/src/main/kotlin/com/example/animated_button/MainActivity.kt deleted file mode 100644 index cac4d02..0000000 --- a/05-advanced-widget/02-animated_button_final/android/app/src/main/kotlin/com/example/animated_button/MainActivity.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.example.animated_button - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() { -} diff --git a/05-advanced-widget/02-animated_button_final/android/app/src/profile/AndroidManifest.xml b/05-advanced-widget/02-animated_button_final/android/app/src/profile/AndroidManifest.xml index 39825d1..399f698 100644 --- a/05-advanced-widget/02-animated_button_final/android/app/src/profile/AndroidManifest.xml +++ b/05-advanced-widget/02-animated_button_final/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,4 @@ - + - + @@ -31,28 +31,8 @@ animated_button - - - - - + diff --git a/05-advanced-widget/02-animated_button_final/windows/CMakeLists.txt b/05-advanced-widget/02-animated_button_final/windows/CMakeLists.txt index 61a022a..c5d37d4 100644 --- a/05-advanced-widget/02-animated_button_final/windows/CMakeLists.txt +++ b/05-advanced-widget/02-animated_button_final/windows/CMakeLists.txt @@ -8,7 +8,7 @@ set(BINARY_NAME "animated_button") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. -cmake_policy(SET CMP0063 NEW) +cmake_policy(VERSION 3.14...3.25) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -52,6 +52,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) # Application build; see runner/CMakeLists.txt. add_subdirectory("runner") + # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) @@ -86,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") diff --git a/05-advanced-widget/02-animated_button_final/windows/flutter/CMakeLists.txt b/05-advanced-widget/02-animated_button_final/windows/flutter/CMakeLists.txt index 930d207..903f489 100644 --- a/05-advanced-widget/02-animated_button_final/windows/flutter/CMakeLists.txt +++ b/05-advanced-widget/02-animated_button_final/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/05-advanced-widget/02-animated_button_final/windows/runner/CMakeLists.txt b/05-advanced-widget/02-animated_button_final/windows/runner/CMakeLists.txt index 17411a8..394917c 100644 --- a/05-advanced-widget/02-animated_button_final/windows/runner/CMakeLists.txt +++ b/05-advanced-widget/02-animated_button_final/windows/runner/CMakeLists.txt @@ -33,6 +33,7 @@ target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") # Add dependency libraries and include directories. Add any application-specific # dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") # Run the Flutter tool portions of the build. This must not be removed. diff --git a/05-advanced-widget/02-animated_button_final/windows/runner/Runner.rc b/05-advanced-widget/02-animated_button_final/windows/runner/Runner.rc index 1a9a404..4f71a91 100644 --- a/05-advanced-widget/02-animated_button_final/windows/runner/Runner.rc +++ b/05-advanced-widget/02-animated_button_final/windows/runner/Runner.rc @@ -89,11 +89,11 @@ BEGIN BEGIN BLOCK "040904e4" BEGIN - VALUE "CompanyName", "com.example" "\0" + VALUE "CompanyName", "com.dicoding" "\0" VALUE "FileDescription", "animated_button" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "animated_button" "\0" - VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2025 com.dicoding. All rights reserved." "\0" VALUE "OriginalFilename", "animated_button.exe" "\0" VALUE "ProductName", "animated_button" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/05-advanced-widget/02-animated_button_final/windows/runner/flutter_window.cpp b/05-advanced-widget/02-animated_button_final/windows/runner/flutter_window.cpp index b43b909..955ee30 100644 --- a/05-advanced-widget/02-animated_button_final/windows/runner/flutter_window.cpp +++ b/05-advanced-widget/02-animated_button_final/windows/runner/flutter_window.cpp @@ -26,6 +26,16 @@ bool FlutterWindow::OnCreate() { } RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } diff --git a/05-advanced-widget/02-animated_button_final/windows/runner/main.cpp b/05-advanced-widget/02-animated_button_final/windows/runner/main.cpp index 63c8ea8..f745454 100644 --- a/05-advanced-widget/02-animated_button_final/windows/runner/main.cpp +++ b/05-advanced-widget/02-animated_button_final/windows/runner/main.cpp @@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"animated_button", origin, size)) { + if (!window.Create(L"animated_button", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/05-advanced-widget/02-animated_button_final/windows/runner/runner.exe.manifest b/05-advanced-widget/02-animated_button_final/windows/runner/runner.exe.manifest index a42ea76..153653e 100644 --- a/05-advanced-widget/02-animated_button_final/windows/runner/runner.exe.manifest +++ b/05-advanced-widget/02-animated_button_final/windows/runner/runner.exe.manifest @@ -9,12 +9,6 @@ - - - - - - diff --git a/05-advanced-widget/02-animated_button_final/windows/runner/utils.cpp b/05-advanced-widget/02-animated_button_final/windows/runner/utils.cpp index f5bf9fa..3a0b465 100644 --- a/05-advanced-widget/02-animated_button_final/windows/runner/utils.cpp +++ b/05-advanced-widget/02-animated_button_final/windows/runner/utils.cpp @@ -45,9 +45,11 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { if (utf16_string == nullptr) { return std::string(); } - int target_length = ::WideCharToMultiByte( + unsigned int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); std::string utf8_string; if (target_length == 0 || target_length > utf8_string.max_size()) { return utf8_string; @@ -55,8 +57,7 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, utf8_string.data(), - target_length, nullptr, nullptr); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/05-advanced-widget/02-animated_button_final/windows/runner/win32_window.cpp b/05-advanced-widget/02-animated_button_final/windows/runner/win32_window.cpp index c10f08d..60608d0 100644 --- a/05-advanced-widget/02-animated_button_final/windows/runner/win32_window.cpp +++ b/05-advanced-widget/02-animated_button_final/windows/runner/win32_window.cpp @@ -1,13 +1,31 @@ #include "win32_window.h" +#include #include #include "resource.h" namespace { +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + // The number of Win32Window objects that currently exist. static int g_active_window_count = 0; @@ -31,8 +49,8 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { GetProcAddress(user32_module, "EnableNonClientDpiScaling")); if (enable_non_client_dpi_scaling != nullptr) { enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); } + FreeLibrary(user32_module); } } // namespace @@ -42,7 +60,7 @@ class WindowClassRegistrar { public: ~WindowClassRegistrar() = default; - // Returns the singleton registar instance. + // Returns the singleton registrar instance. static WindowClassRegistrar* GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); @@ -102,9 +120,9 @@ Win32Window::~Win32Window() { Destroy(); } -bool Win32Window::CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size) { +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { Destroy(); const wchar_t* window_class = @@ -117,7 +135,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title, double scale_factor = dpi / 96.0; HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), Scale(size.width, scale_factor), Scale(size.height, scale_factor), nullptr, nullptr, GetModuleHandle(nullptr), this); @@ -126,9 +144,15 @@ bool Win32Window::CreateAndShow(const std::wstring& title, return false; } + UpdateTheme(window); + return OnCreate(); } +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + // static LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, @@ -188,6 +212,10 @@ Win32Window::MessageHandler(HWND hwnd, SetFocus(child_content_); } return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -243,3 +271,18 @@ bool Win32Window::OnCreate() { void Win32Window::OnDestroy() { // No-op; provided for subclasses. } + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/05-advanced-widget/02-animated_button_final/windows/runner/win32_window.h b/05-advanced-widget/02-animated_button_final/windows/runner/win32_window.h index 17ba431..e901dde 100644 --- a/05-advanced-widget/02-animated_button_final/windows/runner/win32_window.h +++ b/05-advanced-widget/02-animated_button_final/windows/runner/win32_window.h @@ -28,15 +28,16 @@ class Win32Window { Win32Window(); virtual ~Win32Window(); - // Creates and shows a win32 window with |title| and position and size using + // Creates a win32 window with |title| that is positioned and sized using // |origin| and |size|. New windows are created on the default monitor. Window // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size); + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); // Release OS resources associated with window. void Destroy(); @@ -76,7 +77,7 @@ class Win32Window { // OS callback called by message pump. Handles the WM_NCCREATE message which // is passed when the non-client area is being created and enables automatic // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by + // responds to changes in DPI. All other messages are handled by // MessageHandler. static LRESULT CALLBACK WndProc(HWND const window, UINT const message, @@ -86,6 +87,9 @@ class Win32Window { // Retrieves a class instance pointer for |window| static Win32Window* GetThisFromHandle(HWND const window) noexcept; + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + bool quit_on_close_ = false; // window handle for top level window. diff --git a/05-advanced-widget/02-animated_button_starter/.gitignore b/05-advanced-widget/02-animated_button_starter/.gitignore index 24476c5..6c31954 100644 --- a/05-advanced-widget/02-animated_button_starter/.gitignore +++ b/05-advanced-widget/02-animated_button_starter/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/05-advanced-widget/02-animated_button_starter/.metadata b/05-advanced-widget/02-animated_button_starter/.metadata index e1179a6..b11d65d 100644 --- a/05-advanced-widget/02-animated_button_starter/.metadata +++ b/05-advanced-widget/02-animated_button_starter/.metadata @@ -1,11 +1,11 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled. +# This file should be version controlled and should not be manually edited. version: - revision: 18a827f3933c19f51862dde3fa472197683249d6 - channel: stable + revision: "ac4e799d237041cf905519190471f657b657155a" + channel: "stable" project_type: app @@ -13,26 +13,26 @@ project_type: app migration: platforms: - platform: root - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: android - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: ios - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: linux - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: macos - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: web - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: windows - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a # User provided section diff --git a/05-advanced-widget/02-animated_button_starter/android/.gitignore b/05-advanced-widget/02-animated_button_starter/android/.gitignore index 6f56801..be3943c 100644 --- a/05-advanced-widget/02-animated_button_starter/android/.gitignore +++ b/05-advanced-widget/02-animated_button_starter/android/.gitignore @@ -5,9 +5,10 @@ gradle-wrapper.jar /gradlew.bat /local.properties GeneratedPluginRegistrant.java +.cxx/ # Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +# See https://flutter.dev/to/reference-keystore key.properties **/*.keystore **/*.jks diff --git a/05-advanced-widget/02-animated_button_starter/android/app/build.gradle b/05-advanced-widget/02-animated_button_starter/android/app/build.gradle deleted file mode 100644 index 6998b3e..0000000 --- a/05-advanced-widget/02-animated_button_starter/android/app/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion flutter.compileSdkVersion - ndkVersion flutter.ndkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.animated_button" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion - targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/05-advanced-widget/02-animated_button_starter/android/app/build.gradle.kts b/05-advanced-widget/02-animated_button_starter/android/app/build.gradle.kts new file mode 100644 index 0000000..2ed6efb --- /dev/null +++ b/05-advanced-widget/02-animated_button_starter/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.dicoding.animated_button" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.dicoding.animated_button" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/05-advanced-widget/02-animated_button_starter/android/app/src/debug/AndroidManifest.xml b/05-advanced-widget/02-animated_button_starter/android/app/src/debug/AndroidManifest.xml index 39825d1..399f698 100644 --- a/05-advanced-widget/02-animated_button_starter/android/app/src/debug/AndroidManifest.xml +++ b/05-advanced-widget/02-animated_button_starter/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,4 @@ - + + + + + + + diff --git a/05-advanced-widget/02-animated_button_starter/android/app/src/main/kotlin/com/dicoding/animated_button/MainActivity.kt b/05-advanced-widget/02-animated_button_starter/android/app/src/main/kotlin/com/dicoding/animated_button/MainActivity.kt new file mode 100644 index 0000000..72714cf --- /dev/null +++ b/05-advanced-widget/02-animated_button_starter/android/app/src/main/kotlin/com/dicoding/animated_button/MainActivity.kt @@ -0,0 +1,5 @@ +package com.dicoding.animated_button + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/05-advanced-widget/02-animated_button_starter/android/app/src/main/kotlin/com/example/animated_button/MainActivity.kt b/05-advanced-widget/02-animated_button_starter/android/app/src/main/kotlin/com/example/animated_button/MainActivity.kt deleted file mode 100644 index cac4d02..0000000 --- a/05-advanced-widget/02-animated_button_starter/android/app/src/main/kotlin/com/example/animated_button/MainActivity.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.example.animated_button - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() { -} diff --git a/05-advanced-widget/02-animated_button_starter/android/app/src/profile/AndroidManifest.xml b/05-advanced-widget/02-animated_button_starter/android/app/src/profile/AndroidManifest.xml index 39825d1..399f698 100644 --- a/05-advanced-widget/02-animated_button_starter/android/app/src/profile/AndroidManifest.xml +++ b/05-advanced-widget/02-animated_button_starter/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,4 @@ - + - + @@ -31,28 +31,8 @@ animated_button - - - - - + diff --git a/05-advanced-widget/02-animated_button_starter/windows/CMakeLists.txt b/05-advanced-widget/02-animated_button_starter/windows/CMakeLists.txt index 61a022a..c5d37d4 100644 --- a/05-advanced-widget/02-animated_button_starter/windows/CMakeLists.txt +++ b/05-advanced-widget/02-animated_button_starter/windows/CMakeLists.txt @@ -8,7 +8,7 @@ set(BINARY_NAME "animated_button") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. -cmake_policy(SET CMP0063 NEW) +cmake_policy(VERSION 3.14...3.25) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -52,6 +52,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) # Application build; see runner/CMakeLists.txt. add_subdirectory("runner") + # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) @@ -86,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") diff --git a/05-advanced-widget/02-animated_button_starter/windows/flutter/CMakeLists.txt b/05-advanced-widget/02-animated_button_starter/windows/flutter/CMakeLists.txt index 930d207..903f489 100644 --- a/05-advanced-widget/02-animated_button_starter/windows/flutter/CMakeLists.txt +++ b/05-advanced-widget/02-animated_button_starter/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/05-advanced-widget/02-animated_button_starter/windows/runner/CMakeLists.txt b/05-advanced-widget/02-animated_button_starter/windows/runner/CMakeLists.txt index 17411a8..394917c 100644 --- a/05-advanced-widget/02-animated_button_starter/windows/runner/CMakeLists.txt +++ b/05-advanced-widget/02-animated_button_starter/windows/runner/CMakeLists.txt @@ -33,6 +33,7 @@ target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") # Add dependency libraries and include directories. Add any application-specific # dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") # Run the Flutter tool portions of the build. This must not be removed. diff --git a/05-advanced-widget/02-animated_button_starter/windows/runner/Runner.rc b/05-advanced-widget/02-animated_button_starter/windows/runner/Runner.rc index 1a9a404..4f71a91 100644 --- a/05-advanced-widget/02-animated_button_starter/windows/runner/Runner.rc +++ b/05-advanced-widget/02-animated_button_starter/windows/runner/Runner.rc @@ -89,11 +89,11 @@ BEGIN BEGIN BLOCK "040904e4" BEGIN - VALUE "CompanyName", "com.example" "\0" + VALUE "CompanyName", "com.dicoding" "\0" VALUE "FileDescription", "animated_button" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "animated_button" "\0" - VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2025 com.dicoding. All rights reserved." "\0" VALUE "OriginalFilename", "animated_button.exe" "\0" VALUE "ProductName", "animated_button" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/05-advanced-widget/02-animated_button_starter/windows/runner/flutter_window.cpp b/05-advanced-widget/02-animated_button_starter/windows/runner/flutter_window.cpp index b43b909..955ee30 100644 --- a/05-advanced-widget/02-animated_button_starter/windows/runner/flutter_window.cpp +++ b/05-advanced-widget/02-animated_button_starter/windows/runner/flutter_window.cpp @@ -26,6 +26,16 @@ bool FlutterWindow::OnCreate() { } RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } diff --git a/05-advanced-widget/02-animated_button_starter/windows/runner/main.cpp b/05-advanced-widget/02-animated_button_starter/windows/runner/main.cpp index 63c8ea8..f745454 100644 --- a/05-advanced-widget/02-animated_button_starter/windows/runner/main.cpp +++ b/05-advanced-widget/02-animated_button_starter/windows/runner/main.cpp @@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"animated_button", origin, size)) { + if (!window.Create(L"animated_button", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/05-advanced-widget/02-animated_button_starter/windows/runner/runner.exe.manifest b/05-advanced-widget/02-animated_button_starter/windows/runner/runner.exe.manifest index a42ea76..153653e 100644 --- a/05-advanced-widget/02-animated_button_starter/windows/runner/runner.exe.manifest +++ b/05-advanced-widget/02-animated_button_starter/windows/runner/runner.exe.manifest @@ -9,12 +9,6 @@ - - - - - - diff --git a/05-advanced-widget/02-animated_button_starter/windows/runner/utils.cpp b/05-advanced-widget/02-animated_button_starter/windows/runner/utils.cpp index f5bf9fa..3a0b465 100644 --- a/05-advanced-widget/02-animated_button_starter/windows/runner/utils.cpp +++ b/05-advanced-widget/02-animated_button_starter/windows/runner/utils.cpp @@ -45,9 +45,11 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { if (utf16_string == nullptr) { return std::string(); } - int target_length = ::WideCharToMultiByte( + unsigned int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); std::string utf8_string; if (target_length == 0 || target_length > utf8_string.max_size()) { return utf8_string; @@ -55,8 +57,7 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, utf8_string.data(), - target_length, nullptr, nullptr); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/05-advanced-widget/02-animated_button_starter/windows/runner/win32_window.cpp b/05-advanced-widget/02-animated_button_starter/windows/runner/win32_window.cpp index c10f08d..60608d0 100644 --- a/05-advanced-widget/02-animated_button_starter/windows/runner/win32_window.cpp +++ b/05-advanced-widget/02-animated_button_starter/windows/runner/win32_window.cpp @@ -1,13 +1,31 @@ #include "win32_window.h" +#include #include #include "resource.h" namespace { +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + // The number of Win32Window objects that currently exist. static int g_active_window_count = 0; @@ -31,8 +49,8 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { GetProcAddress(user32_module, "EnableNonClientDpiScaling")); if (enable_non_client_dpi_scaling != nullptr) { enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); } + FreeLibrary(user32_module); } } // namespace @@ -42,7 +60,7 @@ class WindowClassRegistrar { public: ~WindowClassRegistrar() = default; - // Returns the singleton registar instance. + // Returns the singleton registrar instance. static WindowClassRegistrar* GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); @@ -102,9 +120,9 @@ Win32Window::~Win32Window() { Destroy(); } -bool Win32Window::CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size) { +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { Destroy(); const wchar_t* window_class = @@ -117,7 +135,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title, double scale_factor = dpi / 96.0; HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), Scale(size.width, scale_factor), Scale(size.height, scale_factor), nullptr, nullptr, GetModuleHandle(nullptr), this); @@ -126,9 +144,15 @@ bool Win32Window::CreateAndShow(const std::wstring& title, return false; } + UpdateTheme(window); + return OnCreate(); } +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + // static LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, @@ -188,6 +212,10 @@ Win32Window::MessageHandler(HWND hwnd, SetFocus(child_content_); } return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -243,3 +271,18 @@ bool Win32Window::OnCreate() { void Win32Window::OnDestroy() { // No-op; provided for subclasses. } + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/05-advanced-widget/02-animated_button_starter/windows/runner/win32_window.h b/05-advanced-widget/02-animated_button_starter/windows/runner/win32_window.h index 17ba431..e901dde 100644 --- a/05-advanced-widget/02-animated_button_starter/windows/runner/win32_window.h +++ b/05-advanced-widget/02-animated_button_starter/windows/runner/win32_window.h @@ -28,15 +28,16 @@ class Win32Window { Win32Window(); virtual ~Win32Window(); - // Creates and shows a win32 window with |title| and position and size using + // Creates a win32 window with |title| that is positioned and sized using // |origin| and |size|. New windows are created on the default monitor. Window // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size); + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); // Release OS resources associated with window. void Destroy(); @@ -76,7 +77,7 @@ class Win32Window { // OS callback called by message pump. Handles the WM_NCCREATE message which // is passed when the non-client area is being created and enables automatic // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by + // responds to changes in DPI. All other messages are handled by // MessageHandler. static LRESULT CALLBACK WndProc(HWND const window, UINT const message, @@ -86,6 +87,9 @@ class Win32Window { // Retrieves a class instance pointer for |window| static Win32Window* GetThisFromHandle(HWND const window) noexcept; + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + bool quit_on_close_ = false; // window handle for top level window. diff --git a/05-advanced-widget/03-custom_painter_project/.gitignore b/05-advanced-widget/03-custom_painter_project/.gitignore index 24476c5..6c31954 100644 --- a/05-advanced-widget/03-custom_painter_project/.gitignore +++ b/05-advanced-widget/03-custom_painter_project/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/05-advanced-widget/03-custom_painter_project/.metadata b/05-advanced-widget/03-custom_painter_project/.metadata index e1179a6..b11d65d 100644 --- a/05-advanced-widget/03-custom_painter_project/.metadata +++ b/05-advanced-widget/03-custom_painter_project/.metadata @@ -1,11 +1,11 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled. +# This file should be version controlled and should not be manually edited. version: - revision: 18a827f3933c19f51862dde3fa472197683249d6 - channel: stable + revision: "ac4e799d237041cf905519190471f657b657155a" + channel: "stable" project_type: app @@ -13,26 +13,26 @@ project_type: app migration: platforms: - platform: root - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: android - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: ios - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: linux - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: macos - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: web - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: windows - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a # User provided section diff --git a/05-advanced-widget/03-custom_painter_project/android/app/build.gradle.kts b/05-advanced-widget/03-custom_painter_project/android/app/build.gradle.kts new file mode 100644 index 0000000..1ecd185 --- /dev/null +++ b/05-advanced-widget/03-custom_painter_project/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.dicoding.custom_painter_project" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.dicoding.custom_painter_project" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/05-advanced-widget/03-custom_painter_project/android/build.gradle.kts b/05-advanced-widget/03-custom_painter_project/android/build.gradle.kts new file mode 100644 index 0000000..dbee657 --- /dev/null +++ b/05-advanced-widget/03-custom_painter_project/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/05-advanced-widget/03-custom_painter_project/android/gradle/wrapper/gradle-wrapper.properties b/05-advanced-widget/03-custom_painter_project/android/gradle/wrapper/gradle-wrapper.properties index cb24abd..ac3b479 100644 --- a/05-advanced-widget/03-custom_painter_project/android/gradle/wrapper/gradle-wrapper.properties +++ b/05-advanced-widget/03-custom_painter_project/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/05-advanced-widget/03-custom_painter_project/android/settings.gradle.kts b/05-advanced-widget/03-custom_painter_project/android/settings.gradle.kts new file mode 100644 index 0000000..fb605bc --- /dev/null +++ b/05-advanced-widget/03-custom_painter_project/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false +} + +include(":app") diff --git a/05-advanced-widget/03-custom_painter_project/ios/Flutter/AppFrameworkInfo.plist b/05-advanced-widget/03-custom_painter_project/ios/Flutter/AppFrameworkInfo.plist index 9625e10..1dc6cf7 100644 --- a/05-advanced-widget/03-custom_painter_project/ios/Flutter/AppFrameworkInfo.plist +++ b/05-advanced-widget/03-custom_painter_project/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 13.0 diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner.xcodeproj/project.pbxproj b/05-advanced-widget/03-custom_painter_project/ios/Runner.xcodeproj/project.pbxproj index e307070..05f9f26 100644 --- a/05-advanced-widget/03-custom_painter_project/ios/Runner.xcodeproj/project.pbxproj +++ b/05-advanced-widget/03-custom_painter_project/ios/Runner.xcodeproj/project.pbxproj @@ -3,11 +3,12 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -15,6 +16,16 @@ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -31,6 +42,8 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -55,6 +68,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -72,6 +93,7 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, ); sourceTree = ""; }; @@ -79,6 +101,7 @@ isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, ); name = Products; sourceTree = ""; @@ -101,6 +124,23 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; @@ -127,9 +167,14 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; @@ -150,11 +195,19 @@ projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -171,10 +224,12 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -185,6 +240,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -200,6 +256,14 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -211,6 +275,14 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -235,6 +307,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -264,6 +337,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -272,7 +346,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -302,10 +376,58 @@ }; name = Profile; }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.dicoding.customPainterProject.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.dicoding.customPainterProject.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.dicoding.customPainterProject.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -335,6 +457,7 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -349,7 +472,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -361,6 +484,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -390,6 +514,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -398,7 +523,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -455,6 +580,16 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/05-advanced-widget/03-custom_painter_project/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a..e3773d4 100644 --- a/05-advanced-widget/03-custom_painter_project/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/05-advanced-widget/03-custom_painter_project/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + + + + diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/AppDelegate.swift b/05-advanced-widget/03-custom_painter_project/ios/Runner/AppDelegate.swift index 70693e4..6266644 100644 --- a/05-advanced-widget/03-custom_painter_project/ios/Runner/AppDelegate.swift +++ b/05-advanced-widget/03-custom_painter_project/ios/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ -import UIKit import Flutter +import UIKit -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 28c6bf0..7353c41 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 2ccbfd9..797d452 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index f091b6b..6ed2d93 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 4cde121..4cd7b00 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index d0ef06e..fe73094 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index dcdc230..321773c 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 2ccbfd9..797d452 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index c8f9ed8..502f463 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index a6d6b86..0ec3034 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index a6d6b86..0ec3034 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 75b2d16..e9f5fea 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index c4df70d..84ac32a 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 6a84f41..8953cba 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index d0e1f58..0467bf1 100644 Binary files a/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/05-advanced-widget/03-custom_painter_project/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/05-advanced-widget/03-custom_painter_project/ios/Runner/Info.plist b/05-advanced-widget/03-custom_painter_project/ios/Runner/Info.plist index 838f34e..244f6b3 100644 --- a/05-advanced-widget/03-custom_painter_project/ios/Runner/Info.plist +++ b/05-advanced-widget/03-custom_painter_project/ios/Runner/Info.plist @@ -41,8 +41,6 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - UIViewControllerBasedStatusBarAppearance - CADisableMinimumFrameDurationOnPhone UIApplicationSupportsIndirectInputEvents diff --git a/05-advanced-widget/03-custom_painter_project/ios/RunnerTests/RunnerTests.swift b/05-advanced-widget/03-custom_painter_project/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/05-advanced-widget/03-custom_painter_project/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/05-advanced-widget/03-custom_painter_project/linux/CMakeLists.txt b/05-advanced-widget/03-custom_painter_project/linux/CMakeLists.txt index ccfc0ce..e051a2f 100644 --- a/05-advanced-widget/03-custom_painter_project/linux/CMakeLists.txt +++ b/05-advanced-widget/03-custom_painter_project/linux/CMakeLists.txt @@ -1,5 +1,5 @@ # Project-level configuration. -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13) project(runner LANGUAGES CXX) # The name of the executable created for the application. Change this to change @@ -54,25 +54,8 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) -add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") - -# Define the application target. To change its name, change BINARY_NAME above, -# not the value here, or `flutter run` will no longer work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add dependency libraries. Add any application-specific dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter) -target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") # Run the Flutter tool portions of the build. This must not be removed. add_dependencies(${BINARY_NAME} flutter_assemble) @@ -86,6 +69,7 @@ set_target_properties(${BINARY_NAME} RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" ) + # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) @@ -122,6 +106,12 @@ foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) COMPONENT Runtime) endforeach(bundled_library) +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") diff --git a/05-advanced-widget/03-custom_painter_project/linux/runner/CMakeLists.txt b/05-advanced-widget/03-custom_painter_project/linux/runner/CMakeLists.txt new file mode 100644 index 0000000..e97dabc --- /dev/null +++ b/05-advanced-widget/03-custom_painter_project/linux/runner/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the application ID. +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/05-advanced-widget/03-custom_painter_project/linux/main.cc b/05-advanced-widget/03-custom_painter_project/linux/runner/main.cc similarity index 100% rename from 05-advanced-widget/03-custom_painter_project/linux/main.cc rename to 05-advanced-widget/03-custom_painter_project/linux/runner/main.cc diff --git a/05-advanced-widget/03-custom_painter_project/linux/my_application.cc b/05-advanced-widget/03-custom_painter_project/linux/runner/my_application.cc similarity index 68% rename from 05-advanced-widget/03-custom_painter_project/linux/my_application.cc rename to 05-advanced-widget/03-custom_painter_project/linux/runner/my_application.cc index 4ed5913..25679d9 100644 --- a/05-advanced-widget/03-custom_painter_project/linux/my_application.cc +++ b/05-advanced-widget/03-custom_painter_project/linux/runner/my_application.cc @@ -14,6 +14,12 @@ struct _MyApplication { G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) +// Called when first Flutter frame received. +static void first_frame_cb(MyApplication* self, FlView *view) +{ + gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); +} + // Implements GApplication::activate. static void my_application_activate(GApplication* application) { MyApplication* self = MY_APPLICATION(application); @@ -48,15 +54,23 @@ static void my_application_activate(GApplication* application) { } gtk_window_set_default_size(window, 1280, 720); - gtk_widget_show(GTK_WIDGET(window)); g_autoptr(FlDartProject) project = fl_dart_project_new(); fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); FlView* view = fl_view_new(project); + GdkRGBA background_color; + // Background defaults to black, override it here if necessary, e.g. #00000000 for transparent. + gdk_rgba_parse(&background_color, "#000000"); + fl_view_set_background_color(view, &background_color); gtk_widget_show(GTK_WIDGET(view)); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + // Show the window when Flutter renders. + // Requires the view to be realized so we can start rendering. + g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), self); + gtk_widget_realize(GTK_WIDGET(view)); + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); gtk_widget_grab_focus(GTK_WIDGET(view)); @@ -81,6 +95,24 @@ static gboolean my_application_local_command_line(GApplication* application, gch return TRUE; } +// Implements GApplication::startup. +static void my_application_startup(GApplication* application) { + //MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application startup. + + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); +} + +// Implements GApplication::shutdown. +static void my_application_shutdown(GApplication* application) { + //MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application shutdown. + + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); +} + // Implements GObject::dispose. static void my_application_dispose(GObject* object) { MyApplication* self = MY_APPLICATION(object); @@ -91,12 +123,20 @@ static void my_application_dispose(GObject* object) { static void my_application_class_init(MyApplicationClass* klass) { G_APPLICATION_CLASS(klass)->activate = my_application_activate; G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_APPLICATION_CLASS(klass)->startup = my_application_startup; + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; G_OBJECT_CLASS(klass)->dispose = my_application_dispose; } static void my_application_init(MyApplication* self) {} MyApplication* my_application_new() { + // Set the program name to the application ID, which helps various systems + // like GTK and desktop environments map this running application to its + // corresponding .desktop file. This ensures better integration by allowing + // the application to be recognized beyond its binary name. + g_set_prgname(APPLICATION_ID); + return MY_APPLICATION(g_object_new(my_application_get_type(), "application-id", APPLICATION_ID, "flags", G_APPLICATION_NON_UNIQUE, diff --git a/05-advanced-widget/03-custom_painter_project/linux/my_application.h b/05-advanced-widget/03-custom_painter_project/linux/runner/my_application.h similarity index 100% rename from 05-advanced-widget/03-custom_painter_project/linux/my_application.h rename to 05-advanced-widget/03-custom_painter_project/linux/runner/my_application.h diff --git a/05-advanced-widget/03-custom_painter_project/macos/Runner.xcodeproj/project.pbxproj b/05-advanced-widget/03-custom_painter_project/macos/Runner.xcodeproj/project.pbxproj index a5c7ae1..05f5390 100644 --- a/05-advanced-widget/03-custom_painter_project/macos/Runner.xcodeproj/project.pbxproj +++ b/05-advanced-widget/03-custom_painter_project/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -21,6 +21,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; @@ -29,6 +30,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 33CC10E52044A3C60003C045 /* Project object */; @@ -52,6 +60,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; 33CC10ED2044A3C60003C045 /* custom_painter_project.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "custom_painter_project.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -71,6 +81,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 33CC10EA2044A3C60003C045 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -81,6 +98,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; 33BA886A226E78AF003329D5 /* Configs */ = { isa = PBXGroup; children = ( @@ -97,6 +122,7 @@ children = ( 33FAB671232836740065AC1E /* Runner */, 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, ); @@ -106,6 +132,7 @@ isa = PBXGroup; children = ( 33CC10ED2044A3C60003C045 /* custom_painter_project.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, ); name = Products; sourceTree = ""; @@ -155,6 +182,24 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 33CC10EC2044A3C60003C045 /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; @@ -181,10 +226,15 @@ 33CC10E52044A3C60003C045 /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; 33CC10EC2044A3C60003C045 = { CreatedOnToolsVersion = 9.2; LastSwiftMigration = 1100; @@ -215,12 +265,20 @@ projectRoot = ""; targets = ( 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, 33CC111A2044C6BA0003C045 /* Flutter Assemble */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 33CC10EB2044A3C60003C045 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -235,6 +293,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -273,6 +332,14 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 33CC10E92044A3C60003C045 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -286,6 +353,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; @@ -306,11 +378,54 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.dicoding.customPainterProject.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/custom_painter_project.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/custom_painter_project"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.dicoding.customPainterProject.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/custom_painter_project.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/custom_painter_project"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.dicoding.customPainterProject.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/custom_painter_project.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/custom_painter_project"; + }; + name = Profile; + }; 338D0CE9231458BD00FA5F75 /* Profile */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -334,9 +449,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -344,7 +461,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -384,6 +501,7 @@ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -407,9 +525,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -423,7 +543,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -437,6 +557,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -460,9 +581,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -470,7 +593,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -536,6 +659,16 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/05-advanced-widget/03-custom_painter_project/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/05-advanced-widget/03-custom_painter_project/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index da3a7bc..fd1f62b 100644 --- a/05-advanced-widget/03-custom_painter_project/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/05-advanced-widget/03-custom_painter_project/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + + + + diff --git a/05-advanced-widget/03-custom_painter_project/macos/Runner/AppDelegate.swift b/05-advanced-widget/03-custom_painter_project/macos/Runner/AppDelegate.swift index d53ef64..b3c1761 100644 --- a/05-advanced-widget/03-custom_painter_project/macos/Runner/AppDelegate.swift +++ b/05-advanced-widget/03-custom_painter_project/macos/Runner/AppDelegate.swift @@ -1,9 +1,13 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } diff --git a/05-advanced-widget/03-custom_painter_project/macos/Runner/Configs/AppInfo.xcconfig b/05-advanced-widget/03-custom_painter_project/macos/Runner/Configs/AppInfo.xcconfig index ad6b76e..adb3f46 100644 --- a/05-advanced-widget/03-custom_painter_project/macos/Runner/Configs/AppInfo.xcconfig +++ b/05-advanced-widget/03-custom_painter_project/macos/Runner/Configs/AppInfo.xcconfig @@ -11,4 +11,4 @@ PRODUCT_NAME = custom_painter_project PRODUCT_BUNDLE_IDENTIFIER = com.dicoding.customPainterProject // The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2022 com.dicoding. All rights reserved. +PRODUCT_COPYRIGHT = Copyright © 2025 com.dicoding. All rights reserved. diff --git a/05-advanced-widget/03-custom_painter_project/macos/Runner/MainFlutterWindow.swift b/05-advanced-widget/03-custom_painter_project/macos/Runner/MainFlutterWindow.swift index 2722837..3cc05eb 100644 --- a/05-advanced-widget/03-custom_painter_project/macos/Runner/MainFlutterWindow.swift +++ b/05-advanced-widget/03-custom_painter_project/macos/Runner/MainFlutterWindow.swift @@ -3,7 +3,7 @@ import FlutterMacOS class MainFlutterWindow: NSWindow { override func awakeFromNib() { - let flutterViewController = FlutterViewController.init() + let flutterViewController = FlutterViewController() let windowFrame = self.frame self.contentViewController = flutterViewController self.setFrame(windowFrame, display: true) diff --git a/05-advanced-widget/03-custom_painter_project/macos/RunnerTests/RunnerTests.swift b/05-advanced-widget/03-custom_painter_project/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..61f3bd1 --- /dev/null +++ b/05-advanced-widget/03-custom_painter_project/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/05-advanced-widget/03-custom_painter_project/pubspec.lock b/05-advanced-widget/03-custom_painter_project/pubspec.lock index e9b9197..08ca527 100644 --- a/05-advanced-widget/03-custom_painter_project/pubspec.lock +++ b/05-advanced-widget/03-custom_painter_project/pubspec.lock @@ -5,51 +5,58 @@ packages: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.13.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "5bbf32bc9e518d41ec49718e2931cd4527292c9b0c6d2dffcf7fe6b9a8a8cf72" + url: "https://pub.dev" source: hosted version: "2.1.0" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.4.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.19.1" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" source: hosted version: "1.0.5" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" flutter: dependency: "direct main" description: flutter @@ -59,7 +66,8 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted version: "2.0.1" flutter_test: @@ -67,94 +75,139 @@ packages: description: flutter source: sdk version: "0.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.dev" + source: hosted + version: "11.0.2" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" + source: hosted + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" source: hosted version: "2.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.11.1" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.16.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.9.1" sky_engine: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: e3320978e3715725e62f04358fd249c1efe5999297b2c6acd626a817593281b0 + url: "https://pub.dev" source: hosted version: "1.9.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "862015c5db1f3f3c4ea3b94dc2490363a84262994b88902315ed74be1155612f" + url: "https://pub.dev" source: hosted version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.7.6" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "15.0.2" sdks: - dart: ">=2.18.2 <3.0.0" + dart: ">=3.9.2 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/05-advanced-widget/03-custom_painter_project/pubspec.yaml b/05-advanced-widget/03-custom_painter_project/pubspec.yaml index d219bd8..18004d0 100644 --- a/05-advanced-widget/03-custom_painter_project/pubspec.yaml +++ b/05-advanced-widget/03-custom_painter_project/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ">=2.18.2 <3.0.0" + sdk: ^3.9.2 dependencies: flutter: diff --git a/05-advanced-widget/03-custom_painter_project/web/index.html b/05-advanced-widget/03-custom_painter_project/web/index.html index 61dc1bd..0140223 100644 --- a/05-advanced-widget/03-custom_painter_project/web/index.html +++ b/05-advanced-widget/03-custom_painter_project/web/index.html @@ -21,7 +21,7 @@ - + @@ -31,28 +31,8 @@ custom_painter_project - - - - - + diff --git a/05-advanced-widget/03-custom_painter_project/windows/CMakeLists.txt b/05-advanced-widget/03-custom_painter_project/windows/CMakeLists.txt index 81535d9..7a90da9 100644 --- a/05-advanced-widget/03-custom_painter_project/windows/CMakeLists.txt +++ b/05-advanced-widget/03-custom_painter_project/windows/CMakeLists.txt @@ -8,7 +8,7 @@ set(BINARY_NAME "custom_painter_project") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. -cmake_policy(SET CMP0063 NEW) +cmake_policy(VERSION 3.14...3.25) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -52,6 +52,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) # Application build; see runner/CMakeLists.txt. add_subdirectory("runner") + # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) @@ -86,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") diff --git a/05-advanced-widget/03-custom_painter_project/windows/flutter/CMakeLists.txt b/05-advanced-widget/03-custom_painter_project/windows/flutter/CMakeLists.txt index 930d207..903f489 100644 --- a/05-advanced-widget/03-custom_painter_project/windows/flutter/CMakeLists.txt +++ b/05-advanced-widget/03-custom_painter_project/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/05-advanced-widget/03-custom_painter_project/windows/runner/CMakeLists.txt b/05-advanced-widget/03-custom_painter_project/windows/runner/CMakeLists.txt index 17411a8..394917c 100644 --- a/05-advanced-widget/03-custom_painter_project/windows/runner/CMakeLists.txt +++ b/05-advanced-widget/03-custom_painter_project/windows/runner/CMakeLists.txt @@ -33,6 +33,7 @@ target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") # Add dependency libraries and include directories. Add any application-specific # dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") # Run the Flutter tool portions of the build. This must not be removed. diff --git a/05-advanced-widget/03-custom_painter_project/windows/runner/Runner.rc b/05-advanced-widget/03-custom_painter_project/windows/runner/Runner.rc index 8a372d1..6002519 100644 --- a/05-advanced-widget/03-custom_painter_project/windows/runner/Runner.rc +++ b/05-advanced-widget/03-custom_painter_project/windows/runner/Runner.rc @@ -93,7 +93,7 @@ BEGIN VALUE "FileDescription", "custom_painter_project" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "custom_painter_project" "\0" - VALUE "LegalCopyright", "Copyright (C) 2022 com.dicoding. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2025 com.dicoding. All rights reserved." "\0" VALUE "OriginalFilename", "custom_painter_project.exe" "\0" VALUE "ProductName", "custom_painter_project" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/05-advanced-widget/03-custom_painter_project/windows/runner/flutter_window.cpp b/05-advanced-widget/03-custom_painter_project/windows/runner/flutter_window.cpp index b43b909..955ee30 100644 --- a/05-advanced-widget/03-custom_painter_project/windows/runner/flutter_window.cpp +++ b/05-advanced-widget/03-custom_painter_project/windows/runner/flutter_window.cpp @@ -26,6 +26,16 @@ bool FlutterWindow::OnCreate() { } RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } diff --git a/05-advanced-widget/03-custom_painter_project/windows/runner/main.cpp b/05-advanced-widget/03-custom_painter_project/windows/runner/main.cpp index 085d881..bdf0f4e 100644 --- a/05-advanced-widget/03-custom_painter_project/windows/runner/main.cpp +++ b/05-advanced-widget/03-custom_painter_project/windows/runner/main.cpp @@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"custom_painter_project", origin, size)) { + if (!window.Create(L"custom_painter_project", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/05-advanced-widget/03-custom_painter_project/windows/runner/runner.exe.manifest b/05-advanced-widget/03-custom_painter_project/windows/runner/runner.exe.manifest index a42ea76..153653e 100644 --- a/05-advanced-widget/03-custom_painter_project/windows/runner/runner.exe.manifest +++ b/05-advanced-widget/03-custom_painter_project/windows/runner/runner.exe.manifest @@ -9,12 +9,6 @@ - - - - - - diff --git a/05-advanced-widget/03-custom_painter_project/windows/runner/utils.cpp b/05-advanced-widget/03-custom_painter_project/windows/runner/utils.cpp index f5bf9fa..3a0b465 100644 --- a/05-advanced-widget/03-custom_painter_project/windows/runner/utils.cpp +++ b/05-advanced-widget/03-custom_painter_project/windows/runner/utils.cpp @@ -45,9 +45,11 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { if (utf16_string == nullptr) { return std::string(); } - int target_length = ::WideCharToMultiByte( + unsigned int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); std::string utf8_string; if (target_length == 0 || target_length > utf8_string.max_size()) { return utf8_string; @@ -55,8 +57,7 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, utf8_string.data(), - target_length, nullptr, nullptr); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/05-advanced-widget/03-custom_painter_project/windows/runner/win32_window.cpp b/05-advanced-widget/03-custom_painter_project/windows/runner/win32_window.cpp index c10f08d..60608d0 100644 --- a/05-advanced-widget/03-custom_painter_project/windows/runner/win32_window.cpp +++ b/05-advanced-widget/03-custom_painter_project/windows/runner/win32_window.cpp @@ -1,13 +1,31 @@ #include "win32_window.h" +#include #include #include "resource.h" namespace { +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + // The number of Win32Window objects that currently exist. static int g_active_window_count = 0; @@ -31,8 +49,8 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { GetProcAddress(user32_module, "EnableNonClientDpiScaling")); if (enable_non_client_dpi_scaling != nullptr) { enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); } + FreeLibrary(user32_module); } } // namespace @@ -42,7 +60,7 @@ class WindowClassRegistrar { public: ~WindowClassRegistrar() = default; - // Returns the singleton registar instance. + // Returns the singleton registrar instance. static WindowClassRegistrar* GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); @@ -102,9 +120,9 @@ Win32Window::~Win32Window() { Destroy(); } -bool Win32Window::CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size) { +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { Destroy(); const wchar_t* window_class = @@ -117,7 +135,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title, double scale_factor = dpi / 96.0; HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), Scale(size.width, scale_factor), Scale(size.height, scale_factor), nullptr, nullptr, GetModuleHandle(nullptr), this); @@ -126,9 +144,15 @@ bool Win32Window::CreateAndShow(const std::wstring& title, return false; } + UpdateTheme(window); + return OnCreate(); } +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + // static LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, @@ -188,6 +212,10 @@ Win32Window::MessageHandler(HWND hwnd, SetFocus(child_content_); } return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -243,3 +271,18 @@ bool Win32Window::OnCreate() { void Win32Window::OnDestroy() { // No-op; provided for subclasses. } + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/05-advanced-widget/03-custom_painter_project/windows/runner/win32_window.h b/05-advanced-widget/03-custom_painter_project/windows/runner/win32_window.h index 17ba431..e901dde 100644 --- a/05-advanced-widget/03-custom_painter_project/windows/runner/win32_window.h +++ b/05-advanced-widget/03-custom_painter_project/windows/runner/win32_window.h @@ -28,15 +28,16 @@ class Win32Window { Win32Window(); virtual ~Win32Window(); - // Creates and shows a win32 window with |title| and position and size using + // Creates a win32 window with |title| that is positioned and sized using // |origin| and |size|. New windows are created on the default monitor. Window // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size); + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); // Release OS resources associated with window. void Destroy(); @@ -76,7 +77,7 @@ class Win32Window { // OS callback called by message pump. Handles the WM_NCCREATE message which // is passed when the non-client area is being created and enables automatic // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by + // responds to changes in DPI. All other messages are handled by // MessageHandler. static LRESULT CALLBACK WndProc(HWND const window, UINT const message, @@ -86,6 +87,9 @@ class Win32Window { // Retrieves a class instance pointer for |window| static Win32Window* GetThisFromHandle(HWND const window) noexcept; + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + bool quit_on_close_ = false; // window handle for top level window. diff --git a/05-advanced-widget/04-quote_list_app_final/.gitignore b/05-advanced-widget/04-quote_list_app_final/.gitignore index 24476c5..6c31954 100644 --- a/05-advanced-widget/04-quote_list_app_final/.gitignore +++ b/05-advanced-widget/04-quote_list_app_final/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/05-advanced-widget/04-quote_list_app_final/.metadata b/05-advanced-widget/04-quote_list_app_final/.metadata index e1179a6..b11d65d 100644 --- a/05-advanced-widget/04-quote_list_app_final/.metadata +++ b/05-advanced-widget/04-quote_list_app_final/.metadata @@ -1,11 +1,11 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled. +# This file should be version controlled and should not be manually edited. version: - revision: 18a827f3933c19f51862dde3fa472197683249d6 - channel: stable + revision: "ac4e799d237041cf905519190471f657b657155a" + channel: "stable" project_type: app @@ -13,26 +13,26 @@ project_type: app migration: platforms: - platform: root - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: android - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: ios - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: linux - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: macos - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: web - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: windows - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a # User provided section diff --git a/05-advanced-widget/04-quote_list_app_final/android/.gitignore b/05-advanced-widget/04-quote_list_app_final/android/.gitignore index 6f56801..be3943c 100644 --- a/05-advanced-widget/04-quote_list_app_final/android/.gitignore +++ b/05-advanced-widget/04-quote_list_app_final/android/.gitignore @@ -5,9 +5,10 @@ gradle-wrapper.jar /gradlew.bat /local.properties GeneratedPluginRegistrant.java +.cxx/ # Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +# See https://flutter.dev/to/reference-keystore key.properties **/*.keystore **/*.jks diff --git a/05-advanced-widget/04-quote_list_app_final/android/app/build.gradle b/05-advanced-widget/04-quote_list_app_final/android/app/build.gradle deleted file mode 100644 index 6910a9b..0000000 --- a/05-advanced-widget/04-quote_list_app_final/android/app/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion flutter.compileSdkVersion - ndkVersion flutter.ndkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.dicoding.quote_list_app" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion - targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/05-advanced-widget/04-quote_list_app_final/android/app/build.gradle.kts b/05-advanced-widget/04-quote_list_app_final/android/app/build.gradle.kts new file mode 100644 index 0000000..b83af69 --- /dev/null +++ b/05-advanced-widget/04-quote_list_app_final/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.dicoding.quote_list_app" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.dicoding.quote_list_app" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/05-advanced-widget/04-quote_list_app_final/android/app/src/debug/AndroidManifest.xml b/05-advanced-widget/04-quote_list_app_final/android/app/src/debug/AndroidManifest.xml index ade96eb..399f698 100644 --- a/05-advanced-widget/04-quote_list_app_final/android/app/src/debug/AndroidManifest.xml +++ b/05-advanced-widget/04-quote_list_app_final/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,4 @@ - + + + + + + + diff --git a/05-advanced-widget/04-quote_list_app_final/android/app/src/main/kotlin/com/dicoding/quote_list_app/MainActivity.kt b/05-advanced-widget/04-quote_list_app_final/android/app/src/main/kotlin/com/dicoding/quote_list_app/MainActivity.kt index df9aa9f..0d94dd6 100644 --- a/05-advanced-widget/04-quote_list_app_final/android/app/src/main/kotlin/com/dicoding/quote_list_app/MainActivity.kt +++ b/05-advanced-widget/04-quote_list_app_final/android/app/src/main/kotlin/com/dicoding/quote_list_app/MainActivity.kt @@ -2,5 +2,4 @@ package com.dicoding.quote_list_app import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() { -} +class MainActivity : FlutterActivity() diff --git a/05-advanced-widget/04-quote_list_app_final/android/app/src/profile/AndroidManifest.xml b/05-advanced-widget/04-quote_list_app_final/android/app/src/profile/AndroidManifest.xml index ade96eb..399f698 100644 --- a/05-advanced-widget/04-quote_list_app_final/android/app/src/profile/AndroidManifest.xml +++ b/05-advanced-widget/04-quote_list_app_final/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,4 @@ - + - + @@ -31,28 +31,8 @@ quote_list_app - - - - - + diff --git a/05-advanced-widget/04-quote_list_app_final/windows/CMakeLists.txt b/05-advanced-widget/04-quote_list_app_final/windows/CMakeLists.txt index 0c79e52..ac8bdb6 100644 --- a/05-advanced-widget/04-quote_list_app_final/windows/CMakeLists.txt +++ b/05-advanced-widget/04-quote_list_app_final/windows/CMakeLists.txt @@ -8,7 +8,7 @@ set(BINARY_NAME "quote_list_app") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. -cmake_policy(SET CMP0063 NEW) +cmake_policy(VERSION 3.14...3.25) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -52,6 +52,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) # Application build; see runner/CMakeLists.txt. add_subdirectory("runner") + # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) @@ -86,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") diff --git a/05-advanced-widget/04-quote_list_app_final/windows/flutter/CMakeLists.txt b/05-advanced-widget/04-quote_list_app_final/windows/flutter/CMakeLists.txt index 930d207..903f489 100644 --- a/05-advanced-widget/04-quote_list_app_final/windows/flutter/CMakeLists.txt +++ b/05-advanced-widget/04-quote_list_app_final/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/05-advanced-widget/04-quote_list_app_final/windows/runner/CMakeLists.txt b/05-advanced-widget/04-quote_list_app_final/windows/runner/CMakeLists.txt index 17411a8..394917c 100644 --- a/05-advanced-widget/04-quote_list_app_final/windows/runner/CMakeLists.txt +++ b/05-advanced-widget/04-quote_list_app_final/windows/runner/CMakeLists.txt @@ -33,6 +33,7 @@ target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") # Add dependency libraries and include directories. Add any application-specific # dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") # Run the Flutter tool portions of the build. This must not be removed. diff --git a/05-advanced-widget/04-quote_list_app_final/windows/runner/Runner.rc b/05-advanced-widget/04-quote_list_app_final/windows/runner/Runner.rc index ac342ca..8e9a35a 100644 --- a/05-advanced-widget/04-quote_list_app_final/windows/runner/Runner.rc +++ b/05-advanced-widget/04-quote_list_app_final/windows/runner/Runner.rc @@ -93,7 +93,7 @@ BEGIN VALUE "FileDescription", "quote_list_app" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "quote_list_app" "\0" - VALUE "LegalCopyright", "Copyright (C) 2022 com.dicoding. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2025 com.dicoding. All rights reserved." "\0" VALUE "OriginalFilename", "quote_list_app.exe" "\0" VALUE "ProductName", "quote_list_app" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/05-advanced-widget/04-quote_list_app_final/windows/runner/flutter_window.cpp b/05-advanced-widget/04-quote_list_app_final/windows/runner/flutter_window.cpp index b43b909..955ee30 100644 --- a/05-advanced-widget/04-quote_list_app_final/windows/runner/flutter_window.cpp +++ b/05-advanced-widget/04-quote_list_app_final/windows/runner/flutter_window.cpp @@ -26,6 +26,16 @@ bool FlutterWindow::OnCreate() { } RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } diff --git a/05-advanced-widget/04-quote_list_app_final/windows/runner/main.cpp b/05-advanced-widget/04-quote_list_app_final/windows/runner/main.cpp index 8c9a160..9a09f7a 100644 --- a/05-advanced-widget/04-quote_list_app_final/windows/runner/main.cpp +++ b/05-advanced-widget/04-quote_list_app_final/windows/runner/main.cpp @@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"quote_list_app", origin, size)) { + if (!window.Create(L"quote_list_app", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/05-advanced-widget/04-quote_list_app_final/windows/runner/runner.exe.manifest b/05-advanced-widget/04-quote_list_app_final/windows/runner/runner.exe.manifest index a42ea76..153653e 100644 --- a/05-advanced-widget/04-quote_list_app_final/windows/runner/runner.exe.manifest +++ b/05-advanced-widget/04-quote_list_app_final/windows/runner/runner.exe.manifest @@ -9,12 +9,6 @@ - - - - - - diff --git a/05-advanced-widget/04-quote_list_app_final/windows/runner/utils.cpp b/05-advanced-widget/04-quote_list_app_final/windows/runner/utils.cpp index f5bf9fa..3a0b465 100644 --- a/05-advanced-widget/04-quote_list_app_final/windows/runner/utils.cpp +++ b/05-advanced-widget/04-quote_list_app_final/windows/runner/utils.cpp @@ -45,9 +45,11 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { if (utf16_string == nullptr) { return std::string(); } - int target_length = ::WideCharToMultiByte( + unsigned int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); std::string utf8_string; if (target_length == 0 || target_length > utf8_string.max_size()) { return utf8_string; @@ -55,8 +57,7 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, utf8_string.data(), - target_length, nullptr, nullptr); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/05-advanced-widget/04-quote_list_app_final/windows/runner/win32_window.cpp b/05-advanced-widget/04-quote_list_app_final/windows/runner/win32_window.cpp index c10f08d..60608d0 100644 --- a/05-advanced-widget/04-quote_list_app_final/windows/runner/win32_window.cpp +++ b/05-advanced-widget/04-quote_list_app_final/windows/runner/win32_window.cpp @@ -1,13 +1,31 @@ #include "win32_window.h" +#include #include #include "resource.h" namespace { +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + // The number of Win32Window objects that currently exist. static int g_active_window_count = 0; @@ -31,8 +49,8 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { GetProcAddress(user32_module, "EnableNonClientDpiScaling")); if (enable_non_client_dpi_scaling != nullptr) { enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); } + FreeLibrary(user32_module); } } // namespace @@ -42,7 +60,7 @@ class WindowClassRegistrar { public: ~WindowClassRegistrar() = default; - // Returns the singleton registar instance. + // Returns the singleton registrar instance. static WindowClassRegistrar* GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); @@ -102,9 +120,9 @@ Win32Window::~Win32Window() { Destroy(); } -bool Win32Window::CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size) { +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { Destroy(); const wchar_t* window_class = @@ -117,7 +135,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title, double scale_factor = dpi / 96.0; HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), Scale(size.width, scale_factor), Scale(size.height, scale_factor), nullptr, nullptr, GetModuleHandle(nullptr), this); @@ -126,9 +144,15 @@ bool Win32Window::CreateAndShow(const std::wstring& title, return false; } + UpdateTheme(window); + return OnCreate(); } +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + // static LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, @@ -188,6 +212,10 @@ Win32Window::MessageHandler(HWND hwnd, SetFocus(child_content_); } return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -243,3 +271,18 @@ bool Win32Window::OnCreate() { void Win32Window::OnDestroy() { // No-op; provided for subclasses. } + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/05-advanced-widget/04-quote_list_app_final/windows/runner/win32_window.h b/05-advanced-widget/04-quote_list_app_final/windows/runner/win32_window.h index 17ba431..e901dde 100644 --- a/05-advanced-widget/04-quote_list_app_final/windows/runner/win32_window.h +++ b/05-advanced-widget/04-quote_list_app_final/windows/runner/win32_window.h @@ -28,15 +28,16 @@ class Win32Window { Win32Window(); virtual ~Win32Window(); - // Creates and shows a win32 window with |title| and position and size using + // Creates a win32 window with |title| that is positioned and sized using // |origin| and |size|. New windows are created on the default monitor. Window // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size); + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); // Release OS resources associated with window. void Destroy(); @@ -76,7 +77,7 @@ class Win32Window { // OS callback called by message pump. Handles the WM_NCCREATE message which // is passed when the non-client area is being created and enables automatic // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by + // responds to changes in DPI. All other messages are handled by // MessageHandler. static LRESULT CALLBACK WndProc(HWND const window, UINT const message, @@ -86,6 +87,9 @@ class Win32Window { // Retrieves a class instance pointer for |window| static Win32Window* GetThisFromHandle(HWND const window) noexcept; + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + bool quit_on_close_ = false; // window handle for top level window. diff --git a/05-advanced-widget/04-quote_list_app_starter/.gitignore b/05-advanced-widget/04-quote_list_app_starter/.gitignore index 24476c5..6c31954 100644 --- a/05-advanced-widget/04-quote_list_app_starter/.gitignore +++ b/05-advanced-widget/04-quote_list_app_starter/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/05-advanced-widget/04-quote_list_app_starter/.metadata b/05-advanced-widget/04-quote_list_app_starter/.metadata index e1179a6..b11d65d 100644 --- a/05-advanced-widget/04-quote_list_app_starter/.metadata +++ b/05-advanced-widget/04-quote_list_app_starter/.metadata @@ -1,11 +1,11 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled. +# This file should be version controlled and should not be manually edited. version: - revision: 18a827f3933c19f51862dde3fa472197683249d6 - channel: stable + revision: "ac4e799d237041cf905519190471f657b657155a" + channel: "stable" project_type: app @@ -13,26 +13,26 @@ project_type: app migration: platforms: - platform: root - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: android - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: ios - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: linux - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: macos - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: web - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a - platform: windows - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 + create_revision: ac4e799d237041cf905519190471f657b657155a + base_revision: ac4e799d237041cf905519190471f657b657155a # User provided section diff --git a/05-advanced-widget/04-quote_list_app_starter/android/.gitignore b/05-advanced-widget/04-quote_list_app_starter/android/.gitignore index 6f56801..be3943c 100644 --- a/05-advanced-widget/04-quote_list_app_starter/android/.gitignore +++ b/05-advanced-widget/04-quote_list_app_starter/android/.gitignore @@ -5,9 +5,10 @@ gradle-wrapper.jar /gradlew.bat /local.properties GeneratedPluginRegistrant.java +.cxx/ # Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +# See https://flutter.dev/to/reference-keystore key.properties **/*.keystore **/*.jks diff --git a/05-advanced-widget/04-quote_list_app_starter/android/app/build.gradle b/05-advanced-widget/04-quote_list_app_starter/android/app/build.gradle deleted file mode 100644 index 6910a9b..0000000 --- a/05-advanced-widget/04-quote_list_app_starter/android/app/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion flutter.compileSdkVersion - ndkVersion flutter.ndkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.dicoding.quote_list_app" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion - targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/05-advanced-widget/04-quote_list_app_starter/android/app/build.gradle.kts b/05-advanced-widget/04-quote_list_app_starter/android/app/build.gradle.kts new file mode 100644 index 0000000..b83af69 --- /dev/null +++ b/05-advanced-widget/04-quote_list_app_starter/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.dicoding.quote_list_app" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.dicoding.quote_list_app" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/05-advanced-widget/04-quote_list_app_starter/android/app/src/debug/AndroidManifest.xml b/05-advanced-widget/04-quote_list_app_starter/android/app/src/debug/AndroidManifest.xml index ade96eb..399f698 100644 --- a/05-advanced-widget/04-quote_list_app_starter/android/app/src/debug/AndroidManifest.xml +++ b/05-advanced-widget/04-quote_list_app_starter/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,4 @@ - + + + + + + + diff --git a/05-advanced-widget/04-quote_list_app_starter/android/app/src/main/kotlin/com/dicoding/quote_list_app/MainActivity.kt b/05-advanced-widget/04-quote_list_app_starter/android/app/src/main/kotlin/com/dicoding/quote_list_app/MainActivity.kt index df9aa9f..0d94dd6 100644 --- a/05-advanced-widget/04-quote_list_app_starter/android/app/src/main/kotlin/com/dicoding/quote_list_app/MainActivity.kt +++ b/05-advanced-widget/04-quote_list_app_starter/android/app/src/main/kotlin/com/dicoding/quote_list_app/MainActivity.kt @@ -2,5 +2,4 @@ package com.dicoding.quote_list_app import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() { -} +class MainActivity : FlutterActivity() diff --git a/05-advanced-widget/04-quote_list_app_starter/android/app/src/profile/AndroidManifest.xml b/05-advanced-widget/04-quote_list_app_starter/android/app/src/profile/AndroidManifest.xml index ade96eb..399f698 100644 --- a/05-advanced-widget/04-quote_list_app_starter/android/app/src/profile/AndroidManifest.xml +++ b/05-advanced-widget/04-quote_list_app_starter/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,4 @@ - + - + @@ -31,28 +31,8 @@ quote_list_app - - - - - + diff --git a/05-advanced-widget/04-quote_list_app_starter/windows/CMakeLists.txt b/05-advanced-widget/04-quote_list_app_starter/windows/CMakeLists.txt index 0c79e52..ac8bdb6 100644 --- a/05-advanced-widget/04-quote_list_app_starter/windows/CMakeLists.txt +++ b/05-advanced-widget/04-quote_list_app_starter/windows/CMakeLists.txt @@ -8,7 +8,7 @@ set(BINARY_NAME "quote_list_app") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. -cmake_policy(SET CMP0063 NEW) +cmake_policy(VERSION 3.14...3.25) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -52,6 +52,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) # Application build; see runner/CMakeLists.txt. add_subdirectory("runner") + # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) @@ -86,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") diff --git a/05-advanced-widget/04-quote_list_app_starter/windows/flutter/CMakeLists.txt b/05-advanced-widget/04-quote_list_app_starter/windows/flutter/CMakeLists.txt index 930d207..903f489 100644 --- a/05-advanced-widget/04-quote_list_app_starter/windows/flutter/CMakeLists.txt +++ b/05-advanced-widget/04-quote_list_app_starter/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/05-advanced-widget/04-quote_list_app_starter/windows/runner/CMakeLists.txt b/05-advanced-widget/04-quote_list_app_starter/windows/runner/CMakeLists.txt index 17411a8..394917c 100644 --- a/05-advanced-widget/04-quote_list_app_starter/windows/runner/CMakeLists.txt +++ b/05-advanced-widget/04-quote_list_app_starter/windows/runner/CMakeLists.txt @@ -33,6 +33,7 @@ target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") # Add dependency libraries and include directories. Add any application-specific # dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") # Run the Flutter tool portions of the build. This must not be removed. diff --git a/05-advanced-widget/04-quote_list_app_starter/windows/runner/Runner.rc b/05-advanced-widget/04-quote_list_app_starter/windows/runner/Runner.rc index ac342ca..8e9a35a 100644 --- a/05-advanced-widget/04-quote_list_app_starter/windows/runner/Runner.rc +++ b/05-advanced-widget/04-quote_list_app_starter/windows/runner/Runner.rc @@ -93,7 +93,7 @@ BEGIN VALUE "FileDescription", "quote_list_app" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "quote_list_app" "\0" - VALUE "LegalCopyright", "Copyright (C) 2022 com.dicoding. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2025 com.dicoding. All rights reserved." "\0" VALUE "OriginalFilename", "quote_list_app.exe" "\0" VALUE "ProductName", "quote_list_app" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/05-advanced-widget/04-quote_list_app_starter/windows/runner/flutter_window.cpp b/05-advanced-widget/04-quote_list_app_starter/windows/runner/flutter_window.cpp index b43b909..955ee30 100644 --- a/05-advanced-widget/04-quote_list_app_starter/windows/runner/flutter_window.cpp +++ b/05-advanced-widget/04-quote_list_app_starter/windows/runner/flutter_window.cpp @@ -26,6 +26,16 @@ bool FlutterWindow::OnCreate() { } RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } diff --git a/05-advanced-widget/04-quote_list_app_starter/windows/runner/main.cpp b/05-advanced-widget/04-quote_list_app_starter/windows/runner/main.cpp index 8c9a160..9a09f7a 100644 --- a/05-advanced-widget/04-quote_list_app_starter/windows/runner/main.cpp +++ b/05-advanced-widget/04-quote_list_app_starter/windows/runner/main.cpp @@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"quote_list_app", origin, size)) { + if (!window.Create(L"quote_list_app", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/05-advanced-widget/04-quote_list_app_starter/windows/runner/runner.exe.manifest b/05-advanced-widget/04-quote_list_app_starter/windows/runner/runner.exe.manifest index a42ea76..153653e 100644 --- a/05-advanced-widget/04-quote_list_app_starter/windows/runner/runner.exe.manifest +++ b/05-advanced-widget/04-quote_list_app_starter/windows/runner/runner.exe.manifest @@ -9,12 +9,6 @@ - - - - - - diff --git a/05-advanced-widget/04-quote_list_app_starter/windows/runner/utils.cpp b/05-advanced-widget/04-quote_list_app_starter/windows/runner/utils.cpp index f5bf9fa..3a0b465 100644 --- a/05-advanced-widget/04-quote_list_app_starter/windows/runner/utils.cpp +++ b/05-advanced-widget/04-quote_list_app_starter/windows/runner/utils.cpp @@ -45,9 +45,11 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { if (utf16_string == nullptr) { return std::string(); } - int target_length = ::WideCharToMultiByte( + unsigned int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); std::string utf8_string; if (target_length == 0 || target_length > utf8_string.max_size()) { return utf8_string; @@ -55,8 +57,7 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, utf8_string.data(), - target_length, nullptr, nullptr); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/05-advanced-widget/04-quote_list_app_starter/windows/runner/win32_window.cpp b/05-advanced-widget/04-quote_list_app_starter/windows/runner/win32_window.cpp index c10f08d..60608d0 100644 --- a/05-advanced-widget/04-quote_list_app_starter/windows/runner/win32_window.cpp +++ b/05-advanced-widget/04-quote_list_app_starter/windows/runner/win32_window.cpp @@ -1,13 +1,31 @@ #include "win32_window.h" +#include #include #include "resource.h" namespace { +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + // The number of Win32Window objects that currently exist. static int g_active_window_count = 0; @@ -31,8 +49,8 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { GetProcAddress(user32_module, "EnableNonClientDpiScaling")); if (enable_non_client_dpi_scaling != nullptr) { enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); } + FreeLibrary(user32_module); } } // namespace @@ -42,7 +60,7 @@ class WindowClassRegistrar { public: ~WindowClassRegistrar() = default; - // Returns the singleton registar instance. + // Returns the singleton registrar instance. static WindowClassRegistrar* GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); @@ -102,9 +120,9 @@ Win32Window::~Win32Window() { Destroy(); } -bool Win32Window::CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size) { +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { Destroy(); const wchar_t* window_class = @@ -117,7 +135,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title, double scale_factor = dpi / 96.0; HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), Scale(size.width, scale_factor), Scale(size.height, scale_factor), nullptr, nullptr, GetModuleHandle(nullptr), this); @@ -126,9 +144,15 @@ bool Win32Window::CreateAndShow(const std::wstring& title, return false; } + UpdateTheme(window); + return OnCreate(); } +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + // static LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, @@ -188,6 +212,10 @@ Win32Window::MessageHandler(HWND hwnd, SetFocus(child_content_); } return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -243,3 +271,18 @@ bool Win32Window::OnCreate() { void Win32Window::OnDestroy() { // No-op; provided for subclasses. } + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/05-advanced-widget/04-quote_list_app_starter/windows/runner/win32_window.h b/05-advanced-widget/04-quote_list_app_starter/windows/runner/win32_window.h index 17ba431..e901dde 100644 --- a/05-advanced-widget/04-quote_list_app_starter/windows/runner/win32_window.h +++ b/05-advanced-widget/04-quote_list_app_starter/windows/runner/win32_window.h @@ -28,15 +28,16 @@ class Win32Window { Win32Window(); virtual ~Win32Window(); - // Creates and shows a win32 window with |title| and position and size using + // Creates a win32 window with |title| that is positioned and sized using // |origin| and |size|. New windows are created on the default monitor. Window // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size); + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); // Release OS resources associated with window. void Destroy(); @@ -76,7 +77,7 @@ class Win32Window { // OS callback called by message pump. Handles the WM_NCCREATE message which // is passed when the non-client area is being created and enables automatic // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by + // responds to changes in DPI. All other messages are handled by // MessageHandler. static LRESULT CALLBACK WndProc(HWND const window, UINT const message, @@ -86,6 +87,9 @@ class Win32Window { // Retrieves a class instance pointer for |window| static Win32Window* GetThisFromHandle(HWND const window) noexcept; + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + bool quit_on_close_ = false; // window handle for top level window.