mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-20 19:12:04 +00:00
add responsive mode
This commit is contained in:
parent
6ef6d943c2
commit
4f2de078de
8 changed files with 325 additions and 161 deletions
|
|
@ -6,7 +6,7 @@ import 'package:mangayomi/models/manga_type.dart';
|
|||
import 'package:mangayomi/views/webview/webview.dart';
|
||||
import 'package:mangayomi/views/browse/browse_screen.dart';
|
||||
import 'package:mangayomi/views/browse/extension/extension_lang.dart';
|
||||
import 'package:mangayomi/views/browse/global_search_screen.dart';
|
||||
import 'package:mangayomi/views/browse/global_search/global_search_screen.dart';
|
||||
import 'package:mangayomi/views/main_view/main_screen.dart';
|
||||
import 'package:mangayomi/views/history/history_screen.dart';
|
||||
import 'package:mangayomi/views/library/library_screen.dart';
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
mediaHeight(BuildContext context, double data) {
|
||||
double mediaHeight(BuildContext context, double data) {
|
||||
return MediaQuery.of(context).size.height * data;
|
||||
}
|
||||
|
||||
mediaWidth(BuildContext context, double data) {
|
||||
double mediaWidth(BuildContext context, double data) {
|
||||
return MediaQuery.of(context).size.width * data;
|
||||
}
|
||||
|
||||
bool isDesktop(BuildContext context) {
|
||||
return MediaQuery.of(context).size.width >= 1200;
|
||||
}
|
||||
|
||||
bool isTablet(BuildContext context) {
|
||||
return MediaQuery.of(context).size.width >= 600;
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import 'package:mangayomi/models/source.dart';
|
|||
import 'package:mangayomi/views/browse/extension/extension_screen.dart';
|
||||
import 'package:mangayomi/views/browse/extension/refresh_source_list_data.dart';
|
||||
import 'package:mangayomi/views/browse/migrate_screen.dart';
|
||||
import 'package:mangayomi/views/browse/sources_screen.dart';
|
||||
import 'package:mangayomi/views/browse/sources/sources_screen.dart';
|
||||
import 'package:mangayomi/views/library/search_text_form_field.dart';
|
||||
|
||||
class BrowseScreen extends ConsumerStatefulWidget {
|
||||
|
|
|
|||
|
|
@ -68,94 +68,203 @@ class _MainScreenState extends State<MainScreen> {
|
|||
}),
|
||||
Flexible(
|
||||
child: Scaffold(
|
||||
body: widget.child,
|
||||
bottomNavigationBar: Consumer(builder: (context, ref, child) {
|
||||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
width: mediaWidth(context, 1),
|
||||
height: isLongPressed
|
||||
? 0
|
||||
: route.location != '/library' &&
|
||||
route.location != '/updates' &&
|
||||
route.location != '/history' &&
|
||||
route.location != '/browse' &&
|
||||
route.location != '/more'
|
||||
? 0
|
||||
: 80,
|
||||
child: NavigationBarTheme(
|
||||
data: NavigationBarThemeData(
|
||||
indicatorShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30)),
|
||||
height: 20,
|
||||
),
|
||||
child: NavigationBar(
|
||||
animationDuration: const Duration(milliseconds: 500),
|
||||
selectedIndex: currentIndex,
|
||||
destinations: const [
|
||||
NavigationDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.collections_bookmark,
|
||||
body: isTablet(context)
|
||||
? Row(
|
||||
children: [
|
||||
Consumer(builder: (context, ref, child) {
|
||||
final isLongPressed =
|
||||
ref.watch(isLongPressedMangaStateProvider);
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 0),
|
||||
width: isLongPressed
|
||||
? 0
|
||||
: route.location != '/library' &&
|
||||
route.location != '/updates' &&
|
||||
route.location != '/history' &&
|
||||
route.location != '/browse' &&
|
||||
route.location != '/more'
|
||||
? 0
|
||||
: 80,
|
||||
child: NavigationRailTheme(
|
||||
data: NavigationRailThemeData(
|
||||
indicatorShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30)),
|
||||
),
|
||||
child: NavigationRail(
|
||||
labelType: NavigationRailLabelType.all,
|
||||
useIndicator: true,
|
||||
destinations: const [
|
||||
NavigationRailDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.collections_bookmark,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.collections_bookmark_outlined,
|
||||
),
|
||||
label: Padding(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Text('Library'))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.new_releases,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.new_releases_outlined,
|
||||
),
|
||||
label: Padding(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Text('Updates'))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.history,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.history_outlined,
|
||||
),
|
||||
label: Padding(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Text("History"),
|
||||
)),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.explore,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.explore_outlined,
|
||||
),
|
||||
label: Padding(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Text("Browse"),
|
||||
)),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.more_horiz,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.more_horiz_outlined,
|
||||
),
|
||||
label: Padding(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Text("More"),
|
||||
)),
|
||||
],
|
||||
selectedIndex: currentIndex,
|
||||
onDestinationSelected: (newIndex) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
currentIndex = newIndex;
|
||||
});
|
||||
}
|
||||
if (newIndex == 0) {
|
||||
route.go('/library');
|
||||
} else if (newIndex == 1) {
|
||||
route.go('/updates');
|
||||
} else if (newIndex == 2) {
|
||||
route.go('/history');
|
||||
} else if (newIndex == 3) {
|
||||
route.go('/browse');
|
||||
} else if (newIndex == 4) {
|
||||
route.go('/more');
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.collections_bookmark_outlined,
|
||||
),
|
||||
label: 'Library'),
|
||||
NavigationDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.new_releases,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.new_releases_outlined,
|
||||
),
|
||||
label: 'Updates'),
|
||||
NavigationDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.history,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.history_outlined,
|
||||
),
|
||||
label: "History"),
|
||||
NavigationDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.explore,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.explore_outlined,
|
||||
),
|
||||
label: "Browse"),
|
||||
NavigationDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.more_horiz,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.more_horiz_outlined,
|
||||
),
|
||||
label: "More"),
|
||||
);
|
||||
}),
|
||||
Expanded(child: widget.child)
|
||||
],
|
||||
onDestinationSelected: (int newIndex) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
currentIndex = newIndex;
|
||||
});
|
||||
}
|
||||
if (newIndex == 0) {
|
||||
route.go('/library');
|
||||
} else if (newIndex == 1) {
|
||||
route.go('/updates');
|
||||
} else if (newIndex == 2) {
|
||||
route.go('/history');
|
||||
} else if (newIndex == 3) {
|
||||
route.go('/browse');
|
||||
} else if (newIndex == 4) {
|
||||
route.go('/more');
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
)
|
||||
: widget.child,
|
||||
bottomNavigationBar: isTablet(context)
|
||||
? null
|
||||
: Consumer(builder: (context, ref, child) {
|
||||
final isLongPressed =
|
||||
ref.watch(isLongPressedMangaStateProvider);
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 0),
|
||||
width: mediaWidth(context, 1),
|
||||
height: isLongPressed
|
||||
? 0
|
||||
: route.location != '/library' &&
|
||||
route.location != '/updates' &&
|
||||
route.location != '/history' &&
|
||||
route.location != '/browse' &&
|
||||
route.location != '/more'
|
||||
? 0
|
||||
: 80,
|
||||
child: NavigationBarTheme(
|
||||
data: NavigationBarThemeData(
|
||||
indicatorShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30)),
|
||||
height: 20,
|
||||
),
|
||||
child: NavigationBar(
|
||||
animationDuration: const Duration(milliseconds: 500),
|
||||
selectedIndex: currentIndex,
|
||||
destinations: const [
|
||||
NavigationDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.collections_bookmark,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.collections_bookmark_outlined,
|
||||
),
|
||||
label: 'Library'),
|
||||
NavigationDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.new_releases,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.new_releases_outlined,
|
||||
),
|
||||
label: 'Updates'),
|
||||
NavigationDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.history,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.history_outlined,
|
||||
),
|
||||
label: "History"),
|
||||
NavigationDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.explore,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.explore_outlined,
|
||||
),
|
||||
label: "Browse"),
|
||||
NavigationDestination(
|
||||
selectedIcon: Icon(
|
||||
Icons.more_horiz,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.more_horiz_outlined,
|
||||
),
|
||||
label: "More"),
|
||||
],
|
||||
onDestinationSelected: (newIndex) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
currentIndex = newIndex;
|
||||
});
|
||||
}
|
||||
if (newIndex == 0) {
|
||||
route.go('/library');
|
||||
} else if (newIndex == 1) {
|
||||
route.go('/updates');
|
||||
} else if (newIndex == 2) {
|
||||
route.go('/history');
|
||||
} else if (newIndex == 3) {
|
||||
route.go('/browse');
|
||||
} else if (newIndex == 4) {
|
||||
route.go('/more');
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -194,12 +194,22 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
fit: BoxFit.cover),
|
||||
Stack(
|
||||
children: [
|
||||
Container(
|
||||
width: mediaWidth(context, 1),
|
||||
height: 465,
|
||||
color: Theme.of(context)
|
||||
.scaffoldBackgroundColor
|
||||
.withOpacity(0.9),
|
||||
Column(
|
||||
children: [
|
||||
Container(
|
||||
width: mediaWidth(context, 1),
|
||||
height: AppBar().preferredSize.height,
|
||||
color: Theme.of(context)
|
||||
.scaffoldBackgroundColor
|
||||
.withOpacity(0.9),
|
||||
),
|
||||
Container(
|
||||
width: mediaWidth(context, 1),
|
||||
height: 465,
|
||||
color:
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
|
|
@ -344,45 +354,83 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
},
|
||||
)),
|
||||
body: SafeArea(
|
||||
child: DraggableScrollbar(
|
||||
padding: const EdgeInsets.only(right: 7),
|
||||
heightScrollThumb: 48.0,
|
||||
backgroundColor: primaryColor(context),
|
||||
scrollThumbBuilder:
|
||||
(backgroundColor, thumbAnimation, labelAnimation, height,
|
||||
{labelConstraints, labelText}) {
|
||||
return FadeTransition(
|
||||
opacity: thumbAnimation,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(20)),
|
||||
height: height,
|
||||
width: 8.0,
|
||||
),
|
||||
);
|
||||
},
|
||||
scrollbarTimeToFade: const Duration(seconds: 2),
|
||||
controller: _scrollController,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.only(top: 0, bottom: 60),
|
||||
itemCount: chapters.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
int finalIndex = index - 1;
|
||||
if (index == 0) {
|
||||
return _bodyContainer(chapterLength: chapters.length);
|
||||
}
|
||||
int reverseIndex = chapters.length -
|
||||
chapters.reversed.toList().indexOf(
|
||||
chapters.reversed.toList()[finalIndex]) -
|
||||
1;
|
||||
final indexx = reverse ? reverseIndex : finalIndex;
|
||||
return ChapterListTileWidget(
|
||||
chapter: chapters[indexx],
|
||||
chapterList: chapterList,
|
||||
);
|
||||
})),
|
||||
child: Row(
|
||||
children: [
|
||||
if (isTablet(context))
|
||||
SizedBox(
|
||||
width: mediaWidth(context, 0.3),
|
||||
height: mediaHeight(context, 1),
|
||||
child: _bodyContainer(chapterLength: chapters.length)),
|
||||
Expanded(
|
||||
child: DraggableScrollbar(
|
||||
padding: const EdgeInsets.only(right: 7),
|
||||
heightScrollThumb: 48.0,
|
||||
backgroundColor: primaryColor(context),
|
||||
scrollThumbBuilder: (backgroundColor, thumbAnimation,
|
||||
labelAnimation, height,
|
||||
{labelConstraints, labelText}) {
|
||||
return FadeTransition(
|
||||
opacity: thumbAnimation,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(20)),
|
||||
height: height,
|
||||
width: 8.0,
|
||||
),
|
||||
);
|
||||
},
|
||||
scrollbarTimeToFade: const Duration(seconds: 2),
|
||||
controller: _scrollController,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.only(top: 0, bottom: 60),
|
||||
itemCount: chapters.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
int finalIndex = index - 1;
|
||||
if (index == 0) {
|
||||
return isTablet(context)
|
||||
? Column(
|
||||
children: [
|
||||
//Description
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets
|
||||
.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
'${chapters.length} chapters',
|
||||
style: const TextStyle(
|
||||
fontWeight:
|
||||
FontWeight.bold),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: _bodyContainer(
|
||||
chapterLength: chapters.length);
|
||||
}
|
||||
int reverseIndex = chapters.length -
|
||||
chapters.reversed.toList().indexOf(
|
||||
chapters.reversed.toList()[finalIndex]) -
|
||||
1;
|
||||
final indexx =
|
||||
reverse ? reverseIndex : finalIndex;
|
||||
return ChapterListTileWidget(
|
||||
chapter: chapters[indexx],
|
||||
chapterList: chapterList,
|
||||
);
|
||||
})),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Consumer(builder: (context, ref, child) {
|
||||
final chap = ref.watch(chaptersListStateProvider);
|
||||
|
|
@ -850,28 +898,29 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
],
|
||||
),
|
||||
)),
|
||||
Column(
|
||||
children: [
|
||||
//Description
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
'$chapterLength chapters',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
)
|
||||
],
|
||||
if (!isTablet(context))
|
||||
Column(
|
||||
children: [
|
||||
//Description
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
'$chapterLength chapters',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -939,7 +988,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
width: 5,
|
||||
),
|
||||
SizedBox(
|
||||
width: mediaWidth(context, 0.4),
|
||||
width: isTablet(context) ? null : mediaWidth(context, 0.4),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
),
|
||||
action: widget.manga.favorite
|
||||
? SizedBox(
|
||||
width: mediaWidth(context, 0.4),
|
||||
width: isTablet(context) ? null : mediaWidth(context, 0.4),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor:
|
||||
|
|
@ -204,9 +204,7 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return
|
||||
|
||||
StatefulBuilder(
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
|
|
|
|||
Loading…
Reference in a new issue