diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..8a678147
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,3 @@
+node_modules
+Dockerfile
+docker-compose.*
diff --git a/.erb/configs/webpack.config.renderer.dev.ts b/.erb/configs/webpack.config.renderer.dev.ts
index f6ca25d8..46e51530 100644
--- a/.erb/configs/webpack.config.renderer.dev.ts
+++ b/.erb/configs/webpack.config.renderer.dev.ts
@@ -16,7 +16,7 @@ import webpackPaths from './webpack.paths';
// When an ESLint server is running, we can't set the NODE_ENV so we'll check if it's
// at the dev webpack config is not accidentally run in a production environment
if (process.env.NODE_ENV === 'production') {
- checkNodeEnv('development');
+ checkNodeEnv('development');
}
const port = process.env.PORT || 4343;
@@ -28,171 +28,174 @@ const requiredByDLLConfig = module.parent!.filename.includes('webpack.config.ren
* Warn if the DLL is not built
*/
if (!requiredByDLLConfig && !(fs.existsSync(webpackPaths.dllPath) && fs.existsSync(manifest))) {
- console.log(
- chalk.black.bgYellow.bold(
- 'The DLL files are missing. Sit back while we build them for you with "npm run build-dll"',
- ),
- );
- execSync('npm run postinstall');
+ console.log(
+ chalk.black.bgYellow.bold(
+ 'The DLL files are missing. Sit back while we build them for you with "npm run build-dll"',
+ ),
+ );
+ execSync('npm run postinstall');
}
const configuration: webpack.Configuration = {
- devtool: 'inline-source-map',
+ devtool: 'inline-source-map',
- mode: 'development',
+ mode: 'development',
- target: ['web', 'electron-renderer'],
+ target: ['web', 'electron-renderer'],
- entry: [
- `webpack-dev-server/client?http://localhost:${port}/dist`,
- 'webpack/hot/only-dev-server',
- path.join(webpackPaths.srcRendererPath, 'index.tsx'),
- ],
-
- output: {
- path: webpackPaths.distRendererPath,
- publicPath: '/',
- filename: 'renderer.dev.js',
- library: {
- type: 'umd',
- },
- },
-
- module: {
- rules: [
- {
- test: /\.s?css$/,
- use: [
- 'style-loader',
- {
- loader: 'css-loader',
- options: {
- modules: {
- localIdentName: '[name]__[local]--[hash:base64:5]',
- exportLocalsConvention: 'camelCaseOnly',
- },
- sourceMap: true,
- importLoaders: 1,
- },
- },
- 'sass-loader',
- ],
- include: /\.module\.s?(c|a)ss$/,
- },
- {
- test: /\.s?css$/,
- use: ['style-loader', 'css-loader', 'sass-loader'],
- exclude: /\.module\.s?(c|a)ss$/,
- },
- // Fonts
- {
- test: /\.(woff|woff2|eot|ttf|otf)$/i,
- type: 'asset/resource',
- },
- // Images
- {
- test: /\.(png|svg|jpg|jpeg|gif)$/i,
- type: 'asset/resource',
- },
+ entry: [
+ `webpack-dev-server/client?http://localhost:${port}/dist`,
+ 'webpack/hot/only-dev-server',
+ path.join(webpackPaths.srcRendererPath, 'index.tsx'),
],
- },
- plugins: [
- ...(requiredByDLLConfig
- ? []
- : [
- new webpack.DllReferencePlugin({
- context: webpackPaths.dllPath,
- manifest: require(manifest),
- sourceType: 'var',
- }),
- ]),
- new webpack.NoEmitOnErrorsPlugin(),
-
- /**
- * Create global constants which can be configured at compile time.
- *
- * Useful for allowing different behaviour between development builds and
- * release builds
- *
- * NODE_ENV should be production so that modules do not perform certain
- * development checks
- *
- * By default, use 'development' as NODE_ENV. This can be overriden with
- * 'staging', for example, by changing the ENV variables in the npm scripts
- */
- new webpack.EnvironmentPlugin({
- NODE_ENV: 'development',
- }),
-
- new webpack.LoaderOptionsPlugin({
- debug: true,
- }),
-
- new ReactRefreshWebpackPlugin(),
-
- new HtmlWebpackPlugin({
- filename: path.join('index.html'),
- template: path.join(webpackPaths.srcRendererPath, 'index.ejs'),
- minify: {
- collapseWhitespace: true,
- removeAttributeQuotes: true,
- removeComments: true,
- },
- isBrowser: false,
- env: process.env.NODE_ENV,
- isDevelopment: process.env.NODE_ENV !== 'production',
- nodeModules: webpackPaths.appNodeModulesPath,
- }),
- ],
-
- node: {
- __dirname: false,
- __filename: false,
- },
-
- devServer: {
- port,
- compress: true,
- hot: true,
- headers: { 'Access-Control-Allow-Origin': '*' },
- static: {
- publicPath: '/',
+ output: {
+ path: webpackPaths.distRendererPath,
+ publicPath: '/',
+ filename: 'renderer.dev.js',
+ library: {
+ type: 'umd',
+ },
},
- historyApiFallback: {
- verbose: true,
- },
- setupMiddlewares(middlewares) {
- console.log('Starting preload.js builder...');
- const preloadProcess = spawn('npm', ['run', 'start:preload'], {
- shell: true,
- stdio: 'inherit',
- })
- .on('close', (code: number) => process.exit(code!))
- .on('error', (spawnError) => console.error(spawnError));
- console.log('Starting remote.js builder...');
- const remoteProcess = spawn('npm', ['run', 'start:remote'], {
- shell: true,
- stdio: 'inherit',
- })
- .on('close', (code: number) => process.exit(code!))
- .on('error', (spawnError) => console.error(spawnError));
-
- console.log('Starting Main Process...');
- spawn('npm', ['run', 'start:main'], {
- shell: true,
- stdio: 'inherit',
- })
- .on('close', (code: number) => {
- preloadProcess.kill();
- remoteProcess.kill();
- process.exit(code!);
- })
- .on('error', (spawnError) => console.error(spawnError));
- return middlewares;
+ module: {
+ rules: [
+ {
+ test: /\.s?css$/,
+ use: [
+ 'style-loader',
+ {
+ loader: 'css-loader',
+ options: {
+ modules: {
+ localIdentName: '[name]__[local]--[hash:base64:5]',
+ exportLocalsConvention: 'camelCaseOnly',
+ },
+ sourceMap: true,
+ importLoaders: 1,
+ },
+ },
+ 'sass-loader',
+ ],
+ include: /\.module\.s?(c|a)ss$/,
+ },
+ {
+ test: /\.s?css$/,
+ use: ['style-loader', 'css-loader', 'sass-loader'],
+ exclude: /\.module\.s?(c|a)ss$/,
+ },
+ // Fonts
+ {
+ test: /\.(woff|woff2|eot|ttf|otf)$/i,
+ type: 'asset/resource',
+ },
+ // Images
+ {
+ test: /\.(png|svg|jpg|jpeg|gif)$/i,
+ type: 'asset/resource',
+ },
+ ],
+ },
+ plugins: [
+ ...(requiredByDLLConfig
+ ? []
+ : [
+ new webpack.DllReferencePlugin({
+ context: webpackPaths.dllPath,
+ manifest: require(manifest),
+ sourceType: 'var',
+ }),
+ ]),
+
+ new webpack.NoEmitOnErrorsPlugin(),
+
+ /**
+ * Create global constants which can be configured at compile time.
+ *
+ * Useful for allowing different behaviour between development builds and
+ * release builds
+ *
+ * NODE_ENV should be production so that modules do not perform certain
+ * development checks
+ *
+ * By default, use 'development' as NODE_ENV. This can be overriden with
+ * 'staging', for example, by changing the ENV variables in the npm scripts
+ */
+ new webpack.EnvironmentPlugin({
+ NODE_ENV: 'development',
+ }),
+
+ new webpack.LoaderOptionsPlugin({
+ debug: true,
+ }),
+
+ new ReactRefreshWebpackPlugin(),
+
+ new HtmlWebpackPlugin({
+ filename: path.join('index.html'),
+ template: path.join(webpackPaths.srcRendererPath, 'index.ejs'),
+ minify: {
+ collapseWhitespace: true,
+ removeAttributeQuotes: true,
+ removeComments: true,
+ },
+ isBrowser: false,
+ env: process.env.NODE_ENV,
+ isDevelopment: process.env.NODE_ENV !== 'production',
+ nodeModules: webpackPaths.appNodeModulesPath,
+ templateParameters: {
+ web: false,
+ },
+ }),
+ ],
+
+ node: {
+ __dirname: false,
+ __filename: false,
+ },
+
+ devServer: {
+ port,
+ compress: true,
+ hot: true,
+ headers: { 'Access-Control-Allow-Origin': '*' },
+ static: {
+ publicPath: '/',
+ },
+ historyApiFallback: {
+ verbose: true,
+ },
+ setupMiddlewares(middlewares) {
+ console.log('Starting preload.js builder...');
+ const preloadProcess = spawn('npm', ['run', 'start:preload'], {
+ shell: true,
+ stdio: 'inherit',
+ })
+ .on('close', (code: number) => process.exit(code!))
+ .on('error', (spawnError) => console.error(spawnError));
+
+ console.log('Starting remote.js builder...');
+ const remoteProcess = spawn('npm', ['run', 'start:remote'], {
+ shell: true,
+ stdio: 'inherit',
+ })
+ .on('close', (code: number) => process.exit(code!))
+ .on('error', (spawnError) => console.error(spawnError));
+
+ console.log('Starting Main Process...');
+ spawn('npm', ['run', 'start:main'], {
+ shell: true,
+ stdio: 'inherit',
+ })
+ .on('close', (code: number) => {
+ preloadProcess.kill();
+ remoteProcess.kill();
+ process.exit(code!);
+ })
+ .on('error', (spawnError) => console.error(spawnError));
+ return middlewares;
+ },
},
- },
};
export default merge(baseConfig, configuration);
diff --git a/.erb/configs/webpack.config.renderer.prod.ts b/.erb/configs/webpack.config.renderer.prod.ts
index 324630a7..379bb2d0 100644
--- a/.erb/configs/webpack.config.renderer.prod.ts
+++ b/.erb/configs/webpack.config.renderer.prod.ts
@@ -21,114 +21,117 @@ checkNodeEnv('production');
deleteSourceMaps();
const devtoolsConfig =
- process.env.DEBUG_PROD === 'true'
- ? {
- devtool: 'source-map',
- }
- : {};
+ process.env.DEBUG_PROD === 'true'
+ ? {
+ devtool: 'source-map',
+ }
+ : {};
const configuration: webpack.Configuration = {
- ...devtoolsConfig,
+ ...devtoolsConfig,
- mode: 'production',
+ mode: 'production',
- target: ['web', 'electron-renderer'],
+ target: ['web', 'electron-renderer'],
- entry: [path.join(webpackPaths.srcRendererPath, 'index.tsx')],
+ entry: [path.join(webpackPaths.srcRendererPath, 'index.tsx')],
- output: {
- path: webpackPaths.distRendererPath,
- publicPath: './',
- filename: 'renderer.js',
- library: {
- type: 'umd',
+ output: {
+ path: webpackPaths.distRendererPath,
+ publicPath: './',
+ filename: 'renderer.js',
+ library: {
+ type: 'umd',
+ },
},
- },
- module: {
- rules: [
- {
- test: /\.s?(a|c)ss$/,
- use: [
- MiniCssExtractPlugin.loader,
- {
- loader: 'css-loader',
- options: {
- modules: {
- localIdentName: '[name]__[local]--[hash:base64:5]',
- exportLocalsConvention: 'camelCaseOnly',
- },
- sourceMap: true,
- importLoaders: 1,
+ module: {
+ rules: [
+ {
+ test: /\.s?(a|c)ss$/,
+ use: [
+ MiniCssExtractPlugin.loader,
+ {
+ loader: 'css-loader',
+ options: {
+ modules: {
+ localIdentName: '[name]__[local]--[hash:base64:5]',
+ exportLocalsConvention: 'camelCaseOnly',
+ },
+ sourceMap: true,
+ importLoaders: 1,
+ },
+ },
+ 'sass-loader',
+ ],
+ include: /\.module\.s?(c|a)ss$/,
+ },
+ {
+ test: /\.s?(a|c)ss$/,
+ use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
+ exclude: /\.module\.s?(c|a)ss$/,
+ },
+ // Fonts
+ {
+ test: /\.(woff|woff2|eot|ttf|otf)$/i,
+ type: 'asset/resource',
+ },
+ // Images
+ {
+ test: /\.(png|svg|jpg|jpeg|gif)$/i,
+ type: 'asset/resource',
},
- },
- 'sass-loader',
],
- include: /\.module\.s?(c|a)ss$/,
- },
- {
- test: /\.s?(a|c)ss$/,
- use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
- exclude: /\.module\.s?(c|a)ss$/,
- },
- // Fonts
- {
- test: /\.(woff|woff2|eot|ttf|otf)$/i,
- type: 'asset/resource',
- },
- // Images
- {
- test: /\.(png|svg|jpg|jpeg|gif)$/i,
- type: 'asset/resource',
- },
+ },
+
+ optimization: {
+ minimize: true,
+ minimizer: [
+ new TerserPlugin({
+ parallel: true,
+ }),
+ new CssMinimizerPlugin(),
+ ],
+ },
+
+ plugins: [
+ /**
+ * Create global constants which can be configured at compile time.
+ *
+ * Useful for allowing different behaviour between development builds and
+ * release builds
+ *
+ * NODE_ENV should be production so that modules do not perform certain
+ * development checks
+ */
+ new webpack.EnvironmentPlugin({
+ NODE_ENV: 'production',
+ DEBUG_PROD: false,
+ }),
+
+ new MiniCssExtractPlugin({
+ filename: 'style.css',
+ }),
+
+ new BundleAnalyzerPlugin({
+ analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled',
+ }),
+
+ new HtmlWebpackPlugin({
+ filename: 'index.html',
+ template: path.join(webpackPaths.srcRendererPath, 'index.ejs'),
+ minify: {
+ collapseWhitespace: true,
+ removeAttributeQuotes: true,
+ removeComments: true,
+ },
+ isBrowser: false,
+ isDevelopment: process.env.NODE_ENV !== 'production',
+ templateParameters: {
+ web: false,
+ },
+ }),
],
- },
-
- optimization: {
- minimize: true,
- minimizer: [
- new TerserPlugin({
- parallel: true,
- }),
- new CssMinimizerPlugin(),
- ],
- },
-
- plugins: [
- /**
- * Create global constants which can be configured at compile time.
- *
- * Useful for allowing different behaviour between development builds and
- * release builds
- *
- * NODE_ENV should be production so that modules do not perform certain
- * development checks
- */
- new webpack.EnvironmentPlugin({
- NODE_ENV: 'production',
- DEBUG_PROD: false,
- }),
-
- new MiniCssExtractPlugin({
- filename: 'style.css',
- }),
-
- new BundleAnalyzerPlugin({
- analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled',
- }),
-
- new HtmlWebpackPlugin({
- filename: 'index.html',
- template: path.join(webpackPaths.srcRendererPath, 'index.ejs'),
- minify: {
- collapseWhitespace: true,
- removeAttributeQuotes: true,
- removeComments: true,
- },
- isBrowser: false,
- isDevelopment: process.env.NODE_ENV !== 'production',
- }),
- ],
};
export default merge(baseConfig, configuration);
diff --git a/.erb/configs/webpack.config.renderer.web.ts b/.erb/configs/webpack.config.renderer.web.ts
index 39fca511..82b5f79a 100644
--- a/.erb/configs/webpack.config.renderer.web.ts
+++ b/.erb/configs/webpack.config.renderer.web.ts
@@ -116,6 +116,9 @@ const configuration: webpack.Configuration = {
env: process.env.NODE_ENV,
isDevelopment: process.env.NODE_ENV !== 'production',
nodeModules: webpackPaths.appNodeModulesPath,
+ templateParameters: {
+ web: false, // with hot reload, we don't have NGINX injecting variables
+ },
}),
],
diff --git a/.erb/configs/webpack.config.web.prod.ts b/.erb/configs/webpack.config.web.prod.ts
index 73cc32fc..ed935fd6 100644
--- a/.erb/configs/webpack.config.web.prod.ts
+++ b/.erb/configs/webpack.config.web.prod.ts
@@ -128,6 +128,9 @@ const configuration: webpack.Configuration = {
},
isBrowser: false,
isDevelopment: process.env.NODE_ENV !== 'production',
+ templateParameters: {
+ web: true,
+ },
}),
],
};
diff --git a/Dockerfile b/Dockerfile
index 856af4d2..fdf2c6ca 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,16 +1,20 @@
# --- Builder stage
FROM node:18-alpine as builder
WORKDIR /app
-COPY . /app
+#Copy package.json first to cache node_modules
+COPY package.json package-lock.json .
# Scripts include electron-specific dependencies, which we don't need
RUN npm install --legacy-peer-deps --ignore-scripts
+#Copy code and build with cached modules
+COPY . .
RUN npm run build:web
# --- Production stage
FROM nginx:alpine-slim
COPY --chown=nginx:nginx --from=builder /app/release/app/dist/web /usr/share/nginx/html
+COPY ./settings.js.template /etc/nginx/templates/settings.js.template
COPY ng.conf.template /etc/nginx/templates/default.conf.template
ENV PUBLIC_PATH="/"
diff --git a/README.md b/README.md
index faa5513b..a4a28652 100644
--- a/README.md
+++ b/README.md
@@ -81,6 +81,8 @@ docker run --name feishin -p 9180:9180 feishin
3. _Optional_ - If you want to host Feishin on a subpath (not `/`), then pass in the following environment variable: `PUBLIC_PATH=PATH`. For example, to host on `/feishin`, pass in `PUBLIC_PATH=/feishin`.
+4. _Optional_ - To hard code the server url, pass the following environment variables: `SERVER_NAME`, `SERVER_TYPE` (one of `jellyfin` or `navidrome`), `SERVER_URL`. To prevent users from changing these settings, pass `SERVER_LOCK=true`. This can only be set if all three of the previous values are set.
+
## FAQ
### MPV is either not working or is rapidly switching between pause/play states
diff --git a/docker-compose.yaml b/docker-compose.yaml
new file mode 100644
index 00000000..44308381
--- /dev/null
+++ b/docker-compose.yaml
@@ -0,0 +1,13 @@
+version: '3.5'
+services:
+ feishin:
+ container_name: feishin
+ image: jeffvli/feishin
+ restart: unless-stopped
+ ports:
+ - 9180:9180
+ environment:
+ - SERVER_NAME=jellyfin # pre defined server name
+ - SERVER_LOCK=true # When true AND name/type/url are set, only username/password can be toggled
+ - SERVER_TYPE=jellyfin # navidrome also works
+ - SERVER_URL= # http://address:port
diff --git a/ng.conf.template b/ng.conf.template
index 3fed35b8..eb46ff72 100644
--- a/ng.conf.template
+++ b/ng.conf.template
@@ -16,4 +16,12 @@ server {
alias /usr/share/nginx/html/;
try_files $uri $uri/ /index.html =404;
}
+
+ location ${PUBLIC_PATH}settings.js {
+ alias /etc/nginx/conf.d/settings.js;
+ }
+
+ location ${PUBLIC_PATH}/settings.js {
+ alias /etc/nginx/conf.d/settings.js;
+ }
}
\ No newline at end of file
diff --git a/package.json b/package.json
index 7be6527b..93e71ab1 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"build:remote": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.remote.prod.ts",
"build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts",
"build:web": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.web.prod.ts",
- "build:docker": "npm run build:web && docker build -t jeffvli/feishin .",
+ "build:docker": "docker build -t jeffvli/feishin .",
"rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app",
"lint": "concurrently \"npm run lint:code\" \"npm run lint:styles\"",
"lint:code": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx --fix",
diff --git a/settings.js.template b/settings.js.template
new file mode 100644
index 00000000..782f0d7e
--- /dev/null
+++ b/settings.js.template
@@ -0,0 +1 @@
+"use strict";window.SERVER_URL="${SERVER_URL}";window.SERVER_NAME="${SERVER_NAME}";window.SERVER_TYPE="${SERVER_TYPE}";window.SERVER_LOCK=${SERVER_LOCK};
diff --git a/src/main/preload/local-settings.ts b/src/main/preload/local-settings.ts
index b8aafba0..c6269411 100644
--- a/src/main/preload/local-settings.ts
+++ b/src/main/preload/local-settings.ts
@@ -1,6 +1,6 @@
import { IpcRendererEvent, ipcRenderer, webFrame } from 'electron';
import Store from 'electron-store';
-import type { TitleTheme } from '/@/renderer/types';
+import { toServerType, type TitleTheme } from '/@/renderer/types';
const store = new Store();
@@ -56,9 +56,20 @@ const themeSet = (theme: TitleTheme): void => {
ipcRenderer.send('theme-set', theme);
};
+const SERVER_TYPE = toServerType(process.env.SERVER_TYPE);
+
+const env = {
+ SERVER_LOCK:
+ SERVER_TYPE !== null ? process.env.SERVER_LOCK?.toLocaleLowerCase() === 'true' : false,
+ SERVER_NAME: process.env.SERVER_NAME ?? '',
+ SERVER_TYPE,
+ SERVER_URL: process.env.SERVER_URL ?? 'http://',
+};
+
export const localSettings = {
disableMediaKeys,
enableMediaKeys,
+ env,
fontError,
get,
passwordGet,
diff --git a/src/renderer/features/servers/components/add-server-form.tsx b/src/renderer/features/servers/components/add-server-form.tsx
index 16fd21b8..d55a34bc 100644
--- a/src/renderer/features/servers/components/add-server-form.tsx
+++ b/src/renderer/features/servers/components/add-server-form.tsx
@@ -8,7 +8,7 @@ import isElectron from 'is-electron';
import { nanoid } from 'nanoid/non-secure';
import { AuthenticationResponse } from '/@/renderer/api/types';
import { useAuthStoreActions } from '/@/renderer/store';
-import { ServerType } from '/@/renderer/types';
+import { ServerType, toServerType } from '/@/renderer/types';
import { api } from '/@/renderer/api';
import { useTranslation } from 'react-i18next';
@@ -33,15 +33,27 @@ export const AddServerForm = ({ onCancel }: AddServerFormProps) => {
const form = useForm({
initialValues: {
legacyAuth: false,
- name: '',
+ name: (localSettings ? localSettings.env.SERVER_NAME : window.SERVER_NAME) ?? '',
password: '',
savePassword: false,
- type: ServerType.JELLYFIN,
- url: 'http://',
+ type:
+ (localSettings
+ ? localSettings.env.SERVER_TYPE
+ : toServerType(window.SERVER_TYPE)) ?? ServerType.JELLYFIN,
+ url: (localSettings ? localSettings.env.SERVER_URL : window.SERVER_URL) ?? 'https://',
username: '',
},
});
+ // server lock for web is only true if lock is true *and* all other properties are set
+ const serverLock =
+ (localSettings
+ ? !!localSettings.env.SERVER_LOCK
+ : !!window.SERVER_LOCK &&
+ window.SERVER_TYPE &&
+ window.SERVER_NAME &&
+ window.SERVER_URL) || false;
+
const isSubmitDisabled = !form.values.name || !form.values.url || !form.values.username;
const handleSubmit = form.onSubmit(async (values) => {
@@ -62,7 +74,7 @@ export const AddServerForm = ({ onCancel }: AddServerFormProps) => {
password: values.password,
username: values.username,
},
- values.type,
+ values.type as ServerType,
);
if (!data) {
@@ -76,7 +88,7 @@ export const AddServerForm = ({ onCancel }: AddServerFormProps) => {
id: nanoid(),
name: values.name,
ndCredential: data.ndCredential,
- type: values.type,
+ type: values.type as ServerType,
url: values.url.replace(/\/$/, ''),
userId: data.userId,
username: data.username,
@@ -117,11 +129,13 @@ export const AddServerForm = ({ onCancel }: AddServerFormProps) => {
>
{
{...form.getInputProps('name')}
/>
Feishin
+ <% if (web) { %>
+
+ <% } %>
diff --git a/src/renderer/preload.d.ts b/src/renderer/preload.d.ts
index db69c9ba..7d8c9258 100644
--- a/src/renderer/preload.d.ts
+++ b/src/renderer/preload.d.ts
@@ -13,6 +13,10 @@ import { Browser } from '/@/main/preload/browser';
declare global {
interface Window {
+ SERVER_LOCK?: boolean;
+ SERVER_NAME?: string;
+ SERVER_TYPE?: string;
+ SERVER_URL?: string;
electron: {
browser: Browser;
discordRpc: DiscordRpc;
diff --git a/src/renderer/types.ts b/src/renderer/types.ts
index 4845d754..fe683f30 100644
--- a/src/renderer/types.ts
+++ b/src/renderer/types.ts
@@ -60,6 +60,17 @@ export enum ServerType {
SUBSONIC = 'subsonic',
}
+export const toServerType = (value?: string): ServerType | null => {
+ switch (value?.toLowerCase()) {
+ case ServerType.JELLYFIN:
+ return ServerType.JELLYFIN;
+ case ServerType.NAVIDROME:
+ return ServerType.NAVIDROME;
+ default:
+ return null;
+ }
+};
+
export type ServerListItem = {
credential: string;
features?: Record;