Commit e838a036 authored by DatHV's avatar DatHV
Browse files

update config

parent 3a2a0642
#!/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 "$@"
...@@ -16,37 +16,17 @@ kill_port() { ...@@ -16,37 +16,17 @@ kill_port() {
lsof -i ":${port}" | awk 'NR>1 {print $2}' | xargs kill -9 2>/dev/null || true lsof -i ":${port}" | awk 'NR>1 {print $2}' | xargs kill -9 2>/dev/null || true
} }
set_env() { set_env_dev() {
local env="$1" echo "🔧 Switching to DEVELOPMENT environment..."
case "${env}" in local src="${PROJECT_ROOT}/assets/config/env_dev.json"
dev) local dest="${PROJECT_ROOT}/assets/config/env.json"
echo "🔧 Switching to DEVELOPMENT environment..." if [ ! -f "${src}" ]; then
local src="${PROJECT_ROOT}/assets/config/env_dev.json" echo "❌ ${src} not found" >&2
local dest="${PROJECT_ROOT}/assets/config/env.json" exit 1
if [ ! -f "${src}" ]; then fi
echo "❌ ${src} not found" >&2 cp "${src}" "${dest}"
exit 1
fi
cp "${src}" "${dest}"
;;
prod)
echo "🚀 Switching to PRODUCTION environment..."
cat > assets/config/env.json <<'EOF'
{
"flavor":"pro",
"baseUrl":"https://api.mypoint.com.vn/8854/gup2start/rest",
"t3Token":"runner-env-flavor-pro",
"enableLogging":false
}
EOF
;;
*)
echo "❌ Invalid environment: ${env}" >&2
exit 1
;;
esac
echo "📋 Current config:" echo "📋 Current config:"
cat assets/config/env.json cat "${dest}"
echo "" echo ""
} }
...@@ -138,7 +118,7 @@ cleanup() { ...@@ -138,7 +118,7 @@ cleanup() {
echo "🔧 Running Development..." echo "🔧 Running Development..."
kill_port "${PORT}" kill_port "${PORT}"
set_env dev set_env_dev
build_web build_web
copy_x_app_sdk copy_x_app_sdk
start_server start_server
......
#!/usr/bin/env bash
# Script to build, export, update Nginx config, and start/reload Nginx
# One command to rule them all! 🚀
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
NGINX_CONF="${HOME}/nginx-gzip.conf"
update_nginx_config() {
echo "🔧 Step 2: Updating Nginx config..."
local latest_export
latest_export=$(ls -td "${PROJECT_ROOT}"/web_dev_export_*/ 2>/dev/null | head -1 || true)
if [ -z "${latest_export}" ]; then
echo "❌ No export directory found. Please run ./export_dev.sh first." >&2
exit 1
fi
latest_export="${latest_export%/}"
echo "📁 Latest export directory: ${latest_export}"
local mime_types_file=""
for candidate in \
"/opt/homebrew/etc/nginx/mime.types" \
"/usr/local/etc/nginx/mime.types" \
"/etc/nginx/mime.types"
do
if [ -f "${candidate}" ]; then
mime_types_file="${candidate}"
break
fi
done
local mime_include_directive
if [ -n "${mime_types_file}" ]; then
echo "🗂 Using mime types file: ${mime_types_file}"
mime_include_directive=" include ${mime_types_file};"
else
echo "⚠️ mime.types not found; falling back to default types."
mime_include_directive=" # mime.types not found; relying on default types"
fi
cat > "${NGINX_CONF}" <<EOF
events {}
http {
${mime_include_directive}
default_type application/octet-stream;
gzip on;
gzip_static on;
gzip_types application/javascript text/css application/json application/wasm font/woff2 image/svg+xml;
gzip_min_length 1024;
server {
listen 8080;
server_name localhost;
root ${latest_export};
index index.html;
location / {
try_files \$uri \$uri/ /index.html;
}
location ~* \.(?:js|css|json|wasm|svg|woff2)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files \$uri \$uri/ /index.html;
}
}
}
EOF
echo "✅ Nginx config updated!"
}
echo "🚀 Starting DEV build and Nginx setup..."
echo ""
# Step 1: Build and export
echo "📦 Step 1: Building and exporting..."
./export_dev.sh
echo ""
update_nginx_config
echo ""
echo "🔄 Step 3: Starting/Reloading Nginx..."
# Check if Nginx is already running
if pgrep -f "nginx.*nginx-gzip.conf" > /dev/null; then
echo " Nginx is running, reloading..."
nginx -s reload -c "${NGINX_CONF}" || {
echo " ⚠️ Reload failed, restarting..."
nginx -s stop -c "${NGINX_CONF}" 2>/dev/null || true
nginx -c "${NGINX_CONF}"
}
else
echo " Starting Nginx..."
nginx -c "${NGINX_CONF}"
fi
echo ""
echo "✅ Done! 🎉"
echo ""
echo "🌐 Your app is available at: http://localhost:8080"
echo ""
echo "📊 To check if gzip is working:"
echo " 1. Open DevTools (F12) → Network tab"
echo " 2. Reload the page"
echo " 3. Click on main.dart.js"
echo " 4. Check Response Headers for 'Content-Encoding: gzip'"
echo ""
echo "🛑 To stop Nginx:"
echo " nginx -s stop -c ${NGINX_CONF}"
#!/usr/bin/env bash
# Script để tự động update imports sau khi migration
# Sử dụng find/replace để update các imports cũ sang mới
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LIB_DIR="${PROJECT_ROOT}/lib"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
update_imports_phase1() {
log_info "Updating imports for Phase 1..."
# Find all Dart files
find "${LIB_DIR}" -name "*.dart" -type f | while read -r file; do
# Skip generated files
if [[ "$file" == *.g.dart ]]; then
continue
fi
# Update configs imports
sed -i '' "s|package:mypoint_flutter_app/configs/|package:mypoint_flutter_app/core/config/|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/env_loader|package:mypoint_flutter_app/core/config/env_loader|g" "$file"
# Update utils imports
sed -i '' "s|package:mypoint_flutter_app/utils/|package:mypoint_flutter_app/core/utils/|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/shared/|package:mypoint_flutter_app/core/utils/|g" "$file"
# Update extensions imports
sed -i '' "s|package:mypoint_flutter_app/extensions/|package:mypoint_flutter_app/core/utils/extensions/|g" "$file"
# Update navigation imports
sed -i '' "s|package:mypoint_flutter_app/deferred/|package:mypoint_flutter_app/core/navigation/|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/directional/|package:mypoint_flutter_app/core/navigation/|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/base/app_navigator|package:mypoint_flutter_app/core/navigation/app_navigator|g" "$file"
# Update resources/theme imports
sed -i '' "s|package:mypoint_flutter_app/resources/base_color|package:mypoint_flutter_app/core/theme/colors|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/resources/text_style|package:mypoint_flutter_app/core/theme/text_styles|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/resources/button_style|package:mypoint_flutter_app/core/theme/button_styles|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/resources/define_image|package:mypoint_flutter_app/core/theme/images|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/resources/|package:mypoint_flutter_app/core/theme/|g" "$file"
# Update core initialization imports
sed -i '' "s|package:mypoint_flutter_app/core/app_initializer|package:mypoint_flutter_app/core/initialization/app_initializer|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/core/web_app_initializer|package:mypoint_flutter_app/core/initialization/web_app_initializer|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/core/deep_link_service|package:mypoint_flutter_app/core/initialization/deep_link_service|g" "$file"
done
log_info "Phase 1 imports updated!"
}
update_imports_phase2() {
log_info "Updating imports for Phase 2..."
find "${LIB_DIR}" -name "*.dart" -type f | while read -r file; do
if [[ "$file" == *.g.dart ]]; then
continue
fi
# Update networking imports
sed -i '' "s|package:mypoint_flutter_app/networking/|package:mypoint_flutter_app/core/network/|g" "$file"
# Update services imports
sed -i '' "s|package:mypoint_flutter_app/services/|package:mypoint_flutter_app/core/services/auth/|g" "$file"
# Update preference imports
sed -i '' "s|package:mypoint_flutter_app/preference/|package:mypoint_flutter_app/core/storage/|g" "$file"
# Update platform imports
sed -i '' "s|package:mypoint_flutter_app/web/|package:mypoint_flutter_app/core/platform/web/|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/permission/|package:mypoint_flutter_app/core/platform/permission/|g" "$file"
sed -i '' "s|package:mypoint_flutter_app/firebase/|package:mypoint_flutter_app/core/platform/firebase/|g" "$file"
done
log_info "Phase 2 imports updated!"
}
main() {
local phase="${1:-}"
if [ -z "$phase" ]; then
echo "Usage: $0 [phase1|phase2]"
echo ""
echo "This script updates imports after running migrate_structure.sh"
exit 1
fi
case "$phase" in
phase1)
update_imports_phase1
;;
phase2)
update_imports_phase2
;;
*)
log_warn "Invalid phase: $phase"
exit 1
;;
esac
log_info "Import update completed!"
log_warn "Please review the changes and test the app"
}
main "$@"
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
background: #ffffff url('assets/assets/images/splash_screen.png') center/cover no-repeat; background: #ffffff url('assets/assets/images/splash_screen.webp') center/cover no-repeat;
z-index: 9999; z-index: 9999;
transition: opacity 0.3s ease, visibility 0.3s ease; transition: opacity 0.3s ease, visibility 0.3s ease;
overflow: hidden; overflow: hidden;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment