Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 110 additions & 57 deletions lib/screens/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import 'package:rentool/services/auth.dart';
import 'package:rentool/services/firestore.dart';
import 'package:rentool/widgets/compact_tool_tile.dart';
import 'package:rentool/widgets/logo_image.dart';
import 'package:rentool/widgets/rentool_circle_avatar.dart';
import 'package:rentool/widgets/rentool_search_bar.dart';
import 'package:rentool/widgets/retractable_tile.dart';
import 'package:rentool/widgets/user_listtile.dart';

class HomePage extends StatefulWidget {
Expand Down Expand Up @@ -49,41 +51,51 @@ class _HomePageState extends State<HomePage> {
super.dispose();
}

bool compactDrawer = false;

void onTapUserDrawerTile() {
Navigator.pop(context);
Navigator.of(context).pushNamed(
UserScreen.routeName,
arguments: UserScreenArguments(uid: AuthServices.currentUid!),
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: RentoolSearchAppBar(
textFieldContoller: _searchController,
onSubmitted: (value) async {
if (value.trim().isEmpty) return;
await Navigator.pushNamed(
context,
SearchScreen.routeName,
arguments: value.trim(),
);
setState(() {
_searchController.clear();
});
},
),
// TODO invistigate opening the drawer causes auth stream to trigger
drawer: Drawer(
final size = MediaQuery.of(context).size;

bool showDrawer = size.width >= 850;

var drawer = SizedBox(
width: compactDrawer ? 70 : null,
child: Drawer(
elevation: showDrawer ? 0 : null,
child: ListView(
children: [
DrawerHeader(
child: LogoImage.primary(),
margin: EdgeInsets.zero,
),
UserListTile(
user: AuthServices.auth.currentUser!,
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed(
UserScreen.routeName,
arguments: UserScreenArguments(uid: AuthServices.currentUid!),
);
},
),
if (!showDrawer)
DrawerHeader(
child: LogoImage.primary(),
margin: EdgeInsets.zero,
)
else
const SizedBox(height: 20),

// User tile
if (compactDrawer)
Padding(
padding: const EdgeInsets.all(8.0),
child: RentoolCircleAvatar.firebaseUser(
user: AuthServices.currentUser!,
),
)
else
UserListTile(
user: AuthServices.auth.currentUser!,
onTap: onTapUserDrawerTile,
),

// Admin panel
FutureBuilder(
future: AuthServices.getIdTokenResult(),
builder: (context, AsyncSnapshot<IdTokenResult?> snapshot) {
Expand All @@ -102,41 +114,46 @@ class _HomePageState extends State<HomePage> {
},
),
const Divider(height: 2),
ListTile(
leading: const Icon(Icons.notifications),
RetractableTile(
compact: compactDrawer,
icon: const Icon(Icons.notifications),
title: Text(AppLocalizations.of(context)!.notifications),
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed(MyNotificationsScreen.routeName);
},
),
ListTile(
leading: const Icon(Icons.send_rounded),
RetractableTile(
compact: compactDrawer,
icon: const Icon(Icons.send_rounded),
title: Text(AppLocalizations.of(context)!.myRequests),
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed(MyRequestsScreen.routeName);
},
),
ListTile(
leading: const Icon(Icons.build_circle),
RetractableTile(
compact: compactDrawer,
icon: const Icon(Icons.build_circle),
title: Text(AppLocalizations.of(context)!.myTools),
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed(MyToolsScreen.routeName);
},
),
const Divider(),
ListTile(
leading: const Icon(Icons.settings),
RetractableTile(
compact: compactDrawer,
icon: const Icon(Icons.settings),
title: Text(AppLocalizations.of(context)!.settings),
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed(SettingsScreen.routeName);
},
),
ListTile(
leading: const Icon(Icons.support),
RetractableTile(
compact: compactDrawer,
icon: const Icon(Icons.support),
title: Text(AppLocalizations.of(context)!.support),
onTap: () async {
Navigator.pop(context);
Expand All @@ -159,24 +176,60 @@ class _HomePageState extends State<HomePage> {
],
),
),
body: Padding(
padding: const EdgeInsets.all(15),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const WelcomeToRentool(),
const Divider(),
const SizedBox(height: 10),
Text(
AppLocalizations.of(context)!.random_tools.toUpperCase(),
style: Theme.of(context).textTheme.overline,
);

return Scaffold(
appBar: RentoolSearchAppBar(
leadingIcon: IconButton(
icon: const Icon(Icons.menu),
onPressed: () => setState(() {
compactDrawer = !compactDrawer;
}),
),
textFieldContoller: _searchController,
onSubmitted: (value) async {
if (value.trim().isEmpty) return;
await Navigator.pushNamed(
context,
SearchScreen.routeName,
arguments: value.trim(),
);
setState(() {
_searchController.clear();
});
},
),
// TODO invistigate opening the drawer causes auth stream to trigger
drawer: showDrawer ? null : drawer,
body: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (showDrawer) ...[
drawer,
const VerticalDivider(width: 1),
],
Expanded(
child: Padding(
padding: const EdgeInsets.all(15),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const WelcomeToRentool(),
const Divider(),
const SizedBox(height: 10),
Text(
AppLocalizations.of(context)!.random_tools.toUpperCase(),
style: Theme.of(context).textTheme.overline,
),
const SizedBox(height: 7),
_buildRandomToolsWrap(),
],
),
),
const SizedBox(height: 7),
_buildRandomToolsWrap(),
],
),
),
),
],
),
);
}
Expand Down
37 changes: 30 additions & 7 deletions lib/screens/post_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -494,13 +494,7 @@ class _PostScreenState extends State<PostScreen> {
scrollDirection: Axis.horizontal,
children: [
if (tool.media.isNotEmpty)
for (var url in tool.media)
Center(
child: MediaContainer(
mediaURL: url,
showDismiss: false,
),
)
for (var url in tool.media) MediaContainerPage(url: url)
else
Center(
child: Text(
Expand Down Expand Up @@ -540,3 +534,32 @@ class _PostScreenState extends State<PostScreen> {
);
}
}

class MediaContainerPage extends StatefulWidget {
const MediaContainerPage({
Key? key,
required this.url,
}) : super(key: key);

final String url;

@override
State<MediaContainerPage> createState() => _MediaContainerPageState();
}

class _MediaContainerPageState extends State<MediaContainerPage>
with AutomaticKeepAliveClientMixin<MediaContainerPage> {
@override
Widget build(BuildContext context) {
super.build(context);
return Center(
child: MediaContainer(
mediaURL: widget.url,
showDismiss: false,
),
);
}

@override
bool get wantKeepAlive => true;
}
16 changes: 5 additions & 11 deletions lib/widgets/compact_tool_tile.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:rentool/models/rentool/rentool_models.dart';
Expand Down Expand Up @@ -53,18 +54,11 @@ class CompactToolTile extends StatelessWidget {
if (tool.media.isNotEmpty) {
return ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
tool.media.first,
child: CachedNetworkImage(
imageUrl: tool.media.first,
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
: null,
),
);
placeholder: (context, string) {
return const Center(child: CircularProgressIndicator());
},
),
);
Expand Down
3 changes: 2 additions & 1 deletion lib/widgets/media_container.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:io';
import 'dart:typed_data';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:http/http.dart' as http;
Expand Down Expand Up @@ -140,7 +141,7 @@ class MediaContainer extends StatelessWidget {
if (data != null) {
imageProvider = MemoryImage(data);
} else if (mediaURL != null) {
imageProvider = NetworkImage(mediaURL!);
imageProvider = CachedNetworkImageProvider(mediaURL!);
} else if (mediaFile != null) {
imageProvider = FileImage(mediaFile!);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/widgets/rentool_circle_avatar.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:rentool/models/rentool/rentool_models.dart';
Expand Down Expand Up @@ -35,7 +36,7 @@ class RentoolCircleAvatar extends StatelessWidget {
Widget build(BuildContext context) {
return CircleAvatar(
backgroundColor: user?.photoURL == null ? Colors.black12 : null,
backgroundImage: user?.photoURL != null ? NetworkImage(user!.photoURL!) : null,
backgroundImage: user?.photoURL != null ? CachedNetworkImageProvider(user!.photoURL!) : null,
child: user?.photoURL == null
? const Icon(
Icons.person,
Expand Down
Loading