Skip to content
Open
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
17 changes: 17 additions & 0 deletions Grayjay.ClientServer/Controllers/SourcesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ public class SourcesController : ControllerBase
{


[HttpGet]
public string GetDynamicIcon(string id)
{
var plugin = StatePlatform.GetClient(id);
if (plugin == null) return null;

try
{
// Call the dynamic getIcon method implemented in the plugin script
return plugin.CallMethod("getIcon");
}
catch (Exception ex)
{
Logger.e(nameof(SourcesController), "Failed to call getIcon for plugin [" + id + "]: " + ex.Message);
return null;
}
}
[HttpGet]
public PluginConfig[] Sources()
{
Expand Down
4 changes: 4 additions & 0 deletions Grayjay.Desktop.Web/src/backend/SourcesBackend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ export abstract class SourcesBackend {
static async sourceInstallPeerTubePrompt(url: string): Promise<IPluginPrompt> {
return await Backend.POST("/sources/SourceInstallPeerTubePrompt", JSON.stringify(url), "application/json") as any;
}

static async getDynamicIcon(id: string): Promise<string | null> {
return await Backend.GET("/sources/GetDynamicIcon?id=" + id) as string;
}

static login(id: string) {
Backend.GET("/sources/SourceLogin?id=" + id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ export interface ISourceConfig {
version: number;
author: string;
authorUrl: string;
iconUrl: string;
iconUrl: string; // <--- Static icon URL read directly from the plugin's JSON config file
sourceUrl: string;
scriptUrl: string;
scriptUrl: string;
allowUrls: string[];
packages: string[];
scriptSignature: string;
Expand All @@ -91,7 +92,7 @@ export interface ISourceConfig {
supportedClaimTypes: number[];
primaryClaimFieldType: number;
settings: ISourceSetting[];
absoluteIconUrl?: string;
absoluteIconUrl?: string; // <--- Computed absolute URL derived from the static iconUrl above
absoluteScriptUrl?: string;
}

Expand Down
16 changes: 10 additions & 6 deletions Grayjay.Desktop.Web/src/pages/Sources/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,11 @@ const SourcesPage: Component = () => {
}}>
<img src={iconThumb} />
</div>
<div class={styles.image}>
<img src={StateGlobal.getSourceConfig(source()!.id)?.absoluteIconUrl} />
</div>
<div class={styles.image}>
{/* Try dynamic icon from plugin.getIcon(), fallback to static absoluteIconUrl (derived from JSON iconUrl) */}
<img src={StateGlobal.getDynamicIcon(source()!.id).then(icon => icon ?? StateGlobal.getSourceConfig(source()!.id)?.absoluteIconUrl)} />
</div>

<div class={styles.name}>
{source()!.name}
</div>
Expand Down Expand Up @@ -198,9 +200,11 @@ const SourcesPage: Component = () => {
groupRememberLast: true,
onPress: () => enableSource(source)
}}>
<div class={styles.image}>
<img src={StateGlobal.getSourceConfig(source.id)?.absoluteIconUrl} />
</div>
<div class={styles.image}>
{/* Try dynamic icon from plugin.getIcon(), fallback to static absoluteIconUrl (derived from JSON iconUrl) */}
<img src={StateGlobal.getDynamicIcon(source.id).then(icon => icon ?? StateGlobal.getSourceConfig(source.id)?.absoluteIconUrl)} />
</div>

<div class={styles.name}>
{source.name}
</div>
Expand Down
6 changes: 5 additions & 1 deletion Grayjay.Desktop.Web/src/state/StateGlobal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export interface StateGlobal {
getSourceConfig: (id: string | undefined) => ISourceConfig | undefined,
getSourceState: (id: string | undefined) => ISourceConfigState | undefined,
getCommonSearchCapabilities: (sourceIds: string[]) => IResultCapabilities | undefined,
getCommonSearchChannelContentsCapabilities: (sourceIds: string[]) => IResultCapabilities | undefined
getCommonSearchChannelContentsCapabilities: (sourceIds: string[]) => IResultCapabilities | undefined,
getDynamicIcon: (id: string) => Promise<string | null>
};

function createState() {
Expand Down Expand Up @@ -174,6 +175,9 @@ function createState() {
return undefined;
return sourceStates$()?.find(x=>x.config.id == id);
},
getDynamicIcon(id: string) {
return SourcesBackend.getDynamicIcon(id);
},
getCommonSearchCapabilities(sourceIds: string[]): IResultCapabilities | undefined {
return getCommonSearchCapabilitiesType(sourceIds, (sourceId) => this.getSourceState(sourceId)?.capabilitiesSearch);
},
Expand Down