🚀 🔖 Release v0.3.0

This commit is contained in:
Aj - Thomas
2022-05-15 19:50:17 +02:00
committed by GitHub
68 changed files with 747 additions and 333 deletions

View File

@@ -1,12 +1,13 @@
name: ✨ Feature Request
description: Request a feature to help improve Homarr!
title: '<title>'
labels: ['✨ Feature']
body:
- type: textarea
id: feature
attributes:
label: Description
description: Describe the feature you would like to see. Tell us how you imagine it and try to provide as much usefull information as possible. **PLEASE** use images or drawings or anything to image your thoughts. Also please do not say "Like X and Y do" as we sometimes don't know what X and Y are.
description: Describe the feature you would like to see. Tell us how you imagine it and try to provide as much useful information as possible. **PLEASE** use images/screenshots, include details about X & Y when requesting changes like X & Y service does, make your description atleast 300 characters. Having an unclear issue with too little detail will result in your issue being marked as invalid and closed.
placeholder: An outline of the feature you would like to see implemented, include as much detail as possible!
validations:
required: true
@@ -21,3 +22,13 @@ body:
- High (App breaking feature)
validations:
required: true
- type: checkboxes
id: idiot-check
attributes:
label: Please tick the boxes
description: Before submitting, please ensure that
options:
- label: You've read the [docs](https://github.com/ajnart/homarr#readme)
required: true
- label: You've checked for [duplicate issues](https://github.com/ajnart/homarr/issues)
required: true

23
.github/ISSUE_TEMPLATE/idea.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: 🤔 Idea
description: Tell us your idea! We may implement it.
title: '<title>'
labels: ['🤔 Idea']
body:
- type: textarea
id: feature
attributes:
label: Description
description: Tell us your idea! Please add as much details as possible.
placeholder: Maybe move ... to ...! Maybe add the version of Homarr somewhere...! Etc.
validations:
required: true
- type: checkboxes
id: idiot-check
attributes:
label: Please tick the boxes
description: Before submitting, please ensure that
options:
- label: You've read the [docs](https://github.com/ajnart/homarr#readme)
required: true
- label: You've checked for [duplicate issues](https://github.com/ajnart/homarr/issues)
required: true

View File

@@ -1,18 +1,24 @@
name: Build and publish Docker image
name: Master docker CI
# Workflow to build and publish docker image
on:
push:
branches: [master]
tags:
- v*
workflow_dispatch:
env:
IMAGE_NAME: homarr
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
# Push image to GitHub Packages.
# See also https://docs.docker.com/docker-hub/builds/
build:
yarn_install_and_build:
# Will run yarn install && yarn build
runs-on: ubuntu-latest
steps:
- name: Setup
@@ -20,9 +26,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Get yarn cache directory path
# to help speed up build times
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Yarn cache
# to help speed up build times
uses: actions/cache@v3
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
@@ -43,6 +51,7 @@ jobs:
- run: yarn install --frozen-lockfile
- run: yarn build
- name: Cache build output
# to copy needed files to docker build job
uses: actions/cache@v2
id: restore-build
with:
@@ -52,11 +61,11 @@ jobs:
./public/
./.next/static/
./.next/standalone/
./packages.jsan
./packages.json
key: ${{ github.sha }}
docker:
needs: [build]
docker_image_build_and_push:
needs: [yarn_install_and_build]
runs-on: ubuntu-latest
permissions:
packages: write
@@ -73,14 +82,14 @@ jobs:
./public/
./.next/static/
./.next/standalone/
./packages.jsan
./packages.json
key: ${{ github.sha }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
# list of Docker images to use as base name for tags
images: ghcr.io/${{ github.repository }}
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=raw,value=latest
@@ -90,7 +99,6 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
registry: ghcr.io

116
.github/workflows/docker_dev.yml vendored Normal file
View File

@@ -0,0 +1,116 @@
name: Development CI
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on:
push:
branches: [dev]
pull_request:
workflow_dispatch:
inputs:
tags:
requierd: true
description: 'Tags to deploy to'
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
# Push image to GitHub Packages.
# See also https://docs.docker.com/docker-hub/builds/
yarn_install_and_build:
runs-on: ubuntu-latest
steps:
- name: Setup
uses: actions/setup-node@v3
- name: Checkout
uses: actions/checkout@v3
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Yarn cache
uses: actions/cache@v3
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: ${{ runner.os }}-yarn-
- name: Nextjs cache
uses: actions/cache@v2
with:
# See here for caching with `yarn` https://github.com/actions/cache/blob/main/examples.md#node---yarn or you can leverage caching with actions/setup-node https://github.com/actions/setup-node
path: |
~/.npm
${{ github.workspace }}/.next/cache
# Generate a new cache whenever packages or source files change.
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
# If source files changed but packages didn't, rebuild from a prior cache.
restore-keys: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
- run: yarn install --frozen-lockfile
- run: yarn build
- name: Cache build output
uses: actions/cache@v2
id: restore-build
with:
path: |
./next.config.js
./pages/
./public/
./.next/static/
./.next/standalone/
./packages.json
key: ${{ github.sha }}
docker_image_build_and_push:
needs: [yarn_install_and_build]
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: actions/cache@v2
id: restore-build
with:
path: |
./next.config.js
./pages/
./public/
./.next/static/
./.next/standalone/
./packages.json
key: ${{ github.sha }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
# list of Docker images to use as base name for tags
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=ref,event=pr
tpye=raw,value=dev,priority=1
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to GHCR
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v3
with:
platforms: linux/amd64,linux/arm64,linux/arm/v7
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -1,5 +1,5 @@
module.exports = {
stories: ['../components/**/*.story.mdx', '../components/**/*.story.*'],
stories: ['../src/components/**/*.story.mdx', '../src/components/**/*.story.*'],
addons: [
'storybook-dark-mode',
'@storybook/addon-links',

View File

@@ -10,11 +10,10 @@ COPY /package.json ./package.json
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --chown=nextjs:nodejs /.next/standalone ./
COPY --chown=nextjs:nodejs /.next/static ./.next/static
COPY /.next/standalone ./
COPY /.next/static ./.next/static
USER nextjs
EXPOSE 7575
ENV PORT 7575
VOLUME /app/data/configs
CMD ["node", "server.js"]
CMD ["node", "server.js"]

View File

@@ -1,7 +1,17 @@
<h3 align="center">Homarr</h3>
<br/>
<p align="center">
<a href="https://github.com/ajnart/homarr/actions/workflows/docker.yml">
<img title="Docker CI Status" src="https://github.com/ajnart/homarr/actions/workflows/docker.yml/badge.svg" alt="CI Status"></a>
<a href="https://github.com/ajnart/homarr/releases/latest">
<img alt="GitHub release (latest SemVer)" src="https://img.shields.io/github/v/release/ajnart/homarr"></a>
<a href="https://github.com/ajnart/homarr/pkgs/container/homarr">
<img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/ajnart/homarr?label=Downloads%20"></a>
</p>
<p align="center">
<img align="end" width=500 src="https://user-images.githubusercontent.com/49837342/168315259-b778c816-10fe-44db-bd25-3eea6f31b233.png" />
<a href="">
<img align="end" width=600 src="https://user-images.githubusercontent.com/49837342/168315259-b778c816-10fe-44db-bd25-3eea6f31b233.png" />
<a/>
</p>
<p align = "center">
A homepage for <i>your</i> server.
@@ -11,10 +21,11 @@
<br />
<i>Join the discord!</i>
<br />
<a href = "https://discord.gg/aCsmEV5RgA" > <img src="https://discordapp.com/api/guilds/972958686051962910/widget.png?style=shield" > </a>
<a href = "https://discord.gg/aCsmEV5RgA" > <img title="Discord" src="https://discordapp.com/api/guilds/972958686051962910/widget.png?style=shield" > </a>
<br/>
<br/>
</p>
# 📃 Table of Contents
- [📃 Table of Contents](#-table-of-contents)
- [🚀 Getting Started](#-getting-started)
@@ -34,11 +45,6 @@ Homarr is a simple and lightweight homepage for your server, that helps you easi
**[⤴️ Back to Top](#-table-of-contents)**
## 🐛 Known Issues
- Application cards not responsive https://github.com/ajnart/homarr/issues/47
- Icon alignment out for specific icons https://github.com/ajnart/homarr/issues/82
## ⚡ Installation
### Deploying from Docker Image 🐳

View File

@@ -1,93 +0,0 @@
import React, { useState } from 'react';
import { motion } from 'framer-motion';
import { Text, AspectRatio, SimpleGrid, Card, Image, Group, Space } from '@mantine/core';
import { useConfig } from '../../tools/state';
import { serviceItem } from '../../tools/types';
import AddItemShelfItem from './AddAppShelfItem';
import { AppShelfItemWrapper } from './AppShelfItemWrapper';
import AppShelfMenu from './AppShelfMenu';
const AppShelf = () => {
const { config } = useConfig();
return (
<SimpleGrid m="xl" cols={5} spacing="xl">
{config.services.map((service) => (
<AppShelfItem key={service.name} service={service} />
))}
<AddItemShelfItem />
</SimpleGrid>
);
};
export function AppShelfItem(props: any) {
const { service }: { service: serviceItem } = props;
const [hovering, setHovering] = useState(false);
return (
<motion.div
key={service.name}
onHoverStart={() => {
setHovering(true);
}}
onHoverEnd={() => {
setHovering(false);
}}
>
<AppShelfItemWrapper hovering={hovering}>
<Card.Section>
<Group position="apart" mx="lg">
<Space />
<Text
// TODO: #1 Remove this hack to get the text to be centered.
ml={15}
style={{
alignSelf: 'center',
alignContent: 'center',
alignItems: 'center',
justifyContent: 'center',
justifyItems: 'center',
}}
mt="sm"
weight={500}
>
{service.name}
</Text>
<motion.div
style={{
alignSelf: 'flex-end',
}}
animate={{
opacity: hovering ? 1 : 0,
}}
>
<AppShelfMenu service={service} />
</motion.div>
</Group>
</Card.Section>
<Card.Section>
<AspectRatio ratio={5 / 3} m="xl">
<motion.i
whileHover={{
cursor: 'pointer',
scale: 1.1,
}}
>
<Image
onClick={() => {
window.open(service.url);
}}
style={{
maxWidth: '50%',
marginBottom: 10,
}}
src={service.icon}
/>
</motion.i>
</AspectRatio>
</Card.Section>
</AppShelfItemWrapper>
</motion.div>
);
}
export default AppShelf;

View File

@@ -1,7 +0,0 @@
import { Welcome } from './Welcome';
export default {
title: 'Welcome',
};
export const Usage = () => <Welcome />;

View File

@@ -1,14 +0,0 @@
import { createStyles } from '@mantine/core';
export default createStyles((theme) => ({
title: {
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
fontSize: 100,
fontWeight: 900,
letterSpacing: -2,
[theme.fn.smallerThan('md')]: {
fontSize: 50,
},
},
}));

View File

@@ -1,12 +0,0 @@
import { render, screen } from '@testing-library/react';
import { Welcome } from './Welcome';
describe('Welcome component', () => {
it('has correct Next.js theming section link', () => {
render(<Welcome />);
expect(screen.getByText('this guide')).toHaveAttribute(
'href',
'https://mantine.dev/theming/next/'
);
});
});

View File

@@ -1,25 +0,0 @@
import { Title, Text, Anchor } from '@mantine/core';
import useStyles from './Welcome.styles';
export function Welcome() {
const { classes } = useStyles();
return (
<>
<Title className={classes.title} align="center" mt={100}>
Welcome to{' '}
<Text inherit variant="gradient" component="span">
Mantine
</Text>
</Title>
<Text color="dimmed" align="center" size="lg" sx={{ maxWidth: 580 }} mx="auto" mt="xl">
This starter Next.js project includes a minimal setup for server side rendering, if you want
to learn more on Mantine + Next.js integration follow{' '}
<Anchor href="https://mantine.dev/theming/next/" size="lg">
this guide
</Anchor>
. To get started edit index.tsx file.
</Text>
</>
);
}

View File

@@ -1,15 +0,0 @@
import { Text } from '@mantine/core';
import * as React from 'react';
export function Logo({ style }: any) {
return (
<Text
sx={style}
weight="bold"
variant="gradient"
gradient={{ from: 'red', to: 'orange', deg: 145 }}
>
Homarr
</Text>
);
}

View File

@@ -10,7 +10,7 @@
],
"settings": {
"searchBar": true,
"searchUrl": "https://google.com/search?q=",
"searchUrl": "https://duckduckgo.com/?q=",
"enabledModules": []
}
}

View File

@@ -1,2 +1,2 @@
export const REPO_URL = 'ajnart/homarr';
export const CURRENT_VERSION = 'v0.2.0';
export const CURRENT_VERSION = 'v0.3.0';

View File

@@ -1,16 +0,0 @@
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleNameMapper: {
'^@/components/(.*)$': '<rootDir>/components/$1',
'^@/pages/(.*)$': '<rootDir>/pages/$1',
},
testEnvironment: 'jest-environment-jsdom',
};
module.exports = createJestConfig(customJestConfig);

View File

@@ -1 +0,0 @@
import '@testing-library/jest-dom/extend-expect';

View File

@@ -1,8 +1,8 @@
{
"name": "homarr",
"version": "0.1.6",
"version": "0.3.0",
"private": "false",
"description": "Homarr - A homepage for your server.",
"description": "Homarr - A homepage for your server.",
"repository": {
"type": "git",
"url": "https://github.com/ajnart/homarr"

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 438 B

After

Width:  |  Height:  |  Size: 14 KiB

BIN
public/imgs/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

BIN
public/imgs/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

247
public/imgs/logo.svg Normal file
View File

@@ -0,0 +1,247 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1000.000000pt" height="1000.000000pt" viewBox="0 0 1000.000000 1000.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,1000.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M6470 9752 c-179 -11 -423 -57 -605 -113 -94 -29 -116 -37 -212 -73
-381 -144 -693 -333 -1030 -621 -6 -5 -63 -61 -126 -123 l-114 -113 -179 88
c-223 110 -305 143 -386 158 -12 3 -34 8 -48 11 -14 3 -100 8 -191 10 -154 4
-171 3 -253 -21 -159 -46 -241 -93 -355 -201 -55 -53 -101 -100 -101 -104 0
-10 76 18 110 41 39 26 206 108 253 124 61 20 202 42 294 44 56 1 105 -6 178
-24 55 -15 110 -28 122 -31 76 -15 317 -112 410 -165 l52 -30 -78 -97 c-152
-190 -244 -324 -230 -333 8 -5 17 -9 20 -9 4 0 12 -13 19 -30 18 -44 5 -139
-39 -269 -20 -62 -34 -114 -31 -116 4 -2 24 14 45 35 22 22 43 40 49 40 5 0
23 -10 40 -23 56 -42 210 -135 276 -167 36 -17 72 -35 80 -39 37 -20 139 -43
187 -43 35 0 64 6 88 21 l36 21 57 -38 c31 -21 76 -46 100 -55 52 -21 149 -32
188 -23 l28 7 -29 23 -29 24 54 34 c78 49 180 84 191 67 37 -57 119 -207 165
-304 75 -157 122 -306 134 -421 16 -157 43 -193 152 -199 56 -4 62 -2 90 26
29 29 30 33 25 89 -13 122 -191 536 -326 759 -53 87 -58 100 -41 102 6 1 13 2
18 3 4 1 39 5 77 10 104 11 156 17 195 21 19 3 62 7 95 10 112 11 246 45 470
120 370 124 716 314 905 497 278 269 418 532 380 714 l-12 58 -35 -43 c-48
-57 -116 -90 -216 -102 -117 -15 -165 -29 -198 -56 -23 -19 -32 -22 -48 -14
-51 27 -95 7 -160 -75 -30 -37 -60 -64 -73 -66 -13 -2 -50 2 -83 10 -79 17
-112 10 -189 -43 -107 -73 -120 -78 -196 -70 -84 8 -97 2 -176 -82 -56 -59
-63 -63 -94 -58 -18 3 -37 8 -41 11 -4 2 -25 7 -47 10 -37 5 -43 2 -111 -60
l-71 -66 -65 0 c-90 0 -160 -28 -221 -90 -47 -47 -52 -50 -103 -50 -49 0 -57
-3 -94 -41 -48 -47 -65 -57 -92 -53 -11 1 -39 6 -62 9 -29 4 -43 11 -43 21 0
30 20 52 53 58 23 4 38 15 45 31 16 35 49 53 112 59 66 7 99 29 169 113 28 34
60 67 72 73 11 6 55 14 97 16 84 5 91 9 133 71 20 29 40 45 65 52 35 10 47 9
141 -10 61 -12 82 -4 163 65 57 49 103 62 173 52 41 -6 43 -5 85 44 68 79 92
86 268 80 84 -3 113 9 175 75 95 100 156 119 227 73 44 -29 61 -28 110 6 57
39 107 56 141 50 26 -6 38 1 92 49 72 66 120 79 184 53 21 -9 39 -15 40 -14 1
2 9 14 18 28 51 75 -5 176 -155 283 -146 104 -224 134 -478 182 -61 11 -221
34 -280 40 -69 8 -327 12 -400 7z"/>
<path d="M8256 8794 c-3 -8 -3 -46 0 -82 4 -47 1 -86 -10 -128 -9 -34 -16 -93
-16 -131 0 -44 -7 -92 -20 -128 -23 -66 -25 -108 -9 -186 9 -47 8 -60 -10
-102 -26 -60 -26 -101 -1 -196 20 -74 20 -75 0 -145 -13 -48 -19 -102 -19
-166 1 -135 -25 -322 -56 -403 -28 -75 -31 -112 -14 -185 13 -54 8 -78 -42
-189 -23 -52 -23 -53 -5 -108 l17 -55 -35 -79 c-33 -71 -36 -87 -36 -168 0
-122 -47 -273 -85 -273 -21 0 -19 21 14 138 17 57 32 131 36 165 3 34 17 104
31 155 23 81 25 99 15 137 -17 67 -14 90 21 158 34 67 36 86 57 467 6 95 14
160 25 190 19 49 15 93 -10 121 -15 16 -14 23 10 83 31 78 32 109 6 176 -27
70 -25 89 15 146 40 56 46 111 19 189 -23 69 -21 113 9 188 26 62 27 74 21
156 -6 80 -5 93 15 124 28 45 27 54 -10 73 -92 47 -184 -42 -338 -326 -161
-298 -197 -386 -285 -705 -103 -375 -123 -584 -96 -1025 12 -204 25 -312 52
-458 11 -62 18 -116 14 -119 -3 -3 -79 10 -168 30 -175 39 -357 74 -429 83
-24 3 -51 7 -58 10 -24 8 -159 18 -241 19 l-75 0 -3 -81 c-4 -127 -9 -124 233
-139 55 -3 111 -7 125 -10 14 -2 48 -6 77 -9 28 -3 77 -9 110 -15 32 -6 76
-13 98 -16 22 -4 56 -10 75 -15 19 -5 51 -11 70 -14 47 -8 85 -15 148 -30 l32
-8 0 -64 c0 -77 13 -110 75 -195 66 -90 81 -119 63 -130 -21 -14 -51 -10 -91
11 -44 24 -45 20 -18 -71 45 -149 37 -167 -56 -132 -10 4 5 -19 34 -50 28 -32
73 -92 99 -135 138 -222 189 -263 378 -302 107 -22 170 -49 187 -82 13 -23 14
-73 3 -120 -5 -25 -3 -28 21 -28 34 0 52 10 136 75 73 56 115 70 181 60 68
-11 138 46 104 84 -20 22 -21 18 62 191 35 74 80 183 100 242 l35 107 56 -40
c74 -53 164 -142 201 -199 91 -142 192 -648 151 -754 -19 -47 -5 -41 24 11 58
105 70 156 69 308 -1 121 -5 152 -27 226 -32 107 -94 250 -142 329 -45 75
-166 204 -234 250 -28 19 -51 39 -51 44 0 5 29 99 65 210 35 111 73 235 84
276 30 112 75 399 86 550 4 47 9 99 11 115 8 66 4 496 -6 593 -32 335 -162
788 -297 1042 -130 243 -283 386 -487 456 -82 28 -82 28 -90 8z"/>
<path d="M6300 7695 c-1 -143 -35 -481 -66 -659 -49 -276 -106 -466 -195 -644
-56 -112 -56 -113 -35 -127 41 -29 54 -19 102 76 149 298 211 539 229 904 7
142 -10 484 -25 499 -7 7 -10 -12 -10 -49z"/>
<path d="M4095 7698 c-3 -7 -6 -56 -7 -108 -3 -89 -4 -95 -23 -92 -11 2 -35
19 -52 39 -18 20 -34 34 -34 32 -1 -2 -3 -33 -4 -69 -4 -82 -13 -153 -27 -207
l-10 -43 -46 40 c-24 22 -48 40 -52 40 -11 0 -24 -221 -17 -309 6 -83 37 -178
66 -205 73 -66 245 -71 421 -12 58 19 130 45 160 56 30 12 69 26 86 31 31 9
31 10 36 87 3 56 12 94 33 140 15 34 25 65 22 68 -3 4 -18 7 -32 7 -40 0 -35
14 50 133 59 81 99 160 91 180 -3 8 -44 13 -123 17 -65 2 -127 7 -138 10 -127
33 -204 66 -321 137 -74 45 -73 45 -79 28z"/>
<path d="M3450 7544 c-123 -70 -410 -433 -412 -522 -2 -71 84 -177 137 -170
19 3 41 40 96 158 9 19 31 61 48 93 22 38 36 81 42 127 10 68 62 184 136 303
28 44 16 47 -47 11z"/>
<path d="M4972 7109 c-21 -6 -32 -15 -29 -23 3 -6 13 -40 22 -75 17 -60 19
-62 46 -56 15 3 45 2 66 -4 90 -23 132 -20 98 9 -33 28 -15 32 98 26 109 -7
226 -20 273 -32 22 -6 24 -4 18 27 -4 19 -9 37 -13 41 -7 8 -256 73 -316 82
-71 12 -229 14 -263 5z"/>
<path d="M4810 7085 c-36 -7 -81 -18 -100 -24 -67 -21 -66 -18 -35 -135 15
-58 33 -106 38 -106 14 0 135 68 142 80 3 5 26 12 50 16 25 3 45 8 45 11 0 3
-6 31 -14 62 -8 31 -17 68 -20 84 -7 30 -9 31 -106 12z"/>
<path d="M7315 6989 c-227 -53 -672 -275 -915 -457 -73 -55 -231 -196 -284
-252 l-48 -53 26 -25 25 -25 83 84 c119 121 227 202 478 361 113 72 265 152
437 232 216 100 260 123 268 136 7 12 -15 11 -70 -1z"/>
<path d="M2974 6954 c-7 -29 1 -307 14 -484 10 -129 25 -174 70 -212 48 -40
97 -53 127 -34 13 9 29 25 35 37 20 37 22 160 6 313 -9 82 -16 172 -16 202 l0
53 -30 -9 c-17 -5 -33 -9 -35 -10 -32 -5 -130 93 -140 141 -8 36 -23 37 -31 3z"/>
<path d="M2484 6858 c-73 -124 -162 -305 -184 -376 -24 -78 -17 -102 47 -142
57 -36 90 -39 103 -7 17 41 49 232 59 359 6 69 13 131 16 139 11 30 22 109 15
109 -4 0 -29 -37 -56 -82z"/>
<path d="M4563 6824 c-64 -39 -317 -95 -423 -94 -96 0 -119 4 -180 25 l-42 15
7 -28 c8 -32 34 -67 105 -142 28 -30 77 -84 108 -120 30 -36 89 -100 131 -142
l76 -78 -63 0 c-34 0 -62 -3 -62 -7 0 -32 78 -102 230 -208 47 -33 135 -96
195 -141 61 -44 120 -86 133 -93 29 -16 50 -4 127 69 33 31 80 70 105 86 25
16 47 31 50 35 5 6 110 66 185 106 85 45 76 75 -57 189 -57 48 -208 192 -336
318 -127 127 -235 232 -240 233 -4 1 -26 -9 -49 -23z"/>
<path d="M5840 6684 c-30 -8 -82 -14 -115 -13 -33 0 -66 0 -73 0 -10 -1 -12
-21 -10 -82 3 -75 5 -84 29 -101 49 -37 193 -36 216 1 14 23 29 211 17 210 -5
-1 -34 -7 -64 -15z"/>
<path d="M3914 6633 c-49 -114 -125 -336 -135 -397 -15 -86 -7 -135 27 -175
46 -55 140 -50 163 7 5 15 11 59 13 97 3 56 13 91 51 179 26 60 47 114 47 122
0 7 -20 36 -45 64 -25 28 -54 68 -65 90 -28 54 -37 56 -56 13z"/>
<path d="M5620 6407 c-12 -34 -36 -88 -53 -120 -16 -31 -28 -60 -25 -62 3 -3
41 3 84 13 43 11 112 20 153 21 41 1 78 4 81 6 4 3 10 30 14 60 3 31 13 72 21
92 14 33 14 35 -3 28 -9 -4 -51 -9 -92 -11 -57 -2 -85 1 -117 16 l-41 18 -22
-61z"/>
<path d="M2257 6308 c7 -119 45 -313 89 -448 54 -167 71 -198 116 -202 42 -4
98 9 120 29 22 20 19 36 -48 243 -61 190 -84 277 -84 314 0 17 -7 29 -17 32
-46 15 -100 41 -134 66 -22 16 -40 28 -42 28 -2 0 -2 -28 0 -62z"/>
<path d="M5935 6220 c-31 -44 -212 -222 -264 -259 -54 -38 -24 2 65 89 91 89
149 158 141 167 -7 6 -266 -22 -357 -39 -225 -42 -501 -216 -745 -470 -199
-206 -250 -272 -266 -349 -32 -150 60 -415 211 -604 152 -190 373 -343 525
-361 161 -19 456 6 511 43 23 16 231 377 296 513 36 76 104 281 153 464 35
128 30 177 -34 351 -69 185 -71 193 -71 248 0 44 -2 48 -16 36 -24 -20 -69
-114 -108 -229 -43 -124 -64 -154 -35 -49 33 121 103 284 150 351 11 14 19 30
19 35 0 5 -25 24 -55 42 -30 18 -59 39 -66 47 -17 21 -24 18 -54 -26z"/>
<path d="M6446 6230 c-44 -16 -83 -35 -88 -42 -9 -14 -2 -158 11 -204 12 -45
34 -52 78 -23 21 14 50 33 66 43 l27 17 -1 119 c0 66 -4 120 -7 119 -4 0 -43
-13 -86 -29z"/>
<path d="M3010 6219 c0 -59 289 -869 310 -869 4 0 14 24 20 53 25 105 54 140
113 133 20 -2 37 -3 37 -1 0 1 -24 70 -54 152 -30 83 -83 241 -119 351 l-63
200 -28 -34 c-23 -30 -33 -34 -72 -34 -53 0 -108 23 -129 54 -15 20 -15 20
-15 -5z"/>
<path d="M6244 6124 c-99 -79 -102 -86 -80 -181 10 -43 30 -114 43 -157 25
-80 25 -80 38 -50 7 16 36 60 64 99 42 56 51 74 46 95 -4 14 -12 73 -19 133
-7 59 -15 109 -17 112 -3 2 -36 -20 -75 -51z"/>
<path d="M3980 6022 c0 -6 -14 -19 -32 -28 -32 -16 -118 -16 -161 1 -12 5 12
-54 79 -191 53 -110 143 -298 201 -419 57 -121 111 -227 119 -235 13 -13 18
-11 41 20 15 19 50 59 80 88 29 29 53 57 53 63 0 6 -63 122 -139 257 -77 136
-162 294 -190 351 -28 57 -51 99 -51 93z"/>
<path d="M6710 5911 c0 -5 20 -53 44 -107 73 -168 156 -442 156 -520 0 -45 4
-55 27 -74 30 -23 30 -23 118 14 33 13 76 26 95 28 31 4 35 8 38 38 6 62 -52
170 -92 170 -12 0 -14 -5 -6 -25 10 -25 4 -55 -10 -55 -4 0 -17 30 -29 68 -34
105 -161 299 -270 415 -51 54 -71 68 -71 48z"/>
<path d="M2571 5645 c-46 -37 -105 -47 -129 -23 -24 24 -11 -5 45 -100 127
-218 184 -296 292 -402 58 -58 138 -126 176 -152 l70 -46 5 53 c5 56 23 85 72
115 l28 17 -55 37 c-69 48 -253 262 -405 473 -25 34 -47 63 -50 63 -3 0 -25
-16 -49 -35z"/>
<path d="M3451 5493 c-38 -19 -78 -74 -87 -121 -6 -27 0 -40 35 -86 81 -105
479 -476 511 -476 6 0 122 145 128 159 7 19 -301 349 -441 473 -42 37 -85 68
-95 68 -9 0 -32 -8 -51 -17z"/>
<path d="M6261 5478 c-5 -18 -26 -95 -46 -172 -43 -164 -75 -256 -122 -350
-19 -37 -33 -69 -31 -70 87 -59 168 -125 365 -303 50 -44 100 -86 112 -92 18
-10 21 -9 21 9 0 11 -9 38 -20 60 -35 69 -24 89 27 46 15 -13 96 -70 178 -127
152 -105 292 -181 354 -193 l33 -6 -16 25 c-76 115 -126 250 -166 440 -12 61
-31 146 -41 190 l-18 80 -88 83 c-47 46 -159 137 -247 203 -89 65 -187 139
-218 164 -32 25 -59 45 -62 45 -2 0 -9 -15 -15 -32z"/>
<path d="M4348 5238 c-144 -142 -397 -435 -508 -588 -30 -41 -57 -77 -61 -80
-3 -3 -47 -66 -96 -140 -171 -258 -272 -462 -317 -640 -15 -63 -15 -69 5 -140
25 -90 96 -235 155 -315 75 -101 203 -224 329 -313 233 -166 540 -300 669
-293 26 1 149 124 355 352 192 213 185 205 287 334 298 379 438 604 535 862
22 57 39 106 39 108 0 3 -10 0 -22 -6 -59 -31 -124 -39 -318 -35 -214 4 -266
13 -379 68 -226 110 -420 341 -526 628 -25 66 -28 90 -29 192 -1 65 -2 118 -2
118 -1 0 -53 -51 -116 -112z"/>
<path d="M7119 5202 c-40 -20 -88 -35 -123 -39 l-58 -6 6 -30 c3 -16 6 -54 6
-83 0 -70 22 -84 90 -59 25 9 71 25 103 34 32 9 62 23 66 29 8 13 -4 139 -17
169 -6 17 -12 16 -73 -15z"/>
<path d="M7547 5062 c-107 -101 -138 -112 -183 -67 -19 19 -25 35 -24 63 1 20
2 41 1 45 -1 5 -19 -14 -41 -42 -25 -31 -60 -61 -91 -77 -55 -27 -60 -29 -159
-49 -63 -13 -90 -32 -90 -64 0 -75 49 -233 138 -441 53 -125 57 -130 106 -130
22 0 68 7 101 14 33 8 105 17 160 20 55 4 108 9 118 12 16 5 16 7 -3 31 -13
17 -17 30 -11 36 5 5 76 16 158 24 81 7 159 16 173 19 l25 6 -22 18 c-13 10
-23 22 -23 27 0 4 63 8 139 8 124 0 181 9 143 22 -31 11 -107 70 -110 84 -2
10 16 31 46 53 28 20 53 43 56 51 17 46 -45 76 -176 85 -80 6 -105 12 -145 35
-71 41 -115 93 -163 189 -23 47 -46 86 -52 86 -5 0 -37 -26 -71 -58z"/>
<path d="M3110 5050 c-30 -32 -60 -89 -60 -113 0 -30 218 -189 335 -245 28
-13 70 -34 95 -45 25 -12 83 -46 129 -76 l83 -54 19 24 c38 49 99 140 99 148
0 7 -271 201 -294 210 -6 2 -38 23 -71 47 -94 65 -234 134 -273 134 -25 0 -41
-8 -62 -30z"/>
<path d="M6768 4376 c-23 -32 -125 -100 -168 -114 -19 -5 -61 -13 -94 -16 -32
-4 -66 -11 -77 -16 -18 -10 -17 -11 3 -45 16 -29 19 -47 16 -93 -3 -31 -9 -65
-13 -76 -8 -18 -4 -18 61 -11 90 9 200 47 272 92 31 20 91 69 132 111 69 68
73 75 56 86 -11 6 -48 30 -84 54 -82 56 -84 56 -104 28z"/>
<path d="M7617 4137 l-168 -258 19 -42 c29 -64 55 -82 118 -81 64 0 107 30
167 114 45 64 47 78 8 51 -59 -42 -69 -12 -20 62 37 57 51 147 47 306 l-3 105
-168 -257z"/>
<path d="M5727 4246 c-18 -28 -87 -175 -87 -186 0 -10 16 -15 90 -29 142 -26
251 -34 442 -35 240 -1 239 -2 245 86 5 62 -18 117 -57 135 -14 6 -63 14 -110
18 -47 4 -98 9 -115 10 -39 4 -264 17 -337 20 -49 2 -60 -1 -71 -19z"/>
<path d="M7380 3778 c-132 -121 -284 -208 -435 -248 -44 -12 -84 -26 -89 -31
-12 -11 56 -94 103 -124 51 -34 83 -37 155 -15 61 19 75 27 181 101 28 19 86
56 130 82 57 34 95 66 133 112 28 35 52 66 52 69 0 4 -18 3 -39 0 -51 -8 -98
18 -120 68 l-16 36 -55 -50z"/>
<path d="M5472 3742 c-73 -100 -95 -133 -91 -136 11 -10 139 -84 169 -98 83
-39 250 -94 340 -113 8 -2 54 -12 101 -24 99 -24 102 -24 94 -11 -3 5 5 31 19
57 23 45 32 58 91 124 l23 27 -96 36 c-272 104 -445 166 -472 171 -16 3 -40 9
-54 15 -15 5 -26 7 -26 5 0 -2 -11 0 -24 5 -23 8 -29 3 -74 -58z"/>
<path d="M3247 3598 c-86 -146 -197 -363 -197 -384 0 -31 93 -210 170 -329
111 -171 289 -335 485 -450 61 -36 171 -90 205 -100 14 -4 30 -12 37 -17 6 -5
34 -12 60 -15 l49 -5 175 150 c194 167 261 232 239 233 -16 1 -36 4 -90 15
-19 4 -40 8 -47 10 -15 3 -103 30 -168 51 -27 9 -66 26 -85 37 -38 22 -192
127 -200 136 -3 3 -36 31 -75 62 -150 119 -296 276 -368 395 -21 34 -59 116
-86 183 l-48 122 -56 -94z"/>
<path d="M6223 3515 c-36 -15 -91 -77 -99 -112 -9 -34 5 -72 36 -94 79 -58
450 -92 655 -60 86 13 205 49 205 63 0 5 -4 7 -8 4 -5 -3 -31 5 -58 18 -57 26
-130 103 -139 147 -4 16 -10 27 -14 25 -26 -16 -282 -25 -341 -12 -140 31
-200 36 -237 21z"/>
<path d="M5280 3493 c0 -4 -13 -24 -29 -43 -124 -152 -122 -149 -103 -167 10
-10 60 -58 112 -107 52 -50 145 -138 205 -196 169 -162 200 -185 252 -185 39
0 49 5 79 37 19 22 34 48 34 62 0 55 -269 393 -388 487 -94 75 -162 122 -162
112z"/>
<path d="M7664 3103 c-32 -43 -63 -83 -68 -89 -6 -6 -29 -31 -51 -55 -63 -68
-155 -144 -205 -169 -113 -56 -129 -89 -73 -151 19 -21 51 -48 70 -60 l34 -21
22 20 c12 11 39 25 59 31 32 11 108 79 108 98 0 4 -5 2 -12 -5 -18 -18 -38
-15 -38 6 0 10 34 69 75 132 74 113 127 229 138 303 3 20 4 37 2 37 -2 0 -30
-35 -61 -77z"/>
<path d="M2978 3107 c-21 -34 -53 -87 -73 -116 -66 -103 -66 -103 10 -253 37
-73 93 -169 124 -212 69 -96 201 -232 279 -284 125 -86 361 -182 444 -182 15
0 47 16 75 36 53 40 173 154 173 166 0 3 -26 12 -57 18 -159 33 -220 63 -387
189 -235 178 -341 305 -483 576 -35 69 -65 125 -66 125 -1 0 -19 -28 -39 -63z"/>
<path d="M5845 2923 c28 -66 6 -126 -53 -142 -20 -6 -43 -11 -51 -11 -25 0 7
-27 125 -106 208 -138 505 -293 577 -301 57 -7 65 7 28 50 -35 39 -53 80 -45
101 3 8 21 20 41 27 20 6 39 21 45 35 13 28 4 42 -32 49 -44 8 -95 28 -145 55
-90 49 -178 96 -320 170 -77 40 -144 77 -149 81 -17 15 -29 10 -21 -8z"/>
<path d="M2810 2819 c0 -6 -41 -92 -91 -192 l-90 -182 80 -160 c44 -88 100
-186 125 -217 98 -123 325 -272 503 -329 71 -22 72 -22 115 -4 28 13 87 63
172 149 l130 130 -55 11 c-174 36 -347 131 -537 295 -107 92 -167 175 -260
357 -70 139 -92 173 -92 142z"/>
<path d="M7160 2680 c-33 -16 -114 -36 -305 -74 -88 -18 -270 -25 -297 -12
-15 7 -18 3 -18 -20 0 -39 -12 -56 -51 -68 -18 -6 -34 -17 -37 -24 -6 -18 66
-83 122 -111 55 -27 122 -24 310 13 321 64 429 96 464 139 11 12 7 16 -20 21
-57 12 -118 81 -118 136 0 23 -4 24 -50 0z"/>
<path d="M2517 2261 c-49 -79 -87 -151 -87 -165 0 -136 113 -336 251 -444 112
-88 271 -171 355 -186 16 -3 40 -8 54 -11 106 -21 112 -20 169 31 29 26 75 80
103 118 l50 71 -29 3 c-128 12 -337 119 -478 245 -87 78 -147 164 -231 334
l-70 144 -87 -140z"/>
<path d="M1575 2228 c-31 -18 -52 -48 -91 -126 -55 -113 -65 -150 -71 -254
-10 -168 27 -325 92 -394 30 -31 38 -35 65 -29 71 16 287 113 626 281 l251
125 -24 87 c-59 212 -46 189 -106 201 -28 6 -65 13 -82 16 -28 5 -46 8 -105
20 -14 2 -41 7 -60 10 -19 3 -71 12 -115 20 -44 8 -96 17 -115 20 -19 3 -46 7
-60 10 -117 21 -185 25 -205 13z"/>
<path d="M2365 1759 c-44 -21 -168 -81 -275 -133 -240 -116 -441 -226 -497
-272 l-42 -34 15 -53 c21 -69 86 -190 145 -269 96 -128 273 -278 329 -278 27
0 34 8 165 175 52 66 277 383 375 529 l91 136 -102 120 c-56 66 -107 120 -113
119 -6 0 -47 -18 -91 -40z"/>
<path d="M2635 1413 c-44 -60 -136 -187 -205 -283 -69 -96 -147 -204 -172
-240 -26 -36 -58 -79 -71 -95 -14 -17 -35 -47 -47 -68 -31 -53 -16 -84 71
-147 96 -70 184 -113 294 -145 309 -90 341 -79 360 120 7 71 65 426 111 673
13 73 24 140 24 148 0 8 -24 25 -52 38 -29 13 -92 42 -140 65 -48 22 -88 41
-90 41 -2 0 -39 -48 -83 -107z"/>
<path d="M3130 1390 c-14 -4 -39 -8 -57 -9 -17 -1 -34 -5 -37 -10 -22 -36
-127 -689 -133 -833 -7 -162 -9 -160 106 -157 47 2 100 6 116 10 17 4 44 10
60 12 86 13 298 79 368 114 66 33 74 54 47 134 -29 88 -159 348 -283 564 -95
166 -105 180 -133 182 -16 1 -40 -2 -54 -7z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -10,6 +10,8 @@ import {
Text,
Card,
LoadingOverlay,
ActionIcon,
Tooltip,
} from '@mantine/core';
import { useForm } from '@mantine/form';
import { motion } from 'framer-motion';
@@ -19,13 +21,42 @@ import { useConfig } from '../../tools/state';
import { ServiceTypeList } from '../../tools/types';
import { AppShelfItemWrapper } from './AppShelfItemWrapper';
export function AddItemShelfButton(props: any) {
const [opened, setOpened] = useState(false);
return (
<>
<Modal
size="xl"
radius="md"
opened={props.opened || opened}
onClose={() => setOpened(false)}
title="Add a service"
>
<AddAppShelfItemForm setOpened={setOpened} />
</Modal>
<ActionIcon
variant="default"
radius="md"
size="xl"
color="blue"
style={props.style}
onClick={() => setOpened(true)}
>
<Tooltip label="Add a service">
<Apps />
</Tooltip>
</ActionIcon>
</>
);
}
export default function AddItemShelfItem(props: any) {
const [opened, setOpened] = useState(false);
return (
<>
<Modal
size="xl"
radius="lg"
radius="md"
opened={props.opened || opened}
onClose={() => setOpened(false)}
title="Add a service"

View File

@@ -1,3 +1,4 @@
import { SimpleGrid } from '@mantine/core';
import AppShelf, { AppShelfItem } from './AppShelf';
export default {
@@ -16,3 +17,10 @@ export default {
export const Default = (args: any) => <AppShelf {...args} />;
export const One = (args: any) => <AppShelfItem {...args} />;
export const Ten = (args: any) => (
<SimpleGrid>
{Array.from(Array(10)).map((_, i) => (
<AppShelfItem {...args} key={i} />
))}
</SimpleGrid>
);

View File

@@ -0,0 +1,104 @@
import React, { useState } from 'react';
import { motion } from 'framer-motion';
import { Text, AspectRatio, SimpleGrid, Card, Image, useMantineTheme } from '@mantine/core';
import { useConfig } from '../../tools/state';
import { serviceItem } from '../../tools/types';
import AppShelfMenu from './AppShelfMenu';
const AppShelf = () => {
const { config } = useConfig();
return (
<SimpleGrid
cols={7}
spacing="xl"
breakpoints={[
{ maxWidth: 2400, cols: 6, spacing: 'xl' },
{ maxWidth: 1800, cols: 5, spacing: 'xl' },
{ maxWidth: 1500, cols: 4, spacing: 'lg' },
{ maxWidth: 800, cols: 3, spacing: 'md' },
{ maxWidth: 400, cols: 3, spacing: 'sm' },
{ maxWidth: 400, cols: 2, spacing: 'sm' },
]}
>
{config.services.map((service) => (
<AppShelfItem key={service.name} service={service} />
))}
</SimpleGrid>
);
};
export function AppShelfItem(props: any) {
const { service }: { service: serviceItem } = props;
const [hovering, setHovering] = useState(false);
const theme = useMantineTheme();
return (
<motion.div
key={service.name}
onHoverStart={() => {
setHovering(true);
}}
onHoverEnd={() => {
setHovering(false);
}}
>
<Card
style={{
boxShadow: hovering ? '0px 0px 3px rgba(0, 0, 0, 0.5)' : '0px 0px 1px rgba(0, 0, 0, 0.5)',
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[1],
}}
radius="md"
>
<Card.Section>
<Text mt="sm" align="center" lineClamp={1} weight={500}>
{service.name}
</Text>
<motion.div
style={{
position: 'absolute',
top: 5,
right: 5,
alignSelf: 'flex-end',
}}
animate={{
opacity: hovering ? 1 : 0,
}}
>
<AppShelfMenu service={service} />
</motion.div>
</Card.Section>
<Card.Section>
<AspectRatio
ratio={3 / 5}
m="xl"
style={{
width: 150,
height: 90,
}}
>
<motion.i
whileHover={{
cursor: 'pointer',
scale: 1.1,
}}
>
<Image
style={{
maxWidth: 80,
}}
fit="contain"
onClick={() => {
window.open(service.url);
}}
src={service.icon}
/>
</motion.i>
</AspectRatio>
</Card.Section>
</Card>
</motion.div>
);
}
export default AppShelf;

View File

@@ -8,10 +8,6 @@ export function AppShelfItemWrapper(props: any) {
style={{
boxShadow: hovering ? '0px 0px 3px rgba(0, 0, 0, 0.5)' : '0px 0px 1px rgba(0, 0, 0, 0.5)',
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[1],
//TODO: #3 Fix this temporary fix and make the width and height dynamic / responsive
width: 200,
height: 180,
}}
radius="md"
>

View File

@@ -22,6 +22,7 @@ export default function SearchBar(props: any) {
return (
<Box
mb={"xl"}
style={{
width: '100%',
}}
@@ -80,8 +81,7 @@ export default function SearchBar(props: any) {
}
>
<Text>
tip: You can prefix your querry with <b>!yt</b> or <b>!t</b> to research on youtube or
for a torrent
tip: Use the prefixes <b>!yt</b> and <b>!t</b> in front of your query to search on YouTube or for a Torrent respectively.
</Text>
</Popover>
</form>

View File

@@ -9,11 +9,12 @@ import {
SegmentedControl,
Indicator,
Alert,
TextInput,
} from '@mantine/core';
import { useColorScheme } from '@mantine/hooks';
import { useEffect, useState } from 'react';
import { AlertCircle, Settings as SettingsIcon } from 'tabler-icons-react';
import { CURRENT_VERSION, REPO_URL } from '../../data/constants';
import { CURRENT_VERSION, REPO_URL } from '../../../data/constants';
import { useConfig } from '../../tools/state';
import { ColorSchemeSwitch } from '../ColorSchemeToggle/ColorSchemeSwitch';
import ConfigChanger from '../Config/ConfigChanger';
@@ -24,11 +25,19 @@ function SettingsMenu(props: any) {
const { config, setConfig } = useConfig();
const colorScheme = useColorScheme();
const { current, latest } = props;
const matches = [
{ label: 'Google', value: 'https://google.com/search?q=' },
{ label: 'DuckDuckGo', value: 'https://duckduckgo.com/?q=' },
{ label: 'Bing', value: 'https://bing.com/search?q=' },
{ label: 'Custom', value: 'Custom' },
];
const [customSearchUrl, setCustomSearchUrl] = useState(config.settings.searchUrl);
const [searchUrl, setSearchUrl] = useState(
matches.find((match) => match.value === config.settings.searchUrl)?.value ?? 'Custom'
);
return (
<Group direction="column" grow>
<Alert
@@ -37,29 +46,49 @@ function SettingsMenu(props: any) {
radius="lg"
hidden={current === latest}
>
Version {latest} is available. Current : {current}
Version {latest} is available. Current: {current}
</Alert>
<Group>
<Group grow direction="column" spacing={0}>
<Text>Search engine</Text>
<SegmentedControl
fullWidth
title="Search engine"
value={
// Match config.settings.searchUrl with a key in the matches array
matches.find((match) => match.value === config.settings.searchUrl)?.value ?? 'Google'
searchUrl
}
onChange={
// Set config.settings.searchUrl to the value of the selected item
(e) =>
(e) => {
setSearchUrl(e);
setConfig({
...config,
settings: {
...config.settings,
searchUrl: e,
},
})
});
}
}
data={matches}
/>
<Text>Search engine</Text>
{searchUrl === 'Custom' && (
<TextInput
label="Querry URL"
placeholder="Custom querry url"
value={customSearchUrl}
onChange={(event) => {
setCustomSearchUrl(event.currentTarget.value);
setConfig({
...config,
settings: {
...config.settings,
searchUrl: event.currentTarget.value,
},
});
}}
/>
)}
</Group>
<Group direction="column">
<Switch
@@ -122,7 +151,7 @@ export function SettingsMenuButton(props: any) {
</Modal>
<ActionIcon
variant="default"
radius="xl"
radius="md"
size="xl"
color="blue"
style={props.style}

View File

@@ -1,18 +1,22 @@
import { Aside as MantineAside } from '@mantine/core';
import { Aside as MantineAside, Group } from '@mantine/core';
import { CalendarModule } from '../modules/calendar/CalendarModule';
import ModuleWrapper from '../modules/moduleWrapper';
export default function Aside() {
return (
<MantineAside
height="100%"
hiddenBreakpoint="md"
hidden
style={{
border: 'none',
}}
width={{
base: 'auto',
}}
>
<ModuleWrapper module={CalendarModule} />
<Group mt="sm" direction="column">
<ModuleWrapper module={CalendarModule} />
</Group>
</MantineAside>
);
}

View File

@@ -1,5 +1,12 @@
import React from 'react';
import { createStyles, Anchor, Text, Group, ActionIcon } from '@mantine/core';
import {
createStyles,
Anchor,
Text,
Group,
ActionIcon,
Footer as FooterComponent,
} from '@mantine/core';
import { BrandGithub } from 'tabler-icons-react';
const useStyles = createStyles((theme) => ({
@@ -48,34 +55,39 @@ export function Footer({ links }: FooterCenteredProps) {
));
return (
<Group
sx={{
position: 'fixed',
bottom: 0,
right: 15,
}}
direction="row"
align="center"
mb={15}
>
<Group className={classes.links}>{items}</Group>
<Group spacing="xs" position="right" noWrap>
<ActionIcon<'a'> component="a" href="https://github.com/ajnart/homarr" size="lg">
<BrandGithub size={18} />
</ActionIcon>
</Group>
<Text
style={{
fontSize: '0.75rem',
textAlign: 'center',
color: '#a0aec0',
<FooterComponent height="auto" style={{ border: 'none' }}>
<Group
sx={{
position: 'fixed',
bottom: 0,
right: 15,
}}
direction="row"
align="center"
mb={15}
>
Made with by @
<Anchor href="https://github.com/ajnart" style={{ color: 'inherit', fontStyle: 'inherit' }}>
ajnart
</Anchor>
</Text>
</Group>
<Group className={classes.links}>{items}</Group>
<Group spacing="xs" position="right" noWrap>
<ActionIcon<'a'> component="a" href="https://github.com/ajnart/homarr" size="lg">
<BrandGithub size={18} />
</ActionIcon>
</Group>
<Text
style={{
fontSize: '0.90rem',
textAlign: 'center',
color: '#a0aec0',
}}
>
Made with by @
<Anchor
href="https://github.com/ajnart"
style={{ color: 'inherit', fontStyle: 'inherit', fontSize: 'inherit' }}
>
ajnart
</Anchor>
</Text>
</Group>
</FooterComponent>
);
}

View File

@@ -1,18 +1,11 @@
import React, { useState } from 'react';
import {
createStyles,
Header as Head,
Container,
Group,
Burger,
Drawer,
Center,
} from '@mantine/core';
import React from 'react';
import { createStyles, Header as Head, Group, Drawer, Center } from '@mantine/core';
import { useBooleanToggle } from '@mantine/hooks';
import { NextLink } from '@mantine/next';
import { Logo } from './Logo';
import { SettingsMenuButton } from '../Settings/SettingsMenu';
import CalendarComponent from '../modules/calendar/CalendarModule';
import { SettingsMenuButton } from '../Settings/SettingsMenu';
import { AddItemShelfButton } from '../AppShelf/AddAppShelfItem';
const HEADER_HEIGHT = 60;
@@ -40,8 +33,6 @@ const useStyles = createStyles((theme) => ({
header: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
height: '100%',
},
@@ -94,62 +85,33 @@ interface HeaderResponsiveProps {
export function Header({ links }: HeaderResponsiveProps) {
const [opened, toggleOpened] = useBooleanToggle(false);
const [active, setActive] = useState('/');
const { classes, cx } = useStyles();
const items = (
<>
{links.map((link) => (
<NextLink
key={link.label}
href={link.link}
className={cx(classes.link, { [classes.linkActive]: active === link.link })}
onClick={(event) => {
setActive(link.link);
toggleOpened(false);
}}
>
{link.label}
</NextLink>
))}
</>
);
return (
<Head height={HEADER_HEIGHT} mb={10} className={classes.root}>
<Container className={classes.header}>
<Group>
<NextLink style={{ textDecoration: 'none' }} href="/">
<Logo style={{ fontSize: 22 }} />
</NextLink>
</Group>
<Group spacing={5} className={classes.links}>
{items}
</Group>
<Head height={HEADER_HEIGHT}>
<Group direction="row" align="center" position="apart" className={classes.header} mx="xl">
<NextLink style={{ textDecoration: 'none' }} href="/">
<Logo style={{ fontSize: 22 }} />
</NextLink>
<Group>
<SettingsMenuButton />
<Burger
opened={opened}
onClick={() => toggleOpened()}
className={classes.burger}
size="sm"
/>
<AddItemShelfButton />
</Group>
</Group>
<Drawer
opened={opened}
overlayOpacity={0.55}
overlayBlur={3}
onClose={() => toggleOpened()}
position="right"
>
{opened ?? (
<Center>
<CalendarComponent />
</Center>
)}
</Drawer>
</Container>
<Drawer
opened={opened}
overlayOpacity={0.55}
overlayBlur={3}
onClose={() => toggleOpened()}
position="right"
>
{opened ?? (
<Center>
<CalendarComponent />
</Center>
)}
</Drawer>
</Head>
);
}

View File

@@ -7,7 +7,7 @@ import Navbar from './Navbar';
const useStyles = createStyles((theme) => ({
main: {
[theme.fn.largerThan('md')]: {
width: 1200,
maxWidth: 1500,
},
},
}));

View File

@@ -0,0 +1,40 @@
import { Group, Image, Text } from '@mantine/core';
import * as React from 'react';
import { CURRENT_VERSION } from '../../../data/constants';
export function Logo({ style }: any) {
return (
<Group>
<Image
width={50}
src="/imgs/logo.png"
style={{
position: 'relative',
left: 15,
}}
/>
<Text
sx={style}
weight="bold"
variant="gradient"
gradient={{ from: 'red', to: 'orange', deg: 145 }}
>
Homarr
</Text>
<Text
style={{
position: 'relative',
left: -14,
bottom: -2,
color: 'gray',
fontStyle: 'inherit',
fontSize: 'inherit',
alignSelf: 'center',
alignContent: 'center',
}}
>
{CURRENT_VERSION}
</Text>
</Group>
);
}

View File

@@ -1,18 +1,22 @@
import { Navbar as MantineNavbar } from '@mantine/core';
import { Group, Navbar as MantineNavbar } from '@mantine/core';
import { DateModule } from '../modules/date/DateModule';
import ModuleWrapper from '../modules/moduleWrapper';
export default function Navbar() {
return (
<MantineNavbar
height="100%"
hiddenBreakpoint="md"
hiddenBreakpoint="lg"
hidden
style={{
border: 'none',
}}
width={{
base: 'auto',
}}
>
<ModuleWrapper module={DateModule} />
<Group mt="sm" direction="column">
<ModuleWrapper module={DateModule} />
</Group>
</MantineNavbar>
);
}

View File

@@ -2,9 +2,8 @@
import { Popover, Box, ScrollArea, Divider, Indicator } from '@mantine/core';
import React, { useEffect, useState } from 'react';
import { Calendar } from '@mantine/dates';
import { CalendarIcon } from '@modulz/radix-icons';
import { showNotification } from '@mantine/notifications';
import { Check } from 'tabler-icons-react';
import { Calendar as CalendarIcon, Check } from 'tabler-icons-react';
import { RadarrMediaDisplay, SonarrMediaDisplay } from './MediaDisplay';
import { useConfig } from '../../../tools/state';
import { IModule } from '../modules';

View File

@@ -5,6 +5,7 @@ import { getCookie, setCookies } from 'cookies-next';
import Head from 'next/head';
import { MantineProvider, ColorScheme, ColorSchemeProvider } from '@mantine/core';
import { NotificationsProvider } from '@mantine/notifications';
import { useHotkeys } from '@mantine/hooks';
import Layout from '../components/layout/Layout';
import { ConfigProvider } from '../tools/state';
import { theme } from '../tools/theme';
@@ -18,6 +19,7 @@ export default function App(props: AppProps & { colorScheme: ColorScheme }) {
setColorScheme(nextColorScheme);
setCookies('color-scheme', nextColorScheme, { maxAge: 60 * 60 * 24 * 30 });
};
useHotkeys([['mod+J', () => toggleColorScheme()]]);
return (
<>

View File

@@ -15,6 +15,6 @@
"jsx": "preserve",
"incremental": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "next.config.js"],
"exclude": ["node_modules"]
}