Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PAINTROID-490 : Search bar on Landing Page #47

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
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
5 changes: 5 additions & 0 deletions lib/pocket_paint_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:l10n/l10n.dart';
import 'package:landing_page_screen/landing_page_screen.dart';
import 'package:onboarding_screen/onboarding_screen.dart';
import 'package:search_bar_screen/search_page_screen.dart';
import 'package:workspace_screen/workspace_screen.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

Expand Down Expand Up @@ -47,6 +48,10 @@ class PocketPaintApp extends StatelessWidget {
return MaterialPageRoute(
builder: (context) => const OnboardingPage(),
);
case '/SearchScreenPage':
return MaterialPageRoute(
builder: (context) => const SearchScreen(),
);
}
return null;
},
Expand Down
17 changes: 15 additions & 2 deletions packages/features/landing_page_screen/lib/src/landing_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class LandingPage extends ConsumerStatefulWidget {
}

class _LandingPageState extends ConsumerState<LandingPage> {
late ProjectDatabase database;
late ProjectDatabase database = database;
late IFileService fileService;
late IImageService imageService;

Expand All @@ -30,6 +30,11 @@ class _LandingPageState extends ConsumerState<LandingPage> {
setState(() {});
}

Future<void> _navigateToSearchScreen() async {
await Navigator.pushNamed(context, '/SearchScreenPage');
setState(() {});
}

Future<bool> _loadProject(IOHandler ioHandler, Project project) async {
project.lastModified = DateTime.now();
await database.projectDAO.insertProject(project);
Expand Down Expand Up @@ -80,7 +85,15 @@ class _LandingPageState extends ConsumerState<LandingPage> {
backgroundColor: lightColorScheme.primary,
appBar: AppBar(
title: Text(widget.title),
actions: const [MainOverflowMenu()],
actions: [
IconButton(
icon: const Icon(Icons.search_rounded, color: Colors.white),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use custom colors we have in light theme. i think: lightColorTheme.onSurface is white color

onPressed: () async {
_navigateToSearchScreen();
}
),
const MainOverflowMenu()
]
),
body: FutureBuilder(
future: _getProjects(),
Expand Down
23 changes: 23 additions & 0 deletions packages/features/search_bar_screen/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
include: package:flutter_lints/flutter.yaml
linter:
rules:
always_use_package_imports: true
avoid_relative_lib_imports: true
prefer_relative_imports: false
prefer_single_quotes: true
avoid_void_async: true
constant_identifier_names: false

analyzer:
errors:
missing_enum_constant_in_switch: error
exhaustive_cases: error
unused_element: error
type_annotate_public_apis: error
missing_required_param: error
invalid_use_of_protected_member: error
unused_import: error

exclude:
- lib/src/**.pb*.dart
- lib/src/data/*.g.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
library search_bar_screen;

export '../src/search_screen.dart';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is duplicated code? it already exists in landing page screen. you can move that code in the component library and use it in both screen packages

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import 'package:component_library/component_library.dart';
import 'package:database/database.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:io_library/io_library.dart';

class ImagePreview extends StatelessWidget {
final Project? project;
final double? width;
final Color color;
final IImageService imageService;

const ImagePreview({
Key? key,
this.width,
required this.color,
this.project,
required this.imageService,
}) : super(key: key);

ImageProvider _getProjectPreviewImageProvider(Uint8List img) =>
Image.memory(img, fit: BoxFit.cover).image;

Uint8List? _getProjectPreview(String? path) =>
imageService.getProjectPreview(path).when(
ok: (preview) => preview,
err: (failure) {
ToastUtils.showShortToast(message: failure.message);
return null;
},
);

@override
Widget build(BuildContext context) {
Uint8List? img;
if (project != null) {
img = _getProjectPreview(project!.imagePreviewPath);
}
var imgPreview = BoxDecoration(color: color);
if (img != null) {
imgPreview = BoxDecoration(
color: color,
image: DecorationImage(
image: _getProjectPreviewImageProvider(img),
),
);
}
if (width != null) {
return Container(
width: width!,
decoration: imgPreview,
);
} else {
return Container(
decoration: imgPreview,
);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicated code

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import 'package:database/database.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:io_library/io_library.dart';
import 'package:search_bar_screen/src/components/image_preview.dart';
import 'package:search_bar_screen/src/components/project_overflow_menu.dart';

class ProjectListTile extends StatelessWidget {
final Project project;
final IImageService imageService;
final int index;
final VoidCallback onTap;

const ProjectListTile({
super.key,
required this.project,
required this.imageService,
required this.index,
required this.onTap,
});

@override
Widget build(BuildContext context) {
final DateFormat dateFormat = DateFormat('dd-MM-yyyy');

return Card(
child: ListTile(
leading: ImagePreview(
project: project,
imageService: imageService,
width: 80,
color: Colors.white,
),
dense: false,
title: Text(
project.name,
style: const TextStyle(color: Color(0xFFFFFFFF)),
),
subtitle: Text(
'last modified: ${dateFormat.format(project.lastModified)}',
style: const TextStyle(color: Color(0xFFFFFFFF)),
),
trailing: ProjectOverflowMenu(
key: Key('ProjectOverflowMenu Key$index'),
project: project,
),
enabled: true,
onTap: onTap,
),
);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicated code

Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import 'dart:io';

import 'package:component_library/component_library.dart';
import 'package:database/database.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:io_library/io_library.dart';

enum ProjectOverflowMenuOption {
deleteProject('Delete'),
getDetails('Details');

const ProjectOverflowMenuOption(this.label);

final String label;
}

class ProjectOverflowMenu extends ConsumerStatefulWidget {
final Project project;

const ProjectOverflowMenu({Key? key, required this.project})
: super(key: key);

@override
ConsumerState<ProjectOverflowMenu> createState() =>
_ProjectOverFlowMenuState();
}

class _ProjectOverFlowMenuState extends ConsumerState<ProjectOverflowMenu> {
late ProjectDatabase database;

@override
Widget build(BuildContext context) {
final db = ref.watch(ProjectDatabase.provider);
db.when(
data: (value) => database = value,
error: (err, stacktrace) =>
ToastUtils.showShortToast(message: 'Error: $err'),
loading: () {},
);

return PopupMenuButton(
color: Theme.of(context).colorScheme.background,
icon: const Icon(Icons.more_vert),
shape: RoundedRectangleBorder(
side: const BorderSide(),
borderRadius: BorderRadius.circular(20),
),
onSelected: _handleSelectedOption,
itemBuilder: (BuildContext context) => ProjectOverflowMenuOption.values
.map((option) =>
PopupMenuItem(value: option, child: Text(option.label)))
.toList(),
);
}

void _handleSelectedOption(ProjectOverflowMenuOption option) {
switch (option) {
case ProjectOverflowMenuOption.deleteProject:
_deleteProject();
break;
case ProjectOverflowMenuOption.getDetails:
_showProjectDetails();
break;
}
}

Future<void> _deleteProject() async {
bool? shouldDelete = await showDeleteDialog(context, widget.project.name);
if (shouldDelete != null && shouldDelete) {
try {
final projectFile = File(widget.project.path);
await projectFile.delete();
if (widget.project.imagePreviewPath != null) {
final previewFile = File(widget.project.imagePreviewPath!);
await previewFile.delete();
}
} catch (err) {
ToastUtils.showShortToast(message: err.toString());
}
if (widget.project.id != null) {
await database.projectDAO.deleteProject(widget.project.id!);
ref.invalidate(ProjectDatabase.provider);
}
}
}

Future<void> _showProjectDetails() async {
await showDetailsDialog(context, widget.project);
}
}
Loading
Loading