Add Infography Screen
This commit is contained in:
parent
445b37bc91
commit
ba20b25ab0
|
|
@ -1,3 +1,3 @@
|
|||
org.gradle.jvmargs=-Xmx1536M
|
||||
org.gradle.jvmargs=-Xmx4608m
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
|
|
|||
|
|
@ -29,20 +29,20 @@ class LightThemeConfig {
|
|||
);
|
||||
|
||||
static const ColorScheme _colorScheme = ColorScheme(
|
||||
primary: _primary,
|
||||
primaryContainer: _white,
|
||||
secondary: Color(0xFFB20436),
|
||||
secondaryContainer: _white,
|
||||
surface: _white,
|
||||
background: _background,
|
||||
error: Color(0xFFF00505),
|
||||
onPrimary: _white,
|
||||
onSecondary: _white,
|
||||
onSurface: _black,
|
||||
onBackground: _white,
|
||||
onError: _white,
|
||||
brightness: Brightness.light,
|
||||
);
|
||||
primary: _primary,
|
||||
primaryContainer: _white,
|
||||
secondary: Color(0xFFB20436),
|
||||
secondaryContainer: _white,
|
||||
surface: _white,
|
||||
background: _background,
|
||||
error: Color(0xFFF00505),
|
||||
onPrimary: _white,
|
||||
onSecondary: _white,
|
||||
onSurface: _black,
|
||||
onBackground: _white,
|
||||
onError: _white,
|
||||
brightness: Brightness.light,
|
||||
outline: Color(0xff007EA7));
|
||||
}
|
||||
|
||||
class DarkThemeConfig {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
class InfoTagModel {
|
||||
final List<InTag> tags;
|
||||
|
||||
InfoTagModel({required this.tags});
|
||||
|
||||
factory InfoTagModel.fromJson(Map<String, dynamic> json) {
|
||||
return InfoTagModel(
|
||||
tags: List<InTag>.from(json['tags'].map((x) => InTag.fromJson(x))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class InTag {
|
||||
final int id;
|
||||
final String label;
|
||||
|
||||
InTag({required this.id, required this.label});
|
||||
|
||||
factory InTag.fromJson(Map<String, dynamic> json) {
|
||||
return InTag(
|
||||
id: json['id'],
|
||||
label: json['label'],
|
||||
);
|
||||
}
|
||||
@override
|
||||
String toString() {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
class InfographyContent {
|
||||
final List<Content> contents;
|
||||
final int lastPage;
|
||||
|
||||
InfographyContent({required this.contents, required this.lastPage});
|
||||
|
||||
factory InfographyContent.fromJson(Map<String, dynamic> json) {
|
||||
return InfographyContent(
|
||||
contents:
|
||||
List<Content>.from(json['contents'].map((x) => Content.fromJson(x))),
|
||||
lastPage: json['lastPage'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Content {
|
||||
final int id;
|
||||
final String title;
|
||||
final String image;
|
||||
final String category;
|
||||
final List<Tag> tags;
|
||||
|
||||
Content(
|
||||
{required this.id,
|
||||
required this.title,
|
||||
required this.image,
|
||||
required this.category,
|
||||
required this.tags});
|
||||
|
||||
factory Content.fromJson(Map<String, dynamic> json) {
|
||||
return Content(
|
||||
id: json['id'],
|
||||
title: json['title'],
|
||||
image: json['image'],
|
||||
category: json['category'],
|
||||
tags: List<Tag>.from(json['tags'].map((x) => Tag.fromJson(x))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Tag {
|
||||
final int id;
|
||||
final String label;
|
||||
|
||||
Tag({required this.id, required this.label});
|
||||
|
||||
factory Tag.fromJson(Map<String, dynamic> json) {
|
||||
return Tag(
|
||||
id: json['id'],
|
||||
label: json['label'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
class InfographyRequestArgs {
|
||||
final int page;
|
||||
final String? q;
|
||||
final List<int>? tag;
|
||||
final List<int>? categories;
|
||||
|
||||
const InfographyRequestArgs({
|
||||
required this.page,
|
||||
this.categories,
|
||||
this.q,
|
||||
this.tag,
|
||||
});
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@ import 'package:didvan/views/direct/direct_state.dart';
|
|||
import 'package:didvan/views/hashtag/hashtag.dart';
|
||||
import 'package:didvan/views/hashtag/hashtag_state.dart';
|
||||
import 'package:didvan/views/home/home.dart';
|
||||
import 'package:didvan/views/home/infography/infography_screen.dart';
|
||||
import 'package:didvan/views/home/infography/infography_screen_state.dart';
|
||||
import 'package:didvan/views/home/main/main_page_state.dart';
|
||||
import 'package:didvan/views/home/home_state.dart';
|
||||
import 'package:didvan/views/news/news.dart';
|
||||
|
|
@ -111,6 +113,12 @@ class RouteGenerator {
|
|||
child: const News(),
|
||||
),
|
||||
);
|
||||
case Routes.infography:
|
||||
return _createRoute(ChangeNotifierProvider<InfographyScreenState>(
|
||||
create: (context) => InfographyScreenState(),
|
||||
child: const InfographyScreen(),
|
||||
));
|
||||
|
||||
case Routes.radarDetails:
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<RadarDetailsState>(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ class Routes {
|
|||
static const String home = '/home';
|
||||
static const String radars = '/radars';
|
||||
static const String news = '/news';
|
||||
static const String infography = '/infography';
|
||||
static const String podcasts = '/podcasts';
|
||||
static const String videocasts = '/videocasts';
|
||||
static const String aboutUs = '/about-us';
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ class RequestService {
|
|||
|
||||
void _handleResponse(http.Response? response) {
|
||||
statusCode = response?.statusCode;
|
||||
//log("Mehradad->" + response!.body.toString());
|
||||
if (_handleError(response)) {
|
||||
if (response!.body.isNotEmpty) {
|
||||
_body = json.decode(response.body);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:didvan/models/requests/infography.dart';
|
||||
import 'package:didvan/models/requests/news.dart';
|
||||
import 'package:didvan/models/requests/radar.dart';
|
||||
import 'package:didvan/models/requests/studio.dart';
|
||||
|
|
@ -7,6 +8,8 @@ class RequestHelper {
|
|||
static const String _baseUserUrl = '$baseUrl/user';
|
||||
static const String _baseRadarUrl = '$baseUrl/radar';
|
||||
static const String _baseNewsUrl = '$baseUrl/news';
|
||||
static const String _baseInfographyUrl = '$baseUrl/home/infography';
|
||||
static const String _baseInfoTagUrl = '$baseUrl/home/infography/tags';
|
||||
static const String _baseStudioUrl = '$baseUrl/studio';
|
||||
static const String _baseStatisticUrl = '$baseUrl/statistic';
|
||||
static const String _baseDirectUrl = '$_baseUserUrl/direct';
|
||||
|
|
@ -106,6 +109,17 @@ class RequestHelper {
|
|||
MapEntry('search', args.search),
|
||||
]);
|
||||
|
||||
static String infographyOverviews({required InfographyRequestArgs args}) =>
|
||||
_baseInfographyUrl +
|
||||
_urlConcatGenerator([
|
||||
MapEntry('page', args.page),
|
||||
MapEntry('category', _urlListConcatGenerator(args.categories)),
|
||||
MapEntry('q', args.q),
|
||||
MapEntry('tag', _urlListConcatGenerator(args.tag)),
|
||||
]);
|
||||
|
||||
static String infographyTags() => _baseInfoTagUrl;
|
||||
|
||||
static String studioSlider(String type) =>
|
||||
'$_baseStudioUrl/slider${_urlConcatGenerator([MapEntry('type', type)])}';
|
||||
static String studioDetails(int id, StudioRequestArgs args) =>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,184 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/models/category.dart';
|
||||
import 'package:didvan/models/infography/info_tag.dart';
|
||||
import 'package:didvan/models/view/action_sheet_data.dart';
|
||||
import 'package:didvan/utils/action_sheet.dart';
|
||||
import 'package:didvan/views/home/infography/infography_screen_state.dart';
|
||||
import 'package:didvan/views/home/main/widgets/infography_item.dart';
|
||||
import 'package:didvan/views/widgets/didvan/checkbox.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/item_title.dart';
|
||||
import 'package:didvan/views/widgets/search_field.dart';
|
||||
import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:animated_custom_dropdown/custom_dropdown.dart';
|
||||
|
||||
class InfographyScreen extends StatefulWidget {
|
||||
const InfographyScreen({super.key});
|
||||
|
||||
@override
|
||||
State<InfographyScreen> createState() => _InfographyScreenState();
|
||||
}
|
||||
|
||||
class _InfographyScreenState extends State<InfographyScreen> {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
int pageNumber = 1;
|
||||
Timer? _timer;
|
||||
final _focusNode = FocusNode();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
context.read<InfographyScreenState>().init();
|
||||
_scrollController.addListener(_onScroll);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onScroll() {
|
||||
if (_scrollController.position.pixels >=
|
||||
_scrollController.position.maxScrollExtent) {
|
||||
pageNumber++;
|
||||
context
|
||||
.read<InfographyScreenState>()
|
||||
.getInfographyContent(page: pageNumber);
|
||||
}
|
||||
}
|
||||
|
||||
void _onChanged(String value) {
|
||||
final state = context.read<InfographyScreenState>();
|
||||
if (value.length < 3 && value.isNotEmpty || state.lastSearch == value) {
|
||||
return;
|
||||
}
|
||||
_timer?.cancel();
|
||||
_timer = Timer(const Duration(seconds: 1), () {
|
||||
state.search = value;
|
||||
state.getInfographyContent(page: 1);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _showFilterBottomSheet() async {
|
||||
final state = context.read<InfographyScreenState>();
|
||||
await ActionSheetUtils.showBottomSheet(
|
||||
data: ActionSheetData(
|
||||
title: 'فیلتر جستجو',
|
||||
smallDismissButton: true,
|
||||
titleIcon: DidvanIcons.filter_regular,
|
||||
dismissTitle: 'حذف فیلتر',
|
||||
confrimTitle: 'نمایش نتایج',
|
||||
onDismissed: () => state.resetFilters(false),
|
||||
onConfirmed: () => state.getInfographyContent(page: 1),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ItemTitle(
|
||||
title: "جستجوی هشتگ",
|
||||
icon: DidvanIcons.hashtag_regular,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
|
||||
child: CustomDropdown<InTag>.multiSelect(
|
||||
closedHeaderPadding: EdgeInsets.all(12),
|
||||
items: state.tags,
|
||||
decoration: CustomDropdownDecoration(
|
||||
closedBorder: Border.all(color: Colors.grey),
|
||||
closedFillColor: Colors.grey.shade100.withOpacity(0.1),
|
||||
),
|
||||
hintText: "انتخاب کنید",
|
||||
onListChanged: (value) {
|
||||
state.selectedTags.addAll(value);
|
||||
log('changing value to: ${value.map((e) => e.label + e.id.toString())}');
|
||||
},
|
||||
),
|
||||
),
|
||||
ItemTitle(
|
||||
title: 'دسته بندی',
|
||||
icon: DidvanIcons.category_regular,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Wrap(
|
||||
children: [
|
||||
for (var i = 0; i < state.categories.length; i++)
|
||||
SizedBox(
|
||||
width: (MediaQuery.of(context).size.width - 40) / 2,
|
||||
child: DidvanCheckbox(
|
||||
title: state.categories[i].label,
|
||||
value: state.selectedCats.contains(state.categories[i]),
|
||||
onChanged: (value) {
|
||||
if (value) {
|
||||
state.selectedCats.add(state.categories[i]);
|
||||
return;
|
||||
}
|
||||
state.selectedCats.remove(state.categories[i]);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StateHandler<InfographyScreenState>(
|
||||
onRetry: context.read<InfographyScreenState>().init,
|
||||
state: context.watch<InfographyScreenState>(),
|
||||
builder: (context, state) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0.0,
|
||||
scrolledUnderElevation: 0.0,
|
||||
title: DidvanText(
|
||||
"اینفوگرافی",
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 80,
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0, vertical: 16.0),
|
||||
child: SearchField(
|
||||
title: "اینفوگرافی",
|
||||
onChanged: _onChanged,
|
||||
focusNode: _focusNode,
|
||||
onFilterButtonPressed: _showFilterBottomSheet,
|
||||
isFiltered: state.filtering),
|
||||
),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
//physics: const ClampingScrollPhysics(),
|
||||
itemCount: state.contents.length,
|
||||
itemBuilder: (context, index) => InfographyItem(
|
||||
image: state.contents[index].image,
|
||||
category: state.contents[index].category,
|
||||
title: state.contents[index].title,
|
||||
tag: state.contents[index].tags,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
import 'package:didvan/constants/assets.dart';
|
||||
import 'package:didvan/models/category.dart';
|
||||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/models/infography/info_tag.dart';
|
||||
import 'package:didvan/models/infography/infography_content.dart';
|
||||
import 'package:didvan/models/requests/infography.dart';
|
||||
import 'package:didvan/providers/core.dart';
|
||||
import 'package:didvan/services/network/request.dart';
|
||||
import 'package:didvan/services/network/request_helper.dart';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:didvan/views/widgets/infography_tag.dart';
|
||||
|
||||
class InfographyScreenState extends CoreProvier {
|
||||
List<Content> contents = [];
|
||||
String search = '';
|
||||
String lastSearch = '';
|
||||
int lastPage = 1;
|
||||
int page = 1;
|
||||
|
||||
final List<InTag> selectedTags = [];
|
||||
List<InTag> tags = [];
|
||||
final List<CategoryData> selectedCats = [];
|
||||
List<CategoryData> categories = [];
|
||||
|
||||
bool isScrolled = false;
|
||||
bool shouldColapse = false;
|
||||
|
||||
bool get filtering => selectedCats.length > 1 && selectedTags.length > 1;
|
||||
|
||||
bool get searching => search.isNotEmpty;
|
||||
|
||||
bool get isColapsed =>
|
||||
(selectedCats.length == 1 &&
|
||||
selectedTags.length == 1 &&
|
||||
!filtering &&
|
||||
isScrolled) ||
|
||||
isScrolled;
|
||||
|
||||
bool get isCategorySelected =>
|
||||
selectedCats.length == 1 && selectedTags.length == 1 && !filtering;
|
||||
|
||||
Future<void> getInfographyContent({required int page}) async {
|
||||
this.page = page;
|
||||
lastSearch = search;
|
||||
if (page == 1) {
|
||||
contents.clear();
|
||||
tags.clear();
|
||||
appState = AppState.busy;
|
||||
}
|
||||
|
||||
final service = RequestService(RequestHelper.infographyOverviews(
|
||||
args: InfographyRequestArgs(
|
||||
page: page,
|
||||
tag: selectedTags.map((e) => e.id).toList(),
|
||||
q: search == '' ? null : search,
|
||||
categories: selectedCats.map((e) => e.id).toList())));
|
||||
final service2 = RequestService(RequestHelper.infographyTags());
|
||||
await service.httpGet();
|
||||
await service2.httpGet();
|
||||
if (service.isSuccess && service2.isSuccess) {
|
||||
lastPage = service.result['lastPage'];
|
||||
|
||||
final content = InfographyContent.fromJson(service.result);
|
||||
final content2 = InfoTagModel.fromJson(service2.result);
|
||||
|
||||
contents.addAll(content.contents);
|
||||
tags.addAll(content2.tags);
|
||||
|
||||
appState = AppState.idle;
|
||||
return;
|
||||
}
|
||||
appState = AppState.failed;
|
||||
}
|
||||
|
||||
void resetFilters(bool isInit) {
|
||||
selectedCats.clear();
|
||||
selectedTags.clear();
|
||||
search = '';
|
||||
lastSearch = '';
|
||||
isScrolled = false;
|
||||
if (!isInit) {
|
||||
getInfographyContent(page: 1);
|
||||
}
|
||||
}
|
||||
|
||||
void init() {
|
||||
// search = '';
|
||||
// lastSearch = '';
|
||||
resetFilters(true);
|
||||
Future.delayed(Duration.zero, () {
|
||||
getInfographyContent(page: 1);
|
||||
});
|
||||
categories = [
|
||||
CategoryData(
|
||||
id: 1,
|
||||
label: 'اقتصادی',
|
||||
asset: Assets.economicCategoryIcon,
|
||||
),
|
||||
CategoryData(
|
||||
id: 2,
|
||||
label: 'سیاسی',
|
||||
asset: Assets.politicalCategoryIcon,
|
||||
),
|
||||
CategoryData(
|
||||
id: 3,
|
||||
label: 'فناوری',
|
||||
asset: Assets.techCategoryIcon,
|
||||
),
|
||||
CategoryData(
|
||||
id: 4,
|
||||
label: 'کسب و کار',
|
||||
asset: Assets.businessCategoryIcon,
|
||||
),
|
||||
CategoryData(
|
||||
id: 5,
|
||||
label: 'زیست محیطی',
|
||||
asset: Assets.enviromentalCategoryIcon,
|
||||
),
|
||||
CategoryData(
|
||||
id: 6,
|
||||
label: 'اجتماعی',
|
||||
asset: Assets.socialCategoryIcon,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/models/home_page_content/home_page_list.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/views/home/infography/infography_screen.dart';
|
||||
import 'package:didvan/views/home/main/main_page_state.dart';
|
||||
import 'package:didvan/views/home/main/widgets/banner.dart';
|
||||
import 'package:didvan/views/home/main/widgets/general_item.dart';
|
||||
|
|
@ -41,10 +43,54 @@ class _MainPageState extends State<MainPage> {
|
|||
}
|
||||
index--;
|
||||
if (index == 4) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.only(top: 32),
|
||||
child: MainPageBanner(
|
||||
isFirst: false,
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 32),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 16,
|
||||
top: 28,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const SizedBox(width: 4),
|
||||
DidvanText(
|
||||
"اینفوگرافی",
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
color: Theme.of(context).colorScheme.title,
|
||||
),
|
||||
],
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => {
|
||||
Navigator.of(context).pushNamed(Routes.infography)
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
DidvanText(
|
||||
"همه",
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
Icon(
|
||||
DidvanIcons.angle_left_light,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const MainPageBanner(
|
||||
isFirst: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -162,30 +208,6 @@ class _MainPageSection extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
// if (list.type == 'radar')
|
||||
// DidvanSlider(
|
||||
// height: 260,
|
||||
// itemCount: list.contents.length,
|
||||
// viewportFraction: 0.65,
|
||||
// itemBuilder: (context, index, realIndex) => Padding(
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
// child: MainPageGeneralItem(
|
||||
// content: list.contents[index],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// if (list.type == 'video')
|
||||
// DidvanSlider(
|
||||
// height: 260,
|
||||
// itemCount: list.contents.length,
|
||||
// viewportFraction: 0.65,
|
||||
// itemBuilder: (context, index, realIndex) => Padding(
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
// child: MainPageGeneralItem(
|
||||
// content: list.contents[index],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
if (list.type == 'podcast')
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 28),
|
||||
|
|
@ -206,44 +228,7 @@ class _MainPageSection extends StatelessWidget {
|
|||
.toList(),
|
||||
),
|
||||
),
|
||||
// if (list.type != 'news' &&
|
||||
// list.type != 'radar' &&
|
||||
// list.type != 'video' &&
|
||||
// list.type != 'podcast')
|
||||
// DidvanSlider(
|
||||
// itemBuilder: (context, index, realIndex) => Padding(
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
// child: MainPageGeneralItem(
|
||||
// content: list.contents[index],
|
||||
// ),
|
||||
// ),
|
||||
// itemCount: list.contents.length,
|
||||
// viewportFraction: 0.65,
|
||||
// height: 260 + _maxSublistCount() * 20,
|
||||
// ),
|
||||
// if (!isLast) const _MainPageDivider(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// class _MainPageDivider extends StatelessWidget {
|
||||
// const _MainPageDivider();
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Container(
|
||||
// height: 2,
|
||||
// margin: const EdgeInsets.only(
|
||||
// top: 8,
|
||||
// left: 20,
|
||||
// right: 20,
|
||||
// ),
|
||||
// width: double.infinity,
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: DesignConfig.highBorderRadius,
|
||||
// color: Theme.of(context).colorScheme.border,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/models/home_page_content/home_page_content.dart';
|
||||
import 'package:didvan/models/requests/infography.dart';
|
||||
import 'package:didvan/models/requests/news.dart';
|
||||
import 'package:didvan/models/requests/radar.dart';
|
||||
import 'package:didvan/providers/core.dart';
|
||||
|
|
@ -49,6 +50,17 @@ class MainPageState extends CoreProvier {
|
|||
link = link ?? '';
|
||||
dynamic args;
|
||||
switch (type) {
|
||||
case 'infography':
|
||||
{
|
||||
link = Routes.infography;
|
||||
args = {
|
||||
'onMarkChanged': (id, value) => markChangeHandler(type, id, value),
|
||||
'id': id,
|
||||
'args': const InfographyRequestArgs(page: 0),
|
||||
'hasUnmarkConfirmation': false,
|
||||
};
|
||||
break;
|
||||
}
|
||||
case 'news':
|
||||
{
|
||||
link = Routes.newsDetails;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/models/infography/infography_content.dart';
|
||||
import 'package:didvan/views/widgets/animated_visibility.dart';
|
||||
import 'package:didvan/views/widgets/didvan/card.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/infography_tag.dart';
|
||||
import 'package:didvan/views/widgets/ink_wrapper.dart';
|
||||
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class _BackButton extends StatefulWidget {
|
||||
const _BackButton({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
__BackButtonState createState() => __BackButtonState();
|
||||
}
|
||||
|
||||
class __BackButtonState extends State<_BackButton> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedVisibility(
|
||||
duration: DesignConfig.lowAnimationDuration,
|
||||
isVisible: true,
|
||||
child: InkWrapper(
|
||||
borderRadius: DesignConfig.lowBorderRadius,
|
||||
onPressed: Navigator.of(context).pop,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.splash,
|
||||
border: Border.all(color: Theme.of(context).colorScheme.border),
|
||||
borderRadius: DesignConfig.lowBorderRadius,
|
||||
),
|
||||
child: const Icon(
|
||||
DidvanIcons.back_regular,
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class InfographyItem extends StatelessWidget {
|
||||
final String image;
|
||||
final String title;
|
||||
final String category;
|
||||
final List<Tag> tag;
|
||||
|
||||
const InfographyItem(
|
||||
{super.key,
|
||||
required this.image,
|
||||
required this.category,
|
||||
required this.title,
|
||||
required this.tag});
|
||||
|
||||
void _openInteractiveViewer(BuildContext context, String image) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: InteractiveViewer(
|
||||
child: Center(
|
||||
child: SkeletonImage(
|
||||
width: min(MediaQuery.of(context).size.width,
|
||||
MediaQuery.of(context).size.height),
|
||||
imageUrl: image,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Positioned(
|
||||
right: 24,
|
||||
top: 24,
|
||||
child: _BackButton(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DidvanCard(
|
||||
margin: const EdgeInsets.all(12),
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: DidvanText(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: GestureDetector(
|
||||
onTap: () => _openInteractiveViewer(context, image),
|
||||
child: SkeletonImage(
|
||||
imageUrl: image,
|
||||
aspectRatio: 16 / 9,
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Wrap(
|
||||
spacing: 4,
|
||||
runSpacing: 4,
|
||||
children: [
|
||||
for (var i = 0; i < tag.length; i++)
|
||||
InfographyTag(
|
||||
tag: tag[i],
|
||||
),
|
||||
],
|
||||
),
|
||||
InfoCat(category: category)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,16 +15,6 @@ class MainPageMainContent extends StatelessWidget {
|
|||
isFirst: true,
|
||||
),
|
||||
const SizedBox(height: 28),
|
||||
// Stack(
|
||||
// children: [
|
||||
// Positioned(
|
||||
// bottom: 13,
|
||||
// child: Container(
|
||||
// width: MediaQuery.of(context).size.width,
|
||||
// height: 2,
|
||||
// color: Theme.of(context).colorScheme.border,
|
||||
// ),
|
||||
// ),
|
||||
Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/models/infography/infography_content.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/ink_wrapper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class InfographyTag extends StatelessWidget {
|
||||
final Tag tag;
|
||||
|
||||
const InfographyTag({
|
||||
Key? key,
|
||||
required this.tag,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWrapper(
|
||||
borderRadius: DesignConfig.lowBorderRadius,
|
||||
onPressed: () => {},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: DesignConfig.lowBorderRadius,
|
||||
border: Border.all(
|
||||
color: Theme.of(context).colorScheme.focusedBorder,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
DidvanIcons.hashtag_regular,
|
||||
color: Theme.of(context).colorScheme.focusedBorder,
|
||||
size: 16,
|
||||
),
|
||||
DidvanText(
|
||||
tag.label,
|
||||
color: Theme.of(context).colorScheme.focusedBorder,
|
||||
style: Theme.of(context).textTheme.labelLarge,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class InfoCat extends StatelessWidget {
|
||||
final String category;
|
||||
|
||||
const InfoCat({
|
||||
Key? key,
|
||||
required this.category,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWrapper(
|
||||
borderRadius: DesignConfig.lowBorderRadius,
|
||||
onPressed: () => {},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: DesignConfig.lowBorderRadius,
|
||||
border: Border.all(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
),
|
||||
child: DidvanText(
|
||||
category,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
style: Theme.of(context).textTheme.labelLarge,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,9 @@ class _SearchFieldState extends State<SearchField> {
|
|||
@override
|
||||
void initState() {
|
||||
widget.focusNode.addListener(() {
|
||||
setState(() {});
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
|
|
|||
48
pubspec.lock
48
pubspec.lock
|
|
@ -9,6 +9,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.7"
|
||||
animated_custom_dropdown:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: animated_custom_dropdown
|
||||
sha256: "9e286defa42f2e774285015d7ff29523a24260888d53f79a3635328fad5bdad7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -134,10 +142,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: collection
|
||||
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.2"
|
||||
version: "1.18.0"
|
||||
cross_file:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -442,10 +450,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: fwfh_text_style
|
||||
sha256: f0883ccb64b7bb3f2a7a091542c2e834fc3e2a6aa54158f46b3c43b55675d8f7
|
||||
sha256: "5f8b587fd223a6bf14aad3d3da5e7ced0628becbd0768f8e7ae25ff6b9f3d2ec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.22.8+3"
|
||||
version: "2.23.8"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -598,14 +606,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -626,10 +626,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.10.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -927,18 +927,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -967,10 +967,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
version: "0.6.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1151,10 +1151,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
version: "0.3.0"
|
||||
webview_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -1212,5 +1212,5 @@ packages:
|
|||
source: hosted
|
||||
version: "6.3.0"
|
||||
sdks:
|
||||
dart: ">=3.1.0 <4.0.0"
|
||||
flutter: ">=3.13.0"
|
||||
dart: ">=3.2.0-194.0.dev <4.0.0"
|
||||
flutter: ">=3.14.0-0"
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ dependencies:
|
|||
assets_audio_player: ^3.1.1
|
||||
fl_chart: ^0.63.0
|
||||
collection: ^1.17.2
|
||||
animated_custom_dropdown: ^3.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Reference in New Issue