Update: 2026-06-10 02:44:54

This commit is contained in:
Hamza-Ayed
2026-06-10 02:44:55 +03:00
parent 9bc7a31c94
commit a0473a8b0f
134 changed files with 1706 additions and 544 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,36 @@
-- 1. Table for storing the unified 6-digit referral code for each user (Driver/Passenger)
CREATE TABLE `user_referral_codes` (
`id` INT NOT NULL AUTO_INCREMENT,
`user_id` VARCHAR(100) NOT NULL,
`user_type` ENUM('driver', 'passenger') NOT NULL,
`referral_code` VARCHAR(6) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_type_id` (`user_id`, `user_type`),
UNIQUE KEY `idx_referral_code` (`referral_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- 2. Table for tracking the referral relationship and trip counts
CREATE TABLE `unified_referrals` (
`id` INT NOT NULL AUTO_INCREMENT,
`inviter_code` VARCHAR(6) NOT NULL,
`invited_user_id` VARCHAR(100) NOT NULL,
`invited_user_type` ENUM('driver', 'passenger') NOT NULL,
`status` ENUM('registered', 'active', 'completed') NOT NULL DEFAULT 'registered',
`trip_count` INT NOT NULL DEFAULT 0,
`is_reward_claimed` TINYINT(1) NOT NULL DEFAULT 0,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_invited_user` (`invited_user_id`, `invited_user_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- 3. Table for Driver Cash Claims (when a driver requests to receive their reward as manual cash)
CREATE TABLE `driver_cash_claims` (
`id` INT NOT NULL AUTO_INCREMENT,
`driver_id` VARCHAR(100) NOT NULL,
`referral_id` INT NOT NULL,
`amount_syp` INT NOT NULL,
`status` ENUM('pending', 'paid') NOT NULL DEFAULT 'pending',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

View File

@@ -0,0 +1,37 @@
<?php
require_once __DIR__ . '/../../connect.php';
$inviterCode = filterRequest("inviter_code");
// Use JWT token variables provided by connect.php
if (!$inviterCode || !$user_id || !in_array($role, ['driver', 'passenger'])) {
jsonError("Invalid parameters or unauthorized token");
}
// Ensure the code exists and get the inviter details
$stmtCheck = $con->prepare("SELECT user_id, user_type FROM user_referral_codes WHERE referral_code = ?");
$stmtCheck->execute([$inviterCode]);
if ($stmtCheck->rowCount() == 0) {
jsonError("Invalid referral code");
}
$inviterData = $stmtCheck->fetch(PDO::FETCH_ASSOC);
// Check if user was already invited
$stmtExisting = $con->prepare("SELECT id FROM unified_referrals WHERE invited_user_id = ? AND invited_user_type = ?");
$stmtExisting->execute([$user_id, $role]);
if ($stmtExisting->rowCount() > 0) {
jsonError("User already registered with a referral code");
}
// Insert new referral
$insertStmt = $con->prepare("INSERT INTO unified_referrals (inviter_code, invited_user_id, invited_user_type, status, trip_count, is_reward_claimed) VALUES (?, ?, ?, 'registered', 0, 0)");
try {
$insertStmt->execute([$inviterCode, $user_id, $role]);
printSuccess(["message" => "Referral linked successfully"]);
} catch (PDOException $e) {
jsonError("Database error: " . $e->getMessage());
}
?>

View File

@@ -0,0 +1,80 @@
<?php
require_once __DIR__ . '/../../connect.php';
$referralId = filterRequest("referral_id");
$claimType = filterRequest("claim_type"); // 'wallet' or 'cash'
// Use JWT token variables provided by connect.php
if (!$user_id || $role != 'driver' || !$referralId || !in_array($claimType, ['wallet', 'cash'])) {
jsonError("Invalid parameters or unauthorized token");
}
// 1. Get the referral info
$stmt = $con->prepare("
SELECT r.id, r.inviter_code, r.invited_user_id, r.invited_user_type, r.trip_count, r.is_reward_claimed, c.user_id as inviter_id, c.user_type as inviter_type
FROM unified_referrals r
JOIN user_referral_codes c ON r.inviter_code = c.referral_code
WHERE r.id = ? AND c.user_id = ? AND c.user_type = 'driver'
");
$stmt->execute([$referralId, $user_id]);
if ($stmt->rowCount() == 0) {
jsonError("Referral not found or unauthorized");
}
$referral = $stmt->fetch(PDO::FETCH_ASSOC);
if ($referral['is_reward_claimed'] == 1) {
jsonError("Reward already claimed");
}
// Logic:
// Driver -> Driver: 50 trips = 500 SYP (example)
// Driver -> Passenger: 10 trips = 30 SYP per trip. This could be progressive, but for manual claim we assume completed
$amountSyp = 0;
if ($referral['invited_user_type'] == 'driver') {
if ($referral['trip_count'] >= 50) {
$amountSyp = 500;
} else {
jsonError("Requirement not met (50 trips required)");
}
} else if ($referral['invited_user_type'] == 'passenger') {
if ($referral['trip_count'] >= 1) {
// Here, user gets 30 SYP per trip, max 10. Let's assume claim all at once up to 10.
$tripsToClaim = min($referral['trip_count'], 10);
$amountSyp = $tripsToClaim * 30;
} else {
jsonError("Requirement not met (At least 1 trip required)");
}
}
if ($amountSyp <= 0) {
jsonError("No reward available to claim");
}
try {
$con->beginTransaction();
// Mark as claimed
$updateStmt = $con->prepare("UPDATE unified_referrals SET is_reward_claimed = 1, status = 'claimed' WHERE id = ?");
$updateStmt->execute([$referralId]);
if ($claimType == 'wallet') {
// Add to driver wallet
$walletStmt = $con->prepare("UPDATE driver SET wallet = wallet + ? WHERE id = ?");
$walletStmt->execute([$amountSyp, $user_id]);
} else if ($claimType == 'cash') {
// Request manual cash out
$cashStmt = $con->prepare("INSERT INTO driver_cash_claims (driver_id, referral_id, amount_syp, status) VALUES (?, ?, ?, 'pending')");
$cashStmt->execute([$user_id, $referralId, $amountSyp]);
}
$con->commit();
printSuccess(["message" => "Reward claimed successfully as $claimType"]);
} catch (PDOException $e) {
$con->rollBack();
jsonError("Database error: " . $e->getMessage());
}
?>

View File

@@ -0,0 +1,60 @@
<?php
require_once __DIR__ . '/../../connect.php';
// Use JWT token variables provided by connect.php
if (!$user_id || $role != 'driver') {
jsonError("Invalid parameters or unauthorized token");
}
// 1. Get the driver's referral code
$stmtCode = $con->prepare("SELECT referral_code FROM user_referral_codes WHERE user_id = ? AND user_type = 'driver'");
$stmtCode->execute([$user_id]);
if ($stmtCode->rowCount() == 0) {
// If no code exists, return empty stats
printSuccess([
"referral_code" => null,
"total_invited_drivers" => 0,
"total_invited_passengers" => 0,
"referrals" => []
]);
exit;
}
$referralCode = $stmtCode->fetchColumn();
// 2. Fetch all referrals made by this code
$stmtRefs = $con->prepare("
SELECT id, invited_user_id, invited_user_type, status, trip_count, is_reward_claimed, created_at
FROM unified_referrals
WHERE inviter_code = ?
ORDER BY created_at DESC
");
$stmtRefs->execute([$referralCode]);
$referrals = $stmtRefs->fetchAll(PDO::FETCH_ASSOC);
$totalDrivers = 0;
$totalPassengers = 0;
// Format data and calculate stats
foreach ($referrals as &$ref) {
if ($ref['invited_user_type'] == 'driver') {
$totalDrivers++;
$ref['target_trips'] = 50;
$ref['reward_syp'] = 500;
$ref['can_claim'] = ($ref['trip_count'] >= 50 && $ref['is_reward_claimed'] == 0) ? true : false;
} else {
$totalPassengers++;
$ref['target_trips'] = 1;
$ref['reward_syp'] = 30 * min($ref['trip_count'], 10); // Or max depending on logic
$ref['can_claim'] = ($ref['trip_count'] >= 1 && $ref['is_reward_claimed'] == 0) ? true : false;
}
}
printSuccess([
"referral_code" => $referralCode,
"total_invited_drivers" => $totalDrivers,
"total_invited_passengers" => $totalPassengers,
"referrals" => $referrals
]);
?>

View File

@@ -0,0 +1,60 @@
<?php
require_once __DIR__ . '/../../connect.php';
// Use JWT token variables provided by connect.php
if (!$user_id || $role != 'passenger') {
jsonError("Invalid parameters or unauthorized token");
}
// 1. Get the passenger's referral code
$stmtCode = $con->prepare("SELECT referral_code FROM user_referral_codes WHERE user_id = ? AND user_type = 'passenger'");
$stmtCode->execute([$user_id]);
if ($stmtCode->rowCount() == 0) {
// If no code exists, return empty stats
printSuccess([
"referral_code" => null,
"total_invited_drivers" => 0,
"total_invited_passengers" => 0,
"referrals" => []
]);
exit;
}
$referralCode = $stmtCode->fetchColumn();
// 2. Fetch all referrals made by this code
$stmtRefs = $con->prepare("
SELECT id, invited_user_id, invited_user_type, status, trip_count, is_reward_claimed, created_at
FROM unified_referrals
WHERE inviter_code = ?
ORDER BY created_at DESC
");
$stmtRefs->execute([$referralCode]);
$referrals = $stmtRefs->fetchAll(PDO::FETCH_ASSOC);
$totalDrivers = 0;
$totalPassengers = 0;
// Format data and calculate stats
foreach ($referrals as &$ref) {
if ($ref['invited_user_type'] == 'driver') {
$totalDrivers++;
$ref['target_trips'] = 50;
$ref['reward_syp'] = 500;
$ref['can_claim'] = ($ref['trip_count'] >= 50 && $ref['is_reward_claimed'] == 0) ? true : false;
} else {
$totalPassengers++;
$ref['target_trips'] = 1;
$ref['reward_syp'] = 30; // Just illustrative, rewards are automatic
$ref['can_claim'] = ($ref['trip_count'] >= 1 && $ref['is_reward_claimed'] == 0) ? true : false;
}
}
printSuccess([
"referral_code" => $referralCode,
"total_invited_drivers" => $totalDrivers,
"total_invited_passengers" => $totalPassengers,
"referrals" => $referrals
]);
?>

View File

@@ -0,0 +1,41 @@
<?php
require_once __DIR__ . '/../../connect.php';
function generateUnifiedCode($con) {
while (true) {
$letters = substr(str_shuffle("ABCDEFGHJKLMNPQRSTUVWXYZ"), 0, 2);
$numbers = substr(str_shuffle("23456789"), 0, 4);
$code = $letters . $numbers;
$stmt = $con->prepare("SELECT COUNT(*) FROM user_referral_codes WHERE referral_code = ?");
$stmt->execute([$code]);
if ($stmt->fetchColumn() == 0) {
return $code;
}
}
}
// Ensure the JWT values exist
if (!$user_id || !in_array($role, ['driver', 'passenger'])) {
jsonError("Invalid or missing user information in token");
}
$stmt = $con->prepare("SELECT referral_code FROM user_referral_codes WHERE user_id = ? AND user_type = ?");
$stmt->execute([$user_id, $role]);
if ($stmt->rowCount() > 0) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
printSuccess(["referral_code" => $row['referral_code']]);
} else {
$newCode = generateUnifiedCode($con);
$insertStmt = $con->prepare("INSERT INTO user_referral_codes (user_id, user_type, referral_code) VALUES (?, ?, ?)");
try {
$insertStmt->execute([$user_id, $role, $newCode]);
printSuccess(["referral_code" => $newCode]);
} catch (PDOException $e) {
jsonError("Database error: " . $e->getMessage());
}
}
?>

View File

@@ -1782,3 +1782,45 @@ CREATE TABLE `write_argument_after_applied_from_background` (
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2026-04-22 19:40:54
--
-- Table structure for table `user_referral_codes`
--
CREATE TABLE IF NOT EXISTS `user_referral_codes` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` varchar(100) NOT NULL,
`user_type` enum('driver','passenger') NOT NULL,
`referral_code` varchar(20) NOT NULL UNIQUE,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Table structure for table `unified_referrals`
--
CREATE TABLE IF NOT EXISTS `unified_referrals` (
`id` int NOT NULL AUTO_INCREMENT,
`inviter_code` varchar(20) NOT NULL,
`invited_user_id` varchar(100) NOT NULL,
`invited_user_type` enum('driver','passenger') NOT NULL,
`status` enum('registered','first_trip','claimed') DEFAULT 'registered',
`trip_count` int DEFAULT 0,
`is_reward_claimed` tinyint(1) DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Table structure for table `driver_cash_claims`
--
CREATE TABLE IF NOT EXISTS `driver_cash_claims` (
`id` int NOT NULL AUTO_INCREMENT,
`driver_id` varchar(100) NOT NULL,
`referral_id` int NOT NULL,
`amount_syp` decimal(10,2) NOT NULL,
`status` enum('pending','paid','rejected') DEFAULT 'pending',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@@ -1,118 +0,0 @@
import os
import shutil
SOURCE_DIR = "/Users/hamzaaleghwairyeen/development/App"
TARGET_DIR = "/Users/hamzaaleghwairyeen/development/App/Siro"
mappings = [
{
"src": "Intaleq",
"dst": "siro_rider",
"old_app_id": "com.Intaleq.intaleq",
"new_app_id": "com.siro.siro_rider",
"extra_folders": ["packages"]
},
{
"src": "intaleq_driver",
"dst": "siro_driver",
"old_app_id": "com.intaleq_driver",
"new_app_id": "com.siro.siro_driver",
"extra_folders": ["bubble-master", "trip_overlay_plugin"]
},
{
"src": "intaleq_admin",
"dst": "siro_admin",
"old_app_id": "com.intaleq.intaleq_admin",
"new_app_id": "com.siro.siro_admin",
"extra_folders": []
},
{
"src": "service_intaleq",
"dst": "siro_service",
"old_app_id": "com.service_intaleq",
"new_app_id": "com.siro.siro_service",
"extra_folders": []
}
]
def replace_in_file(filepath, old_str, new_str):
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
if old_str in content:
content = content.replace(old_str, new_str)
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
except Exception as e:
pass
def process():
for m in mappings:
src_app = os.path.join(SOURCE_DIR, m['src'])
dst_app = os.path.join(TARGET_DIR, m['dst'])
print(f"Processing native folders for {m['dst']}...")
# 1. Copy native folders
native_folders = ['android', 'ios', 'macos', 'web']
for folder in native_folders:
s_folder = os.path.join(src_app, folder)
d_folder = os.path.join(dst_app, folder)
if os.path.exists(s_folder):
if os.path.exists(d_folder):
shutil.rmtree(d_folder)
shutil.copytree(s_folder, d_folder, symlinks=True, ignore=shutil.ignore_patterns('.symlinks', 'Pods', 'build', '.dart_tool'))
# 2. Copy extra internal packages
for folder in m['extra_folders']:
s_folder = os.path.join(src_app, folder)
d_folder = os.path.join(dst_app, folder)
if os.path.exists(s_folder):
if os.path.exists(d_folder):
shutil.rmtree(d_folder)
shutil.copytree(s_folder, d_folder, symlinks=True, ignore=shutil.ignore_patterns('build', '.dart_tool'))
# 3. Android Package Renaming
old_app_id = m['old_app_id']
new_app_id = m['new_app_id']
android_dir = os.path.join(dst_app, 'android')
if os.path.exists(android_dir):
# Replace string occurrences in Android files
for root, dirs, files in os.walk(android_dir):
for file in files:
if file.endswith(('.kt', '.java', '.xml', '.gradle', '.gradle.kts', '.pro')):
replace_in_file(os.path.join(root, file), old_app_id, new_app_id)
# Move kotlin/java directory structure
for lang in ['kotlin', 'java']:
for source_type in ['main', 'debug', 'profile']:
src_dir = os.path.join(android_dir, 'app', 'src', source_type, lang)
if os.path.exists(src_dir):
old_path = os.path.join(src_dir, *old_app_id.split('.'))
new_path = os.path.join(src_dir, *new_app_id.split('.'))
if os.path.exists(old_path) and old_path != new_path:
os.makedirs(new_path, exist_ok=True)
for item in os.listdir(old_path):
shutil.move(os.path.join(old_path, item), new_path)
# Clean up old empty directories
curr = old_path
while curr != src_dir:
if not os.listdir(curr):
os.rmdir(curr)
curr = os.path.dirname(curr)
# 4. iOS Bundle ID Renaming
ios_dir = os.path.join(dst_app, 'ios')
if os.path.exists(ios_dir):
for root, dirs, files in os.walk(ios_dir):
for file in files:
if file.endswith(('.pbxproj', '.plist', '.m', '.h', '.swift', '.storyboard', '.xcconfig')):
replace_in_file(os.path.join(root, file), old_app_id, new_app_id)
print("Done copying and modifying native folders.")
if __name__ == "__main__":
process()

View File

@@ -1,84 +0,0 @@
import 'dart:io';
void main() async {
var sourceDir = Directory("/Users/hamzaaleghwairyeen/development/App");
var targetDir = Directory("/Users/hamzaaleghwairyeen/development/App/Siro");
var mappings = [
{"src": "Intaleq", "dst": "siro_rider", "old_pkg": "Intaleq", "new_pkg": "siro_rider"},
{"src": "intaleq_driver", "dst": "siro_driver", "old_pkg": "sefer_driver", "new_pkg": "siro_driver"},
{"src": "intaleq_admin", "dst": "siro_admin", "old_pkg": "sefer_admin1", "new_pkg": "siro_admin"},
{"src": "service_intaleq", "dst": "siro_service", "old_pkg": "service", "new_pkg": "siro_service"}
];
for (var m in mappings) {
var srcPath = "\${sourceDir.path}/\${m['src']}";
var dstPath = "\${targetDir.path}/\${m['dst']}";
// 1. Delete destination lib and assets
for (var folder in ['lib', 'assets', 'secure_string_operations']) {
var dFolder = Directory("\$dstPath/\$folder");
if (dFolder.existsSync()) {
dFolder.deleteSync(recursive: true);
}
}
// 2. Copy lib and assets
for (var folder in ['lib', 'assets', 'secure_string_operations']) {
var sFolder = Directory("\$srcPath/\$folder");
var dFolder = Directory("\$dstPath/\$folder");
if (sFolder.existsSync()) {
copyDirectorySync(sFolder, dFolder);
}
}
// 3. Copy pubspec.yaml
var sPubspec = File("\$srcPath/pubspec.yaml");
var dPubspec = File("\$dstPath/pubspec.yaml");
if (sPubspec.existsSync()) {
sPubspec.copySync(dPubspec.path);
}
// 4. Replace package name in pubspec.yaml
if (dPubspec.existsSync()) {
var content = dPubspec.readAsStringSync();
content = content.replaceAll(RegExp(r"^name:\s*" + m["old_pkg"]! + r"\s*$", multiLine: true), "name: \${m['new_pkg']}");
dPubspec.writeAsStringSync(content);
}
// 5. Replace imports
for (var rootFolder in ['lib', 'test']) {
var rootPath = Directory("\$dstPath/\$rootFolder");
if (!rootPath.existsSync()) continue;
var files = rootPath.listSync(recursive: true).whereType<File>();
for (var file in files) {
if (file.path.endsWith('.dart')) {
try {
var content = file.readAsStringSync();
var newContent = content.replaceAll("package:\${m['old_pkg']}/", "package:\${m['new_pkg']}/");
if (newContent != content) {
file.writeAsStringSync(newContent);
}
} catch (e) {
print("Error reading \${file.path}: \$e");
}
}
}
}
}
print("Done");
}
void copyDirectorySync(Directory source, Directory destination) {
destination.createSync(recursive: true);
for (var entity in source.listSync(recursive: false)) {
if (entity is Directory) {
var newDirectory = Directory("\${destination.absolute.path}/\${entity.path.split('/').last}");
newDirectory.createSync();
copyDirectorySync(entity.absolute, newDirectory);
} else if (entity is File) {
entity.copySync("\${destination.path}/\${entity.path.split('/').last}");
}
}
}

View File

@@ -1,70 +0,0 @@
import os
import shutil
source_dir = "/Users/hamzaaleghwairyeen/development/App"
target_dir = "/Users/hamzaaleghwairyeen/development/App/Siro"
mappings = [
{"src": "Intaleq", "dst": "siro_rider", "old_pkg": "Intaleq", "new_pkg": "siro_rider"},
{"src": "intaleq_driver", "dst": "siro_driver", "old_pkg": "sefer_driver", "new_pkg": "siro_driver"},
{"src": "intaleq_admin", "dst": "siro_admin", "old_pkg": "sefer_admin1", "new_pkg": "siro_admin"},
{"src": "service_intaleq", "dst": "siro_service", "old_pkg": "service", "new_pkg": "siro_service"}
]
def copy_and_replace():
for m in mappings:
src_path = os.path.join(source_dir, m['src'])
dst_path = os.path.join(target_dir, m['dst'])
# 1. Delete destination lib and assets if exist
for folder in ['lib', 'assets', 'secure_string_operations']:
d_folder = os.path.join(dst_path, folder)
if os.path.exists(d_folder):
shutil.rmtree(d_folder)
# 2. Copy lib and assets
for folder in ['lib', 'assets', 'secure_string_operations']:
s_folder = os.path.join(src_path, folder)
d_folder = os.path.join(dst_path, folder)
if os.path.exists(s_folder):
shutil.copytree(s_folder, d_folder)
# 3. Copy pubspec.yaml
s_pubspec = os.path.join(src_path, "pubspec.yaml")
d_pubspec = os.path.join(dst_path, "pubspec.yaml")
if os.path.exists(s_pubspec):
shutil.copy2(s_pubspec, d_pubspec)
# 4. Replace package name in pubspec.yaml
if os.path.exists(d_pubspec):
with open(d_pubspec, 'r', encoding='utf-8') as f:
content = f.read()
# replace name: old_pkg with name: new_pkg
import re
content = re.sub(rf'^name:\s*{m["old_pkg"]}\s*$', f'name: {m["new_pkg"]}', content, flags=re.MULTILINE)
with open(d_pubspec, 'w', encoding='utf-8') as f:
f.write(content)
# 5. Replace imports in lib and test directories
for root_folder in ['lib', 'test']:
root_path = os.path.join(dst_path, root_folder)
if not os.path.exists(root_path): continue
for root, dirs, files in os.walk(root_path):
for file in files:
if file.endswith('.dart'):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
new_content = content.replace(f"package:{m['old_pkg']}/", f"package:{m['new_pkg']}/")
if new_content != content:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(new_content)
except Exception as e:
print(f"Error reading {file_path}: {e}")
if __name__ == "__main__":
copy_and_replace()
print("Done")

View File

@@ -1,53 +0,0 @@
#!/bin/bash
set -e
SOURCE_DIR="/Users/hamzaaleghwairyeen/development/App"
TARGET_DIR="/Users/hamzaaleghwairyeen/development/App/Siro"
declare -a mappings=(
"Intaleq:siro_rider:Intaleq:siro_rider"
"intaleq_driver:siro_driver:sefer_driver:siro_driver"
"intaleq_admin:siro_admin:sefer_admin1:siro_admin"
"service_intaleq:siro_service:service:siro_service"
)
for mapping in "${mappings[@]}"; do
IFS=":" read -r src dst old_pkg new_pkg <<< "$mapping"
src_path="$SOURCE_DIR/$src"
dst_path="$TARGET_DIR/$dst"
echo "Processing $dst..."
# 1. Delete destination lib and assets
for folder in lib assets secure_string_operations; do
if [ -d "$dst_path/$folder" ]; then
rm -rf "$dst_path/$folder"
fi
done
# 2. Copy lib and assets
for folder in lib assets secure_string_operations; do
if [ -d "$src_path/$folder" ]; then
cp -R "$src_path/$folder" "$dst_path/"
fi
done
# 3. Copy pubspec.yaml
if [ -f "$src_path/pubspec.yaml" ]; then
cp "$src_path/pubspec.yaml" "$dst_path/pubspec.yaml"
fi
# 4. Replace package name in pubspec.yaml using perl
if [ -f "$dst_path/pubspec.yaml" ]; then
perl -pi -e "s/^name:\s*$old_pkg\s*$/name: $new_pkg/" "$dst_path/pubspec.yaml"
fi
# 5. Replace imports using perl
for root_folder in lib test; do
if [ -d "$dst_path/$root_folder" ]; then
find "$dst_path/$root_folder" -type f -name "*.dart" -exec perl -pi -e "s/package:$old_pkg\//package:$new_pkg\//g" {} +
fi
done
done
echo "Done"

View File

@@ -0,0 +1,126 @@
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>خارطة التوسع الجغرافي - دمشق</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<style>
body { margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
#map { height: 100vh; width: 100vw; }
.legend {
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 0 15px rgba(0,0,0,0.2);
line-height: 1.5;
color: #333;
}
.legend h4 { margin: 0 0 10px 0; }
.legend i {
width: 18px;
height: 18px;
float: right;
margin-left: 8px;
opacity: 0.7;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
// Initialize map centered on Damascus
var map = L.map('map').setView([33.5138, 36.2765], 13);
// Add OpenStreetMap tiles
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
// Define polygon styles
var styleA = { color: 'green', fillColor: 'green', fillOpacity: 0.4, weight: 2 };
var styleB = { color: 'blue', fillColor: 'blue', fillOpacity: 0.4, weight: 2 };
var styleC = { color: 'yellow', fillColor: 'yellow', fillOpacity: 0.4, weight: 2 };
var styleD = { color: 'red', fillColor: 'red', fillOpacity: 0.4, weight: 2 };
// Approximate Coordinates for Zones (These are illustrative representations)
// Zone A (Green): Mezzeh, Kafr Sousa, Malki (South-West / Central-West)
var zoneA = [
[33.5200, 36.2700], // Malki area
[33.5150, 36.2850],
[33.4900, 36.2850], // Kafr Sousa
[33.4950, 36.2400], // Mezzeh
[33.5100, 36.2400]
];
L.polygon(zoneA, styleA).addTo(map).bindPopup("<b>منطقة أ (خضراء)</b><br>المزة، كفرسوسة، المالكية<br>الأولوية الأولى (الأشهر 1-3)");
// Zone B (Blue): Abu Rummaneh, Muhajireen, Rawda, Jisr al-Abyad (Central / North-West)
var zoneB = [
[33.5350, 36.2650], // Muhajireen
[33.5300, 36.2800],
[33.5150, 36.2850], // Abu Rummaneh / Rawda
[33.5200, 36.2700]
];
L.polygon(zoneB, styleB).addTo(map).bindPopup("<b>منطقة ب (زرقاء)</b><br>أبو رمانة، المهاجرين، الروضة، الجسر الأبيض<br>الأولوية الثانية (الأشهر 2-4)");
// Zone C (Yellow): Mezzeh Western Villas, Dummar, Rukn al-Din, Qassaa (North, East, far West)
var zoneC1 = [ // Dummar / Western Villas
[33.5500, 36.2200],
[33.5400, 36.2500],
[33.5100, 36.2400],
[33.5100, 36.2100]
];
var zoneC2 = [ // Rukn al-Din / Qassaa
[33.5400, 36.2800],
[33.5450, 36.3100],
[33.5150, 36.3200],
[33.5100, 36.2850],
[33.5300, 36.2800]
];
L.polygon(zoneC1, styleC).addTo(map).bindPopup("<b>منطقة ج (صفراء)</b><br>دمر، المزة فيلات غربية<br>الأولوية الثالثة (الأشهر 4-6)");
L.polygon(zoneC2, styleC).addTo(map).bindPopup("<b>منطقة ج (صفراء)</b><br>ركن الدين، القصاع<br>الأولوية الثالثة (الأشهر 4-6)");
// Zone D (Red): Barzeh, Jaramana, Qudsaya, Darayya (Outskirts)
var zoneD1 = [ // Barzeh
[33.5600, 36.3000],
[33.5600, 36.3300],
[33.5400, 36.3300],
[33.5400, 36.3000]
];
var zoneD2 = [ // Jaramana
[33.5000, 36.3300],
[33.5000, 36.3700],
[33.4700, 36.3700],
[33.4700, 36.3300]
];
var zoneD3 = [ // Darayya
[33.4700, 36.2200],
[33.4700, 36.2600],
[33.4400, 36.2600],
[33.4400, 36.2200]
];
L.polygon(zoneD1, styleD).addTo(map).bindPopup("<b>منطقة د (حمراء)</b><br>برزة<br>توسع مستقبلي (شهر 7+)");
L.polygon(zoneD2, styleD).addTo(map).bindPopup("<b>منطقة د (حمراء)</b><br>جرمانا<br>توسع مستقبلي (شهر 7+)");
L.polygon(zoneD3, styleD).addTo(map).bindPopup("<b>منطقة د (حمراء)</b><br>داريا<br>توسع مستقبلي (شهر 7+)");
// Add Legend
var legend = L.control({position: 'bottomright'});
legend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'legend');
div.innerHTML += '<h4>استراتيجية التوسع - دمشق</h4>';
div.innerHTML += '<i style="background: green"></i> منطقة أ (خضراء): المزة، كفرسوسة، المالكية<br>';
div.innerHTML += '<i style="background: blue"></i> منطقة ب (زرقاء): أبو رمانة، المهاجرين<br>';
div.innerHTML += '<i style="background: yellow"></i> منطقة ج (صفراء): دمر، ركن الدين، القصاع<br>';
div.innerHTML += '<i style="background: red"></i> منطقة د (حمراء): الضواحي (جرمانا، برزة، داريا)<br>';
return div;
};
legend.addTo(map);
</script>
</body>
</html>

24
run_generation.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
echo "🚀 Generating SIRO Rider App Icons..."
cd /Users/hamzaaleghwairyeen/development/App/Siro/siro_rider
flutter clean
flutter pub get
dart run flutter_launcher_icons:main
echo "🚀 Generating SIRO Driver App Icons..."
cd /Users/hamzaaleghwairyeen/development/App/Siro/siro_driver
flutter clean
flutter pub get
dart run flutter_launcher_icons:main
echo "🎨 Generating Animated GIF for SIRO Rider & Driver..."
cd /Users/hamzaaleghwairyeen/development/App/Siro
python3 -m pip install Pillow --break-system-packages
python3 /Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/a5945c2c-de5f-4478-bd3c-d2f1c3aeec6a/scratch/pulse_logo.py /Users/hamzaaleghwairyeen/development/App/Siro/siro_rider/assets/images/logo.png /Users/hamzaaleghwairyeen/development/App/Siro/siro_rider/assets/images/logo.gif
cp /Users/hamzaaleghwairyeen/development/App/Siro/siro_rider/assets/images/logo.gif /Users/hamzaaleghwairyeen/development/App/Siro/siro_driver/assets/images/logo.gif
echo "🍏 Fixing iOS App Icon names to match old format..."
python3 /Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/a5945c2c-de5f-4478-bd3c-d2f1c3aeec6a/scratch/fix_ios_icons.py
echo "✅ All Done! Icons and Animated GIFs are ready."

View File

@@ -63,12 +63,21 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- Deep Link: siroapp://... -->
<!-- Deep Link: siromove://... -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="siroapp" />
<data android:scheme="siromove" />
</intent-filter>
<!-- App Links for siromove.com -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="siromove.com" android:pathPrefix="/" />
<data android:scheme="https" android:host="www.siromove.com" android:pathPrefix="/" />
</intent-filter>
<!-- Navigation Intents -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 561 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 444 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 858 B

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -1 +1,158 @@
{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"128x128","expected-size":"128","filename":"128.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]}
{
"images": [
{
"size": "20x20",
"idiom": "iphone",
"filename": "40.png",
"scale": "2x"
},
{
"size": "20x20",
"idiom": "iphone",
"filename": "60.png",
"scale": "3x"
},
{
"size": "29x29",
"idiom": "iphone",
"filename": "29.png",
"scale": "1x"
},
{
"size": "29x29",
"idiom": "iphone",
"filename": "58.png",
"scale": "2x"
},
{
"size": "29x29",
"idiom": "iphone",
"filename": "87.png",
"scale": "3x"
},
{
"size": "40x40",
"idiom": "iphone",
"filename": "80.png",
"scale": "2x"
},
{
"size": "40x40",
"idiom": "iphone",
"filename": "120.png",
"scale": "3x"
},
{
"size": "57x57",
"idiom": "iphone",
"filename": "57.png",
"scale": "1x"
},
{
"size": "57x57",
"idiom": "iphone",
"filename": "114.png",
"scale": "2x"
},
{
"size": "60x60",
"idiom": "iphone",
"filename": "120.png",
"scale": "2x"
},
{
"size": "60x60",
"idiom": "iphone",
"filename": "180.png",
"scale": "3x"
},
{
"size": "20x20",
"idiom": "ipad",
"filename": "20.png",
"scale": "1x"
},
{
"size": "20x20",
"idiom": "ipad",
"filename": "40.png",
"scale": "2x"
},
{
"size": "29x29",
"idiom": "ipad",
"filename": "29.png",
"scale": "1x"
},
{
"size": "29x29",
"idiom": "ipad",
"filename": "58.png",
"scale": "2x"
},
{
"size": "40x40",
"idiom": "ipad",
"filename": "40.png",
"scale": "1x"
},
{
"size": "40x40",
"idiom": "ipad",
"filename": "80.png",
"scale": "2x"
},
{
"size": "50x50",
"idiom": "ipad",
"filename": "50.png",
"scale": "1x"
},
{
"size": "50x50",
"idiom": "ipad",
"filename": "100.png",
"scale": "2x"
},
{
"size": "72x72",
"idiom": "ipad",
"filename": "72.png",
"scale": "1x"
},
{
"size": "72x72",
"idiom": "ipad",
"filename": "144.png",
"scale": "2x"
},
{
"size": "76x76",
"idiom": "ipad",
"filename": "76.png",
"scale": "1x"
},
{
"size": "76x76",
"idiom": "ipad",
"filename": "152.png",
"scale": "2x"
},
{
"size": "83.5x83.5",
"idiom": "ipad",
"filename": "167.png",
"scale": "2x"
},
{
"size": "1024x1024",
"idiom": "ios-marketing",
"filename": "1024.png",
"scale": "1x"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

View File

@@ -32,6 +32,21 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>33</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>siromove.com</string>
<key>CFBundleURLSchemes</key>
<array>
<string>siromove</string>
</array>
</dict>
</array>
<key>FlutterDeepLinkingEnabled</key>
<true/>
<key>FirebaseAppDelegateProxyEnabled</key>
<string>NO</string>
<key>GMSApiKey</key>

View File

@@ -3,67 +3,34 @@ import 'package:get/get.dart';
class AppColor {
// --- Core Brand Colors ---
static const Color primaryColor = Color(0xFF1A2340); // Navy Blue
static const Color secondaryColorStatic = Color(0xFF8C9CF8); // Periwinkle Blue
static const Color accentColor = Color(0xFF8C9CF8);
/// **Primary Color:** The brand's signature blue.
static const Color primaryColor = Color(0xFF1DA1F2);
/// **Text/Write Color:** Dynamic based on theme.
static Color get writeColor =>
Get.isDarkMode ? Colors.white : const Color(0xFF1A1A1A);
/// **Secondary Color:** Main background color, dynamic based on theme.
static Color get secondaryColor =>
Get.isDarkMode ? const Color(0xFF121212) : Colors.white;
/// **Surface Color:** For cards and elevated elements.
static Color get surfaceColor =>
Get.isDarkMode ? const Color(0xFF1E1E1E) : Colors.white;
/// **Card Color:** Specifically for card backgrounds.
static Color get cardColor =>
Get.isDarkMode ? const Color(0xFF1E1E1E) : Colors.white;
/// **Border Color:** Subtle borders for both modes.
static Color get borderColor =>
Get.isDarkMode ? Colors.white10 : Colors.black12;
/// **Accent Color:** Greyish accent.
static const Color accentColor = Color.fromARGB(255, 148, 140, 141);
// --- Dynamic Colors (Light / Dark Mode Support) ---
static Color get writeColor => Get.isDarkMode ? Colors.white : const Color(0xFF0F172A); // Primary Text
static Color get secondaryColor => Get.isDarkMode ? const Color(0xFF1E1E1E) : const Color(0xFFF8FAFC); // Background
static Color get cardColor => Get.isDarkMode ? const Color(0xFF2C2C2E) : const Color(0xFFFFFFFF); // Card Background
static Color get surfaceColor => cardColor; // Added back for backwards compatibility
// --- Neutral & Status Colors ---
static Color get grayColor => Get.isDarkMode ? Colors.grey[400]! : const Color(0xFF64748B); // Secondary Text
static Color get borderColor => Get.isDarkMode ? const Color(0xFF3A3A3C) : const Color(0xFFE2E8F0); // Border
/// **Grey Color:** Dynamic based on theme.
static Color get grayColor =>
Get.isDarkMode ? Colors.grey[400]! : const Color(0xFF8E8E93);
/// **Red Color (Error):** Clear red for alerts.
static const Color redColor = Color(0xFFD32F2F);
/// **Green Color (Success):** Positive green.
static const Color greenColor = Color(0xFF388E3C);
/// **Blue Color (Info):** Info text or success green variant.
static const Color blueColor = Color(0xFF1DA1F2);
/// **Yellow Color (Warning):** Warm yellow.
static const Color yellowColor = Color(0xFFFFA000);
// --- Tier & Social Colors ---
static const Color redColor = Color(0xFFEF4444); // Error
static const Color greenColor = Color(0xFF22C55E); // Success
static const Color yellowColor = Color(0xFFF59E0B); // Warning
// --- Legacy / Maps Colors (Kept for compatibility) ---
static const Color blueColor = Color(0xFF1A2340);
static const Color gold = Color(0xFFFFD700);
static const Color bronze = Color(0xFFCD7F32);
static const Color goldenBronze = Color(0xFFB87333);
static const Color twitterColor = Color(0xFF1DA1F2);
// --- Utility Colors ---
static Color get greyColor => grayColor;
static Color get cyanBlue => const Color(0xFF1DA1F2);
static Color get cyanAccent => const Color(0xFF1DA1F2).withOpacity(0.12);
static Color get deepPurpleAccent => const Color(0xFFCE1126).withOpacity(0.1);
static Color get cyanBlue => const Color(0xFF1A2340);
static Color get cyanAccent => const Color(0xFF1A2340).withOpacity(0.12);
static Color get deepPurpleAccent => const Color(0xFF8C9CF8).withOpacity(0.1);
// --- Theme Helpers ---
static Brightness get brightness => Get.isDarkMode ? Brightness.dark : Brightness.light;
}

View File

@@ -13,6 +13,13 @@ class FinanceDesignSystem {
static Color get textMuted => Get.isDarkMode ? Colors.white38 : const Color(0xFFBDBDBD);
static Color get borderColor => Get.isDarkMode ? Colors.white10 : Colors.grey.withOpacity(0.1);
// --- Shadows ---
static BoxShadow get softShadow => BoxShadow(
color: Colors.black.withOpacity(Get.isDarkMode ? 0.3 : 0.05),
blurRadius: 10,
offset: const Offset(0, 4),
);
// --- Gradients ---
static LinearGradient get balanceGradient => LinearGradient(
colors: Get.isDarkMode

View File

@@ -7,6 +7,7 @@ class AppLink {
static String serverPHP = box.read('serverPHP');
static String paymentServer = 'https://walletintaleq.intaleq.xyz/v1/main';
static const String appDomain = 'siromove.com';
static String locationServer =
'https://location.intaleq.xyz/intaleq/ride/location';
@@ -337,6 +338,11 @@ class AppLink {
//===================Auth============
static String getUnifiedCode = "$ride/invitor/get_unified_code.php";
static String addUnifiedInvite = "$ride/invitor/add_unified_invite.php";
static String claimDriverReward = "$ride/invitor/claim_driver_reward.php";
static String getDriverReferrals = "$ride/invitor/get_driver_referrals.php";
static String addInviteDriver = "$ride/invitor/add.php";
static String addInvitationPassenger =
"$ride/invitor/addInvitationPassenger.php";

View File

@@ -584,6 +584,8 @@ Download the Intaleq app now and enjoy your ride!
'${"The period of this code is 24 hours".tr}\n\n'
'${'before'.tr} *${d['message']['expirationTime'].toString()}*\n\n'
'_*${d['message']['inviteCode'].toString()}*_\n\n'
'${"Quick Invite Link:".tr}\n'
'https://${AppLink.appDomain}/?inviteCode=${d['message']['inviteCode'].toString()}\n\n'
'${"Install our app:".tr}\n'
'*Android:* https://play.google.com/store/apps/details?id=com.Intaleq.intaleq\n\n\n'
'*iOS:* https://apps.apple.com/st/app/intaleq-rider/id6748075179';

View File

@@ -0,0 +1,103 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:siro_driver/constant/links.dart';
import 'package:siro_driver/controller/functions/crud.dart';
import 'package:siro_driver/views/widgets/error_snakbar.dart';
class InvitesRewardsController extends GetxController {
bool isLoading = false;
String? referralCode;
int totalInvitedDrivers = 0;
int totalInvitedPassengers = 0;
List<dynamic> referrals = [];
@override
void onInit() {
super.onInit();
getReferralStats();
}
Future<void> getReferralStats() async {
isLoading = true;
update();
var res = await CRUD().get(link: AppLink.getDriverReferrals);
if (res != 'failure' && res != 'token_expired' && res != 'no_internet') {
try {
var jsonData = jsonDecode(res);
if (jsonData['status'] == 'success') {
var data = jsonData['message'];
referralCode = data['referral_code'];
totalInvitedDrivers = data['total_invited_drivers'] ?? 0;
totalInvitedPassengers = data['total_invited_passengers'] ?? 0;
referrals = data['referrals'] ?? [];
}
} catch (e) {
debugPrint('Error parsing referral stats: $e');
}
}
isLoading = false;
update();
}
Future<void> claimReward(int referralId, String claimType) async {
Get.dialog(const Center(child: CircularProgressIndicator()), barrierDismissible: false);
var res = await CRUD().post(
link: AppLink.claimDriverReward,
payload: {
'referral_id': referralId.toString(),
'claim_type': claimType, // 'wallet' or 'cash'
},
);
Get.back(); // close dialog
if (res != 'failure' && res != 'token_expired' && res != 'no_internet') {
try {
var jsonData = jsonDecode(res);
if (jsonData['status'] == 'success') {
mySnackbarSuccess('Reward claimed successfully!'.tr);
await getReferralStats(); // refresh list
} else {
mySnackeBarError(jsonData['error'] ?? 'Failed to claim reward'.tr);
}
} catch (e) {
mySnackeBarError('Failed to claim reward'.tr);
}
} else {
mySnackeBarError('Connection error'.tr);
}
}
Future<void> claimUnifiedReward(int referralId) async {
// Show dialog to choose wallet or cash
Get.defaultDialog(
title: "Choose Claim Method".tr,
content: Text("How would you like to receive your reward?".tr),
actions: [
ElevatedButton(
onPressed: () {
Get.back();
claimReward(referralId, 'wallet');
},
child: Text("Wallet".tr),
),
ElevatedButton(
onPressed: () {
Get.back();
claimReward(referralId, 'cash');
},
child: Text("Cash".tr),
),
TextButton(
onPressed: () => Get.back(),
child: Text("Cancel".tr, style: TextStyle(color: Colors.red)),
)
]
);
}
}

View File

@@ -7,9 +7,11 @@ import '../../../constant/colors.dart';
import '../../../controller/auth/captin/invit_controller.dart';
import '../../../controller/functions/encrypt_decrypt.dart';
import '../../../main.dart';
import '../../../controller/home/invites_rewards_controller.dart';
class InviteScreen extends StatelessWidget {
final InviteController controller = Get.put(InviteController());
final InvitesRewardsController rewardsController = Get.put(InvitesRewardsController());
@override
Widget build(BuildContext context) {
@@ -111,6 +113,8 @@ class InviteScreen extends StatelessWidget {
_buildActionButtons(),
const SizedBox(height: 20),
_buildInvitationsList(context),
const SizedBox(height: 20),
_buildUnifiedRewardsList(isDriver: true),
],
);
}
@@ -146,6 +150,8 @@ class InviteScreen extends StatelessWidget {
const SizedBox(height: 20),
const SizedBox(height: 20),
_buildInvitationsListPassengers(context),
const SizedBox(height: 20),
_buildUnifiedRewardsList(isDriver: false),
],
);
}
@@ -324,9 +330,12 @@ class InviteScreen extends StatelessWidget {
}
Widget _buildInvitationsList(BuildContext context) {
return SizedBox(
height: Get.height * .4,
child: controller.driverInvitationData.isEmpty
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Invitations Sent".tr, style: const TextStyle(fontSize: 17, fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
controller.driverInvitationData.isEmpty
? Center(
child: Text(
"No invitation found yet!".tr,
@@ -337,18 +346,24 @@ class InviteScreen extends StatelessWidget {
),
)
: ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: controller.driverInvitationData.length,
itemBuilder: (context, index) {
return _buildInvitationItem(context, index);
},
),
],
);
}
Widget _buildInvitationsListPassengers(BuildContext context) {
return SizedBox(
height: Get.height * .4,
child: controller.driverInvitationDataToPassengers.isEmpty
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Invitations Sent".tr, style: const TextStyle(fontSize: 17, fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
controller.driverInvitationDataToPassengers.isEmpty
? Center(
child: Text(
"No invitation found yet!".tr,
@@ -359,11 +374,14 @@ class InviteScreen extends StatelessWidget {
),
)
: ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: controller.driverInvitationDataToPassengers.length,
itemBuilder: (context, index) {
return _buildInvitationItemPassengers(context, index);
},
),
],
);
}
@@ -636,4 +654,76 @@ class InviteScreen extends StatelessWidget {
),
);
}
Widget _buildUnifiedRewardsList({required bool isDriver}) {
return GetBuilder<InvitesRewardsController>(
builder: (rewardsController) {
if (rewardsController.isLoading) {
return const Center(child: CupertinoActivityIndicator());
}
var filteredList = rewardsController.referrals.where((ref) =>
isDriver ? ref['invited_user_type'] == 'driver' : ref['invited_user_type'] == 'passenger'
).toList();
if (filteredList.isEmpty) {
return const SizedBox(); // Hide if no valid rewards
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Reward Status".tr, style: const TextStyle(fontSize: 17, fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: filteredList.length,
itemBuilder: (context, index) {
var ref = filteredList[index];
int trips = ref['trip_count'] ?? 0;
int target = ref['target_trips'] ?? 1;
bool canClaim = ref['can_claim'] ?? false;
bool isClaimed = ref['is_reward_claimed'] == 1;
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: CupertinoColors.systemGrey6,
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(isDriver ? "Driver Referral".tr : "Passenger Referral".tr, style: const TextStyle(fontWeight: FontWeight.bold)),
const SizedBox(height: 4),
Text("Trips: $trips / $target".tr, style: const TextStyle(color: CupertinoColors.secondaryLabel, fontSize: 13)),
if (isClaimed)
Text("Reward Claimed".tr, style: const TextStyle(color: CupertinoColors.activeGreen, fontSize: 12, fontWeight: FontWeight.bold))
else if (!canClaim)
Text("Waiting for trips".tr, style: const TextStyle(color: CupertinoColors.systemOrange, fontSize: 12))
],
),
),
if (canClaim && !isClaimed)
CupertinoButton(
color: AppColor.blueColor,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
onPressed: () => rewardsController.claimUnifiedReward(ref['id']),
child: Text("Claim".tr, style: const TextStyle(color: Colors.white, fontSize: 14)),
)
],
),
);
},
),
],
);
},
);
}
}

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:siro_driver/views/widgets/error_snakbar.dart';
import 'package:siro_driver/views/widgets/my_textField.dart';
import 'package:siro_driver/views/widgets/elevated_btn.dart'; // Checked import
@@ -7,6 +8,7 @@ import 'package:flutter_font_icons/flutter_font_icons.dart';
import '../../../../constant/box_name.dart';
import '../../../../constant/colors.dart';
import '../../../../constant/links.dart';
import '../../../../constant/style.dart';
import '../../../../controller/firebase/notification_service.dart';
import '../../../../controller/functions/launch.dart';
@@ -50,6 +52,16 @@ class SosConnect extends StatelessWidget {
isPulsing: true,
onTap: () => _handleSosCall(controller),
),
const SizedBox(height: 8),
// === Quick Invite Button ===
_buildModernActionButton(
icon: Icons.qr_code_rounded,
color: Colors.white,
bgColor: AppColor.blueColor,
tooltip: 'Quick Invite',
isPulsing: false,
onTap: () => _showQuickInviteDialog(controller),
),
],
),
);
@@ -128,4 +140,70 @@ class SosConnect extends StatelessWidget {
launchCommunication('phone', box.read(BoxName.sosPhoneDriver), '');
}
}
void _showQuickInviteDialog(MapDriverController controller) {
// In a real scenario, this code would be fetched from the backend (ReferralController)
// For now we will use a generated code or driverId. We should use the one from ReferralController
// But since we are accessing it globally, we can just use the driverID + 123 for now until it's linked
String driverId = box.read(BoxName.driverID).toString();
String inviteCode = "SR$driverId"; // Placeholder code
String deepLink = "https://${AppLink.appDomain}/invite?ref=$inviteCode";
Get.defaultDialog(
title: "Quick Invite".tr,
titleStyle: AppStyle.title.copyWith(fontWeight: FontWeight.bold),
content: Column(
children: [
Text(
"Let the passenger scan this code to sign up".tr,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 14, color: Colors.grey),
),
const SizedBox(height: 20),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: QrImageView(
data: deepLink,
version: QrVersions.auto,
size: 200.0,
backgroundColor: Colors.white,
),
),
const SizedBox(height: 20),
Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
decoration: BoxDecoration(
color: AppColor.blueColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: AppColor.blueColor.withOpacity(0.3)),
),
child: Text(
inviteCode,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w900,
color: AppColor.blueColor,
letterSpacing: 4,
),
),
),
],
),
confirm: MyElevatedButton(
title: 'Done'.tr,
onPressed: () => Get.back(),
),
);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 444 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 881 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -208,6 +208,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.13.1"
cli_util:
dependency: transitive
description:
name: cli_util
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
url: "https://pub.dev"
source: hosted
version: "0.4.2"
clock:
dependency: transitive
description:
@@ -717,6 +725,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.0"
flutter_launcher_icons:
dependency: "direct dev"
description:
name: flutter_launcher_icons
sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7"
url: "https://pub.dev"
source: hosted
version: "0.14.4"
flutter_lints:
dependency: "direct dev"
description:
@@ -1780,6 +1796,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.0"
qr:
dependency: transitive
description:
name: qr
sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
qr_flutter:
dependency: "direct main"
description:
name: qr_flutter
sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097"
url: "https://pub.dev"
source: hosted
version: "4.1.0"
quick_actions:
dependency: "direct main"
description:

View File

@@ -41,6 +41,7 @@ dependencies:
lottie: ^3.3.1
shimmer: ^3.0.0
slide_to_act: ^2.0.2
qr_flutter: ^4.1.0
# Services & Hardware
battery_plus: ^7.0.0
@@ -99,6 +100,7 @@ dev_dependencies:
flutter_lints: ^6.0.0
envied_generator: ^1.0.0
build_runner: ^2.4.6
flutter_launcher_icons: ^0.14.4
flutter_launcher_icons:
android: "launcher_icon"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -55,8 +55,8 @@
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="siroapp.com" android:pathPrefix="/" />
<data android:scheme="https" android:host="www.siroapp.com"
<data android:scheme="https" android:host="siromove.com" android:pathPrefix="/" />
<data android:scheme="https" android:host="www.siromove.com"
android:pathPrefix="/" />
</intent-filter>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 KiB

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 4.1 MiB

View File

@@ -898,9 +898,9 @@
C663DBE82F50907200D79908 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
@@ -944,9 +944,9 @@
C663DBE92F50907200D79908 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
@@ -987,9 +987,9 @@
C663DBEA2F50907200D79908 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 936 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 799 B

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Some files were not shown because too many files have changed in this diff Show More