Translate app UI from Turkish to English
Translates string resources, hardcoded layout text and user-facing strings in Java sources (toasts, dialogs, status labels, upload log). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -100,7 +100,7 @@ public class AbrpUploadService extends Service {
|
|||||||
FIRST_UPLOAD_DELAY_SEC, UPLOAD_INTERVAL_SEC, TimeUnit.SECONDS);
|
FIRST_UPLOAD_DELAY_SEC, UPLOAD_INTERVAL_SEC, TimeUnit.SECONDS);
|
||||||
|
|
||||||
uploadLog.record(new UploadLog.Entry(System.currentTimeMillis(), 0, true,
|
uploadLog.record(new UploadLog.Entry(System.currentTimeMillis(), 0, true,
|
||||||
"Tüketim servisi başlatıldı"));
|
"Consumption service started"));
|
||||||
Log.i(TAG, "Service started, consumption tracking armed");
|
Log.i(TAG, "Service started, consumption tracking armed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ public class AbrpUploadService extends Service {
|
|||||||
wifi.ensureConnected(false);
|
wifi.ensureConnected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateNotification("Tüketim takibi aktif");
|
updateNotification("Consumption tracking active");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- Notification ----------
|
// ---------- Notification ----------
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ public final class ChargingGraphView extends View {
|
|||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
synchronized String tableText() {
|
synchronized String tableText() {
|
||||||
StringBuilder out = new StringBuilder("SOC Şarj gücü\n");
|
StringBuilder out = new StringBuilder("SOC Charge power\n");
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (int soc=0; soc<=100; soc++) if (!Float.isNaN(socPower[soc])) {
|
for (int soc=0; soc<=100; soc++) if (!Float.isNaN(socPower[soc])) {
|
||||||
found = true;
|
found = true;
|
||||||
out.append(String.format(Locale.getDefault(), "%3d %% %6.1f kW\n", soc, socPower[soc]));
|
out.append(String.format(Locale.getDefault(), "%3d %% %6.1f kW\n", soc, socPower[soc]));
|
||||||
}
|
}
|
||||||
return found ? out.toString().trim() : "Henüz şarj ölçümü yok";
|
return found ? out.toString().trim() : "No charging measurements yet";
|
||||||
}
|
}
|
||||||
@Override protected synchronized void onDraw(Canvas c) {
|
@Override protected synchronized void onDraw(Canvas c) {
|
||||||
super.onDraw(c); float left=58, right=getWidth()-12, top=12, bottom=getHeight()-38;
|
super.onDraw(c); float left=58, right=getWidth()-12, top=12, bottom=getHeight()-38;
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ final class ConsumptionCloudClient {
|
|||||||
* Every 30 minutes, takes a delta chunk from the tracker and sends it. Chunks that fail
|
* Every 30 minutes, takes a delta chunk from the tracker and sends it. Chunks that fail
|
||||||
* to send (offline, server error) accumulate in a local cache and are retried on the
|
* to send (offline, server error) accumulate in a local cache and are retried on the
|
||||||
* next cycle — so a drive through a dead-signal area still reaches the cloud once the
|
* next cycle — so a drive through a dead-signal area still reaches the cloud once the
|
||||||
* head unit is back on the hotspot. Every attempt is logged to the in-app "Kayıtlar" tab.
|
* head unit is back on the hotspot. Every attempt is logged to the in-app "Logs" tab.
|
||||||
*
|
*
|
||||||
* @param nowMs wall clock, recorded with the payload — the throttle below runs on a
|
* @param nowMs wall clock, recorded with the payload — the throttle below runs on a
|
||||||
* monotonic clock instead, so a backwards NTP correction cannot stall
|
* monotonic clock instead, so a backwards NTP correction cannot stall
|
||||||
@@ -96,7 +96,7 @@ final class ConsumptionCloudClient {
|
|||||||
// Drain any cached chunks first — a backlog from an offline period has priority.
|
// Drain any cached chunks first — a backlog from an offline period has priority.
|
||||||
int cached = drainChunkCache();
|
int cached = drainChunkCache();
|
||||||
if (cached > 0) {
|
if (cached > 0) {
|
||||||
logEvent(true, 200, "Cache boşaltıldı: " + cached + " chunk gönderildi");
|
logEvent(true, 200, "Cache drained: " + cached + " chunk(s) sent");
|
||||||
invalidateHistory();
|
invalidateHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,14 +115,14 @@ final class ConsumptionCloudClient {
|
|||||||
try {
|
try {
|
||||||
JSONObject body = consumptionBody(chunk, nowMs);
|
JSONObject body = consumptionBody(chunk, nowMs);
|
||||||
if (send("/v1/consumption/daily", "PUT", body)) {
|
if (send("/v1/consumption/daily", "PUT", body)) {
|
||||||
logEvent(true, 200, "Chunk " + chunk.date + " gönderildi (+"
|
logEvent(true, 200, "Chunk " + chunk.date + " sent (+"
|
||||||
+ String.format("%.1f", chunk.day.km) + "km, +"
|
+ String.format("%.1f", chunk.day.km) + "km, +"
|
||||||
+ String.format("%.2f", chunk.day.kwh) + "kWh)");
|
+ String.format("%.2f", chunk.day.kwh) + "kWh)");
|
||||||
invalidateHistory();
|
invalidateHistory();
|
||||||
} else {
|
} else {
|
||||||
cacheChunk(body);
|
cacheChunk(body);
|
||||||
int pending = pendingChunkCount();
|
int pending = pendingChunkCount();
|
||||||
logEvent(false, 0, "Chunk gönderilemedi — cache'de bekliyor (" + pending + " chunk)");
|
logEvent(false, 0, "Chunk not sent — waiting in cache (" + pending + " chunk(s))");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Network failure: cache the chunk for the next cycle.
|
// Network failure: cache the chunk for the next cycle.
|
||||||
@@ -131,7 +131,7 @@ final class ConsumptionCloudClient {
|
|||||||
cacheChunk(body);
|
cacheChunk(body);
|
||||||
} catch (Exception ignored) { }
|
} catch (Exception ignored) { }
|
||||||
int pending = pendingChunkCount();
|
int pending = pendingChunkCount();
|
||||||
logEvent(false, 0, "Çevrimdışı — cache'de bekliyor (" + pending + " chunk): " + e.getMessage());
|
logEvent(false, 0, "Offline — waiting in cache (" + pending + " chunk(s)): " + e.getMessage());
|
||||||
Log.w(TAG, "Chunk sync failed, cached: " + e.getMessage());
|
Log.w(TAG, "Chunk sync failed, cached: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ final class ConsumptionCloudClient {
|
|||||||
return loadChunkCache().length();
|
return loadChunkCache().length();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Records a cloud-sync attempt to the in-app log (the "Kayıtlar" tab). */
|
/** Records a cloud-sync attempt to the in-app log (the "Logs" tab). */
|
||||||
private void logEvent(boolean success, int httpStatus, String detail) {
|
private void logEvent(boolean success, int httpStatus, String detail) {
|
||||||
UploadLog log = AbrpUploadService.log();
|
UploadLog log = AbrpUploadService.log();
|
||||||
if (log == null) return;
|
if (log == null) return;
|
||||||
@@ -220,7 +220,7 @@ final class ConsumptionCloudClient {
|
|||||||
try {
|
try {
|
||||||
syncPendingCharges(charges, pending);
|
syncPendingCharges(charges, pending);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logEvent(false, 0, "Şarj session sync hatası: " + e.getMessage());
|
logEvent(false, 0, "Charging session sync error: " + e.getMessage());
|
||||||
Log.w(TAG, "Charging-session sync unavailable: " + e.getMessage());
|
Log.w(TAG, "Charging-session sync unavailable: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,10 +235,10 @@ final class ConsumptionCloudClient {
|
|||||||
Log.i(TAG, "Uploading charge session: " + id);
|
Log.i(TAG, "Uploading charge session: " + id);
|
||||||
if (send("/v1/charging-sessions/" + id, "PUT", body)) {
|
if (send("/v1/charging-sessions/" + id, "PUT", body)) {
|
||||||
charges.markUploaded(id);
|
charges.markUploaded(id);
|
||||||
logEvent(true, 200, "Şarj session gönderildi: " + id);
|
logEvent(true, 200, "Charging session sent: " + id);
|
||||||
Log.i(TAG, "Successfully uploaded charge session: " + id);
|
Log.i(TAG, "Successfully uploaded charge session: " + id);
|
||||||
} else {
|
} else {
|
||||||
logEvent(false, 0, "Şarj session gönderilemedi: " + id);
|
logEvent(false, 0, "Charging session not sent: " + id);
|
||||||
Log.w(TAG, "Failed to upload charge session: " + id);
|
Log.w(TAG, "Failed to upload charge session: " + id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -310,11 +310,11 @@ final class ConsumptionCloudClient {
|
|||||||
List<DayRecord> fresh = fetchHistory();
|
List<DayRecord> fresh = fetchHistory();
|
||||||
if (!fresh.isEmpty()) cachedHistory = fresh;
|
if (!fresh.isEmpty()) cachedHistory = fresh;
|
||||||
Log.i(TAG, "Fetched " + fresh.size() + " history records from cloud");
|
Log.i(TAG, "Fetched " + fresh.size() + " history records from cloud");
|
||||||
logEvent(true, 200, "History çekildi: " + fresh.size() + " gün");
|
logEvent(true, 200, "History fetched: " + fresh.size() + " day(s)");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String msg = e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage();
|
String msg = e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage();
|
||||||
Log.w(TAG, "History fetch unavailable: " + msg);
|
Log.w(TAG, "History fetch unavailable: " + msg);
|
||||||
logEvent(false, 0, "History fetch hatası: " + msg);
|
logEvent(false, 0, "History fetch error: " + msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,11 +325,11 @@ final class ConsumptionCloudClient {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Immediately attempts to send every cached chunk and take a fresh one, ignoring the
|
* Immediately attempts to send every cached chunk and take a fresh one, ignoring the
|
||||||
* 2-minute throttle. Called from the UI "Şimdi yükle" button. Returns a one-line
|
* 2-minute throttle. Called from the UI "Upload now" button. Returns a one-line
|
||||||
* status for the log.
|
* status for the log.
|
||||||
*/
|
*/
|
||||||
String flushNow(ConsumptionTracker tracker, long nowMs) {
|
String flushNow(ConsumptionTracker tracker, long nowMs) {
|
||||||
if (endpoint.isEmpty() || token.isEmpty()) return "API yapılandırılmamış";
|
if (endpoint.isEmpty() || token.isEmpty()) return "API not configured";
|
||||||
int cached = drainChunkCache();
|
int cached = drainChunkCache();
|
||||||
ConsumptionTracker.CloudSnapshot chunk = tracker.takeChunkDelta();
|
ConsumptionTracker.CloudSnapshot chunk = tracker.takeChunkDelta();
|
||||||
int total = cached;
|
int total = cached;
|
||||||
@@ -348,9 +348,9 @@ final class ConsumptionCloudClient {
|
|||||||
}
|
}
|
||||||
int pending = pendingChunkCount();
|
int pending = pendingChunkCount();
|
||||||
String msg = total > 0
|
String msg = total > 0
|
||||||
? total + " chunk yüklendi" + (pending > 0 ? ", " + pending + " hâlâ bekliyor" : "")
|
? total + " chunk(s) uploaded" + (pending > 0 ? ", " + pending + " still pending" : "")
|
||||||
: (pending > 0 ? pending + " chunk yüklenemedi (internet?)" : "Yüklenecek yeni veri yok");
|
: (pending > 0 ? pending + " chunk(s) could not be uploaded (internet?)" : "No new data to upload");
|
||||||
logEvent(total > 0, total > 0 ? 200 : 0, "Manuel sync: " + msg);
|
logEvent(total > 0, total > 0 ? 200 : 0, "Manual sync: " + msg);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -363,9 +363,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
String ssid = wifi.currentSsid();
|
String ssid = wifi.currentSsid();
|
||||||
wifiSsid.setText(ssid == null ? getString(R.string.wifi_not_connected) : ssid);
|
wifiSsid.setText(ssid == null ? getString(R.string.wifi_not_connected) : ssid);
|
||||||
if (ssid != null) {
|
if (ssid != null) {
|
||||||
wifiState.setText("Bağlı ♥");
|
wifiState.setText("Connected ♥");
|
||||||
} else if (!wifi.isWifiEnabled()) {
|
} else if (!wifi.isWifiEnabled()) {
|
||||||
wifiState.setText("Wi-Fi kapalı");
|
wifiState.setText("Wi-Fi off");
|
||||||
}
|
}
|
||||||
// Left alone otherwise: a message the button just set says more about what is
|
// Left alone otherwise: a message the button just set says more about what is
|
||||||
// happening than "not connected" would.
|
// happening than "not connected" would.
|
||||||
@@ -458,10 +458,10 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
consumptionReset.setOnClickListener(v -> {
|
consumptionReset.setOnClickListener(v -> {
|
||||||
if (consumptionPeriod != ConsumptionTracker.Period.TRIP_A && consumptionPeriod != ConsumptionTracker.Period.TRIP_B) return;
|
if (consumptionPeriod != ConsumptionTracker.Period.TRIP_A && consumptionPeriod != ConsumptionTracker.Period.TRIP_B) return;
|
||||||
String name = consumptionPeriod == ConsumptionTracker.Period.TRIP_A ? "Trip A" : "Trip B";
|
String name = consumptionPeriod == ConsumptionTracker.Period.TRIP_A ? "Trip A" : "Trip B";
|
||||||
new MaterialAlertDialogBuilder(this).setTitle(name + " sıfırlansın mı?")
|
new MaterialAlertDialogBuilder(this).setTitle("Reset " + name + "?")
|
||||||
.setMessage("Bu sayacın kayıtlı tüketim geçmişi kalıcı olarak silinir.")
|
.setMessage("This counter's recorded consumption history will be permanently deleted.")
|
||||||
.setNegativeButton("Vazgeç", null)
|
.setNegativeButton("Cancel", null)
|
||||||
.setPositiveButton("Sıfırla", (d, w) -> {
|
.setPositiveButton("Reset", (d, w) -> {
|
||||||
consumptionTracker.reset(consumptionPeriod);
|
consumptionTracker.reset(consumptionPeriod);
|
||||||
refreshConsumption();
|
refreshConsumption();
|
||||||
}).show();
|
}).show();
|
||||||
@@ -475,9 +475,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
if (!consumptionTracker.setSohPercent(value)) throw new NumberFormatException();
|
if (!consumptionTracker.setSohPercent(value)) throw new NumberFormatException();
|
||||||
consumptionSohLayout.setError(null);
|
consumptionSohLayout.setError(null);
|
||||||
consumptionSohInput.setText(String.format(java.util.Locale.US, "%.1f", value));
|
consumptionSohInput.setText(String.format(java.util.Locale.US, "%.1f", value));
|
||||||
Toast.makeText(this, "SoH kaydedildi", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "SoH saved", Toast.LENGTH_SHORT).show();
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
consumptionSohLayout.setError("1 ile 100 arasında bir değer girin");
|
consumptionSohLayout.setError("Enter a value between 1 and 100");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,9 +533,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
if (!chargeSessionTracker.setPricePerKwh(value)) throw new NumberFormatException();
|
if (!chargeSessionTracker.setPricePerKwh(value)) throw new NumberFormatException();
|
||||||
chargePriceLayout.setError(null);
|
chargePriceLayout.setError(null);
|
||||||
chargePriceInput.setText(String.format(java.util.Locale.US, "%.2f", value));
|
chargePriceInput.setText(String.format(java.util.Locale.US, "%.2f", value));
|
||||||
Toast.makeText(this, "Şarj fiyatı kaydedildi", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Charging price saved", Toast.LENGTH_SHORT).show();
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
chargePriceLayout.setError("Geçerli bir ₺/kWh değeri girin");
|
chargePriceLayout.setError("Enter a valid ₺/kWh value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,9 +550,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
// below — which then describe the previous DC session — be read as this charge.
|
// below — which then describe the previous DC session — be read as this charge.
|
||||||
boolean dc = ChargingState.isDcCharging(
|
boolean dc = ChargingState.isDcCharging(
|
||||||
code, s.getChargePortConnected(), s.getBatteryPowerKw(), s.getSpeedKmh());
|
code, s.getChargePortConnected(), s.getBatteryPowerKw(), s.getSpeedKmh());
|
||||||
chargeStatus.setText(dc ? "DC hızlı şarj"
|
chargeStatus.setText(dc ? "DC fast charging"
|
||||||
: charging ? "AC şarj (ölçülmüyor)"
|
: charging ? "AC charging (not metered)"
|
||||||
: (session.startedAtMs > 0 ? "Son şarj" : "Şarj yok"));
|
: (session.startedAtMs > 0 ? "Last charge" : "Not charging"));
|
||||||
chargeSoc.setText(fmt(s.getSocPercent(), "%.1f %%"));
|
chargeSoc.setText(fmt(s.getSocPercent(), "%.1f %%"));
|
||||||
chargeStartSoc.setText(fmt(session.startSocPercent, "%.1f %%"));
|
chargeStartSoc.setText(fmt(session.startSocPercent, "%.1f %%"));
|
||||||
chargeVoltage.setText(fmt(s.getBatteryVoltageV(), "%.1f V"));
|
chargeVoltage.setText(fmt(s.getBatteryVoltageV(), "%.1f V"));
|
||||||
@@ -586,20 +586,20 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
consumptionSpeed.setText(t.hours <= 0 ? "—" : String.format(java.util.Locale.getDefault(),
|
consumptionSpeed.setText(t.hours <= 0 ? "—" : String.format(java.util.Locale.getDefault(),
|
||||||
"%.1f km/h", t.km / t.hours));
|
"%.1f km/h", t.km / t.hours));
|
||||||
long minutes = Math.round(t.hours * 60d);
|
long minutes = Math.round(t.hours * 60d);
|
||||||
consumptionTime.setText(String.format(java.util.Locale.getDefault(), "%d sa %02d dk",
|
consumptionTime.setText(String.format(java.util.Locale.getDefault(), "%d h %02d min",
|
||||||
minutes / 60, minutes % 60));
|
minutes / 60, minutes % 60));
|
||||||
consumptionSoc.setText(String.format(java.util.Locale.getDefault(), "%.1f %%", t.soc));
|
consumptionSoc.setText(String.format(java.util.Locale.getDefault(), "%.1f %%", t.soc));
|
||||||
// Daily history: cloud first, local fallback for today (not yet uploaded).
|
// Daily history: cloud first, local fallback for today (not yet uploaded).
|
||||||
ConsumptionTracker.Totals day = cloudDay(selectedConsumptionDate);
|
ConsumptionTracker.Totals day = cloudDay(selectedConsumptionDate);
|
||||||
if (day == null) day = consumptionTracker.totalsForDay(selectedConsumptionDate);
|
if (day == null) day = consumptionTracker.totalsForDay(selectedConsumptionDate);
|
||||||
if (day.km == 0 && day.kwh == 0 && day.hours == 0 && day.soc == 0) {
|
if (day.km == 0 && day.kwh == 0 && day.hours == 0 && day.soc == 0) {
|
||||||
consumptionDailyHistory.setText("Bu tarih için kayıt yok");
|
consumptionDailyHistory.setText("No records for this date");
|
||||||
} else {
|
} else {
|
||||||
String average = day.km < 0.1 ? "—" : String.format(java.util.Locale.getDefault(),
|
String average = day.km < 0.1 ? "—" : String.format(java.util.Locale.getDefault(),
|
||||||
"%.1f kWh/100 km", day.kwh * 100d / day.km);
|
"%.1f kWh/100 km", day.kwh * 100d / day.km);
|
||||||
long dayMinutes = Math.round(day.hours * 60d);
|
long dayMinutes = Math.round(day.hours * 60d);
|
||||||
consumptionDailyHistory.setText(String.format(java.util.Locale.getDefault(),
|
consumptionDailyHistory.setText(String.format(java.util.Locale.getDefault(),
|
||||||
"Mesafe %.1f km\nEnerji %.2f kWh\nOrtalama %s\nSüre %d sa %02d dk\nSOC farkı %.1f %%",
|
"Distance %.1f km\nEnergy %.2f kWh\nAverage %s\nDuration %d h %02d min\nSOC change %.1f %%",
|
||||||
day.km, day.kwh, average, dayMinutes / 60, dayMinutes % 60, day.soc));
|
day.km, day.kwh, average, dayMinutes / 60, dayMinutes % 60, day.soc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -666,17 +666,17 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
Integer status = s.getChargingStatus();
|
Integer status = s.getChargingStatus();
|
||||||
if (status != null) {
|
if (status != null) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 1: return "AC şarj ♥";
|
case 1: return "AC charging ♥";
|
||||||
case 10: return "DC hızlı şarj ♥";
|
case 10: return "DC fast charging ♥";
|
||||||
case 5: return "Bağlanıyor…";
|
case 5: return "Connecting…";
|
||||||
case 7: return "Kabloda, şarj yok";
|
case 7: return "Plugged in, not charging";
|
||||||
case 8: return "Durduruldu";
|
case 8: return "Stopped";
|
||||||
case 0: return "Şarj yok";
|
case 0: return "Not charging";
|
||||||
default: return "Durum " + status;
|
default: return "Status " + status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Boolean plugged = s.getChargePortConnected();
|
Boolean plugged = s.getChargePortConnected();
|
||||||
if (plugged != null) return plugged ? "Bağlı ♥" : "Bağlı değil";
|
if (plugged != null) return plugged ? "Connected ♥" : "Not connected";
|
||||||
return "—";
|
return "—";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -689,13 +689,13 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
// ---------- Call log ----------
|
// ---------- Call log ----------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Şimdi yükle" button — forces a cache drain + fresh chunk on a background thread,
|
* "Upload now" button — forces a cache drain + fresh chunk on a background thread,
|
||||||
* ignoring the 2-minute throttle. The result lands in the upload log (Kayıtlar tab).
|
* ignoring the 2-minute throttle. The result lands in the upload log (Logs tab).
|
||||||
*/
|
*/
|
||||||
private void manualFlush() {
|
private void manualFlush() {
|
||||||
if (consumptionCloudClient == null || consumptionTracker == null) return;
|
if (consumptionCloudClient == null || consumptionTracker == null) return;
|
||||||
AbrpUploadService.log().record(new UploadLog.Entry(
|
AbrpUploadService.log().record(new UploadLog.Entry(
|
||||||
System.currentTimeMillis(), 0, true, "Manuel sync başlatıldı…"));
|
System.currentTimeMillis(), 0, true, "Manual sync started…"));
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
String result = consumptionCloudClient.flushNow(
|
String result = consumptionCloudClient.flushNow(
|
||||||
consumptionTracker, System.currentTimeMillis());
|
consumptionTracker, System.currentTimeMillis());
|
||||||
@@ -704,19 +704,19 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tüketim sekmesi "Yenile" button — sends cached chunks + fresh delta, invalidates the
|
* Consumption tab "Refresh" button — sends cached chunks + fresh delta, invalidates the
|
||||||
* history cache so the next poll fetches fresh data from the cloud, then refreshes the UI.
|
* history cache so the next poll fetches fresh data from the cloud, then refreshes the UI.
|
||||||
*/
|
*/
|
||||||
private void refreshFromCloud() {
|
private void refreshFromCloud() {
|
||||||
if (consumptionCloudClient == null || consumptionTracker == null) return;
|
if (consumptionCloudClient == null || consumptionTracker == null) return;
|
||||||
AbrpUploadService.log().record(new UploadLog.Entry(
|
AbrpUploadService.log().record(new UploadLog.Entry(
|
||||||
System.currentTimeMillis(), 0, true, "Tüketim yenileniyor…"));
|
System.currentTimeMillis(), 0, true, "Refreshing consumption…"));
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
consumptionCloudClient.flushNow(consumptionTracker, System.currentTimeMillis());
|
consumptionCloudClient.flushNow(consumptionTracker, System.currentTimeMillis());
|
||||||
consumptionCloudClient.invalidateHistory();
|
consumptionCloudClient.invalidateHistory();
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
refreshConsumption();
|
refreshConsumption();
|
||||||
Toast.makeText(this, "Tüketim yenilendi", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Consumption refreshed", Toast.LENGTH_SHORT).show();
|
||||||
});
|
});
|
||||||
}, "cloud-refresh").start();
|
}, "cloud-refresh").start();
|
||||||
}
|
}
|
||||||
@@ -764,7 +764,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
break;
|
break;
|
||||||
case RUNNING:
|
case RUNNING:
|
||||||
case STARTING:
|
case STARTING:
|
||||||
statusText.setText("Tüketim takibi aktif");
|
statusText.setText("Consumption tracking active");
|
||||||
statusText.setTextColor(COLOR_OK);
|
statusText.setTextColor(COLOR_OK);
|
||||||
break;
|
break;
|
||||||
case STOPPED:
|
case STOPPED:
|
||||||
|
|||||||
@@ -150,14 +150,14 @@ final class WifiAutoConnect {
|
|||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result alreadyOn(String ssid) { return new Result(true, ssid, "Bağlı: " + ssid); }
|
static Result alreadyOn(String ssid) { return new Result(true, ssid, "Connected: " + ssid); }
|
||||||
static Result attempting(String ssid) { return new Result(false, ssid, "Bağlanılıyor: " + ssid); }
|
static Result attempting(String ssid) { return new Result(false, ssid, "Connecting: " + ssid); }
|
||||||
|
|
||||||
static final Result UNSUPPORTED = new Result(false, null, "Wi-Fi yönetilemiyor");
|
static final Result UNSUPPORTED = new Result(false, null, "Wi-Fi cannot be managed");
|
||||||
static final Result WAITING = new Result(false, null, "Bekleniyor…");
|
static final Result WAITING = new Result(false, null, "Bekleniyor…");
|
||||||
static final Result ENABLING = new Result(false, null, "Wi-Fi açılıyor…");
|
static final Result ENABLING = new Result(false, null, "Turning Wi-Fi on…");
|
||||||
static final Result CANNOT_ENABLE = new Result(false, null, "Wi-Fi açılamadı");
|
static final Result CANNOT_ENABLE = new Result(false, null, "Could not turn Wi-Fi on");
|
||||||
static final Result NO_SAVED_NETWORKS = new Result(false, null, "Kayıtlı ağ yok");
|
static final Result NO_SAVED_NETWORKS = new Result(false, null, "No saved networks");
|
||||||
static final Result REFUSED = new Result(false, null, "Sistem izin vermedi");
|
static final Result REFUSED = new Result(false, null, "Sistem izin vermedi");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,30 +2,30 @@
|
|||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true">
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true">
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp">
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp">
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:background="@drawable/bg_glass">
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:background="@drawable/bg_glass">
|
||||||
<TextView android:id="@+id/charge_status" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Şarj yok" android:textAppearance="@style/Text.EV.Title" android:textColor="@color/ev_cyan"/>
|
<TextView android:id="@+id/charge_status" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Not charging" android:textAppearance="@style/Text.EV.Title" android:textColor="@color/ev_cyan"/>
|
||||||
<GridLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:columnCount="2" android:layout_marginTop="12dp">
|
<GridLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:columnCount="2" android:layout_marginTop="12dp">
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="SOC" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_soc" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="SOC" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_soc" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Başlangıç SOC" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_start_soc" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Start SOC" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_start_soc" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Batarya voltajı" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_voltage" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Battery voltage" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_voltage" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Batarya akımı" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_current" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Battery current" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_current" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Şarj gücü" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_power" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Charging power" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_power" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Bataryaya giren net enerji" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_energy" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Net energy into battery" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_energy" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Şebekeden alınan (+%10)" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_grid_energy" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Drawn from grid (+10%)" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_grid_energy" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Şarj süresi" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_duration" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Charging time" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_duration" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Toplam ücret" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_total_cost" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="Total cost" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/charge_total_cost" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="10dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:layout_marginTop="16dp" android:background="@drawable/bg_glass">
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:layout_marginTop="16dp" android:background="@drawable/bg_glass">
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="ŞARJ FİYATI" android:textAppearance="@style/Text.EV.Eyebrow"/>
|
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="CHARGING PRICE" android:textAppearance="@style/Text.EV.Eyebrow"/>
|
||||||
<com.google.android.material.textfield.TextInputLayout android:id="@+id/charge_price_layout" style="@style/Widget.Material3.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:hint="Birim fiyat" app:suffixText="₺/kWh">
|
<com.google.android.material.textfield.TextInputLayout android:id="@+id/charge_price_layout" style="@style/Widget.Material3.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:hint="Unit price" app:suffixText="₺/kWh">
|
||||||
<com.google.android.material.textfield.TextInputEditText android:id="@+id/charge_price_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:maxLength="10" android:minHeight="72dp"/>
|
<com.google.android.material.textfield.TextInputEditText android:id="@+id/charge_price_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:maxLength="10" android:minHeight="72dp"/>
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
<com.google.android.material.button.MaterialButton android:id="@+id/charge_price_save" style="@style/Widget.EV.Button" android:layout_width="match_parent" android:layout_height="72dp" android:layout_marginTop="8dp" android:text="Fiyatı kaydet"/>
|
<com.google.android.material.button.MaterialButton android:id="@+id/charge_price_save" style="@style/Widget.EV.Button" android:layout_width="match_parent" android:layout_height="72dp" android:layout_marginTop="8dp" android:text="Save price"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:layout_marginTop="16dp" android:background="@drawable/bg_glass">
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:layout_marginTop="16dp" android:background="@drawable/bg_glass">
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="ŞARJ EĞRİSİ" android:textAppearance="@style/Text.EV.Eyebrow"/>
|
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="CHARGING CURVE" android:textAppearance="@style/Text.EV.Eyebrow"/>
|
||||||
<com.evsuite.abrp.ChargingGraphView android:id="@+id/charge_graph" android:layout_width="match_parent" android:layout_height="280dp" android:layout_marginTop="12dp"/>
|
<com.evsuite.abrp.ChargingGraphView android:id="@+id/charge_graph" android:layout_width="match_parent" android:layout_height="280dp" android:layout_marginTop="12dp"/>
|
||||||
<TextView android:id="@+id/charge_curve_table" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:fontFamily="monospace" android:text="Henüz şarj ölçümü yok" android:textAppearance="@style/Text.EV.Body" android:textColor="@color/ev_cyan"/>
|
<TextView android:id="@+id/charge_curve_table" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:fontFamily="monospace" android:text="No charging measurements yet" android:textAppearance="@style/Text.EV.Body" android:textColor="@color/ev_cyan"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -3,41 +3,41 @@
|
|||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp">
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp">
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:background="@drawable/bg_glass">
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:background="@drawable/bg_glass">
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical">
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical">
|
||||||
<TextView android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="TÜKETİM DÖNEMİ" android:textAppearance="@style/Text.EV.Eyebrow"/>
|
<TextView android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="CONSUMPTION PERIOD" android:textAppearance="@style/Text.EV.Eyebrow"/>
|
||||||
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_refresh" style="@style/Widget.EV.Button.Outlined" android:layout_width="48dp" android:layout_height="48dp" android:minWidth="0dp" android:padding="0dp" android:contentDescription="Yenile" app:icon="@drawable/ic_refresh" app:iconGravity="textStart" app:iconPadding="0dp" app:iconTint="@color/ev_accent"/>
|
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_refresh" style="@style/Widget.EV.Button.Outlined" android:layout_width="48dp" android:layout_height="48dp" android:minWidth="0dp" android:padding="0dp" android:contentDescription="Refresh" app:icon="@drawable/ic_refresh" app:iconGravity="textStart" app:iconPadding="0dp" app:iconTint="@color/ev_accent"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<HorizontalScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:scrollbars="none">
|
<HorizontalScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:scrollbars="none">
|
||||||
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal">
|
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal">
|
||||||
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_lifetime" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:text="Tüm zamanlar"/>
|
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_lifetime" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:text="Lifetime"/>
|
||||||
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_week" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Son 7 gün"/>
|
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_week" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Last 7 days"/>
|
||||||
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_month" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Son 30 gün"/>
|
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_month" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Last 30 days"/>
|
||||||
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_trip_a" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Trip A"/>
|
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_trip_a" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Trip A"/>
|
||||||
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_trip_b" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Trip B"/>
|
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_trip_b" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Trip B"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
<GridLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:columnCount="2">
|
<GridLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:columnCount="2">
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="Mesafe" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_distance" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="Distance" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_distance" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="Net enerji" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_energy" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="Net energy" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_energy" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="Ortalama tüketim" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_average" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="Average consumption" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_average" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="Ortalama hız" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_speed" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="Average speed" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_speed" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="Süre" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_time" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="Duration" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_time" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="SOC farkı" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_soc" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
<TextView android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="SOC change" android:textAppearance="@style/DataLabel"/><TextView android:id="@+id/consumption_soc" android:layout_width="0dp" android:layout_columnWeight="1" android:padding="12dp" android:text="—" android:textAppearance="@style/DataValue"/>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_reset" style="@style/Widget.EV.Button.Outlined" android:layout_width="match_parent" android:layout_height="64dp" android:layout_marginTop="12dp" android:text="Seçili tripi sıfırla" android:visibility="gone"/>
|
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_reset" style="@style/Widget.EV.Button.Outlined" android:layout_width="match_parent" android:layout_height="64dp" android:layout_marginTop="12dp" android:text="Reset selected trip" android:visibility="gone"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:text="Son 7/30 gün, tüm zamanlar ve Trip A/B cihazda kalıcı saklanır; uygulama ve OTA güncellemeleriyle silinmez." android:textAppearance="@style/Text.EV.Secondary"/>
|
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:text="Last 7/30 days, lifetime and Trip A/B are stored permanently on the device; app and OTA updates do not erase them." android:textAppearance="@style/Text.EV.Secondary"/>
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:layout_marginTop="16dp" android:background="@drawable/bg_glass">
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:layout_marginTop="16dp" android:background="@drawable/bg_glass">
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="BATARYA SAĞLIĞI (SOH)" android:textAppearance="@style/Text.EV.Eyebrow"/>
|
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="BATTERY HEALTH (SOH)" android:textAppearance="@style/Text.EV.Eyebrow"/>
|
||||||
<com.google.android.material.textfield.TextInputLayout android:id="@+id/consumption_soh_layout" style="@style/Widget.Material3.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:hint="Manuel SoH (%)" app:suffixText="%">
|
<com.google.android.material.textfield.TextInputLayout android:id="@+id/consumption_soh_layout" style="@style/Widget.Material3.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:hint="Manual SoH (%)" app:suffixText="%">
|
||||||
<com.google.android.material.textfield.TextInputEditText android:id="@+id/consumption_soh_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:maxLength="5" android:minHeight="72dp"/>
|
<com.google.android.material.textfield.TextInputEditText android:id="@+id/consumption_soh_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:maxLength="5" android:minHeight="72dp"/>
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_soh_save" style="@style/Widget.EV.Button" android:layout_width="match_parent" android:layout_height="72dp" android:layout_marginTop="8dp" android:text="SoH değerini kaydet"/>
|
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_soh_save" style="@style/Widget.EV.Button" android:layout_width="match_parent" android:layout_height="72dp" android:layout_marginTop="8dp" android:text="Save SoH value"/>
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="Bu manuel değer cihazda saklanır ve MongoDB'deki tüm zamanlar kaydına eklenir." android:textAppearance="@style/Text.EV.Secondary"/>
|
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="This manual value is stored on the device and added to the lifetime record in MongoDB." android:textAppearance="@style/Text.EV.Secondary"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:layout_marginTop="16dp" android:background="@drawable/bg_glass">
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" android:layout_marginTop="16dp" android:background="@drawable/bg_glass">
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="GÜNLÜK KAYIT · SON 4 AY" android:textAppearance="@style/Text.EV.Eyebrow"/>
|
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="DAILY LOG · LAST 4 MONTHS" android:textAppearance="@style/Text.EV.Eyebrow"/>
|
||||||
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_date_button" style="@style/Widget.EV.Button.Outlined" android:layout_width="match_parent" android:layout_height="56dp" android:layout_marginTop="12dp" android:text="Tarih seç"/>
|
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_date_button" style="@style/Widget.EV.Button.Outlined" android:layout_width="match_parent" android:layout_height="56dp" android:layout_marginTop="12dp" android:text="Pick a date"/>
|
||||||
<TextView android:id="@+id/consumption_daily_history" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:fontFamily="monospace" android:text="Henüz günlük veri yok" android:textAppearance="@style/Text.EV.Body" android:textColor="@color/ev_cyan"/>
|
<TextView android:id="@+id/consumption_daily_history" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:fontFamily="monospace" android:text="No daily data yet" android:textAppearance="@style/Text.EV.Body" android:textColor="@color/ev_cyan"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -3,45 +3,45 @@
|
|||||||
|
|
||||||
<!-- Main screen -->
|
<!-- Main screen -->
|
||||||
<string name="tab_abrp">ABRP</string>
|
<string name="tab_abrp">ABRP</string>
|
||||||
<string name="tab_service">Aktarım</string>
|
<string name="tab_service">Upload</string>
|
||||||
<string name="tab_vehicle">Genel</string>
|
<string name="tab_vehicle">Overview</string>
|
||||||
<string name="tab_consumption">Tüketim</string>
|
<string name="tab_consumption">Consumption</string>
|
||||||
<string name="tab_charging">Şarj</string>
|
<string name="tab_charging">Charging</string>
|
||||||
<string name="consumption_title">Tüketim</string>
|
<string name="consumption_title">Consumption</string>
|
||||||
<string name="consumption_subtitle">Başlangıç, motor, tüm zamanlar ve trip sayaçları</string>
|
<string name="consumption_subtitle">Since start, motor, lifetime and trip counters</string>
|
||||||
<string name="charging_title">Şarj</string>
|
<string name="charging_title">Charging</string>
|
||||||
<string name="charging_subtitle">Canlı batarya değerleri ve SOC/güç eğrisi</string>
|
<string name="charging_subtitle">Live battery values and SOC/power curve</string>
|
||||||
<string name="tab_wifi">Wi-Fi</string>
|
<string name="tab_wifi">Wi-Fi</string>
|
||||||
<string name="tab_log">Kayıtlar</string>
|
<string name="tab_log">Logs</string>
|
||||||
|
|
||||||
<!-- Wi-Fi page -->
|
<!-- Wi-Fi page -->
|
||||||
<string name="wifi_card_title">Wi-Fi Bağlantısı</string>
|
<string name="wifi_card_title">Wi-Fi Connection</string>
|
||||||
<string name="wifi_current">Bağlı ağ</string>
|
<string name="wifi_current">Connected network</string>
|
||||||
<string name="wifi_state">Durum</string>
|
<string name="wifi_state">Status</string>
|
||||||
<string name="wifi_connect_now">Şimdi Bağlan</string>
|
<string name="wifi_connect_now">Connect Now</string>
|
||||||
<string name="wifi_auto_label">Arka planda otomatik bağlan</string>
|
<string name="wifi_auto_label">Auto-connect in the background</string>
|
||||||
<string name="wifi_auto_hint">Yükleme servisi çalışırken bağlantı koptuğunda kayıtlı ağlara kendi kendine bağlanmayı dener.</string>
|
<string name="wifi_auto_hint">While the upload service is running, it tries to reconnect to saved networks on its own when the connection drops.</string>
|
||||||
<string name="wifi_saved_title">Kayıtlı Ağlar</string>
|
<string name="wifi_saved_title">Saved Networks</string>
|
||||||
<string name="wifi_saved_empty">Kayıtlı ağ okunamadı</string>
|
<string name="wifi_saved_empty">Could not read saved networks</string>
|
||||||
<string name="wifi_not_connected">Bağlı değil</string>
|
<string name="wifi_not_connected">Not connected</string>
|
||||||
|
|
||||||
<!-- Vehicle page -->
|
<!-- Vehicle page -->
|
||||||
<string name="vehicle_live_data">Canlı Araç Verileri</string>
|
<string name="vehicle_live_data">Live Vehicle Data</string>
|
||||||
<string name="vehicle_tires">Lastik Basınçları</string>
|
<string name="vehicle_tires">Tire Pressures</string>
|
||||||
<string name="vehicle_row_soc">Şarj (SOC)</string>
|
<string name="vehicle_row_soc">Charge (SOC)</string>
|
||||||
<string name="vehicle_row_range">Menzil</string>
|
<string name="vehicle_row_range">Range</string>
|
||||||
<string name="vehicle_row_power">Güç</string>
|
<string name="vehicle_row_power">Power</string>
|
||||||
<string name="vehicle_row_speed">Hız</string>
|
<string name="vehicle_row_speed">Speed</string>
|
||||||
<string name="vehicle_row_odometer">Kilometre</string>
|
<string name="vehicle_row_odometer">Odometer</string>
|
||||||
<string name="vehicle_row_batt_temp">Batarya Sıcaklığı</string>
|
<string name="vehicle_row_batt_temp">Battery Temperature</string>
|
||||||
<string name="vehicle_row_cabin_temp">Kabin Sıcaklığı</string>
|
<string name="vehicle_row_cabin_temp">Cabin Temperature</string>
|
||||||
<string name="vehicle_row_hvac">Klima Ayarı</string>
|
<string name="vehicle_row_hvac">Climate Setpoint</string>
|
||||||
<string name="vehicle_row_capacity">Batarya Kapasitesi</string>
|
<string name="vehicle_row_capacity">Battery Capacity</string>
|
||||||
<string name="vehicle_row_charging">Şarj Durumu</string>
|
<string name="vehicle_row_charging">Charging Status</string>
|
||||||
<string name="vehicle_tire_fl">Ön Sol</string>
|
<string name="vehicle_tire_fl">Front Left</string>
|
||||||
<string name="vehicle_tire_fr">Ön Sağ</string>
|
<string name="vehicle_tire_fr">Front Right</string>
|
||||||
<string name="vehicle_tire_rl">Arka Sol</string>
|
<string name="vehicle_tire_rl">Rear Left</string>
|
||||||
<string name="vehicle_tire_rr">Arka Sağ</string>
|
<string name="vehicle_tire_rr">Rear Right</string>
|
||||||
<string name="card_config">Configuration</string>
|
<string name="card_config">Configuration</string>
|
||||||
<string name="hint_api_key">ABRP API Key</string>
|
<string name="hint_api_key">ABRP API Key</string>
|
||||||
<string name="default_abrp_api_key" translatable="false">8cfc314b-03cd-4efe-ab7d-4431cd8f2e2d</string>
|
<string name="default_abrp_api_key" translatable="false">8cfc314b-03cd-4efe-ab7d-4431cd8f2e2d</string>
|
||||||
@@ -51,9 +51,9 @@
|
|||||||
<string name="helper_token">Find your token in the ABRP app: Settings → Connections → Generic (Manual Entry)</string>
|
<string name="helper_token">Find your token in the ABRP app: Settings → Connections → Generic (Manual Entry)</string>
|
||||||
<string name="desc_toggle_api_key">Show or hide API key</string>
|
<string name="desc_toggle_api_key">Show or hide API key</string>
|
||||||
<string name="desc_toggle_token">Show or hide user token</string>
|
<string name="desc_toggle_token">Show or hide user token</string>
|
||||||
<string name="btn_save">Kaydet</string>
|
<string name="btn_save">Save</string>
|
||||||
<string name="btn_test">Bağlantıyı test et</string>
|
<string name="btn_test">Test connection</string>
|
||||||
<string name="btn_import">Dosyadan al</string>
|
<string name="btn_import">Import from file</string>
|
||||||
|
|
||||||
<!-- Config file import -->
|
<!-- Config file import -->
|
||||||
<string name="import_ok">Config imported — press Test to verify</string>
|
<string name="import_ok">Config imported — press Test to verify</string>
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
<!-- Call log -->
|
<!-- Call log -->
|
||||||
<string name="label_call_log">Recent uploads</string>
|
<string name="label_call_log">Recent uploads</string>
|
||||||
<string name="call_log_empty">No upload attempted yet.</string>
|
<string name="call_log_empty">No upload attempted yet.</string>
|
||||||
<string name="btn_flush_now">Şimdi yükle</string>
|
<string name="btn_flush_now">Upload now</string>
|
||||||
<string name="status_starting">Starting…</string>
|
<string name="status_starting">Starting…</string>
|
||||||
<string name="status_running_no_upload">Running — waiting for first upload</string>
|
<string name="status_running_no_upload">Running — waiting for first upload</string>
|
||||||
<string name="status_last_upload">Last upload: %1$s (%2$s)</string>
|
<string name="status_last_upload">Last upload: %1$s (%2$s)</string>
|
||||||
@@ -118,15 +118,15 @@
|
|||||||
<string name="notif_channel_desc">Shows vehicle telemetry upload status</string>
|
<string name="notif_channel_desc">Shows vehicle telemetry upload status</string>
|
||||||
<string name="notif_title">ABRP Uploader</string>
|
<string name="notif_title">ABRP Uploader</string>
|
||||||
<string name="notif_action_stop">Stop</string>
|
<string name="notif_action_stop">Stop</string>
|
||||||
<string name="ota_install_success">Güncelleme kuruldu — uygulamayı yeniden başlatın</string>
|
<string name="ota_install_success">Update installed — restart the app</string>
|
||||||
<string name="ota_install_failed">Kurulum başarısız: %1$s</string>
|
<string name="ota_install_failed">Installation failed: %1$s</string>
|
||||||
<string name="update_check">Güncelleme kontrol et</string>
|
<string name="update_check">Check for updates</string>
|
||||||
<string name="update_checking">Yeni OTA sürümü kontrol ediliyor…</string>
|
<string name="update_checking">Checking for a new OTA version…</string>
|
||||||
<string name="update_dialog_title">Yazılım güncellemesi</string>
|
<string name="update_dialog_title">Software update</string>
|
||||||
<string name="update_downloading">İndiriliyor ve doğrulanıyor…</string>
|
<string name="update_downloading">Downloading and verifying…</string>
|
||||||
<string name="update_downloading_percent">İndiriliyor… %1$d%%</string>
|
<string name="update_downloading_percent">Downloading… %1$d%%</string>
|
||||||
<string name="about_action">About</string>
|
<string name="about_action">About</string>
|
||||||
<string name="about_title">Fatih\'sMG4 Hakkında</string>
|
<string name="about_title">About Fatih\'sMG4</string>
|
||||||
<string name="about_version">Version %1$s</string>
|
<string name="about_version">Version %1$s</string>
|
||||||
<string name="about_attribution">Fork of malys / EVABRPUploader\nand Leon Kernan / ABRP_Uploader</string>
|
<string name="about_attribution">Fork of malys / EVABRPUploader\nand Leon Kernan / ABRP_Uploader</string>
|
||||||
<string name="about_repository">github.com/fatihdonmezdev/FatihsMG4</string>
|
<string name="about_repository">github.com/fatihdonmezdev/FatihsMG4</string>
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="design_battery_short">Batarya</string>
|
<string name="design_battery_short">Battery</string>
|
||||||
<string name="design_probe">VHAL Probe</string>
|
<string name="design_probe">VHAL Probe</string>
|
||||||
<string name="design_brand">MG⁴</string>
|
<string name="design_brand">MG⁴</string>
|
||||||
<string name="design_brand_caption">Fatih’s MG4</string>
|
<string name="design_brand_caption">Fatih’s MG4</string>
|
||||||
<string name="design_brand_footer">ELEKTRİKLE YOLDA</string>
|
<string name="design_brand_footer">ON THE ROAD, ELECTRIC</string>
|
||||||
<string name="design_overview_title">Sürüşe bir bakış.</string>
|
<string name="design_overview_title">Your drive at a glance.</string>
|
||||||
<string name="design_overview_subtitle">Aracından gelen veriler, tek bir yerde.</string>
|
<string name="design_overview_subtitle">Data from your car, all in one place.</string>
|
||||||
<string name="design_abrp_title">Rotana bağlan.</string>
|
<string name="design_abrp_title">Connect to your route.</string>
|
||||||
<string name="design_abrp_subtitle">ABRP hesabınla aracını buluştur.</string>
|
<string name="design_abrp_subtitle">Link your car with your ABRP account.</string>
|
||||||
<string name="design_service_title">Sen yola odaklan.</string>
|
<string name="design_service_title">You focus on the road.</string>
|
||||||
<string name="design_service_subtitle">Verilerin arka planda güncel kalsın.</string>
|
<string name="design_service_subtitle">Your data stays up to date in the background.</string>
|
||||||
<string name="design_wifi_title">Bağlantıda kal.</string>
|
<string name="design_wifi_title">Stay connected.</string>
|
||||||
<string name="design_wifi_subtitle">Yolculuğunun internet bağlantısı.</string>
|
<string name="design_wifi_subtitle">The internet connection for your journey.</string>
|
||||||
<string name="design_log_title">Her aktarım, burada.</string>
|
<string name="design_log_title">Every upload, right here.</string>
|
||||||
<string name="design_log_subtitle">Son gönderimlerin durumu ve ayrıntıları.</string>
|
<string name="design_log_subtitle">Status and details of recent uploads.</string>
|
||||||
<string name="design_battery">BATARYA</string>
|
<string name="design_battery">BATTERY</string>
|
||||||
<string name="design_energy">ENERJİ VE SICAKLIK</string>
|
<string name="design_energy">ENERGY AND TEMPERATURE</string>
|
||||||
<string name="design_tires">LASTİK BASINÇLARI</string>
|
<string name="design_tires">TIRE PRESSURES</string>
|
||||||
<string name="design_account">HESAP BAĞLANTISI</string>
|
<string name="design_account">ACCOUNT LINK</string>
|
||||||
<string name="design_private_title">Sana özel bağlantı.</string>
|
<string name="design_private_title">Your private connection.</string>
|
||||||
<string name="design_private_body">Token, aracını ABRP hesabına bağlar. Bilgilerin bu cihazda şifreli saklanır.</string>
|
<string name="design_private_body">The token links your car to your ABRP account. Your credentials are stored encrypted on this device.</string>
|
||||||
<string name="design_no_data">Okunamayan veriler — olarak gösterilir.</string>
|
<string name="design_no_data">Values that cannot be read are shown as —.</string>
|
||||||
<string name="design_service_controls">AKTARIM KONTROLÜ</string>
|
<string name="design_service_controls">UPLOAD CONTROL</string>
|
||||||
<string name="design_service_timing">GÜNCELLEME SIKLIĞI</string>
|
<string name="design_service_timing">UPDATE FREQUENCY</string>
|
||||||
<string name="design_car_desc">Lastik basınçlarının araç üzerindeki konumları</string>
|
<string name="design_car_desc">Tire pressure positions on the vehicle</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ final class UpdateHook {
|
|||||||
|
|
||||||
/** Answers immediately that this channel does not self-update. */
|
/** Answers immediately that this channel does not self-update. */
|
||||||
static void checkInBackground(Context context, Listener listener) {
|
static void checkInBackground(Context context, Listener listener) {
|
||||||
if (listener != null) listener.onResult("Bu sürümde otomatik güncelleme yok");
|
if (listener != null) listener.onResult("This build has no automatic updates");
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isSupported() { return false; }
|
static boolean isSupported() { return false; }
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ final class OtaUpdater {
|
|||||||
try {
|
try {
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(update.apkUrl))
|
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(update.apkUrl))
|
||||||
.setTitle("FatihsMG4 " + update.versionName)
|
.setTitle("FatihsMG4 " + update.versionName)
|
||||||
.setDescription("Güncelleme indiriliyor")
|
.setDescription("Downloading update")
|
||||||
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||||
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, publicName)
|
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, publicName)
|
||||||
.setAllowedOverMetered(true)
|
.setAllowedOverMetered(true)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ final class UpdateHook {
|
|||||||
if (update != null && update.hashUrl != null)
|
if (update != null && update.hashUrl != null)
|
||||||
new android.os.Handler(android.os.Looper.getMainLooper())
|
new android.os.Handler(android.os.Looper.getMainLooper())
|
||||||
.post(() -> android.widget.Toast.makeText(app,
|
.post(() -> android.widget.Toast.makeText(app,
|
||||||
"Güncelleme hazır: " + update.versionName,
|
"Update available: " + update.versionName,
|
||||||
android.widget.Toast.LENGTH_LONG).show());
|
android.widget.Toast.LENGTH_LONG).show());
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.w(TAG, "Startup update check failed", t);
|
Log.w(TAG, "Startup update check failed", t);
|
||||||
@@ -69,7 +69,7 @@ final class UpdateHook {
|
|||||||
Context app = context.getApplicationContext();
|
Context app = context.getApplicationContext();
|
||||||
android.os.Handler main = new android.os.Handler(android.os.Looper.getMainLooper());
|
android.os.Handler main = new android.os.Handler(android.os.Looper.getMainLooper());
|
||||||
if (!checking.compareAndSet(false, true)) {
|
if (!checking.compareAndSet(false, true)) {
|
||||||
if (listener != null) main.post(() -> listener.onResult("Güncelleme kontrolü zaten sürüyor"));
|
if (listener != null) main.post(() -> listener.onResult("Update check already in progress"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
@@ -78,7 +78,7 @@ final class UpdateHook {
|
|||||||
message = runCheck(app, listener, main);
|
message = runCheck(app, listener, main);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.w(TAG, "Update check threw", t);
|
Log.w(TAG, "Update check threw", t);
|
||||||
message = "Güncelleme kontrolü başarısız";
|
message = "Update check failed";
|
||||||
} finally {
|
} finally {
|
||||||
checking.set(false);
|
checking.set(false);
|
||||||
}
|
}
|
||||||
@@ -97,11 +97,11 @@ final class UpdateHook {
|
|||||||
current = app.getPackageManager()
|
current = app.getPackageManager()
|
||||||
.getPackageInfo(app.getPackageName(), 0).versionName;
|
.getPackageInfo(app.getPackageName(), 0).versionName;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return "Sürüm okunamadı";
|
return "Could not read version";
|
||||||
}
|
}
|
||||||
|
|
||||||
OtaUpdater.Update update = OtaUpdater.check(current);
|
OtaUpdater.Update update = OtaUpdater.check(current);
|
||||||
if (update == null) return "Güncel (" + current + ")";
|
if (update == null) return "Up to date (" + current + ")";
|
||||||
|
|
||||||
Log.i(TAG, "Update available: " + update.versionName);
|
Log.i(TAG, "Update available: " + update.versionName);
|
||||||
String expectedHash;
|
String expectedHash;
|
||||||
@@ -109,16 +109,16 @@ final class UpdateHook {
|
|||||||
expectedHash = OtaUpdater.fetchExpectedSha256(update);
|
expectedHash = OtaUpdater.fetchExpectedSha256(update);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(TAG, "OTA hash unavailable", e);
|
Log.w(TAG, "OTA hash unavailable", e);
|
||||||
return "Güncelleme reddedildi: SHA-256 doğrulaması yok";
|
return "Update refused: no SHA-256 verification";
|
||||||
}
|
}
|
||||||
File apk = OtaUpdater.download(app, update, expectedHash, percent -> {
|
File apk = OtaUpdater.download(app, update, expectedHash, percent -> {
|
||||||
if (listener != null) main.post(() -> listener.onProgress(percent));
|
if (listener != null) main.post(() -> listener.onProgress(percent));
|
||||||
});
|
});
|
||||||
if (apk == null) return "İndirme veya SHA-256 doğrulaması başarısız ("
|
if (apk == null) return "Download or SHA-256 verification failed ("
|
||||||
+ update.versionName + ")";
|
+ update.versionName + ")";
|
||||||
|
|
||||||
if (!OtaUpdater.openDownloads(app))
|
if (!OtaUpdater.openDownloads(app))
|
||||||
return "APK Downloads'a indirildi; dosya yöneticisi açılamadı";
|
return "APK downloaded to Downloads; could not open the file manager";
|
||||||
return update.versionName + ".apk Downloads'a indirildi — dosyaya dokunup kurun";
|
return update.versionName + ".apk downloaded to Downloads — tap the file to install";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user