12 Commits

Author SHA1 Message Date
8084f5171e chore(deps): update dependency eslint-plugin-vue to v9.33.0 2025-07-03 12:03:49 +00:00
ngn
2dabf74007 add submodules option to docker workflow
All checks were successful
docker / docker (push) Successful in 1m57s
ups / ups (push) Successful in 41s
Signed-off-by: ngn <ngn@ngn.tf>
2025-05-13 00:17:26 +03:00
ngn
f71f0e9ab7 add ups workflow and config
Some checks failed
docker / docker (push) Failing after 1m43s
Signed-off-by: ngn <ngn@ngn.tf>
2025-05-12 23:08:30 +03:00
ngn
02e9936059 update placeholder color for the searcbar
All checks were successful
Build and publish the docker image / build (push) Successful in 1m16s
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 12:32:47 +03:00
ngn
38b831243e im fucking losing it
All checks were successful
Build and publish the docker image / build (push) Successful in 1m15s
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 12:26:15 +03:00
ngn
b3a8c61d88 remove searchbar bg and just use bottom border
All checks were successful
Build and publish the docker image / build (push) Successful in 1m18s
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 12:14:08 +03:00
ngn
34a23278d4 i fucking hate js yeah fuck you
All checks were successful
Build and publish the docker image / build (push) Successful in 1m22s
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 11:59:01 +03:00
ngn
9c27a9c8e1 i dont understand
All checks were successful
Build and publish the docker image / build (push) Successful in 1m16s
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 11:22:35 +03:00
ngn
13df871685 fix :style attr for the searchbar
Some checks failed
Build and publish the docker image / build (push) Failing after 1m2s
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 11:13:50 +03:00
ngn
9b017e6153 get rid of the footer
Some checks failed
Build and publish the docker image / build (push) Failing after 1m1s
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 11:06:01 +03:00
ngn
fd255fdeb9 fix submodules option and remove privacy page
All checks were successful
Build and publish the docker image / build (push) Successful in 1m15s
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 10:29:06 +03:00
ngn
ad7a8bb439 make sure the workflow also clones submodules
Some checks failed
Build and publish the docker image / build (push) Failing after 53s
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 10:26:03 +03:00
21 changed files with 4975 additions and 238 deletions

3
.env
View File

@ -2,5 +2,4 @@ SAFETWITCH_BACKEND_DOMAIN=localhost:7000
SAFETWITCH_INSTANCE_DOMAIN=localhost:5173 SAFETWITCH_INSTANCE_DOMAIN=localhost:5173
SAFETWITCH_HTTPS=false SAFETWITCH_HTTPS=false
SAFETWITCH_DEFAULT_LOCALE=en-US SAFETWITCH_DEFAULT_LOCALE=en-US
SAFETWITCH_DEFAULT_THEME=dark SAFETWITCH_FALLBACK_LOCALE=en-US
SAFETWITCH_FALLBACK_LOCALE=en-US

View File

@ -1,28 +1,36 @@
name: Build and publish the docker image name: docker
on: on:
push: push:
branches: ["custom"] branches:
- 'main'
paths-ignore:
- 'README.md'
- 'LICENSE.txt'
- 'docker-compose.example.yml'
- 'ups.json'
env: env:
REGISTRY: git.ngn.tf REGISTRY: git.ngn.tf
IMAGE: ${{gitea.repository}} IMAGE: ${{gitea.repository}}
jobs: jobs:
build: docker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: "https://github.com/actions/checkout@v4" uses: actions/checkout@v4
with:
submodules: true
- name: Login to container repo - name: Login to container repo
uses: "https://github.com/docker/login-action@v1" uses: docker/login-action@v1
with: with:
registry: ${{env.REGISTRY}} registry: ${{env.REGISTRY}}
username: ${{gitea.actor}} username: ${{gitea.actor}}
password: ${{secrets.PACKAGES_TOKEN}} password: ${{secrets.PACKAGES_TOKEN}}
- name: Build image - name: Build docker image
run: | run: |
docker build . --tag ${{env.REGISTRY}}/${{env.IMAGE}}:latest docker build . --tag ${{env.REGISTRY}}/${{env.IMAGE}}:latest
docker push ${{env.REGISTRY}}/${{env.IMAGE}}:latest docker push ${{env.REGISTRY}}/${{env.IMAGE}}:latest

25
.gitea/workflows/ups.yml Normal file
View File

@ -0,0 +1,25 @@
name: ups
on:
schedule:
- cron: "@weekly"
jobs:
ups:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt update -y
sudo apt install -y python3 python3-build python3-requests make
- name: Install ups
run: |
git clone https://git.ngn.tf/ngn/ups && cd ups
make && make install
- name: Run ups
run: PATH=~/.local/bin:$PATH ups-check

View File

@ -5,7 +5,6 @@ ENV SAFETWITCH_INSTANCE_DOMAIN SAFETWITCH_INSTANCE_DOMAIN_PLACEHOLDER
ENV SAFETWITCH_HTTPS SAFETWITCH_HTTPS_PLACEHOLDER ENV SAFETWITCH_HTTPS SAFETWITCH_HTTPS_PLACEHOLDER
ENV SAFETWITCH_DEFAULT_LOCALE SAFETWITCH_DEFAULT_LOCALE_PLACEHOLDER ENV SAFETWITCH_DEFAULT_LOCALE SAFETWITCH_DEFAULT_LOCALE_PLACEHOLDER
ENV SAFETWITCH_FALLBACK_LOCALE SAFETWITCH_FALLBACK_LOCALE_PLACEHOLDER ENV SAFETWITCH_FALLBACK_LOCALE SAFETWITCH_FALLBACK_LOCALE_PLACEHOLDER
ENV SAFETWITCH_DEFAULT_THEME SAFETWITCH_DEFAULT_THEME_PLACEHOLDER
WORKDIR /app WORKDIR /app

View File

@ -1,5 +1,7 @@
# [ngn.tf] | safetwitch # safetwitch - frontend for twitch.tv
![](https://git.ngn.tf/ngn/safetwitch/actions/workflows/build.yml/badge.svg) ![](https://git.ngn.tf/ngn/safetwitch/actions/workflows/docker.yml/badge.svg)
![](https://git.ngn.tf/ngn/safetwitch/actions/workflows/ups.yml/badge.svg)
A fork of the [safetwitch](https://codeberg.org/safetwitch/safetwitch) project, with my personal changes. A fork of the [safetwitch](https://codeberg.org/safetwitch/safetwitch) project,
with my personal changes.

View File

@ -2,10 +2,6 @@ services:
st_frontend: st_frontend:
container_name: safetwitch_frontend container_name: safetwitch_frontend
image: git.ngn.tf/ngn/safetwitch image: git.ngn.tf/ngn/safetwitch
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
ports: ports:
- 8080:8280 - 8080:8280
environment: environment:

View File

@ -10,7 +10,6 @@ else
export SAFETWITCH_BACKEND_DOMAIN_PLACEHOLDER=SAFETWITCH_BACKEND_DOMAIN_PLACEHOLDER export SAFETWITCH_BACKEND_DOMAIN_PLACEHOLDER=SAFETWITCH_BACKEND_DOMAIN_PLACEHOLDER
export SAFETWITCH_INSTANCE_DOMAIN_PLACEHOLDER=SAFETWITCH_INSTANCE_DOMAIN_PLACEHOLDER export SAFETWITCH_INSTANCE_DOMAIN_PLACEHOLDER=SAFETWITCH_INSTANCE_DOMAIN_PLACEHOLDER
export SAFETWITCH_HTTPS_PLACEHOLDER=SAFETWITCH_HTTPS_PLACEHOLDER export SAFETWITCH_HTTPS_PLACEHOLDER=SAFETWITCH_HTTPS_PLACEHOLDER
export SAFETWITCH_DEFAULT_THEME_PLACEHOLDER=SAFETWITCH_DEFAULT_THEME_PLACEHOLDER
export SAFETWITCH_DEFAULT_LOCALE_PLACEHOLDER=SAFETWITCH_DEFAULT_LOCALE_PLACEHOLDER export SAFETWITCH_DEFAULT_LOCALE_PLACEHOLDER=SAFETWITCH_DEFAULT_LOCALE_PLACEHOLDER
export SAFETWITCH_FALLBACK_LOCALE_PLACEHOLDER=SAFETWITCH_FALLBACK_LOCALE_PLACEHOLDER export SAFETWITCH_FALLBACK_LOCALE_PLACEHOLDER=SAFETWITCH_FALLBACK_LOCALE_PLACEHOLDER
fi fi
@ -21,7 +20,6 @@ do
sed -i 's|'${SAFETWITCH_BACKEND_DOMAIN_PLACEHOLDER}'|'${SAFETWITCH_BACKEND_DOMAIN}'|g' $file sed -i 's|'${SAFETWITCH_BACKEND_DOMAIN_PLACEHOLDER}'|'${SAFETWITCH_BACKEND_DOMAIN}'|g' $file
sed -i 's|'${SAFETWITCH_INSTANCE_DOMAIN_PLACEHOLDER}'|'${SAFETWITCH_INSTANCE_DOMAIN}'|g' $file sed -i 's|'${SAFETWITCH_INSTANCE_DOMAIN_PLACEHOLDER}'|'${SAFETWITCH_INSTANCE_DOMAIN}'|g' $file
sed -i 's|'${SAFETWITCH_HTTPS_PLACEHOLDER}'|'${SAFETWITCH_HTTPS}'|g' $file sed -i 's|'${SAFETWITCH_HTTPS_PLACEHOLDER}'|'${SAFETWITCH_HTTPS}'|g' $file
sed -i 's|'${SAFETWITCH_DEFAULT_THEME_PLACEHOLDER}'|'${SAFETWITCH_DEFAULT_THEME}'|g' $file
sed -i 's|'${SAFETWITCH_DEFAULT_LOCALE_PLACEHOLDER}'|'${SAFETWITCH_DEFAULT_LOCALE}'|g' $file sed -i 's|'${SAFETWITCH_DEFAULT_LOCALE_PLACEHOLDER}'|'${SAFETWITCH_DEFAULT_LOCALE}'|g' $file
sed -i 's|'${SAFETWITCH_FALLBACK_LOCALE_PLACEHOLDER}'|'${SAFETWITCH_FALLBACK_LOCALE}'|g' $file sed -i 's|'${SAFETWITCH_FALLBACK_LOCALE_PLACEHOLDER}'|'${SAFETWITCH_FALLBACK_LOCALE}'|g' $file
# Your other variables here... # Your other variables here...
@ -31,9 +29,8 @@ done
echo -e "SAFETWITCH_BACKEND_DOMAIN_PLACEHOLDER=${SAFETWITCH_BACKEND_DOMAIN}" > .env.old echo -e "SAFETWITCH_BACKEND_DOMAIN_PLACEHOLDER=${SAFETWITCH_BACKEND_DOMAIN}" > .env.old
echo -e "SAFETWITCH_INSTANCE_DOMAIN_PLACEHOLDER=${SAFETWITCH_INSTANCE_DOMAIN}" >> .env.old echo -e "SAFETWITCH_INSTANCE_DOMAIN_PLACEHOLDER=${SAFETWITCH_INSTANCE_DOMAIN}" >> .env.old
echo -e "SAFETWITCH_HTTPS_PLACEHOLDER=${SAFETWITCH_HTTPS}" >> .env.old echo -e "SAFETWITCH_HTTPS_PLACEHOLDER=${SAFETWITCH_HTTPS}" >> .env.old
echo -e "SAFETWITCH_DEFAULT_THEME_PLACEHOLDER=${SAFETWITCH_DEFAULT_THEME}" >> .env.old
echo -e "SAFETWITCH_DEFAULT_LOCALE_PLACEHOLDER=${SAFETWITCH_DEFAULT_LOCALE}" >> .env.old echo -e "SAFETWITCH_DEFAULT_LOCALE_PLACEHOLDER=${SAFETWITCH_DEFAULT_LOCALE}" >> .env.old
echo -e "SAFETWITCH_FALLBACK_LOCALE_PLACEHOLDER=${SAFETWITCH_FALLBACK_LOCALE}" >> .env.old echo -e "SAFETWITCH_FALLBACK_LOCALE_PLACEHOLDER=${SAFETWITCH_FALLBACK_LOCALE}" >> .env.old
# Starting NGINX # Starting NGINX
nginx -g 'daemon off;' nginx -g 'daemon off;'

7
env.d.ts vendored
View File

@ -1,7 +1,7 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
// https://github.com/intlify/vue-i18n-next/issues/1403 // https://github.com/intlify/vue-i18n-next/issues/1403
/// <reference types="vite/client" /> /// <reference types="vite/client" />
/// <reference path="node_modules/vue-i18n/dist/vue-i18n.d.ts" /> /// <reference path="node_modules/vue-i18n/dist/vue-i18n.d.ts" />
declare module 'vue-i18n' declare module 'vue-i18n'
@ -13,10 +13,9 @@ interface ImportMetaEnv {
readonly SAFETWITCH_FALLBACK_LOCALE: string readonly SAFETWITCH_FALLBACK_LOCALE: string
readonly SAFETWITCH_COMMIT_HASH: string readonly SAFETWITCH_COMMIT_HASH: string
readonly SAFETWITCH_TAG: string readonly SAFETWITCH_TAG: string
readonly SAFETWITCH_DEFAULT_THEME: string
// more env variables... // more env variables...
} }
interface ImportMeta { interface ImportMeta {
readonly env: ImportMetaEnv readonly env: ImportMetaEnv
} }

5033
package-lock.json generated

File diff suppressed because it is too large Load Diff

5
renovate.json Normal file
View File

@ -0,0 +1,5 @@
{
"extends": ["config:recommended"],
"timezone": "Europe/Istanbul",
"prHourlyLimit": 20
}

View File

@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { RouterView } from 'vue-router' import { RouterView } from 'vue-router'
import NavbarItem from './components/NavbarView.vue' import NavbarItem from './components/NavbarView.vue'
import FooterItem from './components/FooterView.vue'
import DevWarning from './components/DevWarning.vue' import DevWarning from './components/DevWarning.vue'
import { getTheme } from '@/settingsManager' import { getTheme } from '@/settingsManager'
@ -11,13 +10,10 @@ const dev = import.meta.env.DEV
<template> <template>
<dev-warning v-if="dev"></dev-warning> <dev-warning v-if="dev"></dev-warning>
<div :class="getTheme()" class="flex flex-col justify-between min-h-[100vh] bg-primary"> <div :class="getTheme()" class="flex flex-col min-h-[100vh] bg-black">
<navbar-item></navbar-item> <navbar-item></navbar-item>
<Suspense> <Suspense>
<RouterView :key="$route.fullPath" /> <RouterView :key="$route.fullPath" />
</Suspense> </Suspense>
<footer-item></footer-item>
</div> </div>
</template> </template>

View File

@ -1,23 +0,0 @@
<script lang="ts">
const dev = import.meta.env.DEV
export default {
setup() {
let version = `${import.meta.env.SAFETWITCH_TAG}-${import.meta.env.SAFETWITCH_COMMIT_HASH}`
if (dev) {
version = version + '-dev'
}
return {
version
}
}
}
</script>
<template>
<div class="m-2 mt-5 flex justify-center">
<p class="text-contrast font-bold">SafeTwitch {{ version }}</p>
</div>
</template>

View File

@ -70,7 +70,11 @@ export default {
</template> </template>
<style> <style>
a:hover, router-link:hover { nav {
color:
}
ul a:hover, ul router-link:hover {
text-decoration: underline; text-decoration: underline;
} }

View File

@ -15,9 +15,8 @@ export default {
</script> </script>
<template> <template>
<div class="relative md:block"> <div class="relative md:block outline-none">
<label for="searchBar" class="hidden">{{ $t('main.search') }}</label> <label for="searchBar" class="hidden">{{ $t('main.search') }}</label>
<v-icon name="io-search-outline" class="absolute my-auto inset-y-0 left-2"></v-icon>
<input <input
type="text" type="text"
id="searchBar" id="searchBar"
@ -25,7 +24,7 @@ export default {
:placeholder="$t('main.search')" :placeholder="$t('main.search')"
v-model="searchInput" v-model="searchInput"
@keyup.enter="redirectToSearch" @keyup.enter="redirectToSearch"
class="rounded-md p-1 pl-8 w-56 text-white bg-black border-white outline-none placeholder:text-white w-full" class="rounded-md text-white bg-black placeholder:text-white w-full outline-none"
/> />
</div> </div>
</template> </template>

View File

@ -1,7 +1,6 @@
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router'
const UserView = () => import('../views/UserView.vue') const UserView = () => import('../views/UserView.vue')
const PageNotFound = () => import('../views/PageNotFound.vue') const PageNotFound = () => import('../views/PageNotFound.vue')
const PrivacyPageView = () => import('../views/PrivacyPageView.vue')
const HomepageView = () => import('../views/HomepageView.vue') const HomepageView = () => import('../views/HomepageView.vue')
const CategoryView = () => import('../views/CategoryView.vue') const CategoryView = () => import('../views/CategoryView.vue')
const SearchPageView = () => import('../views/SearchPageView.vue') const SearchPageView = () => import('../views/SearchPageView.vue')
@ -34,11 +33,6 @@ const router = createRouter({
path: '/directory/category/:game', path: '/directory/category/:game',
component: CategoryView component: CategoryView
}, },
{
path: '/privacy',
name: 'about',
component: PrivacyPageView
},
{ {
path: '/following', path: '/following',
component: FollowingView component: FollowingView

View File

@ -215,7 +215,7 @@ export function getFollows(): string[] {
* @default string light * @default string light
*/ */
export function getTheme(): string { export function getTheme(): string {
const selectedTheme = localStorage.getItem('theme') || import.meta.env.SAFETWITCH_DEFAULT_THEME const selectedTheme = localStorage.getItem('theme') || "dark"
if (selectedTheme === '') { if (selectedTheme === '') {
return 'light' return 'light'
@ -226,7 +226,7 @@ export function getTheme(): string {
if (t.length === 0) { if (t.length === 0) {
console.error(`Theme ${selectedTheme} does not exist... Perhaps improperly setup instance defaults or improper config? console.error(`Theme ${selectedTheme} does not exist... Perhaps improperly setup instance defaults or improper config?
Stored Theme: ${localStorage.getItem('theme')} Stored Theme: ${localStorage.getItem('theme')}
Default Theme: ${import.meta.env.SAFETWITCH_DEFAULT_THEME} Default Theme: black
`) `)
return 'light' return 'light'
} }
@ -244,7 +244,7 @@ export const themeList = [
// just as if you were to extend tailwind's theme like normal https://tailwindcss.com/docs/theme#extending-the-default-theme // just as if you were to extend tailwind's theme like normal https://tailwindcss.com/docs/theme#extending-the-default-theme
extend: { extend: {
colors: { colors: {
primary: '#000', primary: '#141515',
secondary: '#1e1f1f', secondary: '#1e1f1f',
overlay0: '#282a2a', overlay0: '#282a2a',
overlay1: '#323434', overlay1: '#323434',

View File

@ -83,7 +83,7 @@ export default {
<error-message ></error-message> <error-message ></error-message>
</div> </div>
<div v-show="data" class="max-w-5xl w-[100vw] mx-auto"> <div v-show="data" class="p-5">
<vue-title title="Discover"></vue-title> <vue-title title="Discover"></vue-title>
<div v-if="following && following.length > 0" class="p-2 text-contrast"> <div v-if="following && following.length > 0" class="p-2 text-contrast">
<h1 class="font-bold text-5xl">{{ $t('home.following') }}</h1> <h1 class="font-bold text-5xl">{{ $t('home.following') }}</h1>

View File

@ -1,33 +0,0 @@
<script lang="ts">
export default {}
</script>
<template>
<article class="prose prose-invert bg-crust rounded-lg mx-auto p-8 pt-10 text-contrast">
<h1>Privacy Policy</h1>
<p>
It's.... kind of empty here.
<br /><br />
No logs are kept by SafeTwitch, however instances may log requests with their reverse-proxy.
The following data is stored in your browser from using the site, however never goes outside your browser:
<ul>
<li>Selected settings</li>
<li>Followed streamers</li>
</ul>
The following data is sent outside of your browser to SafeTwitch's backend:
<ul>
<li>Language locale</li>
</ul>
The language locale is sent to SafeTwitch's backend per request, and is used to fetch the data from Twitch in the correct language
<br /><br />
Non-official instances are under their own privacy policy, as they may host SafeTwitch with
different practices that may log requests
</p>
</article>
</template>

View File

@ -115,12 +115,10 @@ export default {
</li> </li>
</ul> </ul>
<!---
<h1 class="font-bold text-3xl mt-2">{{ $t('main.themes') }}</h1> <h1 class="font-bold text-3xl mt-2">{{ $t('main.themes') }}</h1>
<hr class="my-2" /> <hr class="my-2" />
<ul class="flex space-x-2"> <ul class="flex space-x-2">
<!--
Use theme colors for preview
-->
<li <li
v-for="theme in themeList" v-for="theme in themeList"
:key="theme.name" :key="theme.name"
@ -150,5 +148,7 @@ export default {
class="bg-surface0 p-4 py-2 rounded-md" class="bg-surface0 p-4 py-2 rounded-md"
/> />
</div> </div>
-->
</div> </div>
</template> </template>

View File

@ -56,6 +56,6 @@ module.exports = {
] ]
}), }),
require('@tailwindcss/typography'), require('@tailwindcss/typography'),
require("@tailwindcss/forms") require("@tailwindcss/forms")
], ],
} }

5
ups.json Normal file
View File

@ -0,0 +1,5 @@
{
"upstream": "https://codeberg.org/safetwitch/safetwitch",
"provider": "gitea",
"commit": "f274ba527dd9ad9017ce4c97dc62622582ab82c3"
}