feat: add buildSources to construct session source list from settings

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
This commit is contained in:
Brian Krabach
2026-03-30 22:21:45 -07:00
parent 93c5170581
commit ecf57441cf
2 changed files with 78 additions and 0 deletions
+32
View File
@@ -131,6 +131,7 @@ let _previewTimer = null;
var _previewSessionName = null; // track by NAME, not DOM element var _previewSessionName = null; // track by NAME, not DOM element
// ─── Settings state ─────────────────────────────────────────────────────────── // ─── Settings state ───────────────────────────────────────────────────────────
let _sources = [];
let _settingsOpen = false; let _settingsOpen = false;
let _serverSettings = null; let _serverSettings = null;
const DISPLAY_SETTINGS_KEY = 'muxplex.display'; const DISPLAY_SETTINGS_KEY = 'muxplex.display';
@@ -985,6 +986,36 @@ async function patchServerSetting(key, value) {
} }
} }
/**
* Build the list of session sources from server settings.
* Local source is always first with url: ''.
* Remote instances come from settings.remote_instances array.
* Trailing slashes are stripped from remote URLs.
* Default device name is 'This device' when device_name is empty.
* @param {object} settings - server settings object
* @returns {object[]} array of source objects with {url, name, type, status, backoffMs}
*/
function buildSources(settings) {
var localName = (settings && settings.device_name) || 'This device';
var sources = [
{ url: '', name: localName, type: 'local', status: 'authenticated', backoffMs: 2000 },
];
var remotes = (settings && settings.remote_instances) || [];
for (var i = 0; i < remotes.length; i++) {
var r = remotes[i];
if (r && r.url) {
sources.push({
url: r.url.replace(/\/+$/, ''),
name: r.name || r.url,
type: 'remote',
status: 'authenticated',
backoffMs: 2000,
});
}
}
return sources;
}
// ─── Settings dialog ────────────────────────────────────────────────────────── // ─── Settings dialog ──────────────────────────────────────────────────────────
/** /**
@@ -1716,6 +1747,7 @@ if (typeof module !== 'undefined' && module.exports) {
// Server settings // Server settings
loadServerSettings, loadServerSettings,
patchServerSetting, patchServerSetting,
buildSources,
// Fetch wrapper // Fetch wrapper
api, api,
// Header + button with inline name input // Header + button with inline name input
+46
View File
@@ -2004,4 +2004,50 @@ test('createNewSession polls for session before auto-opening (not immediate setT
); );
}); });
// --- buildSources ---
test('buildSources returns only local source when no remote_instances', () => {
const sources = app.buildSources({ device_name: 'Laptop' });
assert.strictEqual(sources.length, 1, 'should return exactly one source (local)');
assert.strictEqual(sources[0].url, '', 'local source url should be empty string');
assert.strictEqual(sources[0].name, 'Laptop', 'local source name should be device_name');
assert.strictEqual(sources[0].type, 'local', 'local source type should be local');
assert.strictEqual(sources[0].status, 'authenticated', 'local source status should be authenticated');
});
test('buildSources returns local + remote sources from remote_instances', () => {
const sources = app.buildSources({
device_name: 'Laptop',
remote_instances: [
{ url: 'https://server1.example.com', name: 'Server 1' },
{ url: 'https://server2.example.com', name: 'Server 2' },
],
});
assert.strictEqual(sources.length, 3, 'should return 3 sources: 1 local + 2 remote');
assert.strictEqual(sources[0].type, 'local', 'first source should be local');
assert.strictEqual(sources[1].type, 'remote', 'second source should be remote');
assert.strictEqual(sources[1].url, 'https://server1.example.com', 'remote source url should match');
assert.strictEqual(sources[1].name, 'Server 1', 'remote source name should match');
assert.strictEqual(sources[2].type, 'remote', 'third source should be remote');
assert.strictEqual(sources[2].url, 'https://server2.example.com', 'remote source url should match');
});
test('buildSources uses hostname fallback when device_name is empty', () => {
const sources = app.buildSources({});
assert.strictEqual(sources.length, 1, 'should return one source');
assert.strictEqual(sources[0].name, 'This device', 'local source name should fall back to This device');
});
test('buildSources strips trailing slash from remote URLs', () => {
const sources = app.buildSources({
device_name: 'Laptop',
remote_instances: [
{ url: 'https://server1.example.com/', name: 'Server 1' },
{ url: 'https://server2.example.com///', name: 'Server 2' },
],
});
assert.strictEqual(sources[1].url, 'https://server1.example.com', 'trailing slash should be stripped from remote URL');
assert.strictEqual(sources[2].url, 'https://server2.example.com', 'multiple trailing slashes should be stripped from remote URL');
});