From b7b4d07da230ec9e3a7c062e247f6f61b0cbe280 Mon Sep 17 00:00:00 2001 From: SeungMin Shin Date: Thu, 13 Apr 2023 18:22:03 +0900 Subject: [PATCH] feat: Make toonflix --- android/app/src/main/AndroidManifest.xml | 13 + ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Release.xcconfig | 1 + ios/Podfile | 41 ++++ ios/Podfile.lock | 29 +++ ios/Runner.xcodeproj/project.pbxproj | 68 ++++++ .../contents.xcworkspacedata | 3 + ios/Runner/Info.plist | 4 + lib/_main.dart | 148 ----------- lib/main.dart | 14 +- lib/models/webtoon_detail_model.dart | 9 + lib/models/webtoon_episode_model.dart | 9 + lib/models/webtoon_model.dart | 8 + lib/screens/Home_screen.dart | 198 +++++---------- lib/screens/detail_dart.dart | 186 ++++++++++++++ lib/services/api_service.dart | 58 +++++ lib/wigets/episode_widget.dart | 54 ++++ lib/wigets/webtoon_widget.dart | 70 ++++++ linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/Flutter-Debug.xcconfig | 1 + macos/Flutter/Flutter-Release.xcconfig | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 4 + macos/Podfile | 40 +++ pubspec.lock | 230 ++++++++++++++++++ pubspec.yaml | 4 +- .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 28 files changed, 905 insertions(+), 298 deletions(-) create mode 100644 ios/Podfile create mode 100644 ios/Podfile.lock delete mode 100644 lib/_main.dart create mode 100644 lib/models/webtoon_detail_model.dart create mode 100644 lib/models/webtoon_episode_model.dart create mode 100644 lib/models/webtoon_model.dart create mode 100644 lib/screens/detail_dart.dart create mode 100644 lib/services/api_service.dart create mode 100644 lib/wigets/episode_widget.dart create mode 100644 lib/wigets/webtoon_widget.dart create mode 100644 macos/Podfile diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 64a3676..301e07f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -31,4 +31,17 @@ android:name="flutterEmbedding" android:value="2" /> + + + + + + + + + + + + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 592ceee..ec97fc6 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 592ceee..c4855bf 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..88359b2 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '11.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..7875f1e --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,29 @@ +PODS: + - Flutter (1.0.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - url_launcher_ios (0.0.1): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/ios" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + +SPEC CHECKSUMS: + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472 + url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 + +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 + +COCOAPODS: 1.12.0 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 4487a24..ca77dd6 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 5B98F97D61E6EA2D98D8FD36 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1A73325E18604D815A0A1B9 /* 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 */; }; @@ -31,7 +32,9 @@ /* 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 = ""; }; + 1C0AC1A2264B2ABF78A54AD4 /* 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 = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 404D160859CFF5DF3AC14623 /* 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 = ""; }; 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 = ""; }; @@ -42,6 +45,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 = ""; }; + BF3C09D2D850764BB75D48EC /* 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 = ""; }; + D1A73325E18604D815A0A1B9 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -49,12 +54,24 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 5B98F97D61E6EA2D98D8FD36 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 2C591F88F1F3FEB33CD051BD /* Pods */ = { + isa = PBXGroup; + children = ( + 1C0AC1A2264B2ABF78A54AD4 /* Pods-Runner.debug.xcconfig */, + BF3C09D2D850764BB75D48EC /* Pods-Runner.release.xcconfig */, + 404D160859CFF5DF3AC14623 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -72,6 +89,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, + 2C591F88F1F3FEB33CD051BD /* Pods */, + A3EADAC3584C3CD550E6B0D2 /* Frameworks */, ); sourceTree = ""; }; @@ -98,6 +117,14 @@ path = Runner; sourceTree = ""; }; + A3EADAC3584C3CD550E6B0D2 /* Frameworks */ = { + isa = PBXGroup; + children = ( + D1A73325E18604D815A0A1B9 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -105,12 +132,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + B82E39EEDD584027125E0D0C /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 2CCEF426E64DE49CD848FC60 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -169,6 +198,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 2CCEF426E64DE49CD848FC60 /* [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; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -199,6 +245,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + B82E39EEDD584027125E0D0C /* [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 */ diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 0140198..287d460 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -47,5 +47,9 @@ UIApplicationSupportsIndirectInputEvents + LSApplicationQueriesSchemes + + https + diff --git a/lib/_main.dart b/lib/_main.dart deleted file mode 100644 index 31fec67..0000000 --- a/lib/_main.dart +++ /dev/null @@ -1,148 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:toonflix/wigets/button.dart'; -import 'package:toonflix/wigets/currency_card.dart'; - -void _main() { - runApp(const App()); -} - -class App extends StatelessWidget { - const App({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - backgroundColor: const Color(0xFF181818), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox( - height: 50, - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - const Text( - 'Hey, Selena', - style: TextStyle( - color: Colors.white, - fontSize: 34, - fontWeight: FontWeight.w600, - ), - ), - Text( - 'Welcome back', - style: TextStyle( - color: Colors.white.withOpacity(0.8), - fontSize: 18, - ), - ), - ], - ) - ], - ), - const SizedBox( - height: 50, - ), - Text( - 'Total Balance', - style: TextStyle( - color: Colors.white.withOpacity(0.8), - fontSize: 22, - ), - ), - const SizedBox( - height: 5, - ), - const Text( - '\$5 194 482', - style: TextStyle( - fontSize: 44, - color: Colors.white, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox( - height: 30, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: const [ - Button( - text: 'Transfer', - bgColor: Colors.amber, - textColor: Colors.black, - ), - Button( - text: 'Request', - bgColor: Color(0xFF1F2123), - textColor: Colors.white, - ), - ], - ), - const SizedBox( - height: 100, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - const Text( - 'Wallets', - style: TextStyle( - color: Colors.white, - fontSize: 36, - fontWeight: FontWeight.w600, - ), - ), - Text('View All', - style: TextStyle( - color: Colors.white.withOpacity(0.8), - fontSize: 18, - )), - ], - ), - const SizedBox( - height: 20, - ), - const CurrencyCard( - name: 'EURO', - code: 'EUR', - amount: '6 428', - icon: Icons.euro, - isInverted: false, - offset: 0, - ), - const CurrencyCard( - name: 'Bitcoin', - code: 'BTC', - amount: '9 785', - icon: Icons.currency_bitcoin, - isInverted: true, - offset: 1, - ), - const CurrencyCard( - name: 'Dollar', - code: 'USD', - amount: '428', - icon: Icons.money_outlined, - isInverted: false, - offset: 2, - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/main.dart b/lib/main.dart index e0a4774..25c041f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:toonflix/screens/Home_screen.dart'; +import 'package:toonflix/services/api_service.dart'; void main() { + ApiService.getTodaysToon(); runApp(const App()); } @@ -11,17 +13,7 @@ class App extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - theme: ThemeData( - textTheme: const TextTheme( - displayLarge: TextStyle( - color: Color(0xFF232B55), - ), - ), - cardColor: const Color(0xFFF4EDDB), - colorScheme: - ColorScheme.fromSwatch(backgroundColor: const Color(0xFFE7626C)), - ), - home: const HomeScreen(), + home: HomeScreen(), ); } } diff --git a/lib/models/webtoon_detail_model.dart b/lib/models/webtoon_detail_model.dart new file mode 100644 index 0000000..dd35e2d --- /dev/null +++ b/lib/models/webtoon_detail_model.dart @@ -0,0 +1,9 @@ +class WebtoonDetailModel { + final String title, about, genre, age; + + WebtoonDetailModel.fromJson(Map json) + : title = json['title'], + about = json['about'], + genre = json['genre'], + age = json['age']; +} diff --git a/lib/models/webtoon_episode_model.dart b/lib/models/webtoon_episode_model.dart new file mode 100644 index 0000000..36a10c5 --- /dev/null +++ b/lib/models/webtoon_episode_model.dart @@ -0,0 +1,9 @@ +class WebtoonEpisodeModel { + final String id, title, rating, date; + + WebtoonEpisodeModel.fromJson(Map json) + : id = json['id'], + title = json['title'], + rating = json['rating'], + date = json['date']; +} diff --git a/lib/models/webtoon_model.dart b/lib/models/webtoon_model.dart new file mode 100644 index 0000000..1ef0c13 --- /dev/null +++ b/lib/models/webtoon_model.dart @@ -0,0 +1,8 @@ +class WebtoonModel { + final String title, thumb, id; + + WebtoonModel.fromJson(Map json) + : title = json['title'], + thumb = json['thumb'], + id = json['id']; +} diff --git a/lib/screens/Home_screen.dart b/lib/screens/Home_screen.dart index 108b694..b001a12 100644 --- a/lib/screens/Home_screen.dart +++ b/lib/screens/Home_screen.dart @@ -1,148 +1,70 @@ -import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:toonflix/models/webtoon_model.dart'; +import 'package:toonflix/services/api_service.dart'; +import 'package:toonflix/wigets/webtoon_widget.dart'; -class HomeScreen extends StatefulWidget { - const HomeScreen({super.key}); +class HomeScreen extends StatelessWidget { + HomeScreen({super.key}); - @override - State createState() => _HomeScreenState(); -} - -class _HomeScreenState extends State { - static const twentyFiveMinutes = 1500; + final Future> webtoons = ApiService.getTodaysToon(); - int totalSeconds = 5; - bool isRunning = false; - int totalPomodoros = 0; - late Timer timer; - - void onTick(Timer timer) { - if (totalSeconds == 0) { - setState(() { - totalPomodoros++; - isRunning = false; - totalSeconds = twentyFiveMinutes; - }); - timer.cancel(); - } else { - setState(() { - totalSeconds--; - }); - } - } - - void onStartPressed() { - setState(() { - isRunning = true; - }); - timer = Timer.periodic(const Duration(seconds: 1), onTick); - } - - void onPausePressed() { - timer.cancel(); - setState(() { - isRunning = false; - }); - } - - void onResetPressed() { - timer.cancel(); - setState(() { - isRunning = false; - totalSeconds = twentyFiveMinutes; - totalPomodoros = 0; - }); - } + @override + Widget build(BuildContext context) { + print(webtoons); - String format(int seconds) { - var duration = Duration(seconds: seconds); + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + elevation: 1, + backgroundColor: Colors.white, + foregroundColor: Colors.green, + title: const Text( + "오늘의 웹툰", + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w500, + ), + ), + ), + body: FutureBuilder( + future: webtoons, + builder: (context, snapshot) { + if (snapshot.hasData) { + return Column(children: [ + const SizedBox( + height: 50, + ), + Expanded( + child: makeList(snapshot), + ) + ]); + } - return duration.toString().split(".").first.substring(2, 7); + return const Center( + child: CircularProgressIndicator(), + ); + }, + ), + ); } - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Theme.of(context).colorScheme.background, - body: Column( - children: [ - Flexible( - flex: 1, - child: Container( - alignment: Alignment.bottomCenter, - child: Text( - format(totalSeconds), - style: TextStyle( - color: Theme.of(context).cardColor, - fontSize: 89, - fontWeight: FontWeight.w600, - ), - ), - )), - Flexible( - flex: 2, - child: Center( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconButton( - iconSize: 120, - color: Theme.of(context).cardColor, - onPressed: isRunning ? onPausePressed : onStartPressed, - icon: Icon(isRunning - ? Icons.pause_circle_outline - : Icons.play_circle_outlined), - ), - IconButton( - iconSize: 120, - color: Theme.of(context).cardColor, - onPressed: onResetPressed, - icon: const Icon(Icons.restore), - ), - ], - ), - )), - Flexible( - flex: 1, - child: Row( - children: [ - Expanded( - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - borderRadius: BorderRadius.circular(40)), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Pomodoros', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .textTheme - .displayLarge - ?.color, - ), - ), - Text( - '$totalPomodoros', - style: TextStyle( - fontSize: 58, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .textTheme - .displayLarge - ?.color, - ), - ), - ], - ), - ), - ), - ], - )) - ], - )); + ListView makeList(AsyncSnapshot> snapshot) { + return ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: snapshot.data!.length, + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + itemBuilder: (context, index) { + var webtoon = snapshot.data![index]; + print(index); + return Webtoon( + title: webtoon.title, + thumb: webtoon.thumb, + id: webtoon.id, + ); + }, + separatorBuilder: (context, index) { + return const SizedBox(width: 40); + }, + ); } } diff --git a/lib/screens/detail_dart.dart b/lib/screens/detail_dart.dart new file mode 100644 index 0000000..222eeb1 --- /dev/null +++ b/lib/screens/detail_dart.dart @@ -0,0 +1,186 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:toonflix/models/webtoon_detail_model.dart'; +import 'package:toonflix/models/webtoon_episode_model.dart'; +import 'package:toonflix/services/api_service.dart'; +import 'package:toonflix/wigets/episode_widget.dart'; + +class DetailScreen extends StatefulWidget { + final String title, thumb, id; + + const DetailScreen({ + super.key, + required this.title, + required this.thumb, + required this.id, + }); + + @override + State createState() => _DetailScreenState(); +} + +class _DetailScreenState extends State { + late Future webtoon; + late Future> episodes; + late SharedPreferences prefs; + bool isLiked = false; + + Future initPrefs() async { + prefs = await SharedPreferences.getInstance(); + final likedToons = prefs.getStringList('likedToons'); + + if (likedToons != null) { + if (likedToons.contains(widget.id) == true) { + setState(() { + isLiked = true; + }); + } + } else { + await prefs.setStringList('likedToons', []); + } + + return likedToons; + } + + @override + void initState() { + super.initState(); + webtoon = ApiService.getToonById(widget.id); + episodes = ApiService.getLastestEpisodesById(widget.id); + initPrefs(); + } + + onHeartTap() async { + final likedToons = prefs.getStringList('likedToons'); + if (likedToons != null) { + if (isLiked) { + likedToons.remove(widget.id); + } else { + likedToons.add(widget.id); + } + + await prefs.setStringList('likedToons', likedToons); + } + + setState(() { + isLiked = !isLiked; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + elevation: 1, + backgroundColor: Colors.white, + foregroundColor: Colors.green, + actions: [ + IconButton( + onPressed: onHeartTap, + icon: Icon( + isLiked ? Icons.favorite : Icons.favorite_outline, + ), + ) + ], + title: Text( + widget.title, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w500, + ), + ), + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(50), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Hero( + tag: widget.id, + child: Container( + width: 200, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + boxShadow: [ + BoxShadow( + blurRadius: 15, + offset: const Offset(10, 10), + color: Colors.black.withOpacity(0.5), + ) + ], + ), + child: Image.network( + widget.thumb, + headers: const { + "User-Agent": + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" + }, + ), + ), + ), + ], + ), + const SizedBox( + height: 25, + ), + FutureBuilder( + future: webtoon, + builder: (context, snapshot) { + if (snapshot.hasData) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + snapshot.data!.about, + style: const TextStyle( + fontSize: 16, + ), + ), + const SizedBox( + height: 15, + ), + Text( + "${snapshot.data!.genre} / ${snapshot.data!.age}", + style: const TextStyle( + fontSize: 16, + ), + ), + ], + ); + } else { + return const CircularProgressIndicator(); + } + }, + ), + const SizedBox( + height: 50, + ), + FutureBuilder( + future: episodes, + builder: (context, snapshot) { + if (snapshot.hasData) { + return Column( + children: [ + for (var episode in snapshot.data!) + Episode( + episode: episode, + webtoonId: widget.id, + ), + ], + ); + } + return const Text("No data"); + }, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/services/api_service.dart b/lib/services/api_service.dart new file mode 100644 index 0000000..50017aa --- /dev/null +++ b/lib/services/api_service.dart @@ -0,0 +1,58 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:toonflix/models/webtoon_detail_model.dart'; +import 'package:toonflix/models/webtoon_episode_model.dart'; +import 'package:toonflix/models/webtoon_model.dart'; + +class ApiService { + static const String baseUrl = + "https://webtoon-crawler.nomadcoders.workers.dev"; + static const String today = "today"; + + static Future> getTodaysToon() async { + List webtoonInstances = []; + + final url = Uri.parse('$baseUrl/$today'); + final response = await http.get(url); + + if (response.statusCode == 200) { + final List webtoons = jsonDecode(response.body); + for (var webtoon in webtoons) { + webtoonInstances.add(WebtoonModel.fromJson(webtoon)); + } + return webtoonInstances; + } + throw Error(); + } + + static Future getToonById(String id) async { + final url = Uri.parse("$baseUrl/$id"); + final response = await http.get(url); + + if (response.statusCode == 200) { + final webtoon = jsonDecode(response.body); + return WebtoonDetailModel.fromJson(webtoon); + } + + throw Error(); + } + + static Future> getLastestEpisodesById( + String id) async { + List episodesInstances = []; + + final url = Uri.parse("$baseUrl/$id/episodes"); + final response = await http.get(url); + + if (response.statusCode == 200) { + final episodes = jsonDecode(response.body); + for (var episode in episodes) { + episodesInstances.add(WebtoonEpisodeModel.fromJson(episode)); + } + return episodesInstances; + } + + throw Error(); + } +} diff --git a/lib/wigets/episode_widget.dart b/lib/wigets/episode_widget.dart new file mode 100644 index 0000000..a7da442 --- /dev/null +++ b/lib/wigets/episode_widget.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:toonflix/models/webtoon_episode_model.dart'; +import 'package:url_launcher/url_launcher_string.dart'; + +class Episode extends StatelessWidget { + const Episode({ + super.key, + required this.episode, + required this.webtoonId, + }); + + final String webtoonId; + final WebtoonEpisodeModel episode; + + onButtonTap() async { + await launchUrlString( + "https://comic.naver.com/webtoon/detail?titleId=$webtoonId&no=${episode.id}"); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onButtonTap, + child: Container( + margin: const EdgeInsets.only(bottom: 10), + decoration: BoxDecoration( + color: Colors.green.shade400, + borderRadius: BorderRadius.circular(20), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + episode.title, + style: const TextStyle( + fontSize: 16, + color: Colors.white, + ), + ), + const Icon( + Icons.chevron_right, + color: Colors.white, + ), + ], + ), + )), + ); + } +} diff --git a/lib/wigets/webtoon_widget.dart b/lib/wigets/webtoon_widget.dart new file mode 100644 index 0000000..074323a --- /dev/null +++ b/lib/wigets/webtoon_widget.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; +import 'package:toonflix/screens/detail_dart.dart'; + +class Webtoon extends StatelessWidget { + final String title, thumb, id; + + const Webtoon({ + super.key, + required this.title, + required this.thumb, + required this.id, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DetailScreen( + title: title, + thumb: thumb, + id: id, + ), + fullscreenDialog: true, + ), + ); + }, + child: Column( + children: [ + Hero( + tag: id, + child: Container( + width: 200, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + boxShadow: [ + BoxShadow( + blurRadius: 15, + offset: const Offset(10, 10), + color: Colors.black.withOpacity(0.5), + ) + ], + ), + child: Image.network( + thumb, + headers: const { + "User-Agent": + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" + }, + ), + ), + ), + const SizedBox( + height: 10, + ), + Text( + title, + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ); + } +} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index e71a16d..f6f23bf 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 2e1de87..f16b4c3 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig index c2efd0b..4b81f9b 100644 --- a/macos/Flutter/Flutter-Debug.xcconfig +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig index c2efd0b..5caa9d1 100644 --- a/macos/Flutter/Flutter-Release.xcconfig +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cccf817..997e35d 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,10 @@ import FlutterMacOS import Foundation +import shared_preferences_foundation +import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/macos/Podfile b/macos/Podfile new file mode 100644 index 0000000..049abe2 --- /dev/null +++ b/macos/Podfile @@ -0,0 +1,40 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/pubspec.lock b/pubspec.lock index b2cb69d..5571bf4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -57,6 +57,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" flutter: dependency: "direct main" description: flutter @@ -75,6 +91,27 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http: + dependency: "direct main" + description: + name: http + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" + source: hosted + version: "0.13.5" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" js: dependency: transitive description: @@ -123,6 +160,110 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.2" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" + url: "https://pub.dev" + source: hosted + version: "2.1.10" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + url: "https://pub.dev" + source: hosted + version: "2.0.6" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + url: "https://pub.dev" + source: hosted + version: "2.1.5" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + process: + dependency: transitive + description: + name: process + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "858aaa72d8f61637d64e776aca82e1c67e6d9ee07979123c5d17115031c1b13b" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "8304d8a1f7d21a429f91dee552792249362b68a331ac5c3c1caf370f658873f6" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "0c1c16c56c9708aa9c361541a6f0e5cc6fc12a3232d866a687a7b7db30032b07" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" + url: "https://pub.dev" + source: hosted + version: "2.2.0" sky_engine: dependency: transitive description: flutter @@ -176,6 +317,78 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.16" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" + url: "https://pub.dev" + source: hosted + version: "6.1.10" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: a52628068d282d01a07cd86e6ba99e497aa45ce8c91159015b2416907d78e411 + url: "https://pub.dev" + source: hosted + version: "6.0.27" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "206fb8334a700ef7754d6a9ed119e7349bc830448098f21a69bf1b4ed038cabc" + url: "https://pub.dev" + source: hosted + version: "3.0.4" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" + url: "https://pub.dev" + source: hosted + version: "2.0.16" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: a83ba3607a507758669cfafb03f9de09bf6e6280c14d9b9cb18f013e406dcacd + url: "https://pub.dev" + source: hosted + version: "3.0.5" vector_math: dependency: transitive description: @@ -184,5 +397,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + win32: + dependency: transitive + description: + name: win32 + sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4 + url: "https://pub.dev" + source: hosted + version: "3.1.4" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + url: "https://pub.dev" + source: hosted + version: "1.0.0" sdks: dart: ">=2.19.6 <3.0.0" + flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index 2475661..e309be2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,11 +30,13 @@ environment: dependencies: flutter: sdk: flutter - + http: ^0.13.5 + url_launcher: ^6.1.7 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 + shared_preferences: ^2.1.0 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8b6d468..4f78848 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,9 @@ #include "generated_plugin_registrant.h" +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b93c4c3..88b22e5 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST