diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 4560056..b62ed1e 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -2,6 +2,8 @@
+ CADisableMinimumFrameDurationOnPhone
+
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
@@ -24,6 +26,8 @@
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
+ UIApplicationSupportsIndirectInputEvents
+
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
@@ -41,9 +45,5 @@
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
- CADisableMinimumFrameDurationOnPhone
-
- UIApplicationSupportsIndirectInputEvents
-
diff --git a/lib/main.dart b/lib/main.dart
index 707cc36..da15773 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'screens/manga_reader_screen.dart';
+import 'pages/manga_reader/manga_reader_page.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
@@ -187,19 +187,10 @@ class ScreenD extends StatelessWidget {
const SizedBox(height: 30),
ElevatedButton(
onPressed: () {
- // 仮の漫画データを直接作成
- final List dummyPages = [
- 'Page 1',
- 'Page 2',
- 'Page 3',
- 'Page 4',
- 'Page 5',
- ];
-
Navigator.push(
context,
MaterialPageRoute(
- builder: (context) => MangaReaderScreen(pages: dummyPages),
+ builder: (context) => const MangaReaderPage(),
),
);
},
diff --git a/lib/pages/manga_reader/manga_reader_page.dart b/lib/pages/manga_reader/manga_reader_page.dart
new file mode 100644
index 0000000..7097a24
--- /dev/null
+++ b/lib/pages/manga_reader/manga_reader_page.dart
@@ -0,0 +1,150 @@
+import 'package:flutter/material.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import '../../providers/providers.dart';
+import 'widgets/manga_page_widget.dart';
+import 'widgets/manga_reader_controls.dart';
+
+class MangaReaderPage extends ConsumerStatefulWidget {
+ const MangaReaderPage({super.key});
+
+ @override
+ ConsumerState createState() => _MangaReaderPageState();
+}
+
+class _MangaReaderPageState extends ConsumerState {
+ late PageController _pageController;
+
+ @override
+ void initState() {
+ super.initState();
+ _pageController = PageController();
+
+ // 初期化時にサンプルページを設定
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ final notifier = ref.read(mangaReaderNotifierProvider.notifier);
+ notifier.setPages([
+ 'Page 1',
+ 'Page 2',
+ 'Page 3',
+ 'Page 4',
+ 'Page 5',
+ ]);
+ });
+ }
+
+ @override
+ void dispose() {
+ _pageController.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final readerState = ref.watch(mangaReaderNotifierProvider);
+ final notifier = ref.read(mangaReaderNotifierProvider.notifier);
+
+ return Scaffold(
+ backgroundColor: Colors.black,
+ appBar: readerState.isControlsVisible
+ ? AppBar(
+ backgroundColor: Colors.black,
+ foregroundColor: Colors.white,
+ title: const Text('漫画ビューワー'),
+ actions: [
+ IconButton(
+ icon: const Icon(Icons.settings),
+ onPressed: () => _showSettings(context),
+ ),
+ ],
+ )
+ : null,
+ body: readerState.pages.isEmpty
+ ? const Center(
+ child: CircularProgressIndicator(
+ color: Colors.white,
+ ),
+ )
+ : Stack(
+ children: [
+ // メインの漫画ページ
+ GestureDetector(
+ onTap: () => notifier.toggleControlsVisibility(),
+ child: PageView.builder(
+ controller: _pageController,
+ itemCount: readerState.pages.length,
+ onPageChanged: (index) {
+ notifier.goToPage(index);
+ },
+ itemBuilder: (context, index) {
+ return MangaPageWidget(
+ pageContent: readerState.pages[index],
+ scale: readerState.scale,
+ );
+ },
+ ),
+ ),
+ // コントロール
+ if (readerState.isControlsVisible)
+ MangaReaderControls(
+ currentPage: readerState.currentPage,
+ totalPages: readerState.pages.length,
+ onPreviousPage: () {
+ notifier.previousPage();
+ _pageController.previousPage(
+ duration: const Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ );
+ },
+ onNextPage: () {
+ notifier.nextPage();
+ _pageController.nextPage(
+ duration: const Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ );
+ },
+ ),
+ ],
+ ),
+ );
+ }
+
+ void _showSettings(BuildContext context) {
+ showDialog(
+ context: context,
+ builder: (context) => AlertDialog(
+ title: const Text('設定'),
+ content: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ ListTile(
+ leading: const Icon(Icons.brightness_6),
+ title: const Text('明るさ調整'),
+ onTap: () {
+ Navigator.pop(context);
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text('明るさ調整機能は未実装です')),
+ );
+ },
+ ),
+ ListTile(
+ leading: const Icon(Icons.zoom_in),
+ title: const Text('表示設定'),
+ onTap: () {
+ Navigator.pop(context);
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text('表示設定機能は未実装です')),
+ );
+ },
+ ),
+ ],
+ ),
+ actions: [
+ TextButton(
+ onPressed: () => Navigator.pop(context),
+ child: const Text('閉じる'),
+ ),
+ ],
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/pages/manga_reader/notifier/manga_reader_notifier.dart b/lib/pages/manga_reader/notifier/manga_reader_notifier.dart
new file mode 100644
index 0000000..4d333b0
--- /dev/null
+++ b/lib/pages/manga_reader/notifier/manga_reader_notifier.dart
@@ -0,0 +1,37 @@
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import '../state/manga_reader_state.dart';
+
+class MangaReaderNotifier extends Notifier {
+ @override
+ MangaReaderState build() => const MangaReaderState();
+
+ void setPages(List pages) {
+ state = state.copyWith(pages: pages);
+ }
+
+ void nextPage() {
+ if (state.currentPage < state.pages.length - 1) {
+ state = state.copyWith(currentPage: state.currentPage + 1);
+ }
+ }
+
+ void previousPage() {
+ if (state.currentPage > 0) {
+ state = state.copyWith(currentPage: state.currentPage - 1);
+ }
+ }
+
+ void goToPage(int page) {
+ if (page >= 0 && page < state.pages.length) {
+ state = state.copyWith(currentPage: page);
+ }
+ }
+
+ void setScale(double scale) {
+ state = state.copyWith(scale: scale.clamp(0.5, 3.0));
+ }
+
+ void toggleControlsVisibility() {
+ state = state.copyWith(isControlsVisible: !state.isControlsVisible);
+ }
+}
\ No newline at end of file
diff --git a/lib/pages/manga_reader/state/manga_reader_state.dart b/lib/pages/manga_reader/state/manga_reader_state.dart
new file mode 100644
index 0000000..ed518b9
--- /dev/null
+++ b/lib/pages/manga_reader/state/manga_reader_state.dart
@@ -0,0 +1,13 @@
+import 'package:freezed_annotation/freezed_annotation.dart';
+
+part 'manga_reader_state.freezed.dart';
+
+@freezed
+class MangaReaderState with _$MangaReaderState {
+ const factory MangaReaderState({
+ @Default(0) int currentPage,
+ @Default(1.0) double scale,
+ @Default(true) bool isControlsVisible,
+ @Default([]) List pages,
+ }) = _MangaReaderState;
+}
\ No newline at end of file
diff --git a/lib/pages/manga_reader/state/manga_reader_state.freezed.dart b/lib/pages/manga_reader/state/manga_reader_state.freezed.dart
new file mode 100644
index 0000000..76030bb
--- /dev/null
+++ b/lib/pages/manga_reader/state/manga_reader_state.freezed.dart
@@ -0,0 +1,221 @@
+// coverage:ignore-file
+// GENERATED CODE - DO NOT MODIFY BY HAND
+// ignore_for_file: type=lint
+// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
+
+part of 'manga_reader_state.dart';
+
+// **************************************************************************
+// FreezedGenerator
+// **************************************************************************
+
+T _$identity(T value) => value;
+
+final _privateConstructorUsedError = UnsupportedError(
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
+
+/// @nodoc
+mixin _$MangaReaderState {
+ int get currentPage => throw _privateConstructorUsedError;
+ double get scale => throw _privateConstructorUsedError;
+ bool get isControlsVisible => throw _privateConstructorUsedError;
+ List get pages => throw _privateConstructorUsedError;
+
+ /// Create a copy of MangaReaderState
+ /// with the given fields replaced by the non-null parameter values.
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ $MangaReaderStateCopyWith get copyWith =>
+ throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class $MangaReaderStateCopyWith<$Res> {
+ factory $MangaReaderStateCopyWith(
+ MangaReaderState value, $Res Function(MangaReaderState) then) =
+ _$MangaReaderStateCopyWithImpl<$Res, MangaReaderState>;
+ @useResult
+ $Res call(
+ {int currentPage,
+ double scale,
+ bool isControlsVisible,
+ List pages});
+}
+
+/// @nodoc
+class _$MangaReaderStateCopyWithImpl<$Res, $Val extends MangaReaderState>
+ implements $MangaReaderStateCopyWith<$Res> {
+ _$MangaReaderStateCopyWithImpl(this._value, this._then);
+
+ // ignore: unused_field
+ final $Val _value;
+ // ignore: unused_field
+ final $Res Function($Val) _then;
+
+ /// Create a copy of MangaReaderState
+ /// with the given fields replaced by the non-null parameter values.
+ @pragma('vm:prefer-inline')
+ @override
+ $Res call({
+ Object? currentPage = null,
+ Object? scale = null,
+ Object? isControlsVisible = null,
+ Object? pages = null,
+ }) {
+ return _then(_value.copyWith(
+ currentPage: null == currentPage
+ ? _value.currentPage
+ : currentPage // ignore: cast_nullable_to_non_nullable
+ as int,
+ scale: null == scale
+ ? _value.scale
+ : scale // ignore: cast_nullable_to_non_nullable
+ as double,
+ isControlsVisible: null == isControlsVisible
+ ? _value.isControlsVisible
+ : isControlsVisible // ignore: cast_nullable_to_non_nullable
+ as bool,
+ pages: null == pages
+ ? _value.pages
+ : pages // ignore: cast_nullable_to_non_nullable
+ as List,
+ ) as $Val);
+ }
+}
+
+/// @nodoc
+abstract class _$$MangaReaderStateImplCopyWith<$Res>
+ implements $MangaReaderStateCopyWith<$Res> {
+ factory _$$MangaReaderStateImplCopyWith(_$MangaReaderStateImpl value,
+ $Res Function(_$MangaReaderStateImpl) then) =
+ __$$MangaReaderStateImplCopyWithImpl<$Res>;
+ @override
+ @useResult
+ $Res call(
+ {int currentPage,
+ double scale,
+ bool isControlsVisible,
+ List pages});
+}
+
+/// @nodoc
+class __$$MangaReaderStateImplCopyWithImpl<$Res>
+ extends _$MangaReaderStateCopyWithImpl<$Res, _$MangaReaderStateImpl>
+ implements _$$MangaReaderStateImplCopyWith<$Res> {
+ __$$MangaReaderStateImplCopyWithImpl(_$MangaReaderStateImpl _value,
+ $Res Function(_$MangaReaderStateImpl) _then)
+ : super(_value, _then);
+
+ /// Create a copy of MangaReaderState
+ /// with the given fields replaced by the non-null parameter values.
+ @pragma('vm:prefer-inline')
+ @override
+ $Res call({
+ Object? currentPage = null,
+ Object? scale = null,
+ Object? isControlsVisible = null,
+ Object? pages = null,
+ }) {
+ return _then(_$MangaReaderStateImpl(
+ currentPage: null == currentPage
+ ? _value.currentPage
+ : currentPage // ignore: cast_nullable_to_non_nullable
+ as int,
+ scale: null == scale
+ ? _value.scale
+ : scale // ignore: cast_nullable_to_non_nullable
+ as double,
+ isControlsVisible: null == isControlsVisible
+ ? _value.isControlsVisible
+ : isControlsVisible // ignore: cast_nullable_to_non_nullable
+ as bool,
+ pages: null == pages
+ ? _value._pages
+ : pages // ignore: cast_nullable_to_non_nullable
+ as List,
+ ));
+ }
+}
+
+/// @nodoc
+
+class _$MangaReaderStateImpl implements _MangaReaderState {
+ const _$MangaReaderStateImpl(
+ {this.currentPage = 0,
+ this.scale = 1.0,
+ this.isControlsVisible = true,
+ final List pages = const []})
+ : _pages = pages;
+
+ @override
+ @JsonKey()
+ final int currentPage;
+ @override
+ @JsonKey()
+ final double scale;
+ @override
+ @JsonKey()
+ final bool isControlsVisible;
+ final List _pages;
+ @override
+ @JsonKey()
+ List get pages {
+ if (_pages is EqualUnmodifiableListView) return _pages;
+ // ignore: implicit_dynamic_type
+ return EqualUnmodifiableListView(_pages);
+ }
+
+ @override
+ String toString() {
+ return 'MangaReaderState(currentPage: $currentPage, scale: $scale, isControlsVisible: $isControlsVisible, pages: $pages)';
+ }
+
+ @override
+ bool operator ==(Object other) {
+ return identical(this, other) ||
+ (other.runtimeType == runtimeType &&
+ other is _$MangaReaderStateImpl &&
+ (identical(other.currentPage, currentPage) ||
+ other.currentPage == currentPage) &&
+ (identical(other.scale, scale) || other.scale == scale) &&
+ (identical(other.isControlsVisible, isControlsVisible) ||
+ other.isControlsVisible == isControlsVisible) &&
+ const DeepCollectionEquality().equals(other._pages, _pages));
+ }
+
+ @override
+ int get hashCode => Object.hash(runtimeType, currentPage, scale,
+ isControlsVisible, const DeepCollectionEquality().hash(_pages));
+
+ /// Create a copy of MangaReaderState
+ /// with the given fields replaced by the non-null parameter values.
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ @override
+ @pragma('vm:prefer-inline')
+ _$$MangaReaderStateImplCopyWith<_$MangaReaderStateImpl> get copyWith =>
+ __$$MangaReaderStateImplCopyWithImpl<_$MangaReaderStateImpl>(
+ this, _$identity);
+}
+
+abstract class _MangaReaderState implements MangaReaderState {
+ const factory _MangaReaderState(
+ {final int currentPage,
+ final double scale,
+ final bool isControlsVisible,
+ final List pages}) = _$MangaReaderStateImpl;
+
+ @override
+ int get currentPage;
+ @override
+ double get scale;
+ @override
+ bool get isControlsVisible;
+ @override
+ List get pages;
+
+ /// Create a copy of MangaReaderState
+ /// with the given fields replaced by the non-null parameter values.
+ @override
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ _$$MangaReaderStateImplCopyWith<_$MangaReaderStateImpl> get copyWith =>
+ throw _privateConstructorUsedError;
+}
diff --git a/lib/pages/manga_reader/widgets/manga_page_widget.dart b/lib/pages/manga_reader/widgets/manga_page_widget.dart
new file mode 100644
index 0000000..aac66ac
--- /dev/null
+++ b/lib/pages/manga_reader/widgets/manga_page_widget.dart
@@ -0,0 +1,53 @@
+import 'package:flutter/material.dart';
+
+class MangaPageWidget extends StatelessWidget {
+ final String pageContent;
+ final double scale;
+
+ const MangaPageWidget({
+ super.key,
+ required this.pageContent,
+ required this.scale,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ color: Colors.black,
+ child: Center(
+ child: InteractiveViewer(
+ panEnabled: false,
+ boundaryMargin: const EdgeInsets.all(0),
+ minScale: 0.5,
+ maxScale: 3.0,
+ child: LayoutBuilder(
+ builder: (context, constraints) {
+ final double width = constraints.maxWidth * 0.9;
+ final double height = constraints.maxHeight * 0.8;
+
+ return Container(
+ width: width,
+ height: height,
+ decoration: BoxDecoration(
+ color: Colors.white,
+ border: Border.all(color: Colors.grey, width: 2),
+ borderRadius: BorderRadius.circular(8),
+ ),
+ child: Center(
+ child: Text(
+ pageContent,
+ style: const TextStyle(
+ fontSize: 36,
+ fontWeight: FontWeight.bold,
+ color: Colors.black,
+ ),
+ ),
+ ),
+ );
+ },
+ ),
+ ),
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/pages/manga_reader/widgets/manga_reader_controls.dart b/lib/pages/manga_reader/widgets/manga_reader_controls.dart
new file mode 100644
index 0000000..0951617
--- /dev/null
+++ b/lib/pages/manga_reader/widgets/manga_reader_controls.dart
@@ -0,0 +1,59 @@
+import 'package:flutter/material.dart';
+
+class MangaReaderControls extends StatelessWidget {
+ final int currentPage;
+ final int totalPages;
+ final VoidCallback onPreviousPage;
+ final VoidCallback onNextPage;
+
+ const MangaReaderControls({
+ super.key,
+ required this.currentPage,
+ required this.totalPages,
+ required this.onPreviousPage,
+ required this.onNextPage,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Positioned(
+ bottom: 0,
+ left: 0,
+ right: 0,
+ child: Container(
+ color: Colors.black,
+ padding: const EdgeInsets.all(16),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ IconButton(
+ onPressed: currentPage > 0 ? onPreviousPage : null,
+ icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
+ iconSize: 32,
+ ),
+ Container(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
+ decoration: BoxDecoration(
+ color: Colors.white24,
+ borderRadius: BorderRadius.circular(16),
+ ),
+ child: Text(
+ '${currentPage + 1} / $totalPages',
+ style: const TextStyle(
+ color: Colors.white,
+ fontSize: 16,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ),
+ IconButton(
+ onPressed: currentPage < totalPages - 1 ? onNextPage : null,
+ icon: const Icon(Icons.arrow_forward_ios, color: Colors.white),
+ iconSize: 32,
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/providers/providers.dart b/lib/providers/providers.dart
new file mode 100644
index 0000000..c20904d
--- /dev/null
+++ b/lib/providers/providers.dart
@@ -0,0 +1,25 @@
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import '../pages/manga_reader/notifier/manga_reader_notifier.dart';
+import '../pages/manga_reader/state/manga_reader_state.dart';
+
+// 漫画リーダーの状態管理
+final mangaReaderNotifierProvider = NotifierProvider(
+ MangaReaderNotifier.new,
+);
+
+// 現在のページ情報を取得するProvider
+final currentPageProvider = Provider((ref) {
+ final state = ref.watch(mangaReaderNotifierProvider);
+ return state.currentPage;
+});
+
+// 現在表示中のページデータを取得するProvider
+final currentPageDataProvider = Provider((ref) {
+ final state = ref.watch(mangaReaderNotifierProvider);
+
+ if (state.pages.isEmpty || state.currentPage >= state.pages.length) {
+ return null;
+ }
+
+ return state.pages[state.currentPage];
+});
\ No newline at end of file
diff --git a/lib/screens/manga_reader_screen.dart b/lib/screens/manga_reader_screen.dart
deleted file mode 100644
index c748827..0000000
--- a/lib/screens/manga_reader_screen.dart
+++ /dev/null
@@ -1,191 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-
-class MangaReaderScreen extends ConsumerStatefulWidget {
- final List pages;
-
- const MangaReaderScreen({super.key, required this.pages});
-
- @override
- ConsumerState createState() => _MangaReaderScreenState();
-}
-
-class _MangaReaderScreenState extends ConsumerState {
- late PageController _pageController;
- int _currentPage = 0;
-
- @override
- void initState() {
- super.initState();
- _pageController = PageController();
- }
-
- @override
- void dispose() {
- _pageController.dispose();
- super.dispose();
- }
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: Colors.black,
- appBar: AppBar(
- backgroundColor: Colors.black,
- foregroundColor: Colors.white,
- title: const Text('漫画ビューワー'),
- actions: [
- IconButton(
- icon: const Icon(Icons.settings),
- onPressed: () {
- _showSettings(context);
- },
- ),
- ],
- ),
- body: PageView.builder(
- controller: _pageController,
- itemCount: widget.pages.length,
- onPageChanged: (index) {
- setState(() {
- _currentPage = index;
- });
- },
- itemBuilder: (context, index) {
- return Container(
- color: Colors.black,
- child: Center(
- child: InteractiveViewer(
- panEnabled: false,
- boundaryMargin: const EdgeInsets.all(0),
- minScale: 1.0,
- maxScale: 3.0,
- child: LayoutBuilder(
- builder: (context, constraints) {
- final double width = constraints.maxWidth * 0.9;
- final double height = constraints.maxHeight * 0.8;
-
- return Container(
- width: width,
- height: height,
- decoration: BoxDecoration(
- color: Colors.white,
- border: Border.all(color: Colors.grey, width: 2),
- borderRadius: BorderRadius.circular(8),
- ),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Text(
- 'Page ${index + 1}',
- style: const TextStyle(
- fontSize: 36,
- fontWeight: FontWeight.bold,
- color: Colors.black,
- ),
- ),
- ],
- ),
- );
- },
- ),
- ),
- ),
- );
- },
- ),
- bottomNavigationBar: Container(
- color: Colors.black,
- padding: const EdgeInsets.all(16),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: [
- IconButton(
- onPressed: _currentPage > 0 ? _previousPage : null,
- icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
- iconSize: 32,
- ),
- Container(
- padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
- decoration: BoxDecoration(
- color: Colors.white24,
- borderRadius: BorderRadius.circular(16),
- ),
- child: Text(
- '${_currentPage + 1} / ${widget.pages.length}',
- style: const TextStyle(
- color: Colors.white,
- fontSize: 16,
- fontWeight: FontWeight.bold,
- ),
- ),
- ),
- IconButton(
- onPressed: _currentPage < widget.pages.length - 1 ? _nextPage : null,
- icon: const Icon(Icons.arrow_forward_ios, color: Colors.white),
- iconSize: 32,
- ),
- ],
- ),
- ),
- );
- }
-
- void _previousPage() {
- if (_currentPage > 0) {
- _pageController.previousPage(
- duration: const Duration(milliseconds: 300),
- curve: Curves.easeInOut,
- );
- }
- }
-
- void _nextPage() {
- if (_currentPage < widget.pages.length - 1) {
- _pageController.nextPage(
- duration: const Duration(milliseconds: 300),
- curve: Curves.easeInOut,
- );
- }
- }
-
- void _showSettings(BuildContext context) {
- showDialog(
- context: context,
- builder: (context) => AlertDialog(
- title: const Text('設定'),
- content: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- ListTile(
- leading: const Icon(Icons.brightness_6),
- title: const Text('明るさ調整'),
- onTap: () {
- Navigator.pop(context);
- ScaffoldMessenger.of(context).showSnackBar(
- const SnackBar(content: Text('明るさ調整機能は未実装です')),
- );
- },
- ),
- ListTile(
- leading: const Icon(Icons.zoom_in),
- title: const Text('表示設定'),
- onTap: () {
- Navigator.pop(context);
- ScaffoldMessenger.of(context).showSnackBar(
- const SnackBar(content: Text('表示設定機能は未実装です')),
- );
- },
- ),
- ],
- ),
- actions: [
- TextButton(
- onPressed: () => Navigator.pop(context),
- child: const Text('閉じる'),
- ),
- ],
- ),
- );
- }
-}
\ No newline at end of file
diff --git a/pubspec.lock b/pubspec.lock
index da8f75b..de23edd 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,6 +1,35 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
+ _fe_analyzer_shared:
+ dependency: transitive
+ description:
+ name: _fe_analyzer_shared
+ sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
+ url: "https://pub.dev"
+ source: hosted
+ version: "72.0.0"
+ _macros:
+ dependency: transitive
+ description: dart
+ source: sdk
+ version: "0.3.2"
+ analyzer:
+ dependency: transitive
+ description:
+ name: analyzer
+ sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.7.0"
+ args:
+ dependency: transitive
+ description:
+ name: args
+ sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.7.0"
async:
dependency: transitive
description:
@@ -17,6 +46,70 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
+ build:
+ dependency: transitive
+ description:
+ name: build
+ sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ build_config:
+ dependency: transitive
+ description:
+ name: build_config
+ sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ build_daemon:
+ dependency: transitive
+ description:
+ name: build_daemon
+ sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.2"
+ build_resolvers:
+ dependency: transitive
+ description:
+ name: build_resolvers
+ sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.2"
+ build_runner:
+ dependency: "direct dev"
+ description:
+ name: build_runner
+ sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.13"
+ build_runner_core:
+ dependency: transitive
+ description:
+ name: build_runner_core
+ sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.3.2"
+ built_collection:
+ dependency: transitive
+ description:
+ name: built_collection
+ sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.1.1"
+ built_value:
+ dependency: transitive
+ description:
+ name: built_value
+ sha256: "082001b5c3dc495d4a42f1d5789990505df20d8547d42507c29050af6933ee27"
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.10.1"
characters:
dependency: transitive
description:
@@ -25,6 +118,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.0"
+ checked_yaml:
+ dependency: transitive
+ description:
+ name: checked_yaml
+ sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.3"
clock:
dependency: transitive
description:
@@ -33,6 +134,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.1"
+ code_builder:
+ dependency: transitive
+ description:
+ name: code_builder
+ sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.10.1"
collection:
dependency: transitive
description:
@@ -41,6 +150,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.18.0"
+ convert:
+ dependency: transitive
+ description:
+ name: convert
+ sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.2"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.6"
cupertino_icons:
dependency: "direct main"
description:
@@ -49,6 +174,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.8"
+ dart_style:
+ dependency: transitive
+ description:
+ name: dart_style
+ sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.7"
fake_async:
dependency: transitive
description:
@@ -57,6 +190,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.1"
+ fixnum:
+ dependency: transitive
+ description:
+ name: fixnum
+ sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
flutter:
dependency: "direct main"
description: flutter
@@ -91,6 +240,46 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ freezed:
+ dependency: "direct dev"
+ description:
+ name: freezed
+ sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.5.7"
+ freezed_annotation:
+ dependency: "direct main"
+ description:
+ name: freezed_annotation
+ sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.4"
+ frontend_server_client:
+ dependency: transitive
+ description:
+ name: frontend_server_client
+ sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.0"
+ glob:
+ dependency: transitive
+ description:
+ name: glob
+ sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.3"
+ graphs:
+ dependency: transitive
+ description:
+ name: graphs
+ sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.2"
hooks_riverpod:
dependency: "direct main"
description:
@@ -99,6 +288,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.6.1"
+ http_multi_server:
+ dependency: transitive
+ description:
+ name: http_multi_server
+ sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.2"
+ http_parser:
+ dependency: transitive
+ description:
+ name: http_parser
+ sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.2"
+ io:
+ dependency: transitive
+ description:
+ name: io
+ sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.5"
+ js:
+ dependency: transitive
+ description:
+ name: js
+ sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.1"
+ json_annotation:
+ dependency: transitive
+ description:
+ name: json_annotation
+ sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.9.0"
leak_tracker:
dependency: transitive
description:
@@ -131,6 +360,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.0"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ macros:
+ dependency: transitive
+ description:
+ name: macros
+ sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.2-main.4"
matcher:
dependency: transitive
description:
@@ -155,6 +400,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.15.0"
+ mime:
+ dependency: transitive
+ description:
+ name: mime
+ sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.0"
+ package_config:
+ dependency: transitive
+ description:
+ name: package_config
+ sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.0"
path:
dependency: transitive
description:
@@ -163,6 +424,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.0"
+ pool:
+ dependency: transitive
+ description:
+ name: pool
+ sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.5.1"
+ pub_semver:
+ dependency: transitive
+ description:
+ name: pub_semver
+ sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.0"
+ pubspec_parse:
+ dependency: transitive
+ description:
+ name: pubspec_parse
+ sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.0"
riverpod:
dependency: transitive
description:
@@ -171,11 +456,35 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.6.1"
+ shelf:
+ dependency: transitive
+ description:
+ name: shelf
+ sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.1"
+ shelf_web_socket:
+ dependency: transitive
+ description:
+ name: shelf_web_socket
+ sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.1"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
+ source_gen:
+ dependency: transitive
+ description:
+ name: source_gen
+ sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.5.0"
source_span:
dependency: transitive
description:
@@ -208,6 +517,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.2"
+ stream_transform:
+ dependency: transitive
+ description:
+ name: stream_transform
+ sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
string_scanner:
dependency: transitive
description:
@@ -232,6 +549,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.2"
+ timing:
+ dependency: transitive
+ description:
+ name: timing
+ sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.2"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.0"
vector_math:
dependency: transitive
description:
@@ -248,6 +581,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "14.2.5"
+ watcher:
+ dependency: transitive
+ description:
+ name: watcher
+ sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.2"
+ web:
+ dependency: transitive
+ description:
+ name: web
+ sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ web_socket:
+ dependency: transitive
+ description:
+ name: web_socket
+ sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.1"
+ web_socket_channel:
+ dependency: transitive
+ description:
+ name: web_socket_channel
+ sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.3"
+ yaml:
+ dependency: transitive
+ description:
+ name: yaml
+ sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.3"
sdks:
dart: ">=3.5.4 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
diff --git a/pubspec.yaml b/pubspec.yaml
index 6b24ead..ae4c854 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -31,13 +31,15 @@ dependencies:
flutter:
sdk: flutter
-
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
# State management
hooks_riverpod: ^2.4.9
+
+ # Data classes (必要最小限のみ)
+ freezed_annotation: ^2.4.1
dev_dependencies:
flutter_test:
@@ -49,6 +51,10 @@ dev_dependencies:
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^4.0.0
+
+ # Code generation
+ build_runner: ^2.4.7
+ freezed: ^2.4.6
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec