Files
intaleq_driver/lib/controller/home/captin/v2_review_delta.html

213 lines
16 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<style>
* { box-sizing: border-box; }
.wrap { padding: 1.25rem 1rem; font-size: 14px; color: var(--color-text-primary); direction: rtl; }
h1 { font-size: 18px; font-weight: 500; margin: 0 0 3px; }
.sub { font-size: 13px; color: var(--color-text-secondary); margin: 0 0 1.25rem; }
.badge { display: inline-flex; align-items: center; font-size: 11px; font-weight: 500; padding: 2px 8px; border-radius: 20px; white-space: nowrap; }
.b-ok { background: var(--color-background-success); color: var(--color-text-success); }
.b-new { background: var(--color-background-danger); color: var(--color-text-danger); }
.b-med { background: var(--color-background-warning); color: var(--color-text-warning); }
.b-min { background: var(--color-background-info); color: var(--color-text-info); }
.progress-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 1.25rem; }
.pcard { background: var(--color-background-secondary); border-radius: var(--border-radius-md); padding: 12px 14px; }
.pcard .val { font-size: 28px; font-weight: 500; }
.pcard .lbl { font-size: 12px; color: var(--color-text-secondary); margin-top: 2px; }
.ok-val { color: var(--color-text-success); }
.bad-val { color: var(--color-text-danger); }
.new-val { color: var(--color-text-warning); }
.section { margin-bottom: 1.4rem; }
.section-hdr { font-size: 14px; font-weight: 500; margin: 0 0 8px; display: flex; align-items: center; gap: 8px; }
.card { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); margin-bottom: 8px; overflow: hidden; }
.card.fixed { border-right: 3px solid var(--color-border-success); }
.card.broken{ border-right: 3px solid var(--color-border-danger); }
.card.new { border-right: 3px solid var(--color-border-warning); }
.card.minor { border-right: 3px solid var(--color-border-info); }
.ch { display: flex; align-items: flex-start; gap: 8px; padding: 10px 14px; cursor: pointer; }
.ch:hover { background: var(--color-background-secondary); }
.ch-icon { font-size: 15px; flex-shrink: 0; margin-top: 1px; }
.ch-title { font-size: 13.5px; font-weight: 500; flex: 1; line-height: 1.4; }
.ch-badge { flex-shrink: 0; }
.chev { font-size: 11px; color: var(--color-text-tertiary); transition: transform .2s; margin-right: auto; margin-left: 4px; }
.chev.open { transform: rotate(90deg); }
.cb { display: none; padding: 0 14px 14px; border-top: 0.5px solid var(--color-border-tertiary); }
.cb.open { display: block; }
.cb p { font-size: 13px; color: var(--color-text-secondary); line-height: 1.7; margin: 8px 0 6px; }
pre { font-family: var(--font-mono); font-size: 11.5px; background: var(--color-background-tertiary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); padding: 9px 11px; overflow-x: auto; margin: 6px 0; line-height: 1.6; white-space: pre; }
.fix { background: var(--color-background-success); border-radius: var(--border-radius-md); padding: 8px 11px; margin-top: 8px; font-size: 13px; line-height: 1.6; }
.fix strong { color: var(--color-text-success); font-size: 11px; display: block; margin-bottom: 2px; }
.warn { background: var(--color-background-warning); border-radius: var(--border-radius-md); padding: 8px 11px; margin-top: 8px; font-size: 13px; line-height: 1.6; }
.warn strong { color: var(--color-text-warning); font-size: 11px; display: block; margin-bottom: 2px; }
code { font-family: var(--font-mono); font-size: 12px; background: var(--color-background-secondary); padding: 0 4px; border-radius: 3px; }
.score-row { display: flex; align-items: center; gap: 10px; font-size: 13px; margin-bottom: 7px; }
.score-lbl { min-width: 160px; color: var(--color-text-secondary); }
.strack { flex: 1; height: 6px; background: var(--color-border-tertiary); border-radius: 3px; position: relative; }
.sfill { height: 100%; border-radius: 3px; }
.sval { min-width: 36px; font-size: 12px; color: var(--color-text-secondary); text-align: left; }
</style>
<div class="wrap">
<h1>مراجعة النسخة المحدّثة — V2</h1>
<p class="sub">مقارنة مع المراجعة السابقة · 16 مشكلة فُحصت</p>
<div class="progress-row">
<div class="pcard"><div class="val ok-val">11</div><div class="lbl">مشكلة مُصلحة ✅</div></div>
<div class="pcard"><div class="val bad-val">2</div><div class="lbl">مشكلة جديدة أدخلتها الإصلاحات ⚠️</div></div>
<div class="pcard"><div class="val new-val">3</div><div class="lbl">مشكلة لم تُعالج بعد</div></div>
<div class="pcard"><div class="val ok-val">69%</div><div class="lbl">تحسن من المراجعة الأولى</div></div>
</div>
<div class="score-row"><span class="score-lbl">صحة المنطق البرمجي</span><div class="strack"><div class="sfill" style="width:72%;background:#3B8BD4"></div></div><span class="sval">72% ↑</span></div>
<div class="score-row"><span class="score-lbl">نظافة الكود</span><div class="strack"><div class="sfill" style="width:63%;background:#1D9E75"></div></div><span class="sval">63% ↑</span></div>
<div class="score-row" style="margin-bottom:1.4rem"><span class="score-lbl">قابلية الصيانة</span><div class="strack"><div class="sfill" style="width:58%;background:#1D9E75"></div></div><span class="sval">58% ↑</span></div>
<!-- FIXED -->
<div class="section">
<div class="section-hdr"><span class="badge b-ok">✅ مُصلح</span> ما تم إصلاحه بشكل صحيح</div>
<div class="card fixed">
<div class="ch" onclick="t(this)"><span class="ch-icon"></span><span class="ch-title">C-1 — استبدال الحلقة التكرارية والاستدعاء الذاتي بـ <code>Timer.periodic</code></span><span class="ch-badge badge b-ok">ممتاز</span><span class="chev"></span></div>
<div class="cb"><p>تم حذف <code>updateLocation()</code> كاملاً واستبدالها بـ <code>startUpdateLocationTimer()</code> و <code>stopUpdateLocationTimer()</code>. التايمر مسجّل في <code>onClose()</code> و <code>_stopAllServices()</code>. إصلاح ممتاز.</p>
<div class="warn"><strong>ملاحظة مهمة</strong>لا يظهر في الكود استدعاء لـ <code>startUpdateLocationTimer()</code> من أي مكان. يجب التأكد أنها تُستدعى من الـ View أو من <code>startRideFromDriver()</code>.</div></div>
</div>
<div class="card fixed">
<div class="ch" onclick="t(this)"><span class="ch-icon"></span><span class="ch-title">C-4 — تحديث <code>myLocation</code> في <code>_handleLocationUpdate()</code></span><span class="chev"></span></div>
<div class="cb"><pre>void _handleLocationUpdate(geo.Position pos) {
final newLoc = LatLng(pos.latitude, pos.longitude);
myLocation = newLoc; // ← [Fix C-4] ✅ صحيح
// ...</pre></div>
</div>
<div class="card fixed">
<div class="ch" onclick="t(this)"><span class="ch-icon"></span><span class="ch-title">M-4 — دمج <code>checkForNextStep()</code> مع <code>_checkNavigationStep()</code></span><span class="chev"></span></div>
<div class="cb"><p><code>checkForNextStep</code> أصبحت wrapper بسيط يستدعي <code>_checkNavigationStep</code>. منطق واحد، لا تعارض.</p></div>
</div>
<div class="card fixed">
<div class="ch" onclick="t(this)"><span class="ch-icon"></span><span class="ch-title">M-5 — <code>disposeEverything()</code> لا تستدعي <code>onClose()</code> يدوياً</span><span class="chev"></span></div>
<div class="cb"><pre>void disposeEverything() {
_stopAllServices(); // ✅ بدون onClose()
}</pre></div>
</div>
<div class="card fixed">
<div class="ch" onclick="t(this)"><span class="ch-icon"></span><span class="ch-title">C-3 جزئي — دالة مساعدة <code>_parseDistanceToMeters()</code> مشتركة</span><span class="chev"></span></div>
<div class="cb"><p>تم استخراج منطق تحليل المسافة إلى دالة واحدة تستخدمها كلا <code>finishRideFromDriver()</code> و <code>_validateTripDistance()</code>. يحل مشكلة التضارب في الوحدات.</p>
<div class="warn"><strong>لم يُحل كاملاً</strong>التحقق من المسافة لا يزال يحدث مرتين (انظر مشكلة C-3 أدناه).</div></div>
</div>
<div class="card fixed">
<div class="ch" onclick="t(this)"><span class="ch-icon"></span><span class="ch-title">M-1 + M-2 + M-6 + N-1 + N-5 — إصلاحات طفيفة متعددة</span><span class="chev"></span></div>
<div class="cb">
<p><strong>M-1:</strong> <code>jitterMeters</code><code>jitterKm = 0.01</code></p>
<p><strong>M-2:</strong> <code>distance</code> المحلية → <code>distToPassenger</code></p>
<p><strong>M-6:</strong> تعليق يوضح أن الوحدة كيلومتر ✅</p>
<p><strong>N-1:</strong> <code>&directionsmode</code><code>?directionsmode</code></p>
<p><strong>N-5:</strong> إضافة <code>update()</code> في <code>getLocationArea()</code></p>
<p><strong>M-3:</strong> حذف <code>_performanceReadings</code> والمتغيرات الميتة ✅</p>
</div>
</div>
</div>
<!-- NEW BUGS -->
<div class="section">
<div class="section-hdr"><span class="badge b-new">🚨 جديد</span> مشاكل أدخلتها الإصلاحات</div>
<div class="card new">
<div class="ch" onclick="t(this)"><span class="ch-icon">🚨</span><span class="ch-title">BUG جديد — <code>Completer</code> في C-2 يُسبب Deadlock عند إغلاق الديالوج بـ Back</span><span class="ch-badge badge b-new">حرج</span><span class="chev"></span></div>
<div class="cb">
<p>الإصلاح استخدم <code>Completer</code> بشكل صحيح لحل مشكلة الـ callback الآني، لكنه أدخل مشكلة أخرى: لو أغلق المستخدم الديالوج بزر الرجوع (Back) في Android بدون ضغط OK، فإن <code>completer.future</code> لن تكتمل أبداً، والدالة ستبقى معلّقة (deadlock) لأن <code>_validateTripDistance()</code> هي <code>async</code> وتنتظر نتيجة لن تأتي:</p>
<pre>final completer = Completer&lt;bool&gt;();
MyDialog().getDialog('Exit Ride?'.tr, '', () {
if (!completer.isCompleted) completer.complete(true);
Get.back();
});
return await completer.future; // ← ينتظر للأبد إذا أُغلق بـ Back</pre>
<div class="fix"><strong>الحل</strong>أضف <code>barrierDismissible: false</code> للديالوج، أو استخدم <code>completer.complete(false)</code> عند إغلاق الديالوج بدون تأكيد (عبر <code>WillPopScope</code> أو <code>onDismissed</code> callback في <code>MyDialog</code>).</div>
</div>
</div>
<div class="card new">
<div class="ch" onclick="t(this)"><span class="ch-icon">🚨</span><span class="ch-title">C-3 لا يزال — المستخدم يرى ديالوجَي تأكيد متتاليَين عند إنهاء الرحلة بالزر</span><span class="ch-badge badge b-new">حرج</span><span class="chev"></span></div>
<div class="cb">
<p>رغم إضافة <code>_parseDistanceToMeters()</code>، تدفق الكود لا يزال يُقدّم ديالوجَين:</p>
<pre>// finishRideFromDriver(isFromSlider: false):
MyDialog().getDialog('Are you sure to exit ride?', '', () {
Get.back();
finishRideFromDriver1(); // ← isFromSlider = false افتراضياً
});
// finishRideFromDriver1():
if (!await _validateTripDistance(false)) return; // ← يُقدّم ديالوجاً ثانياً!</pre>
<p>المستخدم يرى "هل أنت متأكد؟" → يضغط OK → يرى "Exit Ride?" مرة ثانية → ينتظر مجدداً.</p>
<div class="fix"><strong>الحل</strong>احذف الديالوج من <code>finishRideFromDriver()</code> وأبقه في <code>_validateTripDistance()</code> فقط. أو مرّر <code>isFromSlider: true</code> لما يأتي من موافقة مسبقة.</div>
</div>
</div>
</div>
<!-- REMAINING -->
<div class="section">
<div class="section-hdr"><span class="badge b-med">⚠️ لم تُعالج</span> مشاكل لا تزال قائمة</div>
<div class="card broken">
<div class="ch" onclick="t(this)"><span class="ch-icon">⚠️</span><span class="ch-title">M-7 — Null checks على <code>String</code> غير قابلة للـ null</span><span class="chev"></span></div>
<div class="cb">
<pre>if (isSocialPressed == true && passengerId != null && rideId != null) {
// ^^^^^^^^^^^ دائماً non-null</pre>
<p>لو <code>passengerId == ''</code> يمر الشرط ويُرسل بيانات فارغة للسيرفر. الفحص الصحيح: <code>passengerId.isNotEmpty && rideId.isNotEmpty</code>.</p>
</div>
</div>
<div class="card broken">
<div class="ch" onclick="t(this)"><span class="ch-icon">⚠️</span><span class="ch-title">N-2 — تأخير 1 ثانية Hardcoded في <code>argumentLoading()</code></span><span class="chev"></span></div>
<div class="cb">
<pre>await Future.delayed(const Duration(seconds: 1));
await getRoute(...);</pre>
<p>لا يزال موجوداً. Race condition يجب معالجته بـ <code>Completer</code> بدلاً من تخمين الوقت.</p>
</div>
</div>
<div class="card broken">
<div class="ch" onclick="t(this)"><span class="ch-icon">⚠️</span><span class="ch-title">N-4 — <code>step0</code> إلى <code>step4</code> بدلاً من <code>List&lt;String&gt;</code></span><span class="chev"></span></div>
<div class="cb">
<pre>String step0 = ''; String step1 = ''; // ...
step0 = Get.arguments['step0']?.toString() ?? '';
step1 = Get.arguments['step1']?.toString() ?? '';</pre>
<p>لا تزال 5 متغيرات منفصلة. <code>List&lt;String&gt; steps = List.filled(5, '')</code> أوضح وأسهل في المعالجة.</p>
</div>
</div>
</div>
<!-- STILL MINOR -->
<div class="section">
<div class="section-hdr"><span class="badge b-min"> بسيطة</span> ملاحظات إضافية على هذه النسخة</div>
<div class="card minor">
<div class="ch" onclick="t(this)"><span class="ch-icon"></span><span class="ch-title"><code>_suggestOptimization()</code> لا تزال موجودة لكن لا يستدعيها أحد</span><span class="chev"></span></div>
<div class="cb"><p>بعد حذف <code>_performanceReadings</code> و <code>_analyzePerformance()</code>، بقيت <code>_suggestOptimization()</code> معزولة. إما أن تُستدعى من مكان ما أو تُحذف.</p></div>
</div>
<div class="card minor">
<div class="ch" onclick="t(this)"><span class="ch-icon"></span><span class="ch-title">الاستيرادات المكررة لـ <code>dart:math</code> و <code>geolocator</code> لا تزال</span><span class="chev"></span></div>
<div class="cb">
<pre>import 'dart:math';
import 'dart:math' as math; // مكرر
import 'package:geolocator/geolocator.dart' as geo;
import 'package:geolocator/geolocator.dart'; // مكرر</pre>
<p>يُسبب تحذيرات من المحلل ويُشوّش قراءة الكود. احذف النسخة غير المعرّفة.</p>
</div>
</div>
</div>
</div>
<script>
function t(header) {
const b = header.nextElementSibling;
const ch = header.querySelector('.chev');
const o = b.classList.contains('open');
b.classList.toggle('open', !o);
if (ch) ch.classList.toggle('open', !o);
}
</script>