라이브 기록 구간 정시 자동 이동
This commit is contained in:
+76
-56
@@ -461,6 +461,7 @@ let langCode = localStorage.getItem("currentLang") || deviceLang,
|
||||
lastAutoSwitchChecked,
|
||||
lastUpdateSwitchChecked,
|
||||
lastHash,
|
||||
lastLiveHistoryRangeKey,
|
||||
lastLat,
|
||||
lastLng,
|
||||
lastUpdateISOTime,
|
||||
@@ -475,6 +476,7 @@ let langCode = localStorage.getItem("currentLang") || deviceLang,
|
||||
const PLAYBACK_SPEEDS = [2, 5, 10, 20, 50, 100, 500];
|
||||
const PLAYBACK_MIN_VISIBLE_STEPS = 80;
|
||||
const PLAYBACK_TICK_MS = 160;
|
||||
const STAY_MIN_SECONDS = 10 * 60;
|
||||
|
||||
const FALLBACK_BACK_TARGET = 'https://chaegeon.com/';
|
||||
const BACK_HISTORY_KEY = 'chaegeon.backHistory.v1';
|
||||
@@ -489,6 +491,58 @@ function isStandalonePwa() {
|
||||
}
|
||||
let findmydeviceAuthenticated = !FINDMYDEVICE_AUTH_REQUIRED || isStandalonePwa();
|
||||
|
||||
function pad2(value) {
|
||||
return String(value).padStart(2, '0');
|
||||
}
|
||||
|
||||
function toLocalHourValue(date) {
|
||||
return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}T${pad2(date.getHours())}:00`;
|
||||
}
|
||||
|
||||
function toServerTimeValue(value) {
|
||||
return value
|
||||
? (value.includes('T') ? value.replace('T', ' ') : value) + (value.length === 16 ? ':00' : '')
|
||||
: null;
|
||||
}
|
||||
|
||||
function liveHistoryRangeValues(now = new Date()) {
|
||||
const start = new Date(now.getTime() - 24 * 3600 * 1000);
|
||||
start.setMinutes(0, 0, 0);
|
||||
|
||||
const end = new Date(now);
|
||||
end.setMinutes(0, 0, 0);
|
||||
if (now.getMinutes() > 0 || now.getSeconds() > 0 || now.getMilliseconds() > 0) {
|
||||
end.setHours(end.getHours() + 1);
|
||||
}
|
||||
|
||||
const startValue = toLocalHourValue(start);
|
||||
const endValue = toLocalHourValue(end);
|
||||
return {
|
||||
startValue,
|
||||
endValue,
|
||||
startTime: toServerTimeValue(startValue),
|
||||
endTime: toServerTimeValue(endValue),
|
||||
key: `${startValue}|${endValue}`,
|
||||
};
|
||||
}
|
||||
|
||||
function syncLiveHistoryRangeInputs(force = false) {
|
||||
if (_overrideRange) return false;
|
||||
const startEl = document.getElementById('rangeStart');
|
||||
const endEl = document.getElementById('rangeEnd');
|
||||
if (!startEl || !endEl) return false;
|
||||
if (!force && (document.activeElement === startEl || document.activeElement === endEl)) return false;
|
||||
|
||||
const range = liveHistoryRangeValues();
|
||||
const changed = lastLiveHistoryRangeKey !== range.key || startEl.value !== range.startValue || endEl.value !== range.endValue;
|
||||
if (force || changed) {
|
||||
startEl.value = range.startValue;
|
||||
endEl.value = range.endValue;
|
||||
lastLiveHistoryRangeKey = range.key;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
function renderAuthErrorPage() {
|
||||
document.body.innerHTML = `
|
||||
<main class="find-auth-page">
|
||||
@@ -882,26 +936,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const startEl = document.getElementById('rangeStart');
|
||||
const endEl = document.getElementById('rangeEnd');
|
||||
if (startEl && endEl) {
|
||||
const pad = n => String(n).padStart(2, '0');
|
||||
const toLocalHour = d => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:00`;
|
||||
|
||||
// 기준 시각(현재)
|
||||
const current = new Date();
|
||||
|
||||
// 시작: 24시간 전 → 정각 버림
|
||||
const start24 = new Date(current.getTime() - 24 * 3600 * 1000);
|
||||
start24.setMinutes(0, 0, 0);
|
||||
|
||||
// 종료: 현재 시각의 다음 정각 올림
|
||||
const endRoundUp = new Date(current);
|
||||
endRoundUp.setMinutes(0, 0, 0);
|
||||
if (current.getMinutes() > 0 || current.getSeconds() > 0 || current.getMilliseconds() > 0) {
|
||||
endRoundUp.setHours(endRoundUp.getHours() + 1);
|
||||
}
|
||||
|
||||
// 입력값 세팅
|
||||
startEl.value = toLocalHour(start24);
|
||||
endEl.value = toLocalHour(endRoundUp);
|
||||
syncLiveHistoryRangeInputs(true);
|
||||
}
|
||||
|
||||
// 3) 지도 히스토리 초기화 & 라이브 데이터 재요청 + 현재 위치로 이동
|
||||
@@ -920,35 +955,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const endEl = document.getElementById('rangeEnd');
|
||||
if (!startEl || !endEl) return;
|
||||
|
||||
const pad = n => String(n).padStart(2, '0');
|
||||
const toLocalHour = d => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:00`;
|
||||
const toServerTime = v =>
|
||||
v ? (v.includes('T') ? v.replace('T', ' ') : v) + (v.length === 16 ? ':00' : '') : null;
|
||||
|
||||
const now = new Date();
|
||||
|
||||
// 시작: 현재 시각에서 24시간 전, 정각 버림
|
||||
const start24 = new Date(now.getTime() - 24 * 3600 * 1000);
|
||||
start24.setMinutes(0, 0, 0);
|
||||
|
||||
// 종료: 현재 시각, 다음 정각 올림
|
||||
const endRoundUp = new Date(now);
|
||||
endRoundUp.setMinutes(0, 0, 0);
|
||||
if (now.getMinutes() > 0 || now.getSeconds() > 0 || now.getMilliseconds() > 0) {
|
||||
endRoundUp.setHours(endRoundUp.getHours() + 1);
|
||||
const qs = new URLSearchParams(window.location.search);
|
||||
const hasQS = qs.has('startTime') || qs.has('endTime');
|
||||
if (hasQS) {
|
||||
startEl.value = qs.get('startTime')
|
||||
? qs.get('startTime').replace(' ', 'T').slice(0, 16)
|
||||
: liveHistoryRangeValues().startValue;
|
||||
endEl.value = qs.get('endTime')
|
||||
? qs.get('endTime').replace(' ', 'T').slice(0, 16)
|
||||
: liveHistoryRangeValues().endValue;
|
||||
} else {
|
||||
syncLiveHistoryRangeInputs(true);
|
||||
}
|
||||
|
||||
const qs = new URLSearchParams(window.location.search);
|
||||
startEl.value = qs.get('startTime')
|
||||
? qs.get('startTime').replace(' ', 'T').slice(0, 16)
|
||||
: toLocalHour(start24);
|
||||
endEl.value = qs.get('endTime')
|
||||
? qs.get('endTime').replace(' ', 'T').slice(0, 16)
|
||||
: toLocalHour(endRoundUp);
|
||||
|
||||
const hasQS = qs.has('startTime') || qs.has('endTime');
|
||||
|
||||
const fire = debounce(async (userTriggered = false) => {
|
||||
if (!userTriggered && !hasQS) {
|
||||
syncLiveHistoryRangeInputs(false);
|
||||
}
|
||||
const start = startEl.value;
|
||||
const end = endEl.value;
|
||||
if (!start || !end) return;
|
||||
@@ -956,8 +979,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (start > end) endEl.value = start;
|
||||
|
||||
const range = {
|
||||
startTime: toServerTime(startEl.value),
|
||||
endTime: toServerTime(endEl.value)
|
||||
startTime: toServerTimeValue(startEl.value),
|
||||
endTime: toServerTimeValue(endEl.value)
|
||||
};
|
||||
|
||||
const shouldUseHistory = userTriggered || hasQS;
|
||||
@@ -1065,8 +1088,9 @@ setInterval(() => {
|
||||
// 히스토리 범위가 활성화된 경우: hash 체크 생략하고 같은 범위로 재요청(낭비 방지로 5초 권장)
|
||||
if (_overrideRange) return; // 간단히 폴링 정지 (원하면 5초 주기로 같은 범위 재요청하도록 변경 가능)
|
||||
|
||||
const rangeChanged = syncLiveHistoryRangeInputs(false);
|
||||
fetchDeviceData(false).then(({ hash }) => {
|
||||
if (!hash || hash === lastHash) return;
|
||||
if (!rangeChanged && (!hash || hash === lastHash)) return;
|
||||
lastHash = hash;
|
||||
fetchDeviceData(true).then(data => updateDOMWithData(data));
|
||||
});
|
||||
@@ -1676,7 +1700,6 @@ function buildStayPoints(points) {
|
||||
const stays = [];
|
||||
let start = 0;
|
||||
const radius = 80;
|
||||
const minSeconds = 10 * 60;
|
||||
|
||||
for (let i = 1; i <= points.length; i++) {
|
||||
const base = points[start];
|
||||
@@ -1686,7 +1709,7 @@ function buildStayPoints(points) {
|
||||
|
||||
const end = points[Math.max(start, i - 1)];
|
||||
const duration = (toTimestamp(end.time) - toTimestamp(base.time)) / 1000;
|
||||
if (duration >= minSeconds) {
|
||||
if (duration >= STAY_MIN_SECONDS) {
|
||||
const slice = points.slice(start, i);
|
||||
const lat = slice.reduce((sum, p) => sum + Number(p.lat), 0) / slice.length;
|
||||
const lng = slice.reduce((sum, p) => sum + Number(p.lng), 0) / slice.length;
|
||||
@@ -2517,14 +2540,11 @@ function syncUpdateBtn() {
|
||||
}
|
||||
|
||||
function readHistoryRangeInputs() {
|
||||
const toServerTime = value => value
|
||||
? (value.includes('T') ? value.replace('T', ' ') : value) + (value.length === 16 ? ':00' : '')
|
||||
: null;
|
||||
const start = document.getElementById('rangeStart')?.value || '';
|
||||
const end = document.getElementById('rangeEnd')?.value || '';
|
||||
return {
|
||||
startTime: toServerTime(start),
|
||||
endTime: toServerTime(end),
|
||||
startTime: toServerTimeValue(start),
|
||||
endTime: toServerTimeValue(end),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user