Add media server selection to Nostr settings
CI / Lint (pull_request) Successful in 1m3s
CI / Test (pull_request) Successful in 1m16s
Release Drafter / Update release notes draft (pull_request) Successful in 5s

Also, hide the fallback option when there's no server to fall back to
This commit is contained in:
2026-08-21 11:27:03 -06:00
parent cdeb4f5d8c
commit 2746ec035d
5 changed files with 110 additions and 23 deletions
+56 -19
View File
@@ -4,12 +4,14 @@ import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { service } from '@ember/service';
import { fn } from '@ember/helper';
import eq from 'ember-truth-helpers/helpers/eq';
import Icon from '#components/icon';
import {
excludeRequiredRelays,
mergeRequiredRelays,
normalizeRelayUrl,
} from '../../../utils/nostr';
import { DEFAULT_BLOSSOM_SERVER } from '../../../services/blossom';
const stripProtocol = (url) => (url ? url.replace(/^wss?:\/\//, '') : '');
@@ -89,6 +91,15 @@ export default class AppMenuSettingsNostr extends Component {
});
}
get mediaServerOptions() {
const servers = this.nostrData.blossomServers;
return servers.length ? servers : [DEFAULT_BLOSSOM_SERVER];
}
get hasMultipleMediaServers() {
return this.mediaServerOptions.length > 1;
}
@action
updateNewReadRelay(event) {
this.newReadRelay = event.target.value;
@@ -342,31 +353,57 @@ export default class AppMenuSettingsNostr extends Component {
</div>
<div class="form-group">
<label for="nostr-photo-fallback-uploads">Upload photos to fallback
servers</label>
<label for="nostr-media-server">Media server</label>
<select
id="nostr-photo-fallback-uploads"
id="nostr-media-server"
class="form-control"
{{on "change" (fn @onChange "nostrPhotoFallbackUploads")}}
{{on "change" (fn @onChange "nostrMediaServer")}}
>
<option
value="true"
selected={{if this.settings.nostrPhotoFallbackUploads "selected"}}
>
Yes
</option>
<option
value="false"
selected={{unless
this.settings.nostrPhotoFallbackUploads
"selected"
}}
>
No
</option>
{{#each this.mediaServerOptions as |server|}}
<option
value={{server}}
selected={{if
(eq server this.settings.nostrMediaServer)
"selected"
}}
>
{{server}}
</option>
{{/each}}
</select>
</div>
{{#if this.hasMultipleMediaServers}}
<div class="form-group">
<label for="nostr-photo-fallback-uploads">Upload photos to fallback
servers</label>
<select
id="nostr-photo-fallback-uploads"
class="form-control"
{{on "change" (fn @onChange "nostrPhotoFallbackUploads")}}
>
<option
value="true"
selected={{if
this.settings.nostrPhotoFallbackUploads
"selected"
}}
>
Yes
</option>
<option
value="false"
selected={{unless
this.settings.nostrPhotoFallbackUploads
"selected"
}}
>
No
</option>
</select>
</div>
{{/if}}
<div class="form-group">
<label>Cached data</label>
<button
+5 -4
View File
@@ -24,14 +24,15 @@ export default class BlossomService extends Service {
@service settings;
get servers() {
const servers = this.nostrData.blossomServers;
const allServers = servers.length ? servers : [DEFAULT_BLOSSOM_SERVER];
const discovered = this.nostrData.blossomServers;
const mainServer = this.settings.nostrMediaServer || DEFAULT_BLOSSOM_SERVER;
const fallbacks = discovered.filter((server) => server !== mainServer);
if (!this.settings.nostrPhotoFallbackUploads) {
return [allServers[0]];
return [mainServer];
}
return allServers;
return [mainServer, ...fallbacks];
}
async _getAuthHeader(action, hash, serverUrl) {
+11
View File
@@ -15,6 +15,7 @@ import {
uniqNormalizedRelays,
} from '../utils/nostr';
import { getGeohashPrefixesInBbox } from '../utils/geohash-coverage';
import { DEFAULT_BLOSSOM_SERVER } from './blossom';
const DIRECTORY_RELAYS = [
'wss://relay.primal.net',
@@ -437,6 +438,16 @@ export default class NostrDataService extends Service {
} else {
this.blossomServers = [];
}
if (this.blossomServers.length > 0) {
const current = this.settings.nostrMediaServer;
if (
current === DEFAULT_BLOSSOM_SERVER ||
!this.blossomServers.includes(current)
) {
this.settings.update('nostrMediaServer', this.blossomServers[0]);
}
}
});
// 1. Await cache initialization and populate the EventStore with local data
+6
View File
@@ -1,12 +1,15 @@
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { DEFAULT_BLOSSOM_SERVER } from './blossom';
const DEFAULT_SETTINGS = {
overpassApi: 'https://overpass-api.de/api/interpreter',
mapKinetic: true,
photonApi: 'https://photon.komoot.io/api/',
showQuickSearchButtons: true,
nostrPhotoFallbackUploads: false,
nostrMediaServer: DEFAULT_BLOSSOM_SERVER,
nostrReadRelays: null,
nostrWriteRelays: null,
nostrReadRelayExclusions: null,
@@ -21,6 +24,7 @@ export default class SettingsService extends Service {
@tracked showQuickSearchButtons = DEFAULT_SETTINGS.showQuickSearchButtons;
@tracked nostrPhotoFallbackUploads =
DEFAULT_SETTINGS.nostrPhotoFallbackUploads;
@tracked nostrMediaServer = DEFAULT_SETTINGS.nostrMediaServer;
@tracked nostrReadRelays = DEFAULT_SETTINGS.nostrReadRelays;
@tracked nostrWriteRelays = DEFAULT_SETTINGS.nostrWriteRelays;
@tracked nostrReadRelayExclusions = DEFAULT_SETTINGS.nostrReadRelayExclusions;
@@ -114,6 +118,7 @@ export default class SettingsService extends Service {
this.photonApi = finalSettings.photonApi;
this.showQuickSearchButtons = finalSettings.showQuickSearchButtons;
this.nostrPhotoFallbackUploads = finalSettings.nostrPhotoFallbackUploads;
this.nostrMediaServer = finalSettings.nostrMediaServer;
this.nostrReadRelays = finalSettings.nostrReadRelays;
this.nostrWriteRelays = finalSettings.nostrWriteRelays;
this.nostrReadRelayExclusions = finalSettings.nostrReadRelayExclusions;
@@ -132,6 +137,7 @@ export default class SettingsService extends Service {
photonApi: this.photonApi,
showQuickSearchButtons: this.showQuickSearchButtons,
nostrPhotoFallbackUploads: this.nostrPhotoFallbackUploads,
nostrMediaServer: this.nostrMediaServer,
nostrReadRelays: this.nostrReadRelays,
nostrWriteRelays: this.nostrWriteRelays,
nostrReadRelayExclusions: this.nostrReadRelayExclusions,