Dvesign improvemments
This commit is contained in:
+3595
-201
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -577,12 +577,12 @@
|
||||
color: var(--text);
|
||||
}
|
||||
h2 {
|
||||
font-size: 26px;
|
||||
font-size: 24px;
|
||||
font-weight: 800;
|
||||
}
|
||||
h3 {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
font-weight: 800;
|
||||
}
|
||||
.page-copy,
|
||||
.card-copy {
|
||||
@@ -617,11 +617,10 @@
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
.builder-card {
|
||||
background: var(--surface);
|
||||
background: #0f1116;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 18px;
|
||||
border-radius: 12px;
|
||||
padding: 18px;
|
||||
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
.hero-card {
|
||||
padding-bottom: 14px;
|
||||
@@ -671,9 +670,9 @@
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--border);
|
||||
background: #0b0f14;
|
||||
background: #12151b;
|
||||
color: var(--text);
|
||||
font-size: 13px;
|
||||
font-family: inherit;
|
||||
@@ -703,16 +702,16 @@
|
||||
.target-option,
|
||||
.preview-item {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 10px;
|
||||
background: #111419;
|
||||
padding: 12px 14px;
|
||||
}
|
||||
.result-card {
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 10px;
|
||||
background: #111419;
|
||||
padding: 12px 14px;
|
||||
transition: background 0.12s ease, border-color 0.12s ease;
|
||||
}
|
||||
@@ -762,8 +761,8 @@
|
||||
}
|
||||
.empty-note {
|
||||
padding: 14px;
|
||||
border-radius: 14px;
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 10px;
|
||||
background: #111419;
|
||||
border: 1px dashed var(--border);
|
||||
color: var(--text-muted);
|
||||
font-size: 13px;
|
||||
@@ -782,9 +781,9 @@
|
||||
}
|
||||
.status {
|
||||
padding: 10px 12px;
|
||||
border-radius: 14px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
background: var(--bg-secondary);
|
||||
background: #111419;
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text-muted);
|
||||
margin-top: 12px;
|
||||
@@ -801,7 +800,7 @@
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
padding: 9px 16px;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
font-family: inherit;
|
||||
@@ -809,13 +808,14 @@
|
||||
text-align: center;
|
||||
}
|
||||
.btn.ghost {
|
||||
color: #d9e7f8;
|
||||
color: var(--text);
|
||||
border-color: var(--border);
|
||||
background: var(--surface);
|
||||
background: #15181e;
|
||||
}
|
||||
.btn.accent {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
border-color: rgba(42, 215, 239, 0.35);
|
||||
color: #031014;
|
||||
}
|
||||
.btn:disabled {
|
||||
opacity: 0.45;
|
||||
@@ -827,9 +827,9 @@
|
||||
justify-content: center;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 10px;
|
||||
background: var(--surface-active);
|
||||
color: #a9d6ff;
|
||||
border-radius: 8px;
|
||||
background: rgba(40, 193, 220, 0.1);
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
|
||||
+35
-36
@@ -495,21 +495,18 @@
|
||||
|
||||
<style>
|
||||
.section-card {
|
||||
background: var(--surface);
|
||||
border-radius: 20px;
|
||||
background: #101318;
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--border);
|
||||
margin-bottom: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 18px 36px rgba(0, 0, 0, 0.18);
|
||||
transition: border-color 0.15s, transform 0.15s ease, box-shadow 0.15s ease;
|
||||
transition: border-color 0.15s ease, background 0.15s ease;
|
||||
}
|
||||
.section-card:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 22px 42px rgba(0, 0, 0, 0.22);
|
||||
background: #12161d;
|
||||
}
|
||||
.section-card.expanded {
|
||||
border-color: var(--border-strong);
|
||||
box-shadow: 0 24px 48px rgba(0, 0, 0, 0.26);
|
||||
}
|
||||
.section-header {
|
||||
all: unset;
|
||||
@@ -534,9 +531,9 @@
|
||||
cursor: pointer;
|
||||
font-size: 10px;
|
||||
line-height: 1;
|
||||
opacity: 0.6;
|
||||
opacity: 0.7;
|
||||
padding: 3px 4px;
|
||||
color: var(--text);
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.move-btn:disabled {
|
||||
opacity: 0.15;
|
||||
@@ -556,12 +553,12 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 12px;
|
||||
background: var(--bg-secondary);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 8px;
|
||||
background: rgba(40, 193, 220, 0.1);
|
||||
border: 1px solid var(--border);
|
||||
color: #a9d6ff;
|
||||
color: var(--accent);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.section-info {
|
||||
@@ -570,7 +567,7 @@
|
||||
}
|
||||
.section-name {
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
font-size: 14px;
|
||||
color: var(--text);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
@@ -588,10 +585,10 @@
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
color: var(--danger);
|
||||
font-size: 22px;
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
padding: 0 4px;
|
||||
opacity: 0.5;
|
||||
opacity: 0.55;
|
||||
}
|
||||
.remove-btn:hover {
|
||||
opacity: 1;
|
||||
@@ -604,8 +601,9 @@
|
||||
|
||||
/* Editor panel */
|
||||
.section-editor {
|
||||
padding: 8px 16px 18px;
|
||||
padding: 10px 16px 18px;
|
||||
border-top: 1px solid var(--border);
|
||||
background: #0d1015;
|
||||
}
|
||||
.field-grid {
|
||||
display: grid;
|
||||
@@ -629,10 +627,10 @@
|
||||
}
|
||||
.field-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
.hint-inline {
|
||||
font-size: 10px;
|
||||
@@ -644,9 +642,9 @@
|
||||
.field input[type='text'],
|
||||
.field select {
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--border);
|
||||
background: #0b0f14;
|
||||
background: #12151b;
|
||||
color: var(--text);
|
||||
font-size: 13px;
|
||||
font-family: inherit;
|
||||
@@ -668,10 +666,10 @@
|
||||
}
|
||||
.lookup-btn {
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
color: var(--text);
|
||||
background: var(--surface);
|
||||
background: #15181e;
|
||||
}
|
||||
.lookup-btn:disabled {
|
||||
opacity: 0.45;
|
||||
@@ -690,9 +688,9 @@
|
||||
.inline-status {
|
||||
margin-top: 8px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--surface);
|
||||
background: #12151b;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
@@ -714,6 +712,7 @@
|
||||
font-size: 12px;
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text-muted);
|
||||
background: #12151b;
|
||||
transition: all 0.12s;
|
||||
}
|
||||
.chip:hover {
|
||||
@@ -722,8 +721,8 @@
|
||||
}
|
||||
.chip.active {
|
||||
background: var(--accent);
|
||||
border-color: transparent;
|
||||
color: #fff;
|
||||
border-color: rgba(42, 215, 239, 0.3);
|
||||
color: #031014;
|
||||
}
|
||||
|
||||
.field-inline {
|
||||
@@ -740,9 +739,9 @@
|
||||
width: 100%;
|
||||
margin-top: 6px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--border);
|
||||
background: #0b0f14;
|
||||
background: #12151b;
|
||||
color: var(--text);
|
||||
font-size: 12px;
|
||||
font-family: monospace;
|
||||
@@ -762,7 +761,7 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
background: #0b0f14;
|
||||
background: #12151b;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 999px;
|
||||
padding: 4px 8px 4px 10px;
|
||||
@@ -784,7 +783,7 @@
|
||||
.badge {
|
||||
display: inline-block;
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
color: #031014;
|
||||
border-radius: 999px;
|
||||
padding: 2px 6px;
|
||||
font-size: 10px;
|
||||
@@ -803,8 +802,8 @@
|
||||
color: var(--text);
|
||||
margin-top: 6px;
|
||||
padding: 10px 12px;
|
||||
background: #0b0f14;
|
||||
border-radius: 12px;
|
||||
background: #12151b;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.text-muted {
|
||||
color: var(--text-muted);
|
||||
@@ -821,8 +820,8 @@
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 8px 10px;
|
||||
border-radius: 12px;
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 10px;
|
||||
background: #12151b;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.lookup-result:hover {
|
||||
|
||||
@@ -215,19 +215,19 @@
|
||||
|
||||
<style>
|
||||
.panel {
|
||||
padding: 0 4px;
|
||||
padding: 0;
|
||||
}
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
margin: 0 0 18px;
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
margin: 0 0 16px;
|
||||
color: var(--text);
|
||||
}
|
||||
h4 {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--text-muted);
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
@@ -235,9 +235,8 @@
|
||||
margin-bottom: 18px;
|
||||
padding: 16px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 18px;
|
||||
background: var(--surface);
|
||||
box-shadow: 0 16px 32px rgba(0, 0, 0, 0.16);
|
||||
border-radius: 12px;
|
||||
background: #111419;
|
||||
}
|
||||
section:last-of-type {
|
||||
margin-bottom: 12px;
|
||||
@@ -254,9 +253,9 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
input {
|
||||
background: #0b0f14;
|
||||
background: #12151b;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
padding: 10px 12px;
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
@@ -276,7 +275,7 @@
|
||||
}
|
||||
code {
|
||||
font-size: 11px;
|
||||
background: #0b0f14;
|
||||
background: #0c0e12;
|
||||
padding: 2px 5px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
@@ -289,24 +288,25 @@
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
padding: 9px 14px;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
font-family: inherit;
|
||||
transition: all 0.12s;
|
||||
}
|
||||
.btn.ghost {
|
||||
color: #d9e7f8;
|
||||
color: var(--text);
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-secondary);
|
||||
background: #15181e;
|
||||
}
|
||||
.btn.ghost:hover:not(:disabled) {
|
||||
background: var(--surface-hover);
|
||||
color: var(--text);
|
||||
border-color: var(--border-strong);
|
||||
}
|
||||
.btn.accent {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
color: #031014;
|
||||
border: 1px solid rgba(42, 215, 239, 0.35);
|
||||
}
|
||||
.btn.accent:hover:not(:disabled) {
|
||||
opacity: 0.9;
|
||||
@@ -318,18 +318,18 @@
|
||||
.status {
|
||||
margin-top: 8px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 14px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
background: var(--surface);
|
||||
background: #111419;
|
||||
color: var(--text-muted);
|
||||
border-left: 3px solid var(--border);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.status.ok {
|
||||
border-left-color: #22c55e;
|
||||
border-color: rgba(34, 197, 94, 0.3);
|
||||
color: #86efac;
|
||||
}
|
||||
.status.error {
|
||||
border-left-color: var(--danger);
|
||||
border-color: rgba(239, 68, 68, 0.3);
|
||||
color: #fca5a5;
|
||||
}
|
||||
</style>
|
||||
|
||||
+12
-9
@@ -54,7 +54,7 @@
|
||||
.overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.72);
|
||||
background: rgba(0, 0, 0, 0.82);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -62,14 +62,15 @@
|
||||
padding: 20px;
|
||||
}
|
||||
.modal {
|
||||
background: var(--surface-strong);
|
||||
background: #0f1116;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
width: 100%;
|
||||
max-width: 720px;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.42);
|
||||
}
|
||||
.modal-header {
|
||||
display: flex;
|
||||
@@ -103,9 +104,9 @@
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
margin: 0;
|
||||
background: var(--surface);
|
||||
background: #12151b;
|
||||
padding: 14px;
|
||||
border-radius: 8px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.modal-actions {
|
||||
@@ -119,7 +120,7 @@
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
padding: 8px 18px;
|
||||
border-radius: 8px;
|
||||
border-radius: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
font-family: inherit;
|
||||
@@ -127,15 +128,17 @@
|
||||
.action-btn.secondary {
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text);
|
||||
background: #15181e;
|
||||
}
|
||||
.action-btn.secondary:hover {
|
||||
background: var(--surface);
|
||||
background: var(--surface-hover);
|
||||
}
|
||||
.action-btn.primary {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
border: 1px solid rgba(42, 215, 239, 0.35);
|
||||
color: #031014;
|
||||
}
|
||||
.action-btn.primary:hover {
|
||||
opacity: 0.9;
|
||||
background: #35d2ea;
|
||||
}
|
||||
</style>
|
||||
|
||||
+19
-16
@@ -158,8 +158,8 @@
|
||||
padding: 0;
|
||||
}
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
margin: 0 0 18px;
|
||||
color: var(--text);
|
||||
}
|
||||
@@ -168,10 +168,10 @@
|
||||
}
|
||||
.step-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
letter-spacing: 0.08em;
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
@@ -184,9 +184,9 @@
|
||||
.select-input {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--border);
|
||||
background: #0b0f14;
|
||||
background: #12151b;
|
||||
color: var(--text);
|
||||
font-size: 13px;
|
||||
font-family: inherit;
|
||||
@@ -202,9 +202,9 @@
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 16px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--surface);
|
||||
background: #111419;
|
||||
cursor: pointer;
|
||||
transition: all 0.12s;
|
||||
}
|
||||
@@ -237,7 +237,8 @@
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 10px;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid transparent;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
@@ -246,6 +247,7 @@
|
||||
}
|
||||
.section-pick.selected {
|
||||
background: var(--surface-active);
|
||||
border: 1px solid var(--border-strong);
|
||||
}
|
||||
.pick-name {
|
||||
flex: 1;
|
||||
@@ -266,7 +268,8 @@
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 10px;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid transparent;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
@@ -275,6 +278,7 @@
|
||||
}
|
||||
.target-option.selected {
|
||||
background: var(--surface-active);
|
||||
border: 1px solid var(--border-strong);
|
||||
}
|
||||
.target-name {
|
||||
flex: 1;
|
||||
@@ -302,19 +306,18 @@
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 12px;
|
||||
border-radius: 16px;
|
||||
border-radius: 10px;
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
border: 1px solid rgba(42, 215, 239, 0.35);
|
||||
color: #031014;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
font-family: inherit;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.2);
|
||||
transition: opacity 0.12s, transform 0.12s ease;
|
||||
transition: opacity 0.12s, background 0.12s ease;
|
||||
}
|
||||
.sync-btn:hover:not(:disabled) {
|
||||
opacity: 0.95;
|
||||
transform: translateY(-1px);
|
||||
background: #35d2ea;
|
||||
}
|
||||
.sync-btn:disabled {
|
||||
opacity: 0.4;
|
||||
|
||||
+83
-2
@@ -90,7 +90,7 @@ export function createEmptySection(userId) {
|
||||
SectionType: 'items',
|
||||
ImageType: 'Thumb',
|
||||
CollectionType: 'movies',
|
||||
SortBy: 'DateLastContentAdded,SortName',
|
||||
SortBy: 'Random',
|
||||
SortOrder: 'Descending',
|
||||
Monitor: [],
|
||||
ItemTypes: ['Movie'],
|
||||
@@ -142,7 +142,7 @@ export function createBoxSetSection(userId, collectionName, collectionId) {
|
||||
SectionType: 'boxset',
|
||||
ImageType: 'Thumb',
|
||||
ItemTypes: [],
|
||||
SortBy: 'default',
|
||||
SortBy: 'Random',
|
||||
SortOrder: 'Descending',
|
||||
Monitor: [],
|
||||
ExcludedFolders: [],
|
||||
@@ -186,6 +186,40 @@ export function isWatchlistSection(section) {
|
||||
return !!section.Query?.IsFavorite || name.includes('watchlist') || name.includes('watch list');
|
||||
}
|
||||
|
||||
export function isUpNextSection(section) {
|
||||
if (!section) return false;
|
||||
if (section.SectionType === 'resume') return true;
|
||||
|
||||
const name = `${section.CustomName || ''} ${section.Name || ''}`.trim().toLowerCase();
|
||||
return name === 'up next' || name === 'next up' || name === 'resume / up next';
|
||||
}
|
||||
|
||||
export function isNewToEmbySection(section) {
|
||||
if (!section) return false;
|
||||
const name = `${section.CustomName || ''} ${section.Name || ''}`.toLowerCase();
|
||||
return name.includes('new to emby');
|
||||
}
|
||||
|
||||
export function isRecentlyWatchedSection(section) {
|
||||
if (!section) return false;
|
||||
const name = `${section.CustomName || ''} ${section.Name || ''}`.toLowerCase();
|
||||
return section.Query?.IsPlayed === true || name.includes('recently watched');
|
||||
}
|
||||
|
||||
export function isFixedOrderSection(section) {
|
||||
if (!section) return false;
|
||||
return (
|
||||
isUpNextSection(section) ||
|
||||
isWatchlistSection(section) ||
|
||||
isNewToEmbySection(section) ||
|
||||
isRecentlyWatchedSection(section) ||
|
||||
section.SectionType === 'latestepisodereleases' ||
|
||||
section.SectionType === 'latestmoviereleases' ||
|
||||
section.SectionType === 'latestmediablock' ||
|
||||
section.SectionType === 'userviews'
|
||||
);
|
||||
}
|
||||
|
||||
function renameWatchlistLabel(label, targetName) {
|
||||
if (!label || !targetName) return label;
|
||||
if (/^\s*watch\s+list\s*$/i.test(label)) return 'Watch List';
|
||||
@@ -259,6 +293,53 @@ export function getWatchlistLabelsForTarget(sourceSection, targetUser) {
|
||||
};
|
||||
}
|
||||
|
||||
export function applySectionStandards(sourceSection, targetUser) {
|
||||
const section = JSON.parse(JSON.stringify(sourceSection || {}));
|
||||
|
||||
if (isUpNextSection(section)) {
|
||||
section.Name = 'Up Next';
|
||||
section.CustomName = 'Up Next';
|
||||
return section;
|
||||
}
|
||||
|
||||
if (isWatchlistSection(section)) {
|
||||
const labels = getWatchlistLabelsForTarget(section, targetUser);
|
||||
if (labels.Name) section.Name = labels.Name;
|
||||
if (labels.CustomName) section.CustomName = labels.CustomName;
|
||||
return section;
|
||||
}
|
||||
|
||||
if (isNewToEmbySection(section)) {
|
||||
section.Name = 'New to Emby';
|
||||
section.CustomName = 'New to Emby';
|
||||
section.SortBy = 'DateLastContentAdded,SortName';
|
||||
section.SortOrder = 'Descending';
|
||||
return section;
|
||||
}
|
||||
|
||||
if (isRecentlyWatchedSection(section)) {
|
||||
const targetName = getPreferredUserName(targetUser);
|
||||
const label = `Recently Watched${targetName ? ` - ${targetName}` : ''}`;
|
||||
section.Name = label;
|
||||
section.CustomName = label;
|
||||
section.SortBy = 'DatePlayed';
|
||||
section.SortOrder = 'Descending';
|
||||
return section;
|
||||
}
|
||||
|
||||
if (!isFixedOrderSection(section) && ['items', 'collections', 'boxset'].includes(section.SectionType)) {
|
||||
section.SortBy = 'Random';
|
||||
section.SortOrder = 'Descending';
|
||||
}
|
||||
|
||||
if (section.SectionType === 'userviews') {
|
||||
section.Name = 'Libraries';
|
||||
section.CustomName = 'Libraries';
|
||||
}
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build SQL UPDATE statements from modified user data.
|
||||
* Each user's entire homescreensettings JSON is replaced.
|
||||
|
||||
+966
-647
File diff suppressed because it is too large
Load Diff
+104
-1
@@ -2,7 +2,12 @@ import assert from 'node:assert/strict';
|
||||
import { mkdtempSync, rmSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { tmpdir } from 'os';
|
||||
import { createBoxSetSection, createRecentlyWatchedSection, getWatchlistLabelsForTarget } from '../src/lib/constants.js';
|
||||
import {
|
||||
applySectionStandards,
|
||||
createBoxSetSection,
|
||||
createRecentlyWatchedSection,
|
||||
getWatchlistLabelsForTarget
|
||||
} from '../src/lib/constants.js';
|
||||
import { normalizeLookupItem, rankRecommendationResults } from '../src/lib/collection-tools.js';
|
||||
import * as embyUserCache from '../src/lib/server/emby-user-cache.js';
|
||||
|
||||
@@ -152,6 +157,104 @@ test('box set section template links a created collection', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('section standards normalize up next label', () => {
|
||||
const normalized = applySectionStandards(
|
||||
{
|
||||
Name: 'Resume / Up Next',
|
||||
CustomName: 'Resume / Up Next',
|
||||
SectionType: 'resume'
|
||||
},
|
||||
{
|
||||
embyName: 'Bob',
|
||||
sections: []
|
||||
}
|
||||
);
|
||||
|
||||
assert.equal(normalized.Name, 'Up Next');
|
||||
assert.equal(normalized.CustomName, 'Up Next');
|
||||
});
|
||||
|
||||
test('section standards normalize watchlist label for target user', () => {
|
||||
const normalized = applySectionStandards(
|
||||
{
|
||||
Name: "Matt's Watchlist",
|
||||
CustomName: "Matt's Watchlist",
|
||||
SectionType: 'items',
|
||||
Query: { IsFavorite: true }
|
||||
},
|
||||
{
|
||||
embyName: 'Bob',
|
||||
sections: []
|
||||
}
|
||||
);
|
||||
|
||||
assert.equal(normalized.Name, "Bob's Watchlist");
|
||||
assert.equal(normalized.CustomName, "Bob's Watchlist");
|
||||
});
|
||||
|
||||
test('section standards keep new to emby fixed to date added descending', () => {
|
||||
const normalized = applySectionStandards(
|
||||
{
|
||||
Name: 'New To Emby',
|
||||
CustomName: 'New To Emby',
|
||||
SectionType: 'items',
|
||||
SortBy: 'ProductionYear,PremiereDate,SortName',
|
||||
SortOrder: 'Ascending'
|
||||
},
|
||||
{
|
||||
embyName: 'Bob',
|
||||
sections: []
|
||||
}
|
||||
);
|
||||
|
||||
assert.equal(normalized.Name, 'New to Emby');
|
||||
assert.equal(normalized.CustomName, 'New to Emby');
|
||||
assert.equal(normalized.SortBy, 'DateLastContentAdded,SortName');
|
||||
assert.equal(normalized.SortOrder, 'Descending');
|
||||
});
|
||||
|
||||
test('section standards randomize regular curated sections', () => {
|
||||
const normalized = applySectionStandards(
|
||||
{
|
||||
Name: 'Crime / Drama Shows',
|
||||
CustomName: 'Crime / Drama Shows',
|
||||
SectionType: 'items',
|
||||
SortBy: 'ProductionYear,PremiereDate,SortName',
|
||||
SortOrder: 'Ascending',
|
||||
Query: { GenreIds: ['4910', '62'] }
|
||||
},
|
||||
{
|
||||
embyName: 'Bob',
|
||||
sections: []
|
||||
}
|
||||
);
|
||||
|
||||
assert.equal(normalized.SortBy, 'Random');
|
||||
assert.equal(normalized.SortOrder, 'Descending');
|
||||
});
|
||||
|
||||
test('section standards preserve recently watched ordering semantics', () => {
|
||||
const normalized = applySectionStandards(
|
||||
{
|
||||
Name: 'Recently Watched - Matt',
|
||||
CustomName: 'Recently Watched - Matt',
|
||||
SectionType: 'items',
|
||||
SortBy: 'Random',
|
||||
SortOrder: 'Ascending',
|
||||
Query: { IsPlayed: true }
|
||||
},
|
||||
{
|
||||
embyName: 'Bob',
|
||||
sections: []
|
||||
}
|
||||
);
|
||||
|
||||
assert.equal(normalized.Name, 'Recently Watched - Bob');
|
||||
assert.equal(normalized.CustomName, 'Recently Watched - Bob');
|
||||
assert.equal(normalized.SortBy, 'DatePlayed');
|
||||
assert.equal(normalized.SortOrder, 'Descending');
|
||||
});
|
||||
|
||||
test('normalizeLookupItem preserves already-normalized recommendation items', () => {
|
||||
const normalized = normalizeLookupItem({
|
||||
id: 'pick-1',
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user