forked from kherel/selfprivacy.org.app
parent
e849b551fc
commit
d3f494adeb
@ -1,7 +0,0 @@ |
||||
import 'package:flutter/material.dart'; |
||||
|
||||
final shadow8 = BoxShadow( |
||||
offset: Offset(0, 4), |
||||
blurRadius: 8, |
||||
color: Colors.black.withOpacity(.08), |
||||
); |
@ -0,0 +1,27 @@ |
||||
import 'package:flutter_bloc/flutter_bloc.dart'; |
||||
import 'package:selfprivacy/logic/models/job.dart'; |
||||
import 'package:equatable/equatable.dart'; |
||||
export 'package:provider/provider.dart'; |
||||
|
||||
part 'jobs_state.dart'; |
||||
|
||||
class JobsCubit extends Cubit<JobsState> { |
||||
JobsCubit() : super(JobsState.emtpy()); |
||||
|
||||
List<Job> jobsList = []; |
||||
|
||||
void addJob(Job job) { |
||||
final newState = state.addJob(job); |
||||
emit(newState); |
||||
} |
||||
|
||||
void removeJob(String id) { |
||||
final newState = state.removeById(id); |
||||
emit(newState); |
||||
} |
||||
|
||||
void applyAll() { |
||||
print(state.jobList); |
||||
emit(JobsState.emtpy()); |
||||
} |
||||
} |
@ -0,0 +1,25 @@ |
||||
part of 'jobs_cubit.dart'; |
||||
|
||||
class JobsState extends Equatable { |
||||
const JobsState(this.jobList); |
||||
|
||||
final List<Job> jobList; |
||||
|
||||
static JobsState emtpy() => JobsState([]); |
||||
|
||||
bool get isEmpty => jobList.isEmpty; |
||||
|
||||
JobsState addJob(Job job) { |
||||
var newJobsList = [...jobList]; |
||||
newJobsList.add(job); |
||||
return JobsState(newJobsList); |
||||
} |
||||
|
||||
JobsState removeById(String id) { |
||||
var newJobsList = jobList.where((element) => element.id != id).toList(); |
||||
return JobsState(newJobsList); |
||||
} |
||||
|
||||
@override |
||||
List<Object> get props => jobList; |
||||
} |
@ -0,0 +1,15 @@ |
||||
import 'package:equatable/equatable.dart'; |
||||
import 'package:selfprivacy/utils/password_generator2.dart'; |
||||
|
||||
class Job extends Equatable { |
||||
Job({ |
||||
String? id, |
||||
required this.title, |
||||
}) : id = id ?? getRandomString(5); |
||||
|
||||
final String title; |
||||
final String id; |
||||
|
||||
@override |
||||
List<Object> get props => [id, title]; |
||||
} |
@ -0,0 +1,26 @@ |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:selfprivacy/config/brand_theme.dart'; |
||||
|
||||
class BrandBottomSheet extends StatelessWidget { |
||||
const BrandBottomSheet({Key? key, required this.child}) : super(key: key); |
||||
|
||||
final Widget child; |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Container( |
||||
height: MediaQuery.of(context).size.height - |
||||
MediaQuery.of(context).padding.top - |
||||
60, |
||||
child: Scaffold( |
||||
body: SingleChildScrollView( |
||||
physics: ClampingScrollPhysics(), |
||||
child: Container( |
||||
padding: paddingH15V0, |
||||
child: child, |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,29 +0,0 @@ |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:selfprivacy/config/brand_colors.dart'; |
||||
import 'package:selfprivacy/utils/extensions/elevation_extension.dart'; |
||||
|
||||
class BrandCard extends StatelessWidget { |
||||
const BrandCard({ |
||||
Key? key, |
||||
this.child, |
||||
}) : super(key: key); |
||||
|
||||
final Widget? child; |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Container( |
||||
decoration: BoxDecoration( |
||||
color: Theme.of(context).brightness == Brightness.dark |
||||
? BrandColors.black |
||||
: BrandColors.white, |
||||
borderRadius: BorderRadius.circular(20), |
||||
).ev8, |
||||
padding: EdgeInsets.symmetric( |
||||
horizontal: 20, |
||||
vertical: 15, |
||||
), |
||||
child: child, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,61 @@ |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:selfprivacy/config/brand_colors.dart'; |
||||
|
||||
class BrandCards { |
||||
static Widget big({required Widget child}) => _BrandCard( |
||||
child: child, |
||||
padding: EdgeInsets.symmetric( |
||||
horizontal: 20, |
||||
vertical: 15, |
||||
), |
||||
shadow: bigShadow, |
||||
borderRadius: BorderRadius.circular(20), |
||||
); |
||||
static Widget small({required Widget child}) => _BrandCard( |
||||
child: child, |
||||
padding: EdgeInsets.symmetric( |
||||
horizontal: 15, |
||||
vertical: 10, |
||||
), |
||||
shadow: bigShadow, |
||||
borderRadius: BorderRadius.circular(10), |
||||
); |
||||
} |
||||
|
||||
class _BrandCard extends StatelessWidget { |
||||
const _BrandCard({ |
||||
Key? key, |
||||
required this.child, |
||||
required this.padding, |
||||
required this.shadow, |
||||
required this.borderRadius, |
||||
}) : super(key: key); |
||||
|
||||
final Widget child; |
||||
final EdgeInsets padding; |
||||
final List<BoxShadow> shadow; |
||||
final BorderRadius borderRadius; |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Container( |
||||
decoration: BoxDecoration( |
||||
color: Theme.of(context).brightness == Brightness.dark |
||||
? BrandColors.black |
||||
: BrandColors.white, |
||||
borderRadius: borderRadius, |
||||
boxShadow: shadow, |
||||
), |
||||
padding: padding, |
||||
child: child, |
||||
); |
||||
} |
||||
} |
||||
|
||||
final bigShadow = [ |
||||
BoxShadow( |
||||
offset: Offset(0, 4), |
||||
blurRadius: 8, |
||||
color: Colors.black.withOpacity(.08), |
||||
) |
||||
]; |
@ -0,0 +1,67 @@ |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:easy_localization/easy_localization.dart'; |
||||
import 'package:selfprivacy/config/brand_colors.dart'; |
||||
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart'; |
||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; |
||||
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; |
||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; |
||||
|
||||
class JobsContent extends StatelessWidget { |
||||
const JobsContent({Key? key}) : super(key: key); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
var jobs = context.watch<JobsCubit>().state; |
||||
return Column( |
||||
children: [ |
||||
SizedBox(height: 15), |
||||
Center( |
||||
child: BrandText.h2( |
||||
'jobs.title'.tr(), |
||||
), |
||||
), |
||||
if (jobs.isEmpty) |
||||
Padding( |
||||
padding: const EdgeInsets.only(top: 50), |
||||
child: BrandText.body1('jobs.empty'.tr()), |
||||
), |
||||
if (!jobs.isEmpty) ...[ |
||||
...jobs.jobList |
||||
.map( |
||||
(j) => Row( |
||||
children: [ |
||||
Expanded( |
||||
child: BrandCards.small( |
||||
child: Row( |
||||
children: [ |
||||
BrandText.body1(j.title), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
SizedBox(width: 10), |
||||
ElevatedButton( |
||||
style: ElevatedButton.styleFrom( |
||||
primary: BrandColors.red1, |
||||
shape: RoundedRectangleBorder( |
||||
borderRadius: BorderRadius.circular(10), |
||||
), |
||||
), |
||||
onPressed: () => |
||||
context.read<JobsCubit>().removeJob(j.id), |
||||
child: Text('Remove'), |
||||
), |
||||
], |
||||
), |
||||
) |
||||
.toList(), |
||||
SizedBox(height: 20), |
||||
BrandButton.rised( |
||||
onPressed: () => context.read<JobsCubit>().applyAll(), |
||||
text: 'jobs.start'.tr(), |
||||
), |
||||
], |
||||
], |
||||
); |
||||
} |
||||
} |
@ -1,13 +1,4 @@ |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; |
||||
import 'package:easy_localization/easy_localization.dart'; |
||||
|
||||
class PreStyledButtons { |
||||
static Widget close({ |
||||
required VoidCallback onPress, |
||||
}) => |
||||
_CloseButton(onPress: onPress); |
||||
} |
||||
part of 'pre_styled_buttons.dart'; |
||||
|
||||
class _CloseButton extends StatelessWidget { |
||||
const _CloseButton({Key? key, required this.onPress}) : super(key: key); |
@ -0,0 +1,70 @@ |
||||
part of 'pre_styled_buttons.dart'; |
||||
|
||||
class _BrandFlashButton extends StatefulWidget { |
||||
_BrandFlashButton({Key? key}) : super(key: key); |
||||
|
||||
@override |
||||
_BrandFlashButtonState createState() => _BrandFlashButtonState(); |
||||
} |
||||
|
||||
class _BrandFlashButtonState extends State<_BrandFlashButton> |
||||
with SingleTickerProviderStateMixin { |
||||
late AnimationController _animationController; |
||||
late Animation _colorTween; |
||||
|
||||
@override |
||||
void initState() { |
||||
_animationController = |
||||
AnimationController(vsync: this, duration: Duration(milliseconds: 600)); |
||||
_colorTween = ColorTween( |
||||
begin: BrandColors.black, |
||||
end: BrandColors.primary, |
||||
).animate(_animationController); |
||||
super.initState(); |
||||
} |
||||
|
||||
@override |
||||
void dispose() { |
||||
_animationController.dispose(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
late bool wasPrevStateIsEmpty; |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
var hasNoJobs = context.watch<JobsCubit>().state.isEmpty; |
||||
wasPrevStateIsEmpty = hasNoJobs; |
||||
var icon = hasNoJobs ? Ionicons.flash_outline : Ionicons.flash; |
||||
|
||||
return BlocListener<JobsCubit, JobsState>( |
||||
listener: (context, state) { |
||||
if (wasPrevStateIsEmpty && state.jobList.isNotEmpty) { |
||||
wasPrevStateIsEmpty = false; |
||||
_animationController.forward(); |
||||
} else if (!wasPrevStateIsEmpty && state.jobList.isEmpty) { |
||||
_animationController.reverse(); |
||||
} |
||||
}, |
||||
child: IconButton( |
||||
onPressed: () { |
||||
showCupertinoModalBottomSheet( |
||||
expand: false, |
||||
context: context, |
||||
builder: (context) => BrandBottomSheet( |
||||
child: JobsContent(), |
||||
), |
||||
); |
||||
}, |
||||
icon: AnimatedBuilder( |
||||
animation: _colorTween, |
||||
builder: (context, child) { |
||||
return Icon( |
||||
icon, |
||||
color: _colorTween.value, |
||||
); |
||||
}), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,22 @@ |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_bloc/flutter_bloc.dart'; |
||||
import 'package:ionicons/ionicons.dart'; |
||||
import 'package:selfprivacy/config/brand_colors.dart'; |
||||
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart'; |
||||
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; |
||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; |
||||
import 'package:easy_localization/easy_localization.dart'; |
||||
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; |
||||
import 'package:selfprivacy/ui/components/jobs_content/jobs_content.dart'; |
||||
|
||||
part 'close.dart'; |
||||
part 'flash.dart'; |
||||
|
||||
class PreStyledButtons { |
||||
static Widget close({ |
||||
required VoidCallback onPress, |
||||
}) => |
||||
_CloseButton(onPress: onPress); |
||||
|
||||
static Widget flash() => _BrandFlashButton(); |
||||
} |
Loading…
Reference in new issue