Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Hoàng Văn Đạt
mypoint_flutter_app
Commits
6b980613
Commit
6b980613
authored
Nov 14, 2025
by
DatHV
Browse files
update project structure
parent
bfff9e47
Changes
507
Hide whitespace changes
Inline
Side-by-side
lib/
base
/base_view_model.dart
→
lib/
shared/widgets/base_view
/base_view_model.dart
View file @
6b980613
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:fluttertoast/fluttertoast.dart'
;
import
'package:fluttertoast/fluttertoast.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/
base
/app_loading.dart'
;
import
'package:mypoint_flutter_app/
shared/widgets/loading
/app_loading.dart'
;
class
BaseViewModel
extends
GetxController
with
WidgetsBindingObserver
{
class
BaseViewModel
extends
GetxController
with
WidgetsBindingObserver
{
var
isShowLoading
=
false
;
var
isShowLoading
=
false
;
RxBool
isShowKey
=
false
.
obs
;
RxBool
isShowKey
=
false
.
obs
;
FToast
fToast
=
FToast
();
FToast
fToast
=
FToast
();
final
RxBool
isLoading
=
false
.
obs
;
int
_trackedLoadingCount
=
0
;
@override
@override
void
onInit
()
{
void
onInit
()
{
...
@@ -42,4 +44,21 @@ class BaseViewModel extends GetxController with WidgetsBindingObserver {
...
@@ -42,4 +44,21 @@ class BaseViewModel extends GetxController with WidgetsBindingObserver {
void
hideLoading
()
{
void
hideLoading
()
{
AppLoading
().
hide
();
AppLoading
().
hide
();
}
}
@protected
void
beginTrackedLoading
()
{
_trackedLoadingCount
++;
if
(
_trackedLoadingCount
>=
1
)
{
isLoading
.
value
=
true
;
}
}
@protected
void
endTrackedLoading
()
{
// if (_trackedLoadingCount == 0) return;
_trackedLoadingCount
--;
if
(
_trackedLoadingCount
<=
0
)
{
isLoading
.
value
=
false
;
}
}
}
}
lib/
base
/basic_state.dart
→
lib/
shared/widgets/base_view
/basic_state.dart
View file @
6b980613
...
@@ -32,8 +32,7 @@ mixin BasicState<Screen extends BaseScreen> on BaseState<Screen> {
...
@@ -32,8 +32,7 @@ mixin BasicState<Screen extends BaseScreen> on BaseState<Screen> {
);
);
}
}
if
(!
isScaffold
)
{
if
(!
isScaffold
)
{
return
PopScope
(
return
PopScope
(
child:
createBody
());
child:
createBody
());
}
}
return
WillPopScope
(
return
WillPopScope
(
child:
Scaffold
(
child:
Scaffold
(
...
...
lib/widgets/bottom_sheet_helper.dart
→
lib/
shared/
widgets/bottom_sheet_helper.dart
View file @
6b980613
// bottom_sheet_helper.dart
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
...
@@ -20,7 +19,6 @@ class BottomSheetHelper {
...
@@ -20,7 +19,6 @@ class BottomSheetHelper {
borderRadius:
BorderRadius
.
vertical
(
top:
Radius
.
circular
(
16
)),
borderRadius:
BorderRadius
.
vertical
(
top:
Radius
.
circular
(
16
)),
),
),
builder:
(
context
)
{
builder:
(
context
)
{
final
bottom
=
MediaQuery
.
of
(
context
).
padding
.
bottom
;
return
Padding
(
return
Padding
(
padding:
MediaQuery
.
of
(
context
).
viewInsets
.
add
(
padding:
MediaQuery
.
of
(
context
).
viewInsets
.
add
(
const
EdgeInsets
.
only
(
bottom:
0
),
// 👈 Safe area bottom
const
EdgeInsets
.
only
(
bottom:
0
),
// 👈 Safe area bottom
...
...
lib/widgets/button_container.dart
→
lib/
shared/
widgets/button_container.dart
View file @
6b980613
File moved
lib/widgets/custom_app_bar.dart
→
lib/
shared/
widgets/custom_app_bar.dart
View file @
6b980613
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'back_button.dart'
;
import
'back_button.dart'
;
class
CustomAppBar
extends
StatelessWidget
implements
PreferredSizeWidget
{
class
CustomAppBar
extends
StatelessWidget
implements
PreferredSizeWidget
{
...
...
lib/widgets/custom_empty_widget.dart
→
lib/
shared/
widgets/custom_empty_widget.dart
View file @
6b980613
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
class
EmptyWidget
extends
StatelessWidget
{
class
EmptyWidget
extends
StatelessWidget
{
final
String
imageAsset
;
final
String
?
imageAsset
;
final
String
content
;
final
String
?
content
;
final
Size
size
;
final
Size
size
;
final
bool
isLoading
;
const
EmptyWidget
({
const
EmptyWidget
({
super
.
key
,
super
.
key
,
this
.
imageAsset
=
'assets/images/ic_pipi_06.png'
,
this
.
imageAsset
,
this
.
content
=
'Không có dữ liệu hiển thị'
,
this
.
content
,
this
.
size
=
const
Size
(
200
,
200
),
this
.
size
=
const
Size
(
200
,
200
),
this
.
isLoading
=
false
,
});
});
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
displayText
=
content
??
(
isLoading
?
'Đang tải dữ liệu...'
:
'Không có dữ liệu hiển thị'
);
final
assetPath
=
(
imageAsset
!=
null
&&
imageAsset
!.
isNotEmpty
)
?
imageAsset
!
:
(
isLoading
?
'assets/images/ic_pipi_07.png'
:
'assets/images/ic_pipi_03.png'
);
return
Center
(
return
Center
(
child:
Column
(
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
children:
[
Image
.
asset
(
Image
.
asset
(
imageAsset
,
assetPath
,
width:
size
.
width
,
width:
size
.
width
,
height:
size
.
height
,
height:
size
.
height
,
fit:
BoxFit
.
contain
,
fit:
BoxFit
.
contain
,
),
),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
16
),
Text
(
Text
(
conten
t
,
displayTex
t
,
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
style:
const
TextStyle
(
style:
const
TextStyle
(
fontSize:
14
,
fontSize:
14
,
...
...
lib/widgets/custom_navigation_bar.dart
→
lib/
shared/
widgets/custom_navigation_bar.dart
View file @
6b980613
import
'package:auto_size_text/auto_size_text.dart'
;
import
'package:auto_size_text/auto_size_text.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'../
screen
/home/header_home_viewmodel.dart'
;
import
'../
../features
/home/header_home_viewmodel.dart'
;
import
'back_button.dart'
;
import
'back_button.dart'
;
import
'image_loader.dart'
;
import
'image_loader.dart'
;
...
...
lib/widgets/custom_point_text_tag.dart
→
lib/
shared/
widgets/custom_point_text_tag.dart
View file @
6b980613
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:intl/intl.dart'
;
import
'../../core/utils/extensions/num_extension.dart'
;
import
'../extensions/num_extension.dart'
;
import
'../../features/voucher/models/cash_type.dart'
;
import
'../screen/voucher/models/cash_type.dart'
;
class
CustomPointText
extends
StatelessWidget
{
class
CustomPointText
extends
StatelessWidget
{
final
int
point
;
final
int
point
;
...
...
lib/widgets/custom_price_tag.dart
→
lib/
shared/
widgets/custom_price_tag.dart
View file @
6b980613
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'../extensions/num_extension.dart'
;
import
'../
../core/utils/
extensions/num_extension.dart'
;
import
'../
resources
/base_color.dart'
;
import
'../
../core/theme
/base_color.dart'
;
import
'../
screen
/voucher/models/cash_type.dart'
;
import
'../
../features
/voucher/models/cash_type.dart'
;
class
PriceTagWidget
extends
StatelessWidget
{
class
PriceTagWidget
extends
StatelessWidget
{
final
int
point
;
final
int
point
;
...
...
lib/widgets/custom_search_navigation_bar.dart
→
lib/
shared/
widgets/custom_search_navigation_bar.dart
View file @
6b980613
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'../
screen
/home/header_home_viewmodel.dart'
;
import
'../
../features
/home/header_home_viewmodel.dart'
;
import
'back_button.dart'
;
import
'back_button.dart'
;
import
'image_loader.dart'
;
import
'image_loader.dart'
;
...
...
lib/widgets/custom_toast_message.dart
→
lib/
shared/
widgets/custom_toast_message.dart
View file @
6b980613
File moved
lib/widgets/dashed_line.dart
→
lib/
shared/
widgets/dashed_line.dart
View file @
6b980613
...
@@ -7,12 +7,12 @@ class DashedLine extends StatelessWidget {
...
@@ -7,12 +7,12 @@ class DashedLine extends StatelessWidget {
final
Color
color
;
final
Color
color
;
const
DashedLine
({
const
DashedLine
({
Key
?
key
,
super
.
key
,
this
.
height
=
1
,
this
.
height
=
1
,
this
.
dashWidth
=
4
,
this
.
dashWidth
=
4
,
this
.
dashSpacing
=
4
,
this
.
dashSpacing
=
4
,
this
.
color
=
Colors
.
grey
,
this
.
color
=
Colors
.
grey
,
})
:
super
(
key:
key
)
;
});
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
...
...
lib/widgets/image_loader.dart
→
lib/
shared/
widgets/image_loader.dart
View file @
6b980613
File moved
lib/
base
/app_loading.dart
→
lib/
shared/widgets/loading
/app_loading.dart
View file @
6b980613
import
'dart:async'
;
import
'dart:async'
;
import
'dart:collection'
;
import
'dart:collection'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'../config
s
/constants.dart'
;
import
'../
../../app/
config/constants.dart'
;
class
AppLoading
{
class
AppLoading
{
// Singleton ẩn
// Singleton ẩn
...
...
lib/widgets/measure_size.dart
→
lib/
shared/
widgets/measure_size.dart
View file @
6b980613
File moved
lib/widgets/network_image_with_aspect_ratio.dart
→
lib/
shared/
widgets/network_image_with_aspect_ratio.dart
View file @
6b980613
File moved
lib/widgets/support_button.dart
→
lib/
shared/
widgets/support_button.dart
View file @
6b980613
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'../
resources
/base_color.dart'
;
import
'../
../core/theme
/base_color.dart'
;
import
'../
screen
/support/support_screen.dart'
;
import
'../
../features
/support/support_screen.dart'
;
class
SupportButton
extends
StatelessWidget
{
class
SupportButton
extends
StatelessWidget
{
const
SupportButton
({
super
.
key
});
const
SupportButton
({
super
.
key
});
...
...
lib/widgets/time_picker_widget.dart
deleted
100644 → 0
View file @
bfff9e47
// import 'package:flutter/material.dart';
// import 'package:intl/intl.dart';
//
// class DatePickerField extends StatefulWidget {
// final String label;
// final DateTime? initialDate;
// final Function(DateTime) onDateSelected;
// final bool enabled;
//
// const DatePickerField({
// super.key,
// required this.label,
// this.initialDate,
// required this.onDateSelected,
// this.enabled = true,
// });
//
// @override
// State<DatePickerField> createState() => _DatePickerFieldState();
// }
//
// class _DatePickerFieldState extends State<DatePickerField> {
// DateTime? _selectedDate;
//
// @override
// void initState() {
// super.initState();
// _selectedDate = widget.initialDate;
// }
//
// Future<void> _pickDate() async {
// if (!widget.enabled) return;
//
// final now = DateTime.now();
// final picked = await showDatePicker(
// context: context,
// initialDate: _selectedDate ?? now,
// firstDate: DateTime(1900),
// lastDate: DateTime(2100),
// );
//
// if (picked != null) {
// setState(() {
// _selectedDate = picked;
// });
// widget.onDateSelected(picked);
// }
// }
//
// @override
// Widget build(BuildContext context) {
// final displayText = _selectedDate != null
// ? DateFormat('dd/MM/yyyy').format(_selectedDate!)
// : widget.label;
//
// return GestureDetector(
// onTap: _pickDate,
// child: AbsorbPointer(
// child: Container(
// padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
// decoration: BoxDecoration(
// border: Border.all(color: Colors.grey.shade400),
// borderRadius: BorderRadius.circular(8),
// color: widget.enabled ? Colors.white : Colors.grey.shade100,
// ),
// child: Row(
// children: [
// const Icon(Icons.calendar_today, color: Colors.blueGrey, size: 20),
// const SizedBox(width: 12),
// Expanded(
// child: Text(
// displayText,
// style: TextStyle(
// fontSize: 16,
// color: _selectedDate != null
// ? Colors.black87
// : Colors.grey.shade500,
// ),
// ),
// ),
// if (widget.enabled)
// const Icon(Icons.expand_more, color: Colors.grey),
// ],
// ),
// ),
// ),
// );
// }
// }
migrate_structure.sh
deleted
100755 → 0
View file @
bfff9e47
#!/usr/bin/env bash
# Script để tự động di chuyển files theo cấu trúc mới
# Chạy từng phase một, test kỹ sau mỗi phase
set
-euo
pipefail
PROJECT_ROOT
=
"
$(
cd
"
$(
dirname
"
${
BASH_SOURCE
[0]
}
"
)
"
&&
pwd
)
"
LIB_DIR
=
"
${
PROJECT_ROOT
}
/lib"
BACKUP_DIR
=
"
${
PROJECT_ROOT
}
/.migration_backup_
$(
date
+%Y%m%d_%H%M%S
)
"
# Colors for output
RED
=
'\033[0;31m'
GREEN
=
'\033[0;32m'
YELLOW
=
'\033[1;33m'
NC
=
'\033[0m'
# No Color
log_info
()
{
echo
-e
"
${
GREEN
}
[INFO]
${
NC
}
$1
"
}
log_warn
()
{
echo
-e
"
${
YELLOW
}
[WARN]
${
NC
}
$1
"
}
log_error
()
{
echo
-e
"
${
RED
}
[ERROR]
${
NC
}
$1
"
}
create_backup
()
{
log_info
"Creating backup at
${
BACKUP_DIR
}
..."
mkdir
-p
"
${
BACKUP_DIR
}
"
cp
-r
"
${
LIB_DIR
}
"
"
${
BACKUP_DIR
}
/lib"
log_info
"Backup created successfully!"
}
create_directories
()
{
local
phase
=
"
$1
"
log_info
"Creating directories for Phase
${
phase
}
..."
if
[
"
$phase
"
=
"1"
]
;
then
# Phase 1: Core reorganization
mkdir
-p
"
${
LIB_DIR
}
/core/config"
mkdir
-p
"
${
LIB_DIR
}
/core/initialization"
mkdir
-p
"
${
LIB_DIR
}
/core/utils/extensions"
mkdir
-p
"
${
LIB_DIR
}
/core/navigation"
mkdir
-p
"
${
LIB_DIR
}
/core/theme"
log_info
"Phase 1 directories created"
elif
[
"
$phase
"
=
"2"
]
;
then
# Phase 2: Network & Services
mkdir
-p
"
${
LIB_DIR
}
/core/network/api"
mkdir
-p
"
${
LIB_DIR
}
/core/network/interceptor"
mkdir
-p
"
${
LIB_DIR
}
/core/storage/point"
mkdir
-p
"
${
LIB_DIR
}
/core/services/auth"
mkdir
-p
"
${
LIB_DIR
}
/core/platform/web"
mkdir
-p
"
${
LIB_DIR
}
/core/platform/permission"
mkdir
-p
"
${
LIB_DIR
}
/core/platform/firebase"
log_info
"Phase 2 directories created"
elif
[
"
$phase
"
=
"3"
]
;
then
# Phase 3: Feature-based (sẽ tạo khi cần)
log_warn
"Phase 3 directories will be created per feature"
fi
}
phase1_core_reorganization
()
{
log_info
"=== Phase 1: Core Reorganization ==="
# 1. Move configs
log_info
"Moving configs to core/config/..."
if
[
-d
"
${
LIB_DIR
}
/configs"
]
;
then
mv
"
${
LIB_DIR
}
/configs"
/
*
"
${
LIB_DIR
}
/core/config/"
2>/dev/null
||
true
rmdir
"
${
LIB_DIR
}
/configs"
2>/dev/null
||
true
fi
if
[
-f
"
${
LIB_DIR
}
/env_loader.dart"
]
;
then
mv
"
${
LIB_DIR
}
/env_loader.dart"
"
${
LIB_DIR
}
/core/config/"
fi
# 2. Move initialization
log_info
"Moving initialization to core/initialization/..."
if
[
-d
"
${
LIB_DIR
}
/core"
]
;
then
if
[
-f
"
${
LIB_DIR
}
/core/app_initializer.dart"
]
;
then
mv
"
${
LIB_DIR
}
/core/app_initializer.dart"
"
${
LIB_DIR
}
/core/initialization/"
fi
if
[
-f
"
${
LIB_DIR
}
/core/web_app_initializer.dart"
]
;
then
mv
"
${
LIB_DIR
}
/core/web_app_initializer.dart"
"
${
LIB_DIR
}
/core/initialization/"
fi
if
[
-f
"
${
LIB_DIR
}
/core/deep_link_service.dart"
]
;
then
mv
"
${
LIB_DIR
}
/core/deep_link_service.dart"
"
${
LIB_DIR
}
/core/initialization/"
fi
fi
# 3. Move utils and extensions
log_info
"Moving utils and extensions to core/utils/..."
if
[
-d
"
${
LIB_DIR
}
/utils"
]
;
then
# Move non-extension files
for
file
in
"
${
LIB_DIR
}
/utils"
/
*
.dart
;
do
if
[
-f
"
$file
"
]
;
then
mv
"
$file
"
"
${
LIB_DIR
}
/core/utils/"
fi
done
rmdir
"
${
LIB_DIR
}
/utils"
2>/dev/null
||
true
fi
if
[
-d
"
${
LIB_DIR
}
/extensions"
]
;
then
mv
"
${
LIB_DIR
}
/extensions"
/
*
"
${
LIB_DIR
}
/core/utils/extensions/"
2>/dev/null
||
true
rmdir
"
${
LIB_DIR
}
/extensions"
2>/dev/null
||
true
fi
# Move shared files to utils
if
[
-d
"
${
LIB_DIR
}
/shared"
]
;
then
for
file
in
"
${
LIB_DIR
}
/shared"
/
*
.dart
;
do
if
[
-f
"
$file
"
]
;
then
mv
"
$file
"
"
${
LIB_DIR
}
/core/utils/"
fi
done
rmdir
"
${
LIB_DIR
}
/shared"
2>/dev/null
||
true
fi
# 4. Move navigation
log_info
"Moving navigation to core/navigation/..."
if
[
-f
"
${
LIB_DIR
}
/base/app_navigator.dart"
]
;
then
mkdir
-p
"
${
LIB_DIR
}
/core/navigation"
mv
"
${
LIB_DIR
}
/base/app_navigator.dart"
"
${
LIB_DIR
}
/core/navigation/"
fi
if
[
-d
"
${
LIB_DIR
}
/deferred"
]
;
then
mv
"
${
LIB_DIR
}
/deferred"
/
*
"
${
LIB_DIR
}
/core/navigation/"
2>/dev/null
||
true
rmdir
"
${
LIB_DIR
}
/deferred"
2>/dev/null
||
true
fi
if
[
-d
"
${
LIB_DIR
}
/directional"
]
;
then
mv
"
${
LIB_DIR
}
/directional"
/
*
"
${
LIB_DIR
}
/core/navigation/"
2>/dev/null
||
true
rmdir
"
${
LIB_DIR
}
/directional"
2>/dev/null
||
true
fi
# 5. Move resources to theme
log_info
"Moving resources to core/theme/..."
if
[
-d
"
${
LIB_DIR
}
/resources"
]
;
then
mkdir
-p
"
${
LIB_DIR
}
/core/theme"
# Rename files
if
[
-f
"
${
LIB_DIR
}
/resources/base_color.dart"
]
;
then
mv
"
${
LIB_DIR
}
/resources/base_color.dart"
"
${
LIB_DIR
}
/core/theme/colors.dart"
fi
if
[
-f
"
${
LIB_DIR
}
/resources/text_style.dart"
]
;
then
mv
"
${
LIB_DIR
}
/resources/text_style.dart"
"
${
LIB_DIR
}
/core/theme/text_styles.dart"
fi
if
[
-f
"
${
LIB_DIR
}
/resources/button_style.dart"
]
;
then
mv
"
${
LIB_DIR
}
/resources/button_style.dart"
"
${
LIB_DIR
}
/core/theme/button_styles.dart"
fi
if
[
-f
"
${
LIB_DIR
}
/resources/define_image.dart"
]
;
then
mv
"
${
LIB_DIR
}
/resources/define_image.dart"
"
${
LIB_DIR
}
/core/theme/images.dart"
fi
rmdir
"
${
LIB_DIR
}
/resources"
2>/dev/null
||
true
fi
log_info
"Phase 1 completed!"
log_warn
"Please update imports and test the app before proceeding to Phase 2"
}
phase2_network_services
()
{
log_info
"=== Phase 2: Network & Services Reorganization ==="
# 1. Move networking
log_info
"Moving networking to core/network/..."
if
[
-d
"
${
LIB_DIR
}
/networking"
]
;
then
# Move API clients
if
[
-d
"
${
LIB_DIR
}
/networking/api"
]
;
then
mv
"
${
LIB_DIR
}
/networking/api"
/
*
"
${
LIB_DIR
}
/core/network/api/"
2>/dev/null
||
true
fi
# Move interceptors
if
[
-d
"
${
LIB_DIR
}
/networking/interceptor"
]
;
then
mv
"
${
LIB_DIR
}
/networking/interceptor"
/
*
"
${
LIB_DIR
}
/core/network/interceptor/"
2>/dev/null
||
true
fi
# Move other networking files
for
file
in
"
${
LIB_DIR
}
/networking"
/
*
.dart
;
do
if
[
-f
"
$file
"
]
;
then
mv
"
$file
"
"
${
LIB_DIR
}
/core/network/"
fi
done
rmdir
"
${
LIB_DIR
}
/networking/api"
2>/dev/null
||
true
rmdir
"
${
LIB_DIR
}
/networking/interceptor"
2>/dev/null
||
true
rmdir
"
${
LIB_DIR
}
/networking"
2>/dev/null
||
true
fi
# 2. Move services
log_info
"Moving services to core/services/..."
if
[
-d
"
${
LIB_DIR
}
/services"
]
;
then
mkdir
-p
"
${
LIB_DIR
}
/core/services/auth"
for
file
in
"
${
LIB_DIR
}
/services"
/
*
.dart
;
do
if
[
-f
"
$file
"
]
;
then
mv
"
$file
"
"
${
LIB_DIR
}
/core/services/auth/"
fi
done
rmdir
"
${
LIB_DIR
}
/services"
2>/dev/null
||
true
fi
# 3. Move preference to storage
log_info
"Moving preference to core/storage/..."
if
[
-d
"
${
LIB_DIR
}
/preference"
]
;
then
# Move point folder
if
[
-d
"
${
LIB_DIR
}
/preference/point"
]
;
then
mv
"
${
LIB_DIR
}
/preference/point"
"
${
LIB_DIR
}
/core/storage/"
fi
# Move other files
for
file
in
"
${
LIB_DIR
}
/preference"
/
*
.dart
;
do
if
[
-f
"
$file
"
]
;
then
mv
"
$file
"
"
${
LIB_DIR
}
/core/storage/"
fi
done
rmdir
"
${
LIB_DIR
}
/preference"
2>/dev/null
||
true
fi
# 4. Move platform-specific
log_info
"Moving platform-specific to core/platform/..."
# Web
if
[
-d
"
${
LIB_DIR
}
/web"
]
;
then
mv
"
${
LIB_DIR
}
/web"
/
*
"
${
LIB_DIR
}
/core/platform/web/"
2>/dev/null
||
true
rmdir
"
${
LIB_DIR
}
/web"
2>/dev/null
||
true
fi
# Permission
if
[
-d
"
${
LIB_DIR
}
/permission"
]
;
then
mv
"
${
LIB_DIR
}
/permission"
/
*
"
${
LIB_DIR
}
/core/platform/permission/"
2>/dev/null
||
true
rmdir
"
${
LIB_DIR
}
/permission"
2>/dev/null
||
true
fi
# Firebase
if
[
-d
"
${
LIB_DIR
}
/firebase"
]
;
then
mv
"
${
LIB_DIR
}
/firebase"
/
*
"
${
LIB_DIR
}
/core/platform/firebase/"
2>/dev/null
||
true
rmdir
"
${
LIB_DIR
}
/firebase"
2>/dev/null
||
true
fi
log_info
"Phase 2 completed!"
log_warn
"Please update imports and test the app before proceeding to Phase 3"
}
phase3_features
()
{
log_info
"=== Phase 3: Feature-based Organization ==="
log_warn
"Phase 3 requires manual work and careful testing"
log_info
"This phase will create feature structure but won't move files automatically"
# Create feature directories structure
mkdir
-p
"
${
LIB_DIR
}
/features"
# List of features to create
local
features
=(
"auth:login,otp,create_pass"
"home"
"voucher"
"transaction"
"campaign:campaign7day,quiz_campaign,register_campaign,invite_friend_campaign"
"payment:electric_payment,mobile_card,topup,traffic_service"
"point:history_point,history_point_cashback,daily_checkin"
"profile:personal,setting,change_pass,delete_account,biometric"
"notification"
"membership"
"affiliate:affiliate,affiliate_brand_detail"
"game:game,vplay_game_center"
"support:support,faqs,news"
"common:splash,onboarding,webview,qr_code,popup_manager,main_tab_screen"
)
for
feature_info
in
"
${
features
[@]
}
"
;
do
IFS
=
':'
read
-r
feature_name subfeatures
<<<
"
$feature_info
"
log_info
"Creating structure for feature:
${
feature_name
}
"
mkdir
-p
"
${
LIB_DIR
}
/features/
${
feature_name
}
/data/models"
mkdir
-p
"
${
LIB_DIR
}
/features/
${
feature_name
}
/data/repositories"
mkdir
-p
"
${
LIB_DIR
}
/features/
${
feature_name
}
/data/datasources"
mkdir
-p
"
${
LIB_DIR
}
/features/
${
feature_name
}
/domain/entities"
mkdir
-p
"
${
LIB_DIR
}
/features/
${
feature_name
}
/domain/repositories"
mkdir
-p
"
${
LIB_DIR
}
/features/
${
feature_name
}
/domain/usecases"
mkdir
-p
"
${
LIB_DIR
}
/features/
${
feature_name
}
/presentation/screens"
mkdir
-p
"
${
LIB_DIR
}
/features/
${
feature_name
}
/presentation/viewmodels"
mkdir
-p
"
${
LIB_DIR
}
/features/
${
feature_name
}
/presentation/widgets"
# Create placeholder README
cat
>
"
${
LIB_DIR
}
/features/
${
feature_name
}
/README.md"
<<
EOF
#
${
feature_name
^
}
Feature
This feature contains:
-
\`
data/
\`
: Data models, repositories, and data sources
-
\`
domain/
\`
: Business entities and use cases
-
\`
presentation/
\`
: UI screens, viewmodels, and widgets
## Migration Notes
Move related screens from
\`
lib/screen/
\`
to this feature's
\`
presentation/screens/
\`
directory.
EOF
done
log_info
"Feature structures created!"
log_warn
"Now you need to manually move screens from lib/screen/ to appropriate features"
log_warn
"Example: lib/screen/login/ -> lib/features/auth/presentation/screens/login/"
}
update_imports
()
{
log_info
"=== Updating Imports ==="
log_warn
"This is a placeholder. You need to update imports manually or use find/replace"
log_info
"Common import changes:"
echo
" - configs/ -> core/config/"
echo
" - utils/ -> core/utils/"
echo
" - shared/ -> core/utils/"
echo
" - resources/ -> core/theme/"
echo
" - networking/ -> core/network/"
echo
" - services/ -> core/services/"
echo
" - preference/ -> core/storage/"
echo
" - web/ -> core/platform/web/"
echo
" - firebase/ -> core/platform/firebase/"
}
main
()
{
local
phase
=
"
${
1
:-}
"
if
[
-z
"
$phase
"
]
;
then
echo
"Usage:
$0
[phase1|phase2|phase3|all]"
echo
""
echo
"Phases:"
echo
" phase1 - Core reorganization (low risk)"
echo
" phase2 - Network & Services (medium risk)"
echo
" phase3 - Feature-based structure (high risk, manual)"
echo
" all - Run all phases (NOT RECOMMENDED)"
exit
1
fi
log_info
"Starting migration to new structure..."
log_warn
"Make sure you have committed your changes before running this script!"
read
-p
"Continue? (y/N): "
-n
1
-r
echo
if
[[
!
$REPLY
=
~ ^[Yy]
$
]]
;
then
log_info
"Migration cancelled"
exit
0
fi
create_backup
log_info
"Backup created at:
${
BACKUP_DIR
}
"
case
"
$phase
"
in
phase1
)
create_directories 1
phase1_core_reorganization
;;
phase2
)
create_directories 2
phase2_network_services
;;
phase3
)
create_directories 3
phase3_features
;;
all
)
log_error
"Running all phases at once is NOT RECOMMENDED!"
log_error
"Please run each phase separately and test after each one."
exit
1
;;
*
)
log_error
"Invalid phase:
$phase
"
exit
1
;;
esac
log_info
"Migration completed!"
log_info
"Backup location:
${
BACKUP_DIR
}
"
log_warn
"Next steps:"
log_warn
"1. Update imports in your code"
log_warn
"2. Run 'flutter pub get'"
log_warn
"3. Test the app thoroughly"
log_warn
"4. If something breaks, restore from backup"
}
main
"
$@
"
run_dev.sh
View file @
6b980613
...
@@ -120,7 +120,8 @@ class CORSRequestHandler(http.server.SimpleHTTPRequestHandler):
...
@@ -120,7 +120,8 @@ class CORSRequestHandler(http.server.SimpleHTTPRequestHandler):
self.send_header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, Accept, Origin')
self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, Accept, Origin')
# Add cache headers for static assets to speed up localhost loading
# Add cache headers for static assets to speed up localhost loading
if self.path.endswith(('.js', '.wasm', '.css', '.woff2', '.png', '.jpg', '.svg')):
cacheable_exts = ('.js', '.wasm', '.css', '.woff2', '.png', '.jpg', '.jpeg', '.svg', '.webp')
if self.path.endswith(cacheable_exts):
self.send_header('Cache-Control', 'public, max-age=3600')
self.send_header('Cache-Control', 'public, max-age=3600')
super().end_headers()
super().end_headers()
...
...
Prev
1
…
21
22
23
24
25
26
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment