|
91 |
92 |
93 | ---
94 |
95 |
96 |
97 | Version [0.0.1+1](https://github.com/omidhaqi/)
98 |
99 |
100 |
101 |
102 | Developed with ☕ by [Umut](https://github.com/omidhaqi/)
103 |
104 |
105 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
31 |
35 |
39 |
40 |
41 |
42 |
43 |
44 |
46 |
49 |
50 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/lib/data/models/note_model.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'note_model.dart';
4 |
5 | // **************************************************************************
6 | // TypeAdapterGenerator
7 | // **************************************************************************
8 |
9 | class NoteModelAdapter extends TypeAdapter {
10 | @override
11 | final int typeId = 2;
12 |
13 | @override
14 | NoteModel read(BinaryReader reader) {
15 | final numOfFields = reader.readByte();
16 | final fields = {
17 | for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
18 | };
19 | return NoteModel(
20 | id: fields[0] as int,
21 | title: fields[1] as String,
22 | description: fields[2] as String,
23 | color: fields[3] as NoteColor,
24 | dateTime: fields[4] as String,
25 | );
26 | }
27 |
28 | @override
29 | void write(BinaryWriter writer, NoteModel obj) {
30 | writer
31 | ..writeByte(5)
32 | ..writeByte(0)
33 | ..write(obj.id)
34 | ..writeByte(1)
35 | ..write(obj.title)
36 | ..writeByte(2)
37 | ..write(obj.description)
38 | ..writeByte(3)
39 | ..write(obj.color)
40 | ..writeByte(4)
41 | ..write(obj.dateTime);
42 | }
43 |
44 | @override
45 | int get hashCode => typeId.hashCode;
46 |
47 | @override
48 | bool operator ==(Object other) =>
49 | identical(this, other) ||
50 | other is NoteModelAdapter &&
51 | runtimeType == other.runtimeType &&
52 | typeId == other.typeId;
53 | }
54 |
55 | class NoteColorAdapter extends TypeAdapter {
56 | @override
57 | final int typeId = 3;
58 |
59 | @override
60 | NoteColor read(BinaryReader reader) {
61 | switch (reader.readByte()) {
62 | case 0:
63 | return NoteColor.one;
64 | case 1:
65 | return NoteColor.two;
66 | case 2:
67 | return NoteColor.three;
68 | case 3:
69 | return NoteColor.four;
70 | case 4:
71 | return NoteColor.five;
72 | case 5:
73 | return NoteColor.six;
74 | case 6:
75 | return NoteColor.seven;
76 | case 7:
77 | return NoteColor.eight;
78 | case 8:
79 | return NoteColor.nine;
80 | default:
81 | return NoteColor.one;
82 | }
83 | }
84 |
85 | @override
86 | void write(BinaryWriter writer, NoteColor obj) {
87 | switch (obj) {
88 | case NoteColor.one:
89 | writer.writeByte(0);
90 | break;
91 | case NoteColor.two:
92 | writer.writeByte(1);
93 | break;
94 | case NoteColor.three:
95 | writer.writeByte(2);
96 | break;
97 | case NoteColor.four:
98 | writer.writeByte(3);
99 | break;
100 | case NoteColor.five:
101 | writer.writeByte(4);
102 | break;
103 | case NoteColor.six:
104 | writer.writeByte(5);
105 | break;
106 | case NoteColor.seven:
107 | writer.writeByte(6);
108 | break;
109 | case NoteColor.eight:
110 | writer.writeByte(7);
111 | break;
112 | case NoteColor.nine:
113 | writer.writeByte(8);
114 | break;
115 | }
116 | }
117 |
118 | @override
119 | int get hashCode => typeId.hashCode;
120 |
121 | @override
122 | bool operator ==(Object other) =>
123 | identical(this, other) ||
124 | other is NoteColorAdapter &&
125 | runtimeType == other.runtimeType &&
126 | typeId == other.typeId;
127 | }
128 |
--------------------------------------------------------------------------------
/lib/data/models/task_model.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'task_model.dart';
4 |
5 | // **************************************************************************
6 | // TypeAdapterGenerator
7 | // **************************************************************************
8 |
9 | class TaskModelAdapter extends TypeAdapter {
10 | @override
11 | final int typeId = 0;
12 |
13 | @override
14 | TaskModel read(BinaryReader reader) {
15 | final numOfFields = reader.readByte();
16 | final fields = {
17 | for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
18 | };
19 | return TaskModel(
20 | id: fields[0] as int,
21 | title: fields[1] as String,
22 | note: fields[2] as String,
23 | isCompleted: fields[3] as bool,
24 | dateTime: fields[4] as DateTime,
25 | color: fields[5] as TaskColor,
26 | addToNote: fields[6] as bool,
27 | );
28 | }
29 |
30 | @override
31 | void write(BinaryWriter writer, TaskModel obj) {
32 | writer
33 | ..writeByte(7)
34 | ..writeByte(0)
35 | ..write(obj.id)
36 | ..writeByte(1)
37 | ..write(obj.title)
38 | ..writeByte(2)
39 | ..write(obj.note)
40 | ..writeByte(3)
41 | ..write(obj.isCompleted)
42 | ..writeByte(4)
43 | ..write(obj.dateTime)
44 | ..writeByte(5)
45 | ..write(obj.color)
46 | ..writeByte(6)
47 | ..write(obj.addToNote);
48 | }
49 |
50 | @override
51 | int get hashCode => typeId.hashCode;
52 |
53 | @override
54 | bool operator ==(Object other) =>
55 | identical(this, other) ||
56 | other is TaskModelAdapter &&
57 | runtimeType == other.runtimeType &&
58 | typeId == other.typeId;
59 | }
60 |
61 | class TaskColorAdapter extends TypeAdapter {
62 | @override
63 | final int typeId = 1;
64 |
65 | @override
66 | TaskColor read(BinaryReader reader) {
67 | switch (reader.readByte()) {
68 | case 0:
69 | return TaskColor.one;
70 | case 1:
71 | return TaskColor.two;
72 | case 2:
73 | return TaskColor.three;
74 | case 3:
75 | return TaskColor.four;
76 | case 4:
77 | return TaskColor.five;
78 | case 5:
79 | return TaskColor.six;
80 | case 6:
81 | return TaskColor.seven;
82 | case 7:
83 | return TaskColor.eight;
84 | case 8:
85 | return TaskColor.nine;
86 | default:
87 | return TaskColor.one;
88 | }
89 | }
90 |
91 | @override
92 | void write(BinaryWriter writer, TaskColor obj) {
93 | switch (obj) {
94 | case TaskColor.one:
95 | writer.writeByte(0);
96 | break;
97 | case TaskColor.two:
98 | writer.writeByte(1);
99 | break;
100 | case TaskColor.three:
101 | writer.writeByte(2);
102 | break;
103 | case TaskColor.four:
104 | writer.writeByte(3);
105 | break;
106 | case TaskColor.five:
107 | writer.writeByte(4);
108 | break;
109 | case TaskColor.six:
110 | writer.writeByte(5);
111 | break;
112 | case TaskColor.seven:
113 | writer.writeByte(6);
114 | break;
115 | case TaskColor.eight:
116 | writer.writeByte(7);
117 | break;
118 | case TaskColor.nine:
119 | writer.writeByte(8);
120 | break;
121 | }
122 | }
123 |
124 | @override
125 | int get hashCode => typeId.hashCode;
126 |
127 | @override
128 | bool operator ==(Object other) =>
129 | identical(this, other) ||
130 | other is TaskColorAdapter &&
131 | runtimeType == other.runtimeType &&
132 | typeId == other.typeId;
133 | }
134 |
--------------------------------------------------------------------------------
/lib/data/sources/local_data_src.dart:
--------------------------------------------------------------------------------
1 | part of '../../index.dart';
2 |
3 | class TaskLocalDataSrc implements ITaskDataSrc {
4 | TaskLocalDataSrc._constructor();
5 |
6 | static final _instance = TaskLocalDataSrc._constructor();
7 |
8 | factory TaskLocalDataSrc() => _instance;
9 |
10 | void close() {
11 | Hive.close();
12 | }
13 |
14 | @override
15 | Future> getAllTasks() async {
16 | final box = await Hive.openBox(taskBoxName);
17 | return taskMapTOlist(box).toList();
18 | }
19 |
20 | @override
21 | Future> deleteAllTasks() async {
22 | final box = await Hive.openBox(taskBoxName);
23 | await box.clear();
24 | return taskMapTOlist(box).toList();
25 | }
26 |
27 | @override
28 | Future> deleteTask(int id) async {
29 | final box = await Hive.openBox(taskBoxName);
30 | NotificationHelper.cancelNotification(id);
31 | await box.delete(id);
32 |
33 | return taskMapTOlist(box).toList();
34 | }
35 |
36 | @override
37 | Future> saveTask(TaskModel task) async {
38 |
39 | final box = await Hive.openBox(taskBoxName);
40 | NotificationHelper.scheduleNotification(
41 | task.id,
42 | task.title,
43 | task.note,
44 | task.dateTime,
45 | );
46 | await box.put(task.id, task);
47 |
48 | return taskMapTOlist(box).toList();
49 | }
50 |
51 | @override
52 | Future> updateTask(int id, TaskModel task) async {
53 | NotificationHelper.cancelNotification(id);
54 | final box = await Hive.openBox(taskBoxName);
55 | NotificationHelper.scheduleNotification(
56 | task.id,
57 | task.title,
58 | task.note,
59 | task.dateTime,
60 | );
61 | box.put(id, task);
62 |
63 | return taskMapTOlist(box).toList();
64 | }
65 |
66 | @override
67 | Future> isComplateTask(
68 | int id, TaskModel task, bool isComplated) async {
69 | final box = await Hive.openBox(taskBoxName);
70 | isComplated = task.isCompleted;
71 |
72 | box.put(id, task);
73 | if (isComplated) {
74 | NotificationHelper.cancelNotification(id);
75 | } else {
76 | NotificationHelper.scheduleNotification(
77 | task.id,
78 | task.title,
79 | task.note,
80 | task.dateTime,
81 | );
82 | }
83 |
84 | return taskMapTOlist(box).toList();
85 | }
86 | }
87 |
88 | class NoteLocalDataSrc implements INoteDataSrc {
89 | NoteLocalDataSrc._constructor();
90 |
91 | static final _instance = NoteLocalDataSrc._constructor();
92 |
93 | factory NoteLocalDataSrc() => _instance;
94 |
95 | @override
96 | Future> deleteAllNotes() async {
97 | final box = await Hive.openBox(noteBoxName);
98 | box.clear();
99 | return noteMapToList(box).toList();
100 | }
101 |
102 | @override
103 | Future> deleteNote(int id) async {
104 | final box = await Hive.openBox(noteBoxName);
105 | box.delete(id);
106 | return noteMapToList(box).toList();
107 | }
108 |
109 | @override
110 | Future> getAllNotes() async {
111 | final box = await Hive.openBox(noteBoxName);
112 |
113 | return noteMapToList(box).toList();
114 | }
115 |
116 | @override
117 | Future> saveNote(NoteModel note) async {
118 | final box = await Hive.openBox(noteBoxName);
119 |
120 | box.put(note.id, note);
121 | return noteMapToList(box).toList();
122 | }
123 |
124 | @override
125 | Future> updateNote(int id, NoteModel note) async {
126 | final box = await Hive.openBox(noteBoxName);
127 | box.put(id, note);
128 | return noteMapToList(box).toList();
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/assets/images/svg/ic_setting.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/lib/screens/home/task/task_list.dart:
--------------------------------------------------------------------------------
1 | // TaskList.dart
2 |
3 | part of '../../../index.dart';
4 |
5 | class TaskList extends StatelessWidget {
6 | final DateTime selectedDate;
7 |
8 | const TaskList({
9 | super.key,
10 | required this.selectedDate,
11 | });
12 |
13 | bool isSameDay(DateTime date1, DateTime date2) {
14 | return date1.year == date2.year &&
15 | date1.month == date2.month &&
16 | date1.day == date2.day;
17 | }
18 |
19 | @override
20 | Widget build(BuildContext context) {
21 | return Expanded(
22 | child: ValueListenableBuilder>(
23 | valueListenable: taskBox.listenable(),
24 | builder: (context, builderTaskBox, _) {
25 | final todoList = builderTaskBox.values.toList();
26 | final tasksForSelectedDate = todoList
27 | .where((task) => isSameDay(task.dateTime, selectedDate))
28 | .toList();
29 |
30 | if (todoList.isEmpty || tasksForSelectedDate.isEmpty) {
31 | return EmptyVC(
32 | text: S.current.emptyPlan,
33 | );
34 | } else {
35 | return ListView.builder(
36 | itemCount: tasksForSelectedDate.length,
37 | itemBuilder: (contxt, index) {
38 | var taskList = tasksForSelectedDate[index];
39 |
40 | return BlocBuilder(
41 | builder: (context, state) {
42 | return TaskCard(
43 | taskList: taskList,
44 | index: index,
45 | editOnTap: () {
46 | Navigator.push(
47 | context,
48 | CupertinoPageRoute(
49 | builder: (context) => EditTaskScreen(
50 |
51 | taskModel: TaskModel(
52 | id: taskList.id,
53 | title: taskList.title,
54 | note: taskList.note,
55 | isCompleted: taskList.isCompleted,
56 | dateTime: taskList.dateTime,
57 | color: taskList.color,
58 | addToNote: taskList.addToNote,
59 | ),
60 | ),
61 | ),
62 | );
63 | },
64 | deleteOnTap: () {
65 | customeDialogee(
66 | context,
67 | content: S.current.deleteNoteDialogContent,
68 | primaryBtn: S.current.deleteDialogPrimaryBtn,
69 | secendaryBtn: S.current.deleteDialogSecendaryBtn,
70 | onTapPrimaryBtn: () {
71 | BlocProvider.of(context)
72 | .add(DeleteTaskEvent(taskList.id));
73 |
74 | Navigator.pop(context);
75 | },
76 | onTapSecendaryBtn: () {
77 | Navigator.pop(context);
78 | },
79 | );
80 | },
81 | onChanged: (val) {
82 | BlocProvider.of(context)
83 | .add(IsComplatedTaskEvent(
84 | TaskModel(
85 | id: taskList.id,
86 | title: taskList.title,
87 | note: taskList.note,
88 | isCompleted: val!,
89 | dateTime: taskList.dateTime,
90 | color: taskList.color,
91 | addToNote: taskList.addToNote,
92 | ),
93 | taskList.id,
94 | val,
95 | ));
96 | },
97 | value: taskList.isCompleted,
98 | );
99 | },
100 | );
101 | },
102 | );
103 | }
104 | },
105 | ),
106 | );
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/lib/gen/assets.gen.dart:
--------------------------------------------------------------------------------
1 | /// GENERATED CODE - DO NOT MODIFY BY HAND
2 | /// *****************************************************
3 | /// FlutterGen
4 | /// *****************************************************
5 |
6 | // coverage:ignore-file
7 | // ignore_for_file: type=lint
8 | // ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal,deprecated_member_use
9 |
10 | import 'package:flutter/widgets.dart';
11 |
12 | class $AssetsImagesGen {
13 | const $AssetsImagesGen();
14 |
15 | /// Directory path: assets/images/icon
16 | $AssetsImagesIconGen get icon => const $AssetsImagesIconGen();
17 |
18 | /// Directory path: assets/images/svg
19 | $AssetsImagesSvgGen get svg => const $AssetsImagesSvgGen();
20 | }
21 |
22 | class $AssetsImagesIconGen {
23 | const $AssetsImagesIconGen();
24 |
25 | /// File path: assets/images/icon/icon.png
26 | AssetGenImage get icon => const AssetGenImage('assets/images/icon/icon.png');
27 |
28 | /// List of all assets
29 | List get values => [icon];
30 | }
31 |
32 | class $AssetsImagesSvgGen {
33 | const $AssetsImagesSvgGen();
34 |
35 | /// File path: assets/images/svg/ic_notification.svg
36 | String get icNotification => 'assets/images/svg/ic_notification.svg';
37 |
38 | /// File path: assets/images/svg/ic_search.svg
39 | String get icSearch => 'assets/images/svg/ic_search.svg';
40 |
41 | /// File path: assets/images/svg/ic_setting.svg
42 | String get icSetting => 'assets/images/svg/ic_setting.svg';
43 |
44 | /// File path: assets/images/svg/vc_empty_dark.svg
45 | String get vcEmptyDark => 'assets/images/svg/vc_empty_dark.svg';
46 |
47 | /// File path: assets/images/svg/vc_empty_light.svg
48 | String get vcEmptyLight => 'assets/images/svg/vc_empty_light.svg';
49 |
50 | /// File path: assets/images/svg/vc_intro_one_dark.svg
51 | String get vcIntroOneDark => 'assets/images/svg/vc_intro_one_dark.svg';
52 |
53 | /// File path: assets/images/svg/vc_intro_one_light.svg
54 | String get vcIntroOneLight => 'assets/images/svg/vc_intro_one_light.svg';
55 |
56 | /// File path: assets/images/svg/vc_intro_three_dark.svg
57 | String get vcIntroThreeDark => 'assets/images/svg/vc_intro_three_dark.svg';
58 |
59 | /// File path: assets/images/svg/vc_intro_three_light.svg
60 | String get vcIntroThreeLight => 'assets/images/svg/vc_intro_three_light.svg';
61 |
62 | /// File path: assets/images/svg/vc_intro_two_dark.svg
63 | String get vcIntroTwoDark => 'assets/images/svg/vc_intro_two_dark.svg';
64 |
65 | /// File path: assets/images/svg/vc_intro_two_light.svg
66 | String get vcIntroTwoLight => 'assets/images/svg/vc_intro_two_light.svg';
67 |
68 | /// List of all assets
69 | List get values => [
70 | icNotification,
71 | icSearch,
72 | icSetting,
73 | vcEmptyDark,
74 | vcEmptyLight,
75 | vcIntroOneDark,
76 | vcIntroOneLight,
77 | vcIntroThreeDark,
78 | vcIntroThreeLight,
79 | vcIntroTwoDark,
80 | vcIntroTwoLight
81 | ];
82 | }
83 |
84 | class Assets {
85 | Assets._();
86 |
87 | static const $AssetsImagesGen images = $AssetsImagesGen();
88 | }
89 |
90 | class AssetGenImage {
91 | const AssetGenImage(
92 | this._assetName, {
93 | this.size,
94 | this.flavors = const {},
95 | });
96 |
97 | final String _assetName;
98 |
99 | final Size? size;
100 | final Set flavors;
101 |
102 | Image image({
103 | Key? key,
104 | AssetBundle? bundle,
105 | ImageFrameBuilder? frameBuilder,
106 | ImageErrorWidgetBuilder? errorBuilder,
107 | String? semanticLabel,
108 | bool excludeFromSemantics = false,
109 | double? scale,
110 | double? width,
111 | double? height,
112 | Color? color,
113 | Animation? opacity,
114 | BlendMode? colorBlendMode,
115 | BoxFit? fit,
116 | AlignmentGeometry alignment = Alignment.center,
117 | ImageRepeat repeat = ImageRepeat.noRepeat,
118 | Rect? centerSlice,
119 | bool matchTextDirection = false,
120 | bool gaplessPlayback = false,
121 | bool isAntiAlias = false,
122 | String? package,
123 | FilterQuality filterQuality = FilterQuality.low,
124 | int? cacheWidth,
125 | int? cacheHeight,
126 | }) {
127 | return Image.asset(
128 | _assetName,
129 | key: key,
130 | bundle: bundle,
131 | frameBuilder: frameBuilder,
132 | errorBuilder: errorBuilder,
133 | semanticLabel: semanticLabel,
134 | excludeFromSemantics: excludeFromSemantics,
135 | scale: scale,
136 | width: width,
137 | height: height,
138 | color: color,
139 | opacity: opacity,
140 | colorBlendMode: colorBlendMode,
141 | fit: fit,
142 | alignment: alignment,
143 | repeat: repeat,
144 | centerSlice: centerSlice,
145 | matchTextDirection: matchTextDirection,
146 | gaplessPlayback: gaplessPlayback,
147 | isAntiAlias: isAntiAlias,
148 | package: package,
149 | filterQuality: filterQuality,
150 | cacheWidth: cacheWidth,
151 | cacheHeight: cacheHeight,
152 | );
153 | }
154 |
155 | ImageProvider provider({
156 | AssetBundle? bundle,
157 | String? package,
158 | }) {
159 | return AssetImage(
160 | _assetName,
161 | bundle: bundle,
162 | package: package,
163 | );
164 | }
165 |
166 | String get path => _assetName;
167 |
168 | String get keyName => _assetName;
169 | }
170 |
--------------------------------------------------------------------------------
/lib/generated/intl/messages_en.dart:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
2 | // This is a library that provides messages for a en locale. All the
3 | // messages from the main program should be duplicated here with the same
4 | // function name.
5 |
6 | // Ignore issues from commonly used lints in this file.
7 | // ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
8 | // ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
9 | // ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
10 | // ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes
11 | // ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes
12 |
13 | import 'package:intl/intl.dart';
14 | import 'package:intl/message_lookup_by_library.dart';
15 |
16 | final messages = new MessageLookup();
17 |
18 | typedef String MessageIfAbsent(String messageStr, List args);
19 |
20 | class MessageLookup extends MessageLookupByLibrary {
21 | String get localeName => 'en';
22 |
23 | final messages = _notInlinedMessages(_notInlinedMessages);
24 | static Map _notInlinedMessages(_) => {
25 | "addNoteSnackBar": MessageLookupByLibrary.simpleMessage(
26 | "Note added successfully",
27 | ),
28 | "addTaskSnackBar": MessageLookupByLibrary.simpleMessage(
29 | "Task added successfully",
30 | ),
31 | "addToNote": MessageLookupByLibrary.simpleMessage(
32 | "Add the task note to notes!",
33 | ),
34 | "appVersion": MessageLookupByLibrary.simpleMessage("0.0.1+1"),
35 | "author": MessageLookupByLibrary.simpleMessage("Made with ☕ by Umut"),
36 | "createAt": MessageLookupByLibrary.simpleMessage("Created at :"),
37 | "darkMode": MessageLookupByLibrary.simpleMessage("Dark Mode"),
38 | "deleteDialogPrimaryBtn": MessageLookupByLibrary.simpleMessage("Delete it"),
39 | "deleteDialogSecendaryBtn": MessageLookupByLibrary.simpleMessage("Cancel"),
40 | "deleteNoteDialogContent": MessageLookupByLibrary.simpleMessage(
41 | "Are you sure you want to delete this note?",
42 | ),
43 | "deleteNoteSnackBar": MessageLookupByLibrary.simpleMessage(
44 | "Note deleted successfully",
45 | ),
46 | "deleteTaskDialogContent": MessageLookupByLibrary.simpleMessage(
47 | "Are you sure you want to delete this task?",
48 | ),
49 | "deleteTaskSnackBar": MessageLookupByLibrary.simpleMessage(
50 | "The task successfully deleted",
51 | ),
52 | "discard": MessageLookupByLibrary.simpleMessage("Discard"),
53 | "done": MessageLookupByLibrary.simpleMessage("Done"),
54 | "editNote": MessageLookupByLibrary.simpleMessage("Edit the note!"),
55 | "editNoteSnackBar": MessageLookupByLibrary.simpleMessage(
56 | "Note edited successfully",
57 | ),
58 | "editTask": MessageLookupByLibrary.simpleMessage("Edit Task"),
59 | "editTaskSnackBar": MessageLookupByLibrary.simpleMessage(
60 | "The task edited successfully",
61 | ),
62 | "emptyNote": MessageLookupByLibrary.simpleMessage(
63 | "You have not added a note yet",
64 | ),
65 | "emptyPlan": MessageLookupByLibrary.simpleMessage(
66 | "You have no plans today",
67 | ),
68 | "emptyTextFieldError": MessageLookupByLibrary.simpleMessage(
69 | "You must fill in the title",
70 | ),
71 | "error": MessageLookupByLibrary.simpleMessage("ERROR"),
72 | "goal": MessageLookupByLibrary.simpleMessage("Set a goal !"),
73 | "language": MessageLookupByLibrary.simpleMessage("Language"),
74 | "letsGo": MessageLookupByLibrary.simpleMessage("Let\'\'s Go..."),
75 | "name": MessageLookupByLibrary.simpleMessage("On . Time"),
76 | "newTask": MessageLookupByLibrary.simpleMessage("New Task"),
77 | "note": MessageLookupByLibrary.simpleMessage("Note"),
78 | "noteTextFieldNoteHint": MessageLookupByLibrary.simpleMessage(
79 | "Write your note here...",
80 | ),
81 | "noteTextFieldTitleHint": MessageLookupByLibrary.simpleMessage("Title"),
82 | "plan": MessageLookupByLibrary.simpleMessage("Plan for tomorrow!"),
83 | "planning": MessageLookupByLibrary.simpleMessage("Planning"),
84 | "save": MessageLookupByLibrary.simpleMessage("Save"),
85 | "settings": MessageLookupByLibrary.simpleMessage("Settings"),
86 | "target": MessageLookupByLibrary.simpleMessage("Touch it!"),
87 | "taskCardNote": MessageLookupByLibrary.simpleMessage("Note: "),
88 | "taskCardPlace": MessageLookupByLibrary.simpleMessage("Place: "),
89 | "taskCardTime": MessageLookupByLibrary.simpleMessage("Time:"),
90 | "taskNoteHint": MessageLookupByLibrary.simpleMessage(
91 | "Write your note here",
92 | ),
93 | "taskNoteTitle": MessageLookupByLibrary.simpleMessage("Note"),
94 | "taskPlaceHint": MessageLookupByLibrary.simpleMessage(
95 | "What is the name of the place you want to go?",
96 | ),
97 | "taskPlaceTitle": MessageLookupByLibrary.simpleMessage("Place"),
98 | "taskTitle": MessageLookupByLibrary.simpleMessage("Title"),
99 | "taskTitleHint": MessageLookupByLibrary.simpleMessage(
100 | "Write your title here",
101 | ),
102 | "tasks": MessageLookupByLibrary.simpleMessage("Tasks"),
103 | "theme": MessageLookupByLibrary.simpleMessage("Theme"),
104 | "time": MessageLookupByLibrary.simpleMessage("Time"),
105 | "tryAgain": MessageLookupByLibrary.simpleMessage("Try Again"),
106 | "well": MessageLookupByLibrary.simpleMessage("Ok"),
107 | };
108 | }
109 |
--------------------------------------------------------------------------------
/lib/generated/intl/messages_fa.dart:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
2 | // This is a library that provides messages for a fa locale. All the
3 | // messages from the main program should be duplicated here with the same
4 | // function name.
5 |
6 | // Ignore issues from commonly used lints in this file.
7 | // ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
8 | // ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
9 | // ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
10 | // ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes
11 | // ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes
12 |
13 | import 'package:intl/intl.dart';
14 | import 'package:intl/message_lookup_by_library.dart';
15 |
16 | final messages = new MessageLookup();
17 |
18 | typedef String MessageIfAbsent(String messageStr, List args);
19 |
20 | class MessageLookup extends MessageLookupByLibrary {
21 | String get localeName => 'fa';
22 |
23 | final messages = _notInlinedMessages(_notInlinedMessages);
24 | static Map _notInlinedMessages(_) => {
25 | "addNoteSnackBar": MessageLookupByLibrary.simpleMessage(
26 | "یادداشت با موفقیت اضافه شد...",
27 | ),
28 | "addTaskSnackBar": MessageLookupByLibrary.simpleMessage(
29 | "تسک با موفقیت اضافه شد",
30 | ),
31 | "addToNote": MessageLookupByLibrary.simpleMessage(
32 | "یادداشت تسک رو به یادداشت ها اضافه کن!",
33 | ),
34 | "appVersion": MessageLookupByLibrary.simpleMessage("0.0.1+1"),
35 | "author": MessageLookupByLibrary.simpleMessage("ساخته شده با ☕ توسط امید"),
36 | "createAt": MessageLookupByLibrary.simpleMessage("ایجاد شده در :"),
37 | "darkMode": MessageLookupByLibrary.simpleMessage("حالت تاریک"),
38 | "deleteDialogPrimaryBtn": MessageLookupByLibrary.simpleMessage("حذفش کن"),
39 | "deleteDialogSecendaryBtn": MessageLookupByLibrary.simpleMessage(
40 | "دستم خورد",
41 | ),
42 | "deleteNoteDialogContent": MessageLookupByLibrary.simpleMessage(
43 | "مطمئنی میخوای این یادداشت رو حذف کنی؟",
44 | ),
45 | "deleteNoteSnackBar": MessageLookupByLibrary.simpleMessage(
46 | "یادداشت با موفقیت حذف شد",
47 | ),
48 | "deleteTaskDialogContent": MessageLookupByLibrary.simpleMessage(
49 | "مطمئنی میخوای این تسک رو حذف کنی؟",
50 | ),
51 | "deleteTaskSnackBar": MessageLookupByLibrary.simpleMessage(
52 | "تسک با موفقیت حذف شد",
53 | ),
54 | "discard": MessageLookupByLibrary.simpleMessage("بیخیال"),
55 | "done": MessageLookupByLibrary.simpleMessage("انجام شد"),
56 | "editNote": MessageLookupByLibrary.simpleMessage(
57 | "یادداشت رو هم ویرایش کن!",
58 | ),
59 | "editNoteSnackBar": MessageLookupByLibrary.simpleMessage(
60 | "یادداشت با موفقیت ویرایش شد...",
61 | ),
62 | "editTask": MessageLookupByLibrary.simpleMessage("ویرایش برنامه"),
63 | "editTaskSnackBar": MessageLookupByLibrary.simpleMessage(
64 | "تسک با موفقیت ویرایش شد",
65 | ),
66 | "emptyNote": MessageLookupByLibrary.simpleMessage(
67 | "هنوز یادداشتی اضافه نکردی",
68 | ),
69 | "emptyPlan": MessageLookupByLibrary.simpleMessage("امروز برنامهای نداری"),
70 | "emptyTextFieldError": MessageLookupByLibrary.simpleMessage(
71 | "حداقل عنوان رو پر کن",
72 | ),
73 | "error": MessageLookupByLibrary.simpleMessage("خطا"),
74 | "goal": MessageLookupByLibrary.simpleMessage("! هدف گذاری کن"),
75 | "language": MessageLookupByLibrary.simpleMessage("زبان"),
76 | "letsGo": MessageLookupByLibrary.simpleMessage("!...بزن بریم"),
77 | "name": MessageLookupByLibrary.simpleMessage("آن . تایم"),
78 | "newTask": MessageLookupByLibrary.simpleMessage("برنامه جدید"),
79 | "note": MessageLookupByLibrary.simpleMessage("یادداشت"),
80 | "noteTextFieldNoteHint": MessageLookupByLibrary.simpleMessage(
81 | "یادداشت خودتو اینجا بنویس...",
82 | ),
83 | "noteTextFieldTitleHint": MessageLookupByLibrary.simpleMessage("عنوان"),
84 | "plan": MessageLookupByLibrary.simpleMessage("!برنامه ریزی کن"),
85 | "planning": MessageLookupByLibrary.simpleMessage("برنامه ریزی"),
86 | "save": MessageLookupByLibrary.simpleMessage("ثبت"),
87 | "settings": MessageLookupByLibrary.simpleMessage("تنظیمات"),
88 | "target": MessageLookupByLibrary.simpleMessage("!برس بهش"),
89 | "taskCardNote": MessageLookupByLibrary.simpleMessage("یادداشت:"),
90 | "taskCardPlace": MessageLookupByLibrary.simpleMessage("مکان:"),
91 | "taskCardTime": MessageLookupByLibrary.simpleMessage("ساعت:"),
92 | "taskNoteHint": MessageLookupByLibrary.simpleMessage(
93 | "یادداشت خود را در اینجا وارد کنید",
94 | ),
95 | "taskNoteTitle": MessageLookupByLibrary.simpleMessage("یادداشت"),
96 | "taskPlaceHint": MessageLookupByLibrary.simpleMessage(
97 | "اسم جایی که میخای بری چیه؟",
98 | ),
99 | "taskPlaceTitle": MessageLookupByLibrary.simpleMessage("مکان"),
100 | "taskTitle": MessageLookupByLibrary.simpleMessage("عنوان"),
101 | "taskTitleHint": MessageLookupByLibrary.simpleMessage(
102 | "عنوان خود را اینجا وارد کنید",
103 | ),
104 | "tasks": MessageLookupByLibrary.simpleMessage("برنامهها"),
105 | "theme": MessageLookupByLibrary.simpleMessage("تم"),
106 | "time": MessageLookupByLibrary.simpleMessage("ساعت"),
107 | "tryAgain": MessageLookupByLibrary.simpleMessage("تلاش مجدد"),
108 | "well": MessageLookupByLibrary.simpleMessage("!خب"),
109 | };
110 | }
111 |
--------------------------------------------------------------------------------
/lib/screens/settings/settings_page.dart:
--------------------------------------------------------------------------------
1 | part of '../../index.dart';
2 |
3 | class SettingsPage extends StatelessWidget {
4 | const SettingsPage({super.key});
5 |
6 | @override
7 | Widget build(BuildContext context) {
8 | var groupValue = context.read().state.locale.languageCode;
9 | return SafeArea(
10 | child: BlocConsumer(
11 | listener: (context, state) {
12 | groupValue = state.locale.languageCode;
13 | },
14 | builder: (context, state) {
15 | return Scaffold(
16 | appBar: AppBar(
17 | automaticallyImplyLeading: false,
18 | centerTitle: true,
19 | title: Text(
20 | S.current.settings,
21 | style: AppTextStyles.appBarTitle,
22 | ),
23 | ),
24 | body: Directionality(
25 | textDirection: TextDirection.ltr,
26 | child: Column(
27 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
28 | crossAxisAlignment: CrossAxisAlignment.center,
29 | children: [
30 | Column(
31 | mainAxisAlignment: MainAxisAlignment.start,
32 | crossAxisAlignment: CrossAxisAlignment.end,
33 | children: [
34 | Padding(
35 | padding: const EdgeInsets.only(right: AppDimens.medium),
36 | child: Text(S.current.language),
37 | ),
38 | const Padding(
39 | padding:
40 | EdgeInsets.symmetric(horizontal: AppDimens.small),
41 | child: Divider(),
42 | ),
43 | SizedBox(
44 | width: double.infinity,
45 | height: 150,
46 | child: ListView.builder(
47 | itemCount: languageModel.length,
48 | itemBuilder: (context, index) {
49 | var item = languageModel[index];
50 | return RadioListTile(
51 | value: item.languageCode,
52 | groupValue: groupValue,
53 | onChanged: (value) {
54 | BlocProvider.of(context).add(
55 | LoadLocalizations(
56 | Locale(
57 | item.languageCode,
58 | ),
59 | ),
60 | );
61 | },
62 | title: Row(
63 | mainAxisAlignment: MainAxisAlignment.end,
64 | children: [
65 | Text(item.language),
66 | ],
67 | ),
68 | subtitle: Row(
69 | mainAxisAlignment: MainAxisAlignment.end,
70 | children: [
71 | Text(item.subLanguage),
72 | ],
73 | ),
74 | );
75 | }),
76 | ),
77 | Padding(
78 | padding: const EdgeInsets.only(right: AppDimens.medium),
79 | child: Text(S.current.theme),
80 | ),
81 | const Padding(
82 | padding:
83 | EdgeInsets.symmetric(horizontal: AppDimens.small),
84 | child: Divider(),
85 | ),
86 | Padding(
87 | padding: const EdgeInsets.symmetric(
88 | horizontal: AppDimens.medium),
89 | child: Directionality(
90 | textDirection: TextDirection.rtl,
91 | child: Row(
92 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
93 | crossAxisAlignment: CrossAxisAlignment.center,
94 | children: [
95 | Padding(
96 | padding: const EdgeInsets.symmetric(
97 | horizontal: AppDimens.medium),
98 | child: Text(S.current.darkMode),
99 | ),
100 | Switch(
101 | value: state.themeMode == ThemeMode.dark,
102 | onChanged: (value) {
103 | context
104 | .read()
105 | .add(ThemeChanged(isDark: value));
106 | },
107 | )
108 | ],
109 | ),
110 | ),
111 | ),
112 | ],
113 | ),
114 | Padding(
115 | padding:const EdgeInsets.only(bottom: AppDimens.large),
116 | child: Column(
117 | children: [
118 | Text(S.current.appVersion,style: AppTextStyles.appInfoTextStyle,),
119 | Text(S.current.author,style: AppTextStyles.appInfoTextStyle,),
120 | ],
121 | ),
122 | )
123 | ],
124 | ),
125 | ),
126 | );
127 | },
128 | ),
129 | );
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/lib/screens/home/home_page.dart:
--------------------------------------------------------------------------------
1 | part of '../../index.dart';
2 |
3 | class HomePage extends StatelessWidget {
4 | const HomePage({super.key});
5 |
6 | @override
7 | Widget build(BuildContext context) {
8 | FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
9 | FlutterLocalNotificationsPlugin();
10 | flutterLocalNotificationsPlugin
11 | .resolvePlatformSpecificImplementation<
12 | AndroidFlutterLocalNotificationsPlugin>()
13 | ?.requestNotificationsPermission();
14 | Size size = MediaQuery.sizeOf(context);
15 | return SafeArea(
16 | child: Scaffold(
17 | appBar: CustomAppBar(
18 | appBarHeight: 100,
19 | child: Text(
20 | S.current.name,
21 | style: AppTextStyles.appNameTextStyle,
22 | ),
23 | ),
24 | body: Column(
25 | children: [
26 | Expanded(
27 | flex: 1,
28 | child: Row(
29 | mainAxisAlignment: MainAxisAlignment.center,
30 | children: [
31 | ConstrainedBox(
32 | constraints: BoxConstraints(
33 | maxWidth: min(size.width * 0.9, 400),
34 | ),
35 | child: Container(
36 | height: size.height / 16.4,
37 | decoration: BoxDecoration(
38 | color: Theme.of(context).colorScheme.primary,
39 | borderRadius: BorderRadius.circular(10),
40 | ),
41 | child: Row(
42 | mainAxisAlignment: MainAxisAlignment.spaceAround,
43 | children: [
44 | Expanded(
45 | child: ZoomTapAnimation(
46 | onTap: () {
47 | context.read().add(const ChangePage(0));
48 | },
49 | child: BlocBuilder(
50 | builder: (context, state) {
51 | return Container(
52 | margin: const EdgeInsets.symmetric(horizontal: 4),
53 | height: size.height / 19,
54 | decoration: BoxDecoration(
55 | borderRadius: BorderRadius.circular(8),
56 | color: state.selectedPageIndex == 0
57 | ? Theme.of(context).colorScheme.onPrimary
58 | : Colors.transparent,
59 | ),
60 | child: Center(
61 | child: Text(S.current.planning,
62 | style: AppTextStyles.chipTextStyle.apply(
63 | color: state.selectedPageIndex == 0
64 | ? Theme.of(context)
65 | .colorScheme
66 | .primary
67 | : Theme.of(context)
68 | .colorScheme
69 | .onPrimary,
70 | )),
71 | ),
72 | );
73 | },
74 | ),
75 | ),
76 | ),
77 | Expanded(
78 | child: ZoomTapAnimation(
79 | onTap: () {
80 | context.read().add(const ChangePage(1));
81 | },
82 | child: BlocBuilder(
83 | builder: (context, state) {
84 | return Container(
85 | margin: const EdgeInsets.symmetric(horizontal: 4),
86 | height: size.height / 19,
87 | decoration: BoxDecoration(
88 | borderRadius: BorderRadius.circular(8),
89 | color: state.selectedPageIndex == 1
90 | ? Theme.of(context).colorScheme.onPrimary
91 | : Colors.transparent,
92 | ),
93 | child: Center(
94 | child: Text(
95 | S.current.note,
96 | style: AppTextStyles.chipTextStyle.apply(
97 | color: state.selectedPageIndex == 1
98 | ? Theme.of(context)
99 | .colorScheme
100 | .primary
101 | : Theme.of(context)
102 | .colorScheme
103 | .onPrimary,
104 | ),
105 | ),
106 | ),
107 | );
108 | },
109 | ),
110 | ),
111 | ),
112 | ],
113 | ),
114 | ),
115 | ),
116 | ],
117 | ),
118 | ),
119 | Expanded(
120 | flex: 13,
121 | child: BlocBuilder(
122 | builder: (context, state) {
123 | return IndexedStack(
124 | alignment: Alignment.topCenter,
125 | index: state.selectedPageIndex,
126 | children: const [
127 | Tasks(),
128 | Notes(),
129 | ],
130 | );
131 | },
132 | ),
133 | ),
134 | ],
135 | ),
136 | floatingActionButton: BlocBuilder(
137 | builder: (context, state) {
138 | return state.selectedPageIndex == 1
139 | ? FloatingActionButton(
140 | child: Icon(
141 | Icons.add,
142 | color: Theme.of(context).colorScheme.surface,
143 | ),
144 | onPressed: () {
145 | Navigator.push(
146 | context,
147 | CupertinoPageRoute(
148 | builder: (context) => const AddNoteScreen(),
149 | ),
150 | );
151 | },
152 | )
153 | : const SizedBox.shrink();
154 | },
155 | ),
156 | ),
157 | );
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/lib/screens/home/task/tasks.dart:
--------------------------------------------------------------------------------
1 | // Tasks.dart
2 |
3 | part of '../../../index.dart';
4 |
5 | Box taskBox = Hive.box(taskBoxName);
6 |
7 | class Tasks extends StatefulWidget {
8 | const Tasks({super.key});
9 |
10 | @override
11 | State createState() => _TasksState();
12 | }
13 |
14 | class _TasksState extends State {
15 | DateTime _selectedDate = DateTime.now();
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | final todoList = taskBox.values.toList();
20 | final taskDates = todoList
21 | .map((task) => DateTime(
22 | task.dateTime.year, task.dateTime.month, task.dateTime.day))
23 | .toSet()
24 | .toList();
25 |
26 | String day = DateTimeExtensions(_selectedDate).toJalali().day.toPersianNumberInt();
27 | String month = DateTimeExtensions(_selectedDate).toJalali().month.toPesianMonth();
28 | String year = DateTimeExtensions(_selectedDate).toJalali().year.toPersianNumberInt();
29 |
30 | return BlocBuilder(
31 | builder: (context, state) {
32 | return Column(
33 | children: [
34 | if (state.locale.languageCode == "fa")
35 | Column(
36 | children: [
37 | Container(
38 | margin: const EdgeInsets.only(top: AppDimens.medium),
39 | padding: const EdgeInsets.symmetric(
40 | horizontal: AppDimens.medium),
41 | child: Text(
42 | ' $day, $month , $year',
43 | style: AppTextStyles.appTopText,
44 | textDirection: TextDirection.rtl,
45 | ),
46 | ),
47 | Padding(
48 | padding: const EdgeInsets.only(top: AppDimens.medium),
49 | child: PersianHorizontalDatePicker(
50 | weekDayTextStyle: AppTextStyles.selectedTextStyle.apply(
51 | color: Theme.of(context).colorScheme.onSurface,
52 | ),
53 | dayTextStyle: AppTextStyles.selectedTextStyle.apply(
54 | color: Theme.of(context).colorScheme.onSurface,
55 | ),
56 | monthTextStyle: AppTextStyles.selectedTextStyle.apply(
57 | color: Theme.of(context).colorScheme.onSurface,
58 | ),
59 | markedDates: taskDates,
60 | hasShadow: false,
61 | initialSelectedDate: DateTime.now(),
62 | datePickerHeight: 90,
63 | startDate: DateTime.now().subtract(const Duration(days: 30)),
64 | endDate: DateTime.now().add(const Duration(days: 30)),
65 | backgroundColor: Colors.transparent,
66 | onBackgroundColor: Theme.of(context).colorScheme.onSurface,
67 | selectedOnBackgroundColor: Theme.of(context).colorScheme.surface,
68 | selectedBackgroundColor:
69 | Theme.of(context).colorScheme.onSurface,
70 | onDateSelected: (date) {
71 | setState(() {
72 | _selectedDate = date!;
73 | });
74 | },
75 | ),
76 | ),
77 | ],
78 | ),
79 | if (state.locale.languageCode == "en")
80 | Column(
81 | children: [
82 | Container(
83 | margin: const EdgeInsets.only(top: AppDimens.medium),
84 | padding: const EdgeInsets.symmetric(
85 | horizontal: AppDimens.medium),
86 | child: Text(
87 | ' ${_selectedDate.day}, ${_selectedDate.month.toGregorianMonth()} , ${_selectedDate.year}',
88 | style: AppTextStyles.appTopText,
89 | ),
90 | ),
91 | Padding(
92 | padding: const EdgeInsets.only(top: AppDimens.medium),
93 | child: PersianHorizontalDatePicker(
94 | weekDayTextStyle: AppTextStyles.selectedTextStyle.apply(
95 | color: Theme.of(context).colorScheme.onSurface,
96 | ),
97 | dayTextStyle: AppTextStyles.selectedTextStyle.apply(
98 | color: Theme.of(context).colorScheme.onSurface,
99 | ),
100 | monthTextStyle: AppTextStyles.selectedTextStyle.apply(
101 | color: Theme.of(context).colorScheme.onSurface,
102 | ),
103 | markedDates: taskDates,
104 | isPersianDate: false,
105 | hasShadow: false,
106 | initialSelectedDate: DateTime.now(),
107 | datePickerHeight: 90,
108 | startDate: DateTime(2024, 6, 6),
109 | endDate: DateTime(2050, 6, 6),
110 | backgroundColor: Colors.transparent,
111 | onBackgroundColor: Theme.of(context).colorScheme.onSurface,
112 | selectedOnBackgroundColor: Theme.of(context).colorScheme.surface,
113 | selectedBackgroundColor:
114 | Theme.of(context).colorScheme.onSurface,
115 | onDateSelected: (date) {
116 | setState(() {
117 | _selectedDate = date!;
118 | });
119 | },
120 | ),
121 | ),
122 | ],
123 | ),
124 | Row(
125 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
126 | children: [
127 | Padding(
128 | padding: const EdgeInsets.all(AppDimens.medium),
129 | child: Text(
130 | S.current.tasks,
131 | style: AppTextStyles.bodyTitleTextStyle.apply(
132 | color: Theme.of(context).colorScheme.onSurface,
133 | ),
134 | ),
135 | ),
136 | Padding(
137 | padding:
138 | const EdgeInsets.symmetric(horizontal: AppDimens.medium),
139 | child: IconButton.filled(
140 | iconSize: 35,
141 | onPressed: () {
142 | Navigator.push(
143 | context,
144 | CupertinoPageRoute(
145 | builder: (context) => AddTaskScreen(
146 | date: _selectedDate,
147 | ),
148 | ),
149 | );
150 | },
151 | icon: const Icon(Icons.add_rounded),
152 | ),
153 | ),
154 | ],
155 | ),
156 | BlocConsumer(
157 | listener: (context, state) {
158 | if (state is DeleteTaskState) {
159 | ScaffoldMessenger.of(context).showSnackBar(
160 | SnackBar(
161 | duration: const Duration(seconds: 1),
162 | content: Text(
163 | S.current.deleteTaskSnackBar,
164 | ),
165 | ),
166 | );
167 | }
168 | },
169 | builder: (context, state) {
170 | if (state is TaskLoadedState) {
171 |
172 | return TaskList(
173 | selectedDate: _selectedDate,
174 | );
175 | } else if (state is DeleteAllTasksState ||
176 | state is DeleteTaskState ||
177 | state is SaveTaskState ||
178 | state is UpdateTaskState ||
179 | state is IsComplatedTaskState) {
180 | return TaskList(
181 | selectedDate: _selectedDate,
182 | );
183 | } else if (state is TaskError) {
184 | return Text(S.current.error);
185 | } else if (state is TaskLoadingState) {
186 | return const LinearProgressIndicator();
187 | } else {
188 | return ElevatedButton(
189 | onPressed: () {
190 | BlocProvider.of(context).add(TaskInit());
191 | },
192 | child: Text(S.current.tryAgain),
193 | );
194 | }
195 | },
196 | ),
197 | ],
198 | );
199 | },
200 | );
201 | }
202 |
203 | }
204 |
--------------------------------------------------------------------------------
/lib/screens/home/note/add_note_screen.dart:
--------------------------------------------------------------------------------
1 | part of '../../../index.dart';
2 |
3 | class AddNoteScreen extends StatefulWidget {
4 | const AddNoteScreen({
5 | super.key,
6 | });
7 |
8 | @override
9 | State createState() => _AddNoteScreenState();
10 | }
11 |
12 | class _AddNoteScreenState extends State {
13 | final TextEditingController _titleController = TextEditingController();
14 |
15 | final TextEditingController _descriptionController = TextEditingController();
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | var lang = BlocProvider.of(context).state.locale.languageCode;
20 | var uuid = const Uuid();
21 | String uuidString = uuid.v4();
22 | List bytes = utf8.encode(uuidString);
23 | int noteId = bytes.fold(0, (previousValue, element) {
24 | return previousValue + element;
25 | });
26 | return SafeArea(
27 | child: Scaffold(
28 | backgroundColor: Color(_noteSelectedColor.code),
29 | body: Column(
30 | children: [
31 | Expanded(
32 | child: ListView(
33 | keyboardDismissBehavior:
34 | ScrollViewKeyboardDismissBehavior.onDrag,
35 | padding: const EdgeInsets.symmetric(
36 | horizontal: 20,
37 | vertical: 20,
38 | ),
39 | children: [
40 | TextField(
41 | controller: _titleController,
42 | style: AppTextStyles.noteTitleTextStyle
43 | .apply(color: AppColors.appPrimaryDark),
44 | decoration: InputDecoration(
45 | hintText: S.current.noteTextFieldTitleHint,
46 | border: InputBorder.none,
47 | contentPadding: EdgeInsets.zero,
48 | hintStyle: const TextStyle(
49 | color: Color.fromARGB(132, 22, 25, 40)),
50 | counterText: '',
51 | ),
52 | minLines: 1,
53 | maxLines: 8,
54 | maxLength: 140,
55 | ),
56 | const SizedBox(height: 20),
57 | TextField(
58 | controller: _descriptionController,
59 | style: AppTextStyles.noteDecTextStyle
60 | .apply(color: AppColors.appPrimaryDark),
61 | decoration: InputDecoration(
62 | hintText: S.current.noteTextFieldNoteHint,
63 | border: InputBorder.none,
64 | hintStyle: const TextStyle(
65 | color: Color.fromARGB(132, 22, 25, 40)),
66 | contentPadding: EdgeInsets.zero,
67 | ),
68 | minLines: 2,
69 | maxLines: 100,
70 | ),
71 | ],
72 | ),
73 | ),
74 | Column(
75 | children: [
76 | Padding(
77 | padding: const EdgeInsets.only(right: AppDimens.small),
78 | child: NoteColorSelector(
79 | selectedColor: _noteSelectedColor,
80 | onColorSelected: (color) {
81 | setState(() {
82 | _noteSelectedColor = color;
83 | });
84 | },
85 | ),
86 | ),
87 | Padding(
88 | padding: const EdgeInsets.all(AppDimens.small),
89 | child: Row(
90 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
91 | children: [
92 | Expanded(
93 | child: SizedBox(
94 | height: 50,
95 | child: BlocConsumer(
96 | listener: (context, state) {
97 | if (state is SaveNoteState) {
98 | ScaffoldMessenger.of(context).showSnackBar(
99 | SnackBar(
100 | duration: const Duration(milliseconds: 500),
101 | content: Text(
102 | S.current.addNoteSnackBar,
103 | ),
104 | ),
105 | );
106 | }
107 | },
108 | builder: (context, state) {
109 | return TextButton(
110 | style: const ButtonStyle(
111 | backgroundColor: WidgetStatePropertyAll(
112 | AppColors.appPrimaryDark),
113 | ),
114 | onPressed: () {
115 | if (_titleController.text.isEmpty) {
116 | ScaffoldMessenger.of(context).showSnackBar(
117 | SnackBar(
118 | content: Text(
119 | S.current.emptyTextFieldError,
120 | ),
121 | ),
122 | );
123 | } else {
124 | if (lang == 'fa') {
125 | String dateTime =
126 | '${DateTime.now().hour.toPersianNumberInt()}:${DateTime.now().minute.toPersianNumberInt()} / ${Jalali.now().day.toPersianNumberInt()} - ${Jalali.now().month.toPesianMonth()} ';
127 | BlocProvider.of(context).add(
128 | SaveNoteEvent(
129 | NoteModel(
130 | id: noteId,
131 | title: _titleController.text,
132 | description:
133 | _descriptionController.text,
134 | color: _noteSelectedColor,
135 | dateTime: dateTime),
136 | ),
137 | );
138 | } else {
139 | String gDateTime =
140 | '${DateTime.now().hour}:${DateTime.now().minute} / ${DateTime.now().day} - ${DateTime.now().month.toGregorianMonth()} ';
141 |
142 | BlocProvider.of(context).add(
143 | SaveNoteEvent(
144 | NoteModel(
145 | id: noteId,
146 | title: _titleController.text,
147 | description:
148 | _descriptionController.text,
149 | color: _noteSelectedColor,
150 | dateTime: gDateTime),
151 | ),
152 | );
153 | }
154 |
155 | Navigator.pop(context);
156 | }
157 | },
158 | child: Text(
159 | S.current.save,
160 | style: const TextStyle(
161 | color: AppColors.appOnPrimaryDark),
162 | ),
163 | );
164 | },
165 | ),
166 | ),
167 | ),
168 | AppDimens.small.width,
169 | Expanded(
170 | child: SizedBox(
171 | height: 50,
172 | child: TextButton(
173 | style: const ButtonStyle(
174 | backgroundColor: WidgetStatePropertyAll(
175 | AppColors.appPrimaryDark,
176 | ),
177 | ),
178 | onPressed: () {
179 | Navigator.pop(context);
180 | },
181 | child: Text(
182 | S.current.discard,
183 | style: const TextStyle(
184 | color: AppColors.appOnPrimaryDark),
185 | ),
186 | ),
187 | ),
188 | ),
189 | ],
190 | ),
191 | )
192 | ],
193 | )
194 | ],
195 | ),
196 | ),
197 | );
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2024 [OmidHaqi]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/lib/generated/l10n.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 | import 'package:flutter/material.dart';
3 | import 'package:intl/intl.dart';
4 | import 'intl/messages_all.dart';
5 |
6 | // **************************************************************************
7 | // Generator: Flutter Intl IDE plugin
8 | // Made by Localizely
9 | // **************************************************************************
10 |
11 | // ignore_for_file: non_constant_identifier_names, lines_longer_than_80_chars
12 | // ignore_for_file: join_return_with_assignment, prefer_final_in_for_each
13 | // ignore_for_file: avoid_redundant_argument_values, avoid_escaping_inner_quotes
14 |
15 | class S {
16 | S();
17 |
18 | static S? _current;
19 |
20 | static S get current {
21 | assert(
22 | _current != null,
23 | 'No instance of S was loaded. Try to initialize the S delegate before accessing S.current.',
24 | );
25 | return _current!;
26 | }
27 |
28 | static const AppLocalizationDelegate delegate = AppLocalizationDelegate();
29 |
30 | static Future load(Locale locale) {
31 | final name =
32 | (locale.countryCode?.isEmpty ?? false)
33 | ? locale.languageCode
34 | : locale.toString();
35 | final localeName = Intl.canonicalizedLocale(name);
36 | return initializeMessages(localeName).then((_) {
37 | Intl.defaultLocale = localeName;
38 | final instance = S();
39 | S._current = instance;
40 |
41 | return instance;
42 | });
43 | }
44 |
45 | static S of(BuildContext context) {
46 | final instance = S.maybeOf(context);
47 | assert(
48 | instance != null,
49 | 'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?',
50 | );
51 | return instance!;
52 | }
53 |
54 | static S? maybeOf(BuildContext context) {
55 | return Localizations.of(context, S);
56 | }
57 |
58 | /// `On . Time`
59 | String get name {
60 | return Intl.message('On . Time', name: 'name', desc: '', args: []);
61 | }
62 |
63 | /// `Language`
64 | String get language {
65 | return Intl.message('Language', name: 'language', desc: '', args: []);
66 | }
67 |
68 | /// `Settings`
69 | String get settings {
70 | return Intl.message('Settings', name: 'settings', desc: '', args: []);
71 | }
72 |
73 | /// `Theme`
74 | String get theme {
75 | return Intl.message('Theme', name: 'theme', desc: '', args: []);
76 | }
77 |
78 | /// `Dark Mode`
79 | String get darkMode {
80 | return Intl.message('Dark Mode', name: 'darkMode', desc: '', args: []);
81 | }
82 |
83 | /// `Planning`
84 | String get planning {
85 | return Intl.message('Planning', name: 'planning', desc: '', args: []);
86 | }
87 |
88 | /// `Note`
89 | String get note {
90 | return Intl.message('Note', name: 'note', desc: '', args: []);
91 | }
92 |
93 | /// `Ok`
94 | String get well {
95 | return Intl.message('Ok', name: 'well', desc: '', args: []);
96 | }
97 |
98 | /// `Let''s Go...`
99 | String get letsGo {
100 | return Intl.message('Let\'\'s Go...', name: 'letsGo', desc: '', args: []);
101 | }
102 |
103 | /// `Set a goal !`
104 | String get goal {
105 | return Intl.message('Set a goal !', name: 'goal', desc: '', args: []);
106 | }
107 |
108 | /// `Plan for tomorrow!`
109 | String get plan {
110 | return Intl.message('Plan for tomorrow!', name: 'plan', desc: '', args: []);
111 | }
112 |
113 | /// `Touch it!`
114 | String get target {
115 | return Intl.message('Touch it!', name: 'target', desc: '', args: []);
116 | }
117 |
118 | /// `Done`
119 | String get done {
120 | return Intl.message('Done', name: 'done', desc: '', args: []);
121 | }
122 |
123 | /// `Tasks`
124 | String get tasks {
125 | return Intl.message('Tasks', name: 'tasks', desc: '', args: []);
126 | }
127 |
128 | /// `You have not added a note yet`
129 | String get emptyNote {
130 | return Intl.message(
131 | 'You have not added a note yet',
132 | name: 'emptyNote',
133 | desc: '',
134 | args: [],
135 | );
136 | }
137 |
138 | /// `You have no plans today`
139 | String get emptyPlan {
140 | return Intl.message(
141 | 'You have no plans today',
142 | name: 'emptyPlan',
143 | desc: '',
144 | args: [],
145 | );
146 | }
147 |
148 | /// `New Task`
149 | String get newTask {
150 | return Intl.message('New Task', name: 'newTask', desc: '', args: []);
151 | }
152 |
153 | /// `Title`
154 | String get taskTitle {
155 | return Intl.message('Title', name: 'taskTitle', desc: '', args: []);
156 | }
157 |
158 | /// `Write your title here`
159 | String get taskTitleHint {
160 | return Intl.message(
161 | 'Write your title here',
162 | name: 'taskTitleHint',
163 | desc: '',
164 | args: [],
165 | );
166 | }
167 |
168 | /// `Note`
169 | String get taskNoteTitle {
170 | return Intl.message('Note', name: 'taskNoteTitle', desc: '', args: []);
171 | }
172 |
173 | /// `Write your note here`
174 | String get taskNoteHint {
175 | return Intl.message(
176 | 'Write your note here',
177 | name: 'taskNoteHint',
178 | desc: '',
179 | args: [],
180 | );
181 | }
182 |
183 | /// `Place`
184 | String get taskPlaceTitle {
185 | return Intl.message('Place', name: 'taskPlaceTitle', desc: '', args: []);
186 | }
187 |
188 | /// `What is the name of the place you want to go?`
189 | String get taskPlaceHint {
190 | return Intl.message(
191 | 'What is the name of the place you want to go?',
192 | name: 'taskPlaceHint',
193 | desc: '',
194 | args: [],
195 | );
196 | }
197 |
198 | /// `Time`
199 | String get time {
200 | return Intl.message('Time', name: 'time', desc: '', args: []);
201 | }
202 |
203 | /// `Task added successfully`
204 | String get addTaskSnackBar {
205 | return Intl.message(
206 | 'Task added successfully',
207 | name: 'addTaskSnackBar',
208 | desc: '',
209 | args: [],
210 | );
211 | }
212 |
213 | /// `The task successfully deleted`
214 | String get deleteTaskSnackBar {
215 | return Intl.message(
216 | 'The task successfully deleted',
217 | name: 'deleteTaskSnackBar',
218 | desc: '',
219 | args: [],
220 | );
221 | }
222 |
223 | /// `You must fill in the title`
224 | String get emptyTextFieldError {
225 | return Intl.message(
226 | 'You must fill in the title',
227 | name: 'emptyTextFieldError',
228 | desc: '',
229 | args: [],
230 | );
231 | }
232 |
233 | /// `Save`
234 | String get save {
235 | return Intl.message('Save', name: 'save', desc: '', args: []);
236 | }
237 |
238 | /// `Discard`
239 | String get discard {
240 | return Intl.message('Discard', name: 'discard', desc: '', args: []);
241 | }
242 |
243 | /// `Edit Task`
244 | String get editTask {
245 | return Intl.message('Edit Task', name: 'editTask', desc: '', args: []);
246 | }
247 |
248 | /// `The task edited successfully`
249 | String get editTaskSnackBar {
250 | return Intl.message(
251 | 'The task edited successfully',
252 | name: 'editTaskSnackBar',
253 | desc: '',
254 | args: [],
255 | );
256 | }
257 |
258 | /// `Are you sure you want to delete this task?`
259 | String get deleteTaskDialogContent {
260 | return Intl.message(
261 | 'Are you sure you want to delete this task?',
262 | name: 'deleteTaskDialogContent',
263 | desc: '',
264 | args: [],
265 | );
266 | }
267 |
268 | /// `Delete it`
269 | String get deleteDialogPrimaryBtn {
270 | return Intl.message(
271 | 'Delete it',
272 | name: 'deleteDialogPrimaryBtn',
273 | desc: '',
274 | args: [],
275 | );
276 | }
277 |
278 | /// `Cancel`
279 | String get deleteDialogSecendaryBtn {
280 | return Intl.message(
281 | 'Cancel',
282 | name: 'deleteDialogSecendaryBtn',
283 | desc: '',
284 | args: [],
285 | );
286 | }
287 |
288 | /// `Title`
289 | String get noteTextFieldTitleHint {
290 | return Intl.message(
291 | 'Title',
292 | name: 'noteTextFieldTitleHint',
293 | desc: '',
294 | args: [],
295 | );
296 | }
297 |
298 | /// `Write your note here...`
299 | String get noteTextFieldNoteHint {
300 | return Intl.message(
301 | 'Write your note here...',
302 | name: 'noteTextFieldNoteHint',
303 | desc: '',
304 | args: [],
305 | );
306 | }
307 |
308 | /// `Note added successfully`
309 | String get addNoteSnackBar {
310 | return Intl.message(
311 | 'Note added successfully',
312 | name: 'addNoteSnackBar',
313 | desc: '',
314 | args: [],
315 | );
316 | }
317 |
318 | /// `Note edited successfully`
319 | String get editNoteSnackBar {
320 | return Intl.message(
321 | 'Note edited successfully',
322 | name: 'editNoteSnackBar',
323 | desc: '',
324 | args: [],
325 | );
326 | }
327 |
328 | /// `Created at :`
329 | String get createAt {
330 | return Intl.message('Created at :', name: 'createAt', desc: '', args: []);
331 | }
332 |
333 | /// `Are you sure you want to delete this note?`
334 | String get deleteNoteDialogContent {
335 | return Intl.message(
336 | 'Are you sure you want to delete this note?',
337 | name: 'deleteNoteDialogContent',
338 | desc: '',
339 | args: [],
340 | );
341 | }
342 |
343 | /// `Note deleted successfully`
344 | String get deleteNoteSnackBar {
345 | return Intl.message(
346 | 'Note deleted successfully',
347 | name: 'deleteNoteSnackBar',
348 | desc: '',
349 | args: [],
350 | );
351 | }
352 |
353 | /// `ERROR`
354 | String get error {
355 | return Intl.message('ERROR', name: 'error', desc: '', args: []);
356 | }
357 |
358 | /// `Try Again`
359 | String get tryAgain {
360 | return Intl.message('Try Again', name: 'tryAgain', desc: '', args: []);
361 | }
362 |
363 | /// `Time:`
364 | String get taskCardTime {
365 | return Intl.message('Time:', name: 'taskCardTime', desc: '', args: []);
366 | }
367 |
368 | /// `Place: `
369 | String get taskCardPlace {
370 | return Intl.message('Place: ', name: 'taskCardPlace', desc: '', args: []);
371 | }
372 |
373 | /// `Note: `
374 | String get taskCardNote {
375 | return Intl.message('Note: ', name: 'taskCardNote', desc: '', args: []);
376 | }
377 |
378 | /// `0.0.1+1`
379 | String get appVersion {
380 | return Intl.message('0.0.1+1', name: 'appVersion', desc: '', args: []);
381 | }
382 |
383 | /// `Made with ☕ by Umut`
384 | String get author {
385 | return Intl.message(
386 | 'Made with ☕ by Umut',
387 | name: 'author',
388 | desc: '',
389 | args: [],
390 | );
391 | }
392 |
393 | /// `Add the task note to notes!`
394 | String get addToNote {
395 | return Intl.message(
396 | 'Add the task note to notes!',
397 | name: 'addToNote',
398 | desc: '',
399 | args: [],
400 | );
401 | }
402 |
403 | /// `Edit the note!`
404 | String get editNote {
405 | return Intl.message('Edit the note!', name: 'editNote', desc: '', args: []);
406 | }
407 | }
408 |
409 | class AppLocalizationDelegate extends LocalizationsDelegate {
410 | const AppLocalizationDelegate();
411 |
412 | List get supportedLocales {
413 | return const [
414 | Locale.fromSubtags(languageCode: 'en'),
415 | Locale.fromSubtags(languageCode: 'fa'),
416 | ];
417 | }
418 |
419 | @override
420 | bool isSupported(Locale locale) => _isSupported(locale);
421 | @override
422 | Future load(Locale locale) => S.load(locale);
423 | @override
424 | bool shouldReload(AppLocalizationDelegate old) => false;
425 |
426 | bool _isSupported(Locale locale) {
427 | for (var supportedLocale in supportedLocales) {
428 | if (supportedLocale.languageCode == locale.languageCode) {
429 | return true;
430 | }
431 | }
432 | return false;
433 | }
434 | }
435 |
--------------------------------------------------------------------------------
/lib/screens/home/note/edit_note_screen.dart:
--------------------------------------------------------------------------------
1 | part of '../../../index.dart';
2 |
3 | class EditNoteScreen extends StatefulWidget {
4 | const EditNoteScreen({super.key, required this.note});
5 |
6 | final NoteModel note;
7 |
8 | @override
9 | State createState() => _EditNoteScreenState();
10 | }
11 |
12 | class _EditNoteScreenState extends State {
13 |
14 | late TextEditingController _titleController;
15 | late TextEditingController _descriptionController;
16 |
17 | @override
18 | void initState() {
19 | _titleController = TextEditingController(text: widget.note.title);
20 | _descriptionController =
21 | TextEditingController(text: widget.note.description);
22 | super.initState();
23 | }
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | var lang = BlocProvider.of(context).state.locale.languageCode;
28 |
29 | return SafeArea(
30 | child: Scaffold(
31 | backgroundColor: Color(_noteSelectedColor.code),
32 | body: Column(
33 | children: [
34 | Expanded(
35 | child: ListView(
36 | keyboardDismissBehavior:
37 | ScrollViewKeyboardDismissBehavior.onDrag,
38 | padding: const EdgeInsets.symmetric(
39 | horizontal: 20,
40 | vertical: 20,
41 | ),
42 | children: [
43 | Stack(children: [
44 | TextField(
45 | controller: _titleController,
46 | style: AppTextStyles.noteTitleTextStyle
47 | .apply(color: AppColors.appPrimaryDark),
48 | decoration: InputDecoration(
49 | hintText: S.current.noteTextFieldTitleHint,
50 | hintStyle: const TextStyle(
51 | color: Color.fromARGB(132, 22, 25, 40)),
52 | border: InputBorder.none,
53 | contentPadding: EdgeInsets.zero,
54 | counterText: '',
55 | ),
56 | minLines: 1,
57 | maxLines: 8,
58 | maxLength: 140,
59 | ),
60 | Positioned(
61 | left: lang == 'fa' ? 0 : null,
62 | right: lang == 'en' ? 0 : null,
63 | child: IconButton(
64 | onPressed: () {
65 | customeDialogee(
66 | context,
67 | content: S.current.deleteNoteDialogContent,
68 | primaryBtn: S.current.deleteDialogPrimaryBtn,
69 | onTapPrimaryBtn: () {
70 | BlocProvider.of(context).add(
71 | DeleteNoteEvent(
72 | widget.note.id,
73 | ),
74 | );
75 | Navigator.pop(context);
76 | Navigator.pop(context);
77 | },
78 | onTapSecendaryBtn: () {
79 | Navigator.pop(context);
80 | },
81 | secendaryBtn: S.current.deleteDialogSecendaryBtn,
82 | );
83 |
84 |
85 | },
86 | icon: const Icon(
87 | Icons.delete_rounded,
88 | color: AppColors.appPrimaryDark,
89 | ),
90 | ),
91 | ),
92 | ]),
93 | const SizedBox(height: 20),
94 | TextField(
95 | controller: _descriptionController,
96 | style: AppTextStyles.noteDecTextStyle
97 | .apply(color: AppColors.appPrimaryDark),
98 | decoration: InputDecoration(
99 | hintText: S.current.noteTextFieldTitleHint,
100 | border: InputBorder.none,
101 | hintStyle: const TextStyle(
102 | color: Color.fromARGB(132, 22, 25, 40),
103 | ),
104 | contentPadding: EdgeInsets.zero,
105 | ),
106 | minLines: 2,
107 | maxLines: 100,
108 | onChanged: (value) {},
109 | ),
110 | const SizedBox(height: 20),
111 | Row(
112 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
113 | children: [
114 | Text(
115 | S.current.createAt,
116 | style: AppTextStyles.noteDecTextStyle
117 | .apply(color: AppColors.appPrimaryDark),
118 | ),
119 | Text(
120 | widget.note.dateTime,
121 | style: AppTextStyles.noteDecTextStyle
122 | .apply(color: AppColors.appPrimaryDark),
123 | ),
124 | ],
125 | ),
126 | ],
127 | ),
128 | ),
129 | Column(
130 | children: [
131 | Padding(
132 | padding: const EdgeInsets.only(right: AppDimens.small),
133 | child: NoteColorSelector(
134 | selectedColor: _noteSelectedColor,
135 | onColorSelected: (color) {
136 | setState(() {
137 | _noteSelectedColor = color;
138 | });
139 | },
140 | ),
141 | ),
142 | Padding(
143 | padding: const EdgeInsets.all(AppDimens.small),
144 | child: Row(
145 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
146 | children: [
147 | Expanded(
148 | child: SizedBox(
149 | height: 50,
150 | child: BlocConsumer(
151 | listener: (context, state) {
152 | if (state is UpdateNoteState) {
153 | ScaffoldMessenger.of(context).showSnackBar(
154 | SnackBar(
155 | duration: const Duration(milliseconds: 500),
156 | content: Text(
157 | S.current.editNoteSnackBar,
158 | ),
159 | ),
160 | );
161 | }
162 | },
163 | builder: (context, state) {
164 | return TextButton(
165 | style: const ButtonStyle(
166 | backgroundColor: WidgetStatePropertyAll(
167 | AppColors.appPrimaryDark,
168 | ),
169 | ),
170 | onPressed: () {
171 | if (_titleController.text.isEmpty) {
172 | ScaffoldMessenger.of(context).showSnackBar(
173 | SnackBar(
174 | content: Text(
175 | S.current.emptyTextFieldError,
176 | ),
177 | ),
178 | );
179 | } else {
180 | if (lang == 'fa') {
181 | String persianDateTime =
182 | '${DateTime.now().hour.toPersianNumberInt()}:${DateTime.now().minute.toPersianNumberInt()} / ${Jalali.now().day.toPersianNumberInt()} - ${Jalali.now().month.toPesianMonth()} ';
183 | BlocProvider.of(context).add(
184 | UpdateNoteEvent(
185 | NoteModel(
186 | id: widget.note.id,
187 | title: _titleController.text,
188 | description:
189 | _descriptionController.text,
190 | color: _noteSelectedColor,
191 | dateTime: persianDateTime),
192 | widget.note.id),
193 | );
194 | } else {
195 | String gDateTime =
196 | '${DateTime.now().hour}:${DateTime.now().minute} / ${DateTime.now().day} - ${DateTime.now().month.toGregorianMonth()} ';
197 | BlocProvider.of(context).add(
198 | UpdateNoteEvent(
199 | NoteModel(
200 | id: widget.note.id,
201 | title: _titleController.text,
202 | description:
203 | _descriptionController.text,
204 | color: _noteSelectedColor,
205 | dateTime: gDateTime),
206 | widget.note.id),
207 | );
208 | }
209 |
210 | Navigator.pop(context);
211 | }
212 | },
213 | child: Text(
214 | S.current.save,
215 | style: const TextStyle(
216 | color: AppColors.appOnPrimaryDark,
217 | ),
218 | ),
219 | );
220 | },
221 | ),
222 | ),
223 | ),
224 | AppDimens.small.width,
225 | Expanded(
226 | child: SizedBox(
227 | height: 50,
228 | child: TextButton(
229 | style: const ButtonStyle(
230 | backgroundColor: WidgetStatePropertyAll(
231 | AppColors.appPrimaryDark,
232 | ),
233 | ),
234 | onPressed: () {
235 | Navigator.pop(context);
236 | },
237 | child: Text(
238 | S.current.discard,
239 | style: const TextStyle(
240 | color: AppColors.appOnPrimaryDark),
241 | ),
242 | ),
243 | ),
244 | ),
245 | ],
246 | ),
247 | ),
248 | ],
249 | ),
250 | ],
251 | ),
252 | ),
253 | );
254 | }
255 | }
256 |
--------------------------------------------------------------------------------