mirror of
https://github.com/meditohq/medito-app.git
synced 2024-09-11 12:15:46 +03:00
Fix home screen (#639)
* fix: shortcut grid fixed, home screen shimmer flickering fixed * fix: home screen tiles fixed * chore: fix naming convention * fix: naming convention fixed
This commit is contained in:
parent
1bc54d0c5a
commit
e2cc35c27a
@ -8,6 +8,9 @@ const String materialIcons = 'MaterialIcons';
|
||||
const padding12 = 12.0;
|
||||
const padding16 = 16.0;
|
||||
const padding20 = 20.0;
|
||||
const fontSize16 = 16.0;
|
||||
const fontSize14 = 14.0;
|
||||
const smallScreenWidth = 480.0;
|
||||
const miniPlayerHeight = 56.0;
|
||||
const height32 = SizedBox(height: 32);
|
||||
const height24 = SizedBox(height: 24);
|
||||
|
@ -58,7 +58,7 @@ class _HomeViewState extends ConsumerState<HomeView>
|
||||
height24,
|
||||
TilesWidget(),
|
||||
SizedBox(
|
||||
height: 120,
|
||||
height: 140,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -74,16 +74,14 @@ class _HomeViewState extends ConsumerState<HomeView>
|
||||
}
|
||||
|
||||
Future<void> _onRefresh() async {
|
||||
ref.invalidate(homeProvider);
|
||||
await ref.read(homeProvider.future);
|
||||
ref.invalidate(remoteStatsProvider);
|
||||
await ref.read(remoteStatsProvider.future);
|
||||
ref.invalidate(fetchHomeHeaderProvider);
|
||||
await ref.read(fetchHomeHeaderProvider.future);
|
||||
ref.invalidate(fetchShortcutsProvider);
|
||||
await ref.read(fetchShortcutsProvider.future);
|
||||
ref.invalidate(fetchQuoteProvider);
|
||||
await ref.read(fetchQuoteProvider.future);
|
||||
ref.invalidate(fetchHomeHeaderProvider);
|
||||
await ref.read(fetchHomeHeaderProvider.future);
|
||||
ref.invalidate(remoteStatsProvider);
|
||||
await ref.read(remoteStatsProvider.future);
|
||||
}
|
||||
|
||||
FloatingActionButton _buildFloatingButton(BuildContext context) {
|
||||
|
@ -6,7 +6,7 @@ import 'package:Medito/utils/utils.dart';
|
||||
import 'package:Medito/widgets/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:reorderable_grid_view/reorderable_grid_view.dart';
|
||||
import 'package:reorderables/reorderables.dart';
|
||||
|
||||
class ShortcutsWidget extends ConsumerStatefulWidget {
|
||||
const ShortcutsWidget({super.key});
|
||||
@ -17,95 +17,16 @@ class ShortcutsWidget extends ConsumerStatefulWidget {
|
||||
|
||||
class _ShortcutsWidgetState extends ConsumerState<ShortcutsWidget> {
|
||||
late ShortcutsModel data;
|
||||
|
||||
late List<Widget> shortcutsWidgetList = [];
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var response = ref.watch(fetchShortcutsProvider);
|
||||
ref.listen(fetchShortcutsProvider, (previous, next) {
|
||||
if (next.hasValue) {
|
||||
data = next.value!;
|
||||
}
|
||||
});
|
||||
|
||||
return response.when(
|
||||
skipLoadingOnRefresh: false,
|
||||
skipLoadingOnReload: true,
|
||||
data: (_) => _buildShortcuts(),
|
||||
error: (err, stack) => MeditoErrorWidget(
|
||||
message: err.toString(),
|
||||
onTap: () => ref.refresh(fetchShortcutsProvider),
|
||||
isLoading: response.isLoading,
|
||||
isScaffold: false,
|
||||
),
|
||||
loading: () => const ShortcutsShimmerWidget(),
|
||||
);
|
||||
}
|
||||
|
||||
Padding _buildShortcuts() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(canvasColor: ColorConstants.onyx),
|
||||
child: ReorderableGridView.count(
|
||||
crossAxisSpacing: 8,
|
||||
mainAxisSpacing: 8,
|
||||
crossAxisCount: 2,
|
||||
shrinkWrap: true,
|
||||
childAspectRatio: 3,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
padding: EdgeInsets.zero,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
children: data.shortcuts
|
||||
.map(
|
||||
(e) => InkWell(
|
||||
key: ValueKey(e.id),
|
||||
onTap: () => handleNavigation(context: context, e.type, [
|
||||
e.path.toString().getIdFromPath(),
|
||||
e.path,
|
||||
]),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
color: ColorConstants.onyx,
|
||||
),
|
||||
padding: EdgeInsets.all(12),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
e.title,
|
||||
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
onReorder: (oldIndex, newIndex) {
|
||||
setState(() {
|
||||
var _data = [...data.shortcuts];
|
||||
final element = _data.removeAt(oldIndex);
|
||||
_data.insert(newIndex, element);
|
||||
data = data.copyWith(shortcuts: _data);
|
||||
var ids = _data.map((e) => e.id).toList();
|
||||
ref.read(updateShortcutsIdsInPreferenceProvider(ids: ids));
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void handleChipPress(
|
||||
void _handleChipPress(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
HomeChipsItemsModel element,
|
||||
ShortcutsItemsModel element,
|
||||
) async {
|
||||
_handleTrackEvent(ref, element.id, element.title);
|
||||
await handleNavigation(
|
||||
@ -124,4 +45,99 @@ class _ShortcutsWidgetState extends ConsumerState<ShortcutsWidget> {
|
||||
);
|
||||
ref.read(eventsProvider(event: event.toJson()));
|
||||
}
|
||||
|
||||
void _onReorder(int oldIndex, int newIndex) {
|
||||
setState(() {
|
||||
_handleShortcutWidgetPlacement(newIndex, oldIndex);
|
||||
_handleShortcutItemPlacementInPreference(oldIndex, newIndex);
|
||||
});
|
||||
}
|
||||
|
||||
void _handleShortcutItemPlacementInPreference(int oldIndex, int newIndex) {
|
||||
var _data = [...data.shortcuts];
|
||||
final element = _data.removeAt(oldIndex);
|
||||
_data.insert(newIndex, element);
|
||||
data = data.copyWith(shortcuts: _data);
|
||||
var ids = _data.map((e) => e.id).toList();
|
||||
ref.read(updateShortcutsIdsInPreferenceProvider(ids: ids));
|
||||
}
|
||||
|
||||
void _handleShortcutWidgetPlacement(int newIndex, int oldIndex) {
|
||||
shortcutsWidgetList.insert(
|
||||
newIndex,
|
||||
shortcutsWidgetList.removeAt(oldIndex),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var response = ref.watch(fetchShortcutsProvider);
|
||||
ref.listen(fetchShortcutsProvider, (previous, next) {
|
||||
if (next.hasValue) {
|
||||
data = next.value!;
|
||||
shortcutsWidgetList = _getShortcutsItemWidgetList();
|
||||
}
|
||||
});
|
||||
|
||||
return response.when(
|
||||
skipLoadingOnRefresh: false,
|
||||
skipLoadingOnReload: true,
|
||||
data: (_) => _buildShortcuts(),
|
||||
error: (err, stack) => MeditoErrorWidget(
|
||||
message: err.toString(),
|
||||
onTap: () => ref.refresh(fetchShortcutsProvider),
|
||||
isLoading: response.isLoading,
|
||||
isScaffold: false,
|
||||
),
|
||||
loading: () => const ShortcutsShimmerWidget(),
|
||||
);
|
||||
}
|
||||
|
||||
ReorderableWrap _buildShortcuts() {
|
||||
return ReorderableWrap(
|
||||
spacing: 8.0,
|
||||
runSpacing: 8.0,
|
||||
padding: EdgeInsets.zero,
|
||||
maxMainAxisCount: 2,
|
||||
minMainAxisCount: 2,
|
||||
onReorder: _onReorder,
|
||||
children: shortcutsWidgetList,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _getShortcutsItemWidgetList() {
|
||||
var size = MediaQuery.of(context).size;
|
||||
final containerHeight = 48.0;
|
||||
final containerWidth = (size.width / 2) - (padding20 + 2);
|
||||
|
||||
return data.shortcuts
|
||||
.map((e) => IntrinsicWidth(
|
||||
child: InkWell(
|
||||
key: ValueKey(e.id),
|
||||
onTap: () => _handleChipPress(context, ref, e),
|
||||
child: Container(
|
||||
height: containerHeight,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
color: ColorConstants.onyx,
|
||||
),
|
||||
padding: EdgeInsets.all(12),
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: containerWidth,
|
||||
minWidth: containerWidth,
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
'${e.title}',
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ class TilesWidget extends ConsumerWidget {
|
||||
|
||||
return stats.when(
|
||||
skipLoadingOnRefresh: false,
|
||||
data: (data) => _buildTiles(context, ref, data.tiles),
|
||||
data: (data) => _buildTiles(ref, data.tiles),
|
||||
error: (err, stack) => Expanded(
|
||||
child: MeditoErrorWidget(
|
||||
message: err.toString(),
|
||||
@ -31,7 +31,6 @@ class TilesWidget extends ConsumerWidget {
|
||||
}
|
||||
|
||||
Padding _buildTiles(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
List<TilesModel> data,
|
||||
) {
|
||||
@ -40,10 +39,6 @@ class TilesWidget extends ConsumerWidget {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: data.map((e) {
|
||||
var fontStyle = Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
fontFamily: DmSerif,
|
||||
color: ColorConstants.walterWhite,
|
||||
);
|
||||
var isFirstItem = data[0] == e;
|
||||
|
||||
return Expanded(
|
||||
@ -51,39 +46,51 @@ class TilesWidget extends ConsumerWidget {
|
||||
padding: EdgeInsets.only(
|
||||
left: padding16,
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: isFirstItem ? () => onTapTile(context, ref) : null,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
color: ColorConstants.onyx,
|
||||
),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
padding: EdgeInsets.all(padding16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(
|
||||
IconData(
|
||||
formatIcon(e.icon),
|
||||
fontFamily: materialIcons,
|
||||
),
|
||||
size: 24,
|
||||
color: ColorConstants.getColorFromString(e.color),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
var fontSize = _getFontSize(constraints);
|
||||
var fontStyle =
|
||||
Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
fontFamily: DmSerif,
|
||||
color: ColorConstants.walterWhite,
|
||||
fontSize: fontSize,
|
||||
);
|
||||
|
||||
return InkWell(
|
||||
onTap: isFirstItem ? () => _onTapTile(context, ref) : null,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
color: ColorConstants.onyx,
|
||||
),
|
||||
height8,
|
||||
Text(
|
||||
e.title,
|
||||
style: fontStyle,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
padding: EdgeInsets.all(padding16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(
|
||||
IconData(
|
||||
formatIcon(e.icon),
|
||||
fontFamily: materialIcons,
|
||||
),
|
||||
size: 24,
|
||||
color: ColorConstants.getColorFromString(e.color),
|
||||
),
|
||||
height8,
|
||||
Text(
|
||||
e.title,
|
||||
style: fontStyle,
|
||||
),
|
||||
height4,
|
||||
Text(
|
||||
e.subtitle,
|
||||
style: fontStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
height4,
|
||||
Text(
|
||||
e.subtitle,
|
||||
style: fontStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -92,7 +99,17 @@ class TilesWidget extends ConsumerWidget {
|
||||
);
|
||||
}
|
||||
|
||||
void onTapTile(BuildContext context, WidgetRef ref) {
|
||||
double _getFontSize(BoxConstraints constraints) {
|
||||
final width = constraints.maxWidth;
|
||||
var fontSize = fontSize16;
|
||||
if (width <= smallScreenWidth) {
|
||||
fontSize = fontSize14;
|
||||
}
|
||||
|
||||
return fontSize;
|
||||
}
|
||||
|
||||
void _onTapTile(BuildContext context, WidgetRef ref) {
|
||||
ref.invalidate(remoteStatsProvider);
|
||||
ref.read(remoteStatsProvider);
|
||||
showModalBottomSheet<void>(
|
||||
|
@ -1089,14 +1089,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
reorderable_grid_view:
|
||||
reorderables:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: reorderable_grid_view
|
||||
sha256: e36c6229a97105a10c79e15ab4b9b14ee9f6c488574ff2be9e858c82af47cda6
|
||||
name: reorderables
|
||||
sha256: "004a886e4878df1ee27321831c838bc1c976311f4ca6a74ce7d561e506540a77"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.8"
|
||||
version: "0.6.0"
|
||||
riverpod:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -65,7 +65,7 @@ dependencies:
|
||||
permission_handler: ^10.4.5
|
||||
app_settings: ^5.1.1
|
||||
vibration: ^1.7.3
|
||||
reorderable_grid_view: ^2.2.8
|
||||
reorderables: ^0.6.0
|
||||
|
||||
dependency_overrides:
|
||||
firebase_core_platform_interface: 4.5.1
|
||||
|
Loading…
Reference in New Issue
Block a user