Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions selfdrive/carrot/web/css/pages/settings/device.css
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,7 @@
}

.page--setting #settingScreenItems .setting-popular-detail-block .setting-popular-detail__row {
grid-template-columns: 42px minmax(0, 1fr) 48px;
grid-template-columns: 18px minmax(0, 1fr) 48px;
min-height: 48px;
padding: 8px 11px;
gap: 10px;
Expand All @@ -1072,24 +1072,28 @@
border-bottom: 1px solid color-mix(in srgb, var(--md-outline-var) 16%, transparent);
}

.setting-popular-detail__rank,
.setting-popular-detail__count {
color: var(--md-on-surface-var);
font-size: var(--fs-label-sm);
font-weight: 850;
}

.page--setting #settingScreenItems .setting-popular-detail-block .setting-popular-detail__rank {
.setting-popular-detail__marker {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 28px;
width: 18px;
height: 18px;
}

.setting-popular-detail__marker::before {
content: "";
display: block;
width: 6px;
height: 6px;
border-radius: 999px;
background: color-mix(in srgb, var(--md-primary) 12%, var(--md-surface-cont-h));
color: color-mix(in srgb, var(--md-on-surface-var) 78%, transparent);
font-size: 10px;
font-weight: 900;
background: color-mix(in srgb, var(--md-primary) 46%, var(--md-on-surface-var));
opacity: 0.72;
}

.setting-popular-detail__main {
Expand Down
10 changes: 5 additions & 5 deletions selfdrive/carrot/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
<link rel="stylesheet" href="/css/pages/terminal.css?v=2606-01" />
<link rel="stylesheet" href="/css/pages/settings/base.css?v=2606-21" />
<link rel="stylesheet" href="/css/pages/settings/panels.css?v=2606-12" />
<link rel="stylesheet" href="/css/pages/settings/device.css?v=2606-41" />
<link rel="stylesheet" href="/css/pages/settings/device.css?v=2606-42" />
<link rel="stylesheet" href="/css/pages/tools/base.css?v=2605-43" />
<link rel="stylesheet" href="/css/pages/tools/qr.css?v=2605-40" />
<link rel="stylesheet" href="/css/pages/tools/main.css?v=2605-53" />
Expand Down Expand Up @@ -705,9 +705,9 @@ <h2 id="carrotTitle" class="page-title">Home</h2>
<script src="/js/vendor/qrcode-generator.js?v=1.4.4"></script>
<script src="/js/vendor/jsQR.js?v=1.4.0"></script>
<script src="/js/translations/registry.js?v=2605-09"></script>
<script src="/js/translations/ko.js?v=2606-09"></script>
<script src="/js/translations/en.js?v=2606-09"></script>
<script src="/js/translations/zh.js?v=2606-09"></script>
<script src="/js/translations/ko.js?v=2606-11"></script>
<script src="/js/translations/en.js?v=2606-11"></script>
<script src="/js/translations/zh.js?v=2606-11"></script>
<script src="/js/realtime/hud_card.js?v=2604-05"></script>
<script src="/js/shared/constants.js?v=2604-72"></script>
<script src="/js/shared/dom.js?v=2604-72"></script>
Expand All @@ -722,7 +722,7 @@ <h2 id="carrotTitle" class="page-title">Home</h2>
<script src="/js/shared/ui/effects.js?v=2604-72"></script>
<script src="/js/shared/ui/navigation.js?v=2606-19"></script>
<script src="/js/pages/car.js?v=2604-75"></script>
<script src="/js/pages/setting.js?v=2606-37"></script>
<script src="/js/pages/setting.js?v=2606-39"></script>
<script src="/js/pages/setting_device_config.js?v=2605-05"></script>
<script src="/js/pages/setting_device_render.js?v=2605-04"></script>
<script src="/js/pages/setting_device_network.js?v=2605-01"></script>
Expand Down
96 changes: 79 additions & 17 deletions selfdrive/carrot/web/js/pages/setting.js
Original file line number Diff line number Diff line change
Expand Up @@ -972,16 +972,39 @@ function isSettingPopularValueInRange(p, raw) {
return value >= min && value <= max;
}

function compareSettingPopularValueItems(p, a, b, aIndex = 0, bIndex = 0) {
const aCount = Number(a?.count ?? 0);
const bCount = Number(b?.count ?? 0);
const safeACount = Number.isFinite(aCount) ? aCount : 0;
const safeBCount = Number.isFinite(bCount) ? bCount : 0;
if (safeACount !== safeBCount) return safeBCount - safeACount;

const aValue = normalizeSettingPopularNumericValue(p, a?.value);
const bValue = normalizeSettingPopularNumericValue(p, b?.value);
if (aValue !== null && bValue !== null && aValue !== bValue) return aValue - bValue;
if (aValue !== null && bValue === null) return -1;
if (aValue === null && bValue !== null) return 1;

const aText = formatSettingPopularValue(p, a?.value);
const bText = formatSettingPopularValue(p, b?.value);
const textOrder = aText.localeCompare(bText, LANG === "ko" ? "ko-KR" : undefined, { numeric: true, sensitivity: "base" });
if (textOrder !== 0) return textOrder;

return aIndex - bIndex;
}

function getSettingPopularDisplayEntry(p, entry) {
if (!entry || typeof entry !== "object") return null;
const sample = Number(entry?.sample ?? entry?.sample_count ?? 0);
if (!Number.isFinite(sample) || sample < 1) return null;
if (!isSettingPopularValueInRange(p, entry?.value)) return null;
const topValues = Array.isArray(entry?.top_values)
? entry.top_values.filter((item) => {
? entry.top_values.map((item, index) => ({ item, index })).filter(({ item }) => {
const count = Number(item?.count ?? 0);
return Number.isFinite(count) && count > 0 && isSettingPopularValueInRange(p, item?.value);
}).slice(0, 10)
}).sort((a, b) => compareSettingPopularValueItems(p, a.item, b.item, a.index, b.index))
.slice(0, 10)
.map(({ item }) => item)
: [];
return { ...entry, top_values: topValues };
}
Expand All @@ -990,25 +1013,65 @@ function getSettingPopularCarKeyLabel() {
return String(settingPopularValuesState.carKey || "").trim() || getUIText("setting_popular_value_my_model", "내 차종");
}

function getSettingPopularPrimaryCount(entry) {
const values = Array.isArray(entry?.top_values) ? entry.top_values : [];
const count = Number(values[0]?.count ?? entry?.top_count ?? entry?.count ?? 0);
return Number.isFinite(count) ? count : 0;
}

function getSettingPopularSummaryValues(entry) {
const values = Array.isArray(entry?.top_values) ? entry.top_values : [];
if (!values.length) return [];

const topCount = getSettingPopularPrimaryCount(entry);
if (topCount < 2) return [];

const tiedValues = values.filter((item) => {
const count = Number(item?.count ?? 0);
return Number.isFinite(count) && count === topCount;
});

return tiedValues.length <= 2 ? tiedValues : [];
}

function hasSettingPopularClearTop(entry) {
return getSettingPopularSummaryValues(entry).length > 0;
}

function renderSettingPopularChipText(p, entry) {
const sample = Number(entry?.sample ?? entry?.sample_count ?? 0);
const value = formatSettingPopularValue(p, entry?.value);
if (!sample || !value) return "";
return getUIText("setting_popular_value_chip", "{label} ({sample}대) {value}", {
label: getUIText("setting_popular_value_chip_label", "내 차종 인기값"),
const summaryValues = getSettingPopularSummaryValues(entry);
if (!summaryValues.length) return "";
const sample = getSettingPopularPrimaryCount(entry);
const values = summaryValues.map((item) => formatSettingPopularValue(p, item?.value)).filter(Boolean);
if (!sample || !values.length) return "";
const label = getUIText("setting_popular_value_chip_label", "내 차종 인기값");
if (values.length === 1) {
return getUIText("setting_popular_value_chip", "{label} ({sample}대) {value}", {
label,
sample,
value: values[0],
});
}
return getUIText("setting_popular_value_chip_tied", "{label} (각 {sample}대) {values}", {
label,
sample,
value: `"${value}"`,
values: values.join(" · "),
});
}

function renderSettingPopularChipHtml(p, entry) {
const sample = Number(entry?.sample ?? entry?.sample_count ?? 0);
const value = formatSettingPopularValue(p, entry?.value);
if (!sample || !value) return "";
const summaryValues = getSettingPopularSummaryValues(entry);
if (!summaryValues.length) return "";
const sample = getSettingPopularPrimaryCount(entry);
const values = summaryValues.map((item) => formatSettingPopularValue(p, item?.value)).filter(Boolean);
if (!sample || !values.length) return "";
const sampleText = values.length === 1
? getUIText("setting_popular_value_chip_sample", "{sample}대", { sample })
: getUIText("setting_popular_value_chip_each_sample", "각 {sample}대", { sample });
return `
<span class="setting-popular-value-chip__car">${escapeHtml(getUIText("setting_popular_value_chip_label", "내 차종 인기값"))}</span>
<span class="setting-popular-value-chip__label">(</span><span class="setting-popular-value-chip__accent">${escapeHtml(getUIText("setting_popular_value_chip_sample", "{sample}대", { sample }))}</span><span class="setting-popular-value-chip__label">)</span>
<span class="setting-popular-value-chip__accent">${escapeHtml(`"${value}"`)}</span>
<span class="setting-popular-value-chip__label">(</span><span class="setting-popular-value-chip__accent">${escapeHtml(sampleText)}</span><span class="setting-popular-value-chip__label">)</span>
<span class="setting-popular-value-chip__accent">${escapeHtml(values.join(" · "))}</span>
`;
}

Expand Down Expand Up @@ -1040,14 +1103,13 @@ function renderSettingPopularDetailHtml(p, entry) {
const counts = values.map((item) => Number(item?.count ?? 0)).filter((count) => Number.isFinite(count) && count > 0);
const maxCount = Math.max(1, ...counts);

const rows = values.map((item, index) => {
const rank = Number(item?.rank) || index + 1;
const rows = values.map((item) => {
const value = formatSettingPopularValue(p, item?.value);
const count = Number(item?.count ?? 0);
const width = Math.max(4, Math.min(100, Math.round((Math.max(0, count) / maxCount) * 100)));
return `
<button type="button" class="setting-popular-detail__row" style="--setting-popular-width:${width}%" data-setting-popular-value="${escapeHtml(item?.value ?? "")}">
<span class="setting-popular-detail__rank">${escapeHtml(`${rank}위`)}</span>
<span class="setting-popular-detail__marker" aria-hidden="true"></span>
<span class="setting-popular-detail__main">
<span class="setting-popular-detail__value">${escapeHtml(value)}</span>
${values.length > 1 ? `<span class="setting-popular-detail__bar" aria-hidden="true"></span>` : ""}
Expand All @@ -1066,7 +1128,7 @@ function renderSettingPopularDetailHtml(p, entry) {
<div class="setting-popular-detail${values.length <= 1 ? " setting-popular-detail--single" : ""}">
<div class="setting-popular-detail__head">
<span class="setting-popular-detail__name">${escapeHtml(getSettingPopularDetailTitle())}</span>
<span class="setting-popular-detail__range">${escapeHtml(getUIText("setting_popular_value_top10", "1~10위"))}</span>
<span class="setting-popular-detail__range">${escapeHtml(getUIText("setting_popular_value_common_values", "많이 쓰는 값"))}</span>
</div>
<div class="setting-popular-detail__rows">${rows}</div>
${updatedHtml}
Expand Down
3 changes: 3 additions & 0 deletions selfdrive/carrot/web/js/translations/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,13 +351,16 @@ window.CarrotTranslations.register("en", {
setting_reset_default_done: "Restored to default",
setting_popular_value_my_model: "My model",
setting_popular_value_chip: "{label} ({sample} vehicles) {value}",
setting_popular_value_chip_tied: "{label} ({sample} each) {values}",
setting_popular_value_chip_label: "popular value for my model",
setting_popular_value_chip_sample: "{sample} vehicles",
setting_popular_value_chip_each_sample: "{sample} each",
setting_popular_value_chip_mid: "use",
setting_popular_value_chip_suffix: "",
setting_popular_value_title: "Popular values for my model",
setting_popular_value_car_title: "{car} popular values",
setting_popular_value_top10: "Top 1-10",
setting_popular_value_common_values: "Common values",
setting_popular_value_empty: "No setting values to show.",
setting_popular_value_apply_title: "Apply setting value",
setting_popular_value_apply_confirm: "Apply this setting value ({value})?",
Expand Down
3 changes: 3 additions & 0 deletions selfdrive/carrot/web/js/translations/ko.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,13 +349,16 @@ window.CarrotTranslations.register("ko", {
setting_reset_default_done: "기본값으로 되돌렸습니다",
setting_popular_value_my_model: "내 차종",
setting_popular_value_chip: "{label} ({sample}대) {value}",
setting_popular_value_chip_tied: "{label} (각 {sample}대) {values}",
setting_popular_value_chip_label: "내 차종 인기값",
setting_popular_value_chip_sample: "{sample}대",
setting_popular_value_chip_each_sample: "각 {sample}대",
setting_popular_value_chip_mid: "가",
setting_popular_value_chip_suffix: "사용",
setting_popular_value_title: "내 차종 인기값",
setting_popular_value_car_title: "{car} 인기값",
setting_popular_value_top10: "1~10위",
setting_popular_value_common_values: "많이 쓰는 값",
setting_popular_value_empty: "표시할 설정값이 없습니다.",
setting_popular_value_apply_title: "설정값 적용",
setting_popular_value_apply_confirm: "{value} 설정을 적용하시겠습니까?",
Expand Down
3 changes: 3 additions & 0 deletions selfdrive/carrot/web/js/translations/zh.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,13 +349,16 @@ window.CarrotTranslations.register("zh", {
setting_reset_default_done: "已恢复为默认值",
setting_popular_value_my_model: "本车型",
setting_popular_value_chip: "{label}({sample}台){value}",
setting_popular_value_chip_tied: "{label}(各{sample}台){values}",
setting_popular_value_chip_label: "本车型热门值",
setting_popular_value_chip_sample: "{sample}台",
setting_popular_value_chip_each_sample: "各{sample}台",
setting_popular_value_chip_mid: "使用",
setting_popular_value_chip_suffix: "",
setting_popular_value_title: "本车型热门值",
setting_popular_value_car_title: "{car} 热门值",
setting_popular_value_top10: "1~10名",
setting_popular_value_common_values: "常用值",
setting_popular_value_empty: "没有可显示的设置值。",
setting_popular_value_apply_title: "应用设置值",
setting_popular_value_apply_confirm: "应用此设置值({value})?",
Expand Down
Loading