mirror of
https://github.com/imgfloat/client.git
synced 2026-02-04 19:49:26 +00:00
Add custom domain option
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -10,3 +10,4 @@ res/icon/linux/32x32.png filter=lfs diff=lfs merge=lfs -text
|
|||||||
res/icon/linux/48x48.png filter=lfs diff=lfs merge=lfs -text
|
res/icon/linux/48x48.png filter=lfs diff=lfs merge=lfs -text
|
||||||
res/icon/linux/512x512.png filter=lfs diff=lfs merge=lfs -text
|
res/icon/linux/512x512.png filter=lfs diff=lfs merge=lfs -text
|
||||||
res/icon/linux/64x64.png filter=lfs diff=lfs merge=lfs -text
|
res/icon/linux/64x64.png filter=lfs diff=lfs merge=lfs -text
|
||||||
|
res/icon/brand.png filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"plugins": ["prettier-plugin-java"],
|
"plugins": [],
|
||||||
"printWidth":120,
|
"printWidth":120,
|
||||||
"tabWidth":4,
|
"tabWidth":4,
|
||||||
"useTabs":false,
|
"useTabs":false,
|
||||||
|
|||||||
7
Makefile
7
Makefile
@@ -15,17 +15,16 @@ node_modules: package-lock.json
|
|||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run:
|
run:
|
||||||
$(ELECTRON) src/main.js
|
LOCAL_DOMAIN=1 $(ELECTRON) src/main.js
|
||||||
|
|
||||||
.PHONY: run-x
|
.PHONY: run-x
|
||||||
run-x:
|
run-x:
|
||||||
./util/run-xorg $(ELECTRON)
|
LOCAL_DOMAIN=1 ./util/run-xorg $(ELECTRON)
|
||||||
|
|
||||||
.PHONY: run-wl
|
.PHONY: run-wl
|
||||||
run-wl:
|
run-wl:
|
||||||
./util/run-wl $(ELECTRON)
|
LOCAL_DOMAIN=1 ./util/run-wl $(ELECTRON)
|
||||||
|
|
||||||
.PHONY: fix
|
.PHONY: fix
|
||||||
fix: node_modules
|
fix: node_modules
|
||||||
./node_modules/.bin/prettier --write src
|
./node_modules/.bin/prettier --write src
|
||||||
|
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "imgfloat-client",
|
"name": "imgfloat-client",
|
||||||
"version": "1.0.0",
|
"version": "1.0.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "imgfloat-client",
|
"name": "imgfloat-client",
|
||||||
"version": "1.0.0",
|
"version": "1.0.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"electron-updater": "^6.7.3"
|
"electron-updater": "^6.7.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"appId": "dev.kruhlmann.imgfloat",
|
"appId": "dev.kruhlmann.imgfloat",
|
||||||
"productName": "Imgfloat",
|
"productName": "Imgfloat",
|
||||||
"files": [
|
"files": [
|
||||||
"src/main.js",
|
"src/**",
|
||||||
"res/**"
|
"res/**"
|
||||||
],
|
],
|
||||||
"publish": {
|
"publish": {
|
||||||
|
|||||||
BIN
res/icon/brand.png
LFS
Normal file
BIN
res/icon/brand.png
LFS
Normal file
Binary file not shown.
@@ -9,7 +9,7 @@
|
|||||||
<div class="channels-shell">
|
<div class="channels-shell">
|
||||||
<header class="channels-header">
|
<header class="channels-header">
|
||||||
<div class="brand">
|
<div class="brand">
|
||||||
<img class="brand-mark" alt="brand" src="https://imgfloat.kruhlmann.dev/img/brand.png" />
|
<img class="brand-mark" alt="brand" src="../res/icon/brand.png" />
|
||||||
<div>
|
<div>
|
||||||
<div class="brand-title">Imgfloat</div>
|
<div class="brand-title">Imgfloat</div>
|
||||||
<div class="brand-subtitle">Twitch overlay manager</div>
|
<div class="brand-subtitle">Twitch overlay manager</div>
|
||||||
@@ -35,6 +35,15 @@
|
|||||||
autofocus
|
autofocus
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
/>
|
/>
|
||||||
|
<label class="sr-only" for="domain-input">Server domain</label>
|
||||||
|
<input
|
||||||
|
id="domain-input"
|
||||||
|
name="domain"
|
||||||
|
class="text-input"
|
||||||
|
type="url"
|
||||||
|
autocomplete="off"
|
||||||
|
spellcheck="false"
|
||||||
|
/>
|
||||||
<datalist id="channel-suggestions"></datalist>
|
<datalist id="channel-suggestions"></datalist>
|
||||||
<button type="submit" class="button block">Open overlay</button>
|
<button type="submit" class="button block">Open overlay</button>
|
||||||
</form>
|
</form>
|
||||||
@@ -44,6 +53,7 @@
|
|||||||
<script>
|
<script>
|
||||||
const form = document.getElementById("channel-search-form");
|
const form = document.getElementById("channel-search-form");
|
||||||
const input = document.getElementById("channel-search");
|
const input = document.getElementById("channel-search");
|
||||||
|
const domainInput = document.getElementById("domain-input");
|
||||||
|
|
||||||
window.store.loadBroadcaster().then((value) => {
|
window.store.loadBroadcaster().then((value) => {
|
||||||
if (value && input.value === "") {
|
if (value && input.value === "") {
|
||||||
@@ -51,13 +61,35 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Promise.all([window.store.loadDomain(), window.store.loadDefaultDomain()]).then(
|
||||||
|
([savedDomain, defaultDomain]) => {
|
||||||
|
domainInput.value = savedDomain || defaultDomain;
|
||||||
|
domainInput.placeholder = defaultDomain;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
domainInput.addEventListener("change", () => {
|
||||||
|
const trimmedDomain = domainInput.value.trim();
|
||||||
|
if (trimmedDomain) {
|
||||||
|
window.store.saveDomain(trimmedDomain);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
form.addEventListener("submit", (e) => {
|
form.addEventListener("submit", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const channel = input.value.trim();
|
const channel = input.value.trim();
|
||||||
|
const fallbackDomain = domainInput.placeholder || "";
|
||||||
|
const domain = domainInput.value.trim() || fallbackDomain;
|
||||||
if (!channel) return;
|
if (!channel) return;
|
||||||
|
|
||||||
|
if (domain) {
|
||||||
|
window.store.saveDomain(domain);
|
||||||
|
}
|
||||||
const params = new URLSearchParams({ broadcaster: channel });
|
const params = new URLSearchParams({ broadcaster: channel });
|
||||||
|
if (domain) {
|
||||||
|
params.set("domain", domain);
|
||||||
|
}
|
||||||
window.location.href = `broadcast.html?${params.toString()}`;
|
window.location.href = `broadcast.html?${params.toString()}`;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ import { BroadcastRenderer } from "./broadcast/renderer.js";
|
|||||||
import { saveSelectedBroadcaster } from "./ipc.js";
|
import { saveSelectedBroadcaster } from "./ipc.js";
|
||||||
import { showToast } from "./toast.js";
|
import { showToast } from "./toast.js";
|
||||||
|
|
||||||
const domain = "https://imgfloat.kruhlmann.dev";
|
const normalizeDomain = (value) => value?.trim()?.replace(/\/+$/, "");
|
||||||
|
const domainParam = new URL(window.location.href).searchParams.get("domain");
|
||||||
|
const defaultDomain = await window.store.loadDefaultDomain();
|
||||||
|
const savedDomain = await window.store.loadDomain();
|
||||||
|
const domain = normalizeDomain(domainParam || savedDomain || defaultDomain);
|
||||||
|
|
||||||
globalThis.onerror = (error, url, line) => {
|
globalThis.onerror = (error, url, line) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@@ -17,6 +21,9 @@ const broadcaster = new URL(window.location.href).searchParams.get("broadcaster"
|
|||||||
if (!broadcaster) {
|
if (!broadcaster) {
|
||||||
throw new Error("No broadcaster");
|
throw new Error("No broadcaster");
|
||||||
}
|
}
|
||||||
|
if (!domain) {
|
||||||
|
throw new Error("No domain configured");
|
||||||
|
}
|
||||||
saveSelectedBroadcaster(broadcaster);
|
saveSelectedBroadcaster(broadcaster);
|
||||||
|
|
||||||
const renderer = new BroadcastRenderer({
|
const renderer = new BroadcastRenderer({
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export class BroadcastRenderer {
|
|||||||
const body = JSON.parse(payload.body);
|
const body = JSON.parse(payload.body);
|
||||||
this.handleEvent(body);
|
this.handleEvent(body);
|
||||||
});
|
});
|
||||||
fetch(`https://imgfloat.kruhlmann.dev/api/channels/${this.broadcaster}/assets`)
|
fetch(`${this.domain}/api/channels/${this.broadcaster}/assets`)
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
if (!r.ok) {
|
if (!r.ok) {
|
||||||
throw new Error("Failed to load assets");
|
throw new Error("Failed to load assets");
|
||||||
@@ -121,7 +121,7 @@ export class BroadcastRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fetchCanvasSettings() {
|
async fetchCanvasSettings() {
|
||||||
return fetch(`https://imgfloat.kruhlmann.dev/api/channels/${encodeURIComponent(this.broadcaster)}/canvas`)
|
return fetch(`${this.domain}/api/channels/${encodeURIComponent(this.broadcaster)}/canvas`)
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
if (!r.ok) {
|
if (!r.ok) {
|
||||||
throw new Error("Failed to load canvas");
|
throw new Error("Failed to load canvas");
|
||||||
|
|||||||
29
src/main.js
29
src/main.js
@@ -7,6 +7,22 @@ const { readStore, writeStore } = require("./store.js");
|
|||||||
const STORE_PATH = path.join(app.getPath("userData"), "settings.json");
|
const STORE_PATH = path.join(app.getPath("userData"), "settings.json");
|
||||||
const INITIAL_WINDOW_WIDTH_PX = 960;
|
const INITIAL_WINDOW_WIDTH_PX = 960;
|
||||||
const INITIAL_WINDOW_HEIGHT_PX = 640;
|
const INITIAL_WINDOW_HEIGHT_PX = 640;
|
||||||
|
const LOCAL_DOMAIN = "http://localhost:8080";
|
||||||
|
const DEFAULT_DOMAIN = "https://imgfloat.kruhlmann.dev";
|
||||||
|
|
||||||
|
function normalizeDomain(domain) {
|
||||||
|
return domain?.trim()?.replace(/\/+$/, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveDefaultDomain() {
|
||||||
|
if (process.env.DEVTOOLS || process.env.LOCAL_DOMAIN) {
|
||||||
|
return normalizeDomain(LOCAL_DOMAIN);
|
||||||
|
}
|
||||||
|
const buildTimeDomain = process.env.IMGFLOAT_DOMAIN || DEFAULT_DOMAIN;
|
||||||
|
return normalizeDomain(buildTimeDomain);
|
||||||
|
}
|
||||||
|
|
||||||
|
const runtimeDefaultDomain = resolveDefaultDomain();
|
||||||
|
|
||||||
let ELECTRON_WINDOW;
|
let ELECTRON_WINDOW;
|
||||||
|
|
||||||
@@ -74,6 +90,19 @@ ipcMain.handle("load-broadcaster", () => {
|
|||||||
return store.lastBroadcaster ?? "";
|
return store.lastBroadcaster ?? "";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle("save-domain", (_, domain) => {
|
||||||
|
const store = readStore(STORE_PATH);
|
||||||
|
store.lastDomain = normalizeDomain(domain);
|
||||||
|
writeStore(STORE_PATH, store);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle("load-domain", () => {
|
||||||
|
const store = readStore(STORE_PATH);
|
||||||
|
return normalizeDomain(store.lastDomain) || runtimeDefaultDomain;
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle("load-default-domain", () => runtimeDefaultDomain);
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
if (process.env.CI) {
|
if (process.env.CI) {
|
||||||
process.on("uncaughtException", (err) => {
|
process.on("uncaughtException", (err) => {
|
||||||
|
|||||||
@@ -3,5 +3,8 @@ const { contextBridge, ipcRenderer } = require("electron");
|
|||||||
contextBridge.exposeInMainWorld("store", {
|
contextBridge.exposeInMainWorld("store", {
|
||||||
saveBroadcaster: (value) => ipcRenderer.invoke("save-broadcaster", value),
|
saveBroadcaster: (value) => ipcRenderer.invoke("save-broadcaster", value),
|
||||||
loadBroadcaster: () => ipcRenderer.invoke("load-broadcaster"),
|
loadBroadcaster: () => ipcRenderer.invoke("load-broadcaster"),
|
||||||
|
saveDomain: (value) => ipcRenderer.invoke("save-domain", value),
|
||||||
|
loadDomain: () => ipcRenderer.invoke("load-domain"),
|
||||||
|
loadDefaultDomain: () => ipcRenderer.invoke("load-default-domain"),
|
||||||
setWindowSize: (width, height) => ipcRenderer.invoke("set-window-size", width, height),
|
setWindowSize: (width, height) => ipcRenderer.invoke("set-window-size", width, height),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user