@mp-consulting/homebridge-philips-ambilight-tv 1.5.13 → 1.5.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -739,26 +739,57 @@
|
|
|
739
739
|
// EDIT SOURCES SCREEN
|
|
740
740
|
// ============================================================================
|
|
741
741
|
|
|
742
|
+
// Session cache of the raw source list fetched from each TV, keyed by a stable
|
|
743
|
+
// TV id. Reopening the sources screen renders from this cache instead of
|
|
744
|
+
// issuing another /get-sources request. That sidesteps a Homebridge Config UI
|
|
745
|
+
// X bug (#14) where the response to a *second* request is dropped — it tries
|
|
746
|
+
// to postMessage to a stale/detached plugin iframe (contentWindow === null)
|
|
747
|
+
// and throws — leaving the screen stuck on "Fetching sources". Use "Refresh
|
|
748
|
+
// from TV" to deliberately re-fetch.
|
|
749
|
+
const sourcesCache = new Map();
|
|
750
|
+
const sourcesCacheKey = (tv) => tv.mac || tv.ip;
|
|
751
|
+
|
|
752
|
+
/** Merge freshly-fetched (or cached) raw sources with the TV's saved config
|
|
753
|
+
* and render the two-column list. */
|
|
754
|
+
const showSources = (tv, rawSources) => {
|
|
755
|
+
const withCustom = injectCustomApps(rawSources, tv.customApps);
|
|
756
|
+
const existingConfig = tv.sources || [];
|
|
757
|
+
state.sources = mergeSourcesWithConfig(withCustom, existingConfig);
|
|
758
|
+
renderSourcesList();
|
|
759
|
+
$('sourcesLoadingSpinner').style.display = 'none';
|
|
760
|
+
$('sourcesErrorContainer').style.display = 'none';
|
|
761
|
+
$('sourcesListContainer').style.display = 'block';
|
|
762
|
+
};
|
|
763
|
+
|
|
742
764
|
const openEditSourcesScreen = async (index) => {
|
|
743
765
|
state.editingSourcesTvIndex = index;
|
|
744
766
|
const tv = state.configuredTvs[index];
|
|
745
767
|
|
|
746
768
|
$('editSourcesTvName').textContent = tv.name;
|
|
747
|
-
$('sourcesLoadingSpinner').style.display = 'block';
|
|
748
769
|
$('sourcesListContainer').style.display = 'none';
|
|
749
770
|
$('sourcesErrorContainer').style.display = 'none';
|
|
750
771
|
|
|
751
772
|
showScreen('editSourcesScreen');
|
|
752
773
|
|
|
774
|
+
// Render from the session cache when we already fetched this TV's sources,
|
|
775
|
+
// avoiding a second request that Config UI X may fail to deliver (#14).
|
|
776
|
+
const cached = sourcesCache.get(sourcesCacheKey(tv));
|
|
777
|
+
if (cached) {
|
|
778
|
+
$('sourcesLoadingSpinner').style.display = 'none';
|
|
779
|
+
showSources(tv, cached);
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
$('sourcesLoadingSpinner').style.display = 'block';
|
|
753
784
|
await loadSources(tv);
|
|
754
785
|
};
|
|
755
786
|
|
|
756
787
|
let sourcesLoading = false;
|
|
757
788
|
|
|
758
789
|
const loadSources = async (tv) => {
|
|
759
|
-
// Guard against overlapping fetches: a hung request keeps its
|
|
760
|
-
// pending for the full 20s, and firing more only stacks dead
|
|
761
|
-
// behind it. Ignore re-triggers until the current one settles.
|
|
790
|
+
// Guard against overlapping fetches: a hung request (see #14) keeps its
|
|
791
|
+
// promise pending for the full 20s, and firing more only stacks dead
|
|
792
|
+
// requests behind it. Ignore re-triggers until the current one settles.
|
|
762
793
|
if (sourcesLoading) {
|
|
763
794
|
return;
|
|
764
795
|
}
|
|
@@ -774,15 +805,9 @@
|
|
|
774
805
|
);
|
|
775
806
|
|
|
776
807
|
if (result.success) {
|
|
777
|
-
//
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
const existingConfig = tv.sources || [];
|
|
781
|
-
state.sources = mergeSourcesWithConfig(withCustom, existingConfig);
|
|
782
|
-
renderSourcesList();
|
|
783
|
-
|
|
784
|
-
$('sourcesLoadingSpinner').style.display = 'none';
|
|
785
|
-
$('sourcesListContainer').style.display = 'block';
|
|
808
|
+
// Cache the raw list so reopening the screen doesn't re-request (#14).
|
|
809
|
+
sourcesCache.set(sourcesCacheKey(tv), result.sources);
|
|
810
|
+
showSources(tv, result.sources);
|
|
786
811
|
} else {
|
|
787
812
|
showSourcesError(result.error);
|
|
788
813
|
}
|
|
@@ -1036,12 +1061,17 @@
|
|
|
1036
1061
|
tv.sources = [];
|
|
1037
1062
|
await saveConfig();
|
|
1038
1063
|
|
|
1039
|
-
//
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1064
|
+
// Re-render with the default order. Prefer the cached list so we don't fire
|
|
1065
|
+
// another /get-sources request (Config UI X may drop its response, #14);
|
|
1066
|
+
// only re-fetch if we somehow have no cache yet.
|
|
1067
|
+
const cached = sourcesCache.get(sourcesCacheKey(tv));
|
|
1068
|
+
if (cached) {
|
|
1069
|
+
showSources(tv, cached);
|
|
1070
|
+
} else {
|
|
1071
|
+
$('sourcesLoadingSpinner').style.display = 'block';
|
|
1072
|
+
$('sourcesListContainer').style.display = 'none';
|
|
1073
|
+
await loadSources(tv);
|
|
1074
|
+
}
|
|
1045
1075
|
|
|
1046
1076
|
homebridge.toast.success('Source order reset to original');
|
|
1047
1077
|
};
|
|
@@ -1171,6 +1201,15 @@
|
|
|
1171
1201
|
$('sourcesErrorContainer').style.display = 'none';
|
|
1172
1202
|
loadSources(state.configuredTvs[state.editingSourcesTvIndex]);
|
|
1173
1203
|
});
|
|
1204
|
+
$('refreshSourcesBtn').addEventListener('click', () => {
|
|
1205
|
+
const tv = state.configuredTvs[state.editingSourcesTvIndex];
|
|
1206
|
+
// Drop the cached list so the user gets a genuine re-fetch from the TV.
|
|
1207
|
+
sourcesCache.delete(sourcesCacheKey(tv));
|
|
1208
|
+
$('sourcesListContainer').style.display = 'none';
|
|
1209
|
+
$('sourcesErrorContainer').style.display = 'none';
|
|
1210
|
+
$('sourcesLoadingSpinner').style.display = 'block';
|
|
1211
|
+
loadSources(tv);
|
|
1212
|
+
});
|
|
1174
1213
|
|
|
1175
1214
|
// ============================================================================
|
|
1176
1215
|
// INITIALIZATION
|
|
@@ -489,9 +489,14 @@
|
|
|
489
489
|
</div>
|
|
490
490
|
</div>
|
|
491
491
|
<div class="d-flex justify-content-between mt-2">
|
|
492
|
-
<
|
|
493
|
-
<
|
|
494
|
-
|
|
492
|
+
<div class="d-flex gap-2">
|
|
493
|
+
<button id="resetSourcesOrderBtn" class="btn btn-outline-secondary btn-sm">
|
|
494
|
+
<i class="bi bi-arrow-counterclockwise"></i> Reset
|
|
495
|
+
</button>
|
|
496
|
+
<button id="refreshSourcesBtn" class="btn btn-outline-secondary btn-sm" title="Re-fetch the source and app list from the TV">
|
|
497
|
+
<i class="bi bi-arrow-clockwise"></i> Refresh from TV
|
|
498
|
+
</button>
|
|
499
|
+
</div>
|
|
495
500
|
<button id="doneEditSourcesBtn" class="btn btn-primary btn-sm">
|
|
496
501
|
<i class="bi bi-check-lg"></i> Done
|
|
497
502
|
</button>
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@mp-consulting/homebridge-philips-ambilight-tv",
|
|
3
3
|
"displayName": "Philips Ambilight TV",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "1.5.
|
|
5
|
+
"version": "1.5.14",
|
|
6
6
|
"description": "Homebridge plugin to control Philips Ambilight TV as a HomeKit Television accessory.",
|
|
7
7
|
"author": "Mickael Palma",
|
|
8
8
|
"license": "(Apache-2.0 AND MIT)",
|