theme-change: removed in favor of built in
This commit is contained in:
parent
2e71aa15ca
commit
d90dbb5156
6
Makefile
6
Makefile
|
@ -9,7 +9,6 @@ export GOOSE_MIGRATION_DIR=db/migrations
|
||||||
|
|
||||||
export REDMAGE_WEB_DEPENDENCIES_HTMX_VERSION=$(shell echo "$${REDMAGE_WEB_DEPENDENCIES_HTMX_VERSION:-1.9.12}")
|
export REDMAGE_WEB_DEPENDENCIES_HTMX_VERSION=$(shell echo "$${REDMAGE_WEB_DEPENDENCIES_HTMX_VERSION:-1.9.12}")
|
||||||
export REDMAGE_WEB_DEPENDENCIES_DAYJS_VERSION=$(shell echo "$${REDMAGE_WEB_DEPENDENCIES_DAYJS_VERSION:-1.11.10}")
|
export REDMAGE_WEB_DEPENDENCIES_DAYJS_VERSION=$(shell echo "$${REDMAGE_WEB_DEPENDENCIES_DAYJS_VERSION:-1.11.10}")
|
||||||
export REDMAGE_WEB_DEPENDENCIES_THEMECHANGE_VERSION=$(shell echo "$${REDMAGE_WEB_DEPENDENCIES_THEMECHANGE_VERSION:-2.0.2}")
|
|
||||||
|
|
||||||
start: dev-dependencies
|
start: dev-dependencies
|
||||||
@tailwindcss -i views/style.css -o public/style.css --watch &
|
@tailwindcss -i views/style.css -o public/style.css --watch &
|
||||||
|
@ -63,11 +62,6 @@ build-dependencies:
|
||||||
echo "Dayjs Timezone ${REDMAGE_WEB_DEPENDENCIES_DAYJS_VERSION} plugin not found, installing it"
|
echo "Dayjs Timezone ${REDMAGE_WEB_DEPENDENCIES_DAYJS_VERSION} plugin not found, installing it"
|
||||||
curl -o public/dayjs-timezone-${REDMAGE_WEB_DEPENDENCIES_DAYJS_VERSION}.min.js https://cdnjs.cloudflare.com/ajax/libs/dayjs/${REDMAGE_WEB_DEPENDENCIES_DAYJS_VERSION}/plugin/timezone.min.js
|
curl -o public/dayjs-timezone-${REDMAGE_WEB_DEPENDENCIES_DAYJS_VERSION}.min.js https://cdnjs.cloudflare.com/ajax/libs/dayjs/${REDMAGE_WEB_DEPENDENCIES_DAYJS_VERSION}/plugin/timezone.min.js
|
||||||
fi
|
fi
|
||||||
@if [ ! -f "public/theme-change-${REDMAGE_WEB_DEPENDENCIES_THEMECHANGE_VERSION}.min.js" ]; then
|
|
||||||
mkdir -p public
|
|
||||||
echo "Theme change ${REDMAGE_WEB_DEPENDENCIES_THEMECHANGE_VERSION} not found, installing it"
|
|
||||||
curl -o public/theme-change-${REDMAGE_WEB_DEPENDENCIES_THEMECHANGE_VERSION}.min.js https://cdn.jsdelivr.net/npm/theme-change@${REDMAGE_WEB_DEPENDENCIES_THEMECHANGE_VERSION}/index.js
|
|
||||||
fi
|
|
||||||
|
|
||||||
build: build-dependencies prepare
|
build: build-dependencies prepare
|
||||||
go build -o redmage
|
go build -o redmage
|
||||||
|
|
24
api/api.go
24
api/api.go
|
@ -31,8 +31,7 @@ type API struct {
|
||||||
|
|
||||||
config *config.Config
|
config *config.Config
|
||||||
|
|
||||||
imageSemaphore chan struct{}
|
imageSemaphore chan struct{}
|
||||||
subredditSemaphore chan struct{}
|
|
||||||
|
|
||||||
reddit *reddit.Reddit
|
reddit *reddit.Reddit
|
||||||
|
|
||||||
|
@ -56,17 +55,16 @@ func New(deps Dependencies) *API {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
api := &API{
|
api := &API{
|
||||||
db: bob.New(deps.DB),
|
db: bob.New(deps.DB),
|
||||||
sqldb: deps.DB,
|
sqldb: deps.DB,
|
||||||
scheduler: cron.New(),
|
scheduler: cron.New(),
|
||||||
scheduleMap: make(map[cron.EntryID]*models.Subreddit, 8),
|
scheduleMap: make(map[cron.EntryID]*models.Subreddit, 8),
|
||||||
downloadBroadcast: broadcast.NewRelay[bmessage.ImageDownloadMessage](),
|
downloadBroadcast: broadcast.NewRelay[bmessage.ImageDownloadMessage](),
|
||||||
config: deps.Config,
|
config: deps.Config,
|
||||||
imageSemaphore: make(chan struct{}, deps.Config.Int("download.concurrency.images")),
|
imageSemaphore: make(chan struct{}, deps.Config.Int("download.concurrency.images")),
|
||||||
subredditSemaphore: make(chan struct{}, deps.Config.Int("download.concurrency.subreddits")),
|
reddit: deps.Reddit,
|
||||||
reddit: deps.Reddit,
|
subscriber: deps.Subscriber,
|
||||||
subscriber: deps.Subscriber,
|
publisher: deps.Publisher,
|
||||||
publisher: deps.Publisher,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := api.StartScheduler(context.Background()); err != nil {
|
if err := api.StartScheduler(context.Background()); err != nil {
|
||||||
|
|
|
@ -56,9 +56,8 @@ var DefaultConfig = map[string]any{
|
||||||
|
|
||||||
"telemetry.trace.ratio": 1,
|
"telemetry.trace.ratio": 1,
|
||||||
|
|
||||||
"web.dependencies.htmx.version": "1.9.12",
|
"web.dependencies.htmx.version": "1.9.12",
|
||||||
"web.dependencies.dayjs.version": "1.11.10",
|
"web.dependencies.dayjs.version": "1.11.10",
|
||||||
"web.dependencies.themechange.version": "2.0.2",
|
|
||||||
|
|
||||||
"runtime.version": "0.0.1",
|
"runtime.version": "0.0.1",
|
||||||
"runtime.environment": "development",
|
"runtime.environment": "development",
|
||||||
|
|
|
@ -2,7 +2,7 @@ package components
|
||||||
|
|
||||||
templ Doctype() {
|
templ Doctype() {
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="en" data-theme="dark">
|
||||||
{ children... }
|
{ children... }
|
||||||
</html>
|
</html>
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,15 @@ import "github.com/tigorlazuardi/redmage/views"
|
||||||
|
|
||||||
templ Head(vc *views.Context, extras ...templ.Component) {
|
templ Head(vc *views.Context, extras ...templ.Component) {
|
||||||
<head>
|
<head>
|
||||||
|
<script>
|
||||||
|
document.querySelector('html').dataset.theme = localStorage.getItem('theme') || '';
|
||||||
|
</script>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<meta name="keywords" content="Reddit, Image, Downloader"/>
|
<meta name="keywords" content="Reddit, Image, Downloader"/>
|
||||||
<link rel="stylesheet" href="/public/style.css"/>
|
<link rel="stylesheet" href="/public/style.css"/>
|
||||||
<link rel="icon" href="/public/favicon.svg"/>
|
<link rel="icon" href="/public/favicon.svg"/>
|
||||||
@Dayjs(vc)
|
@Dayjs(vc)
|
||||||
@HTMX(vc)
|
@HTMX(vc)
|
||||||
@ThemeChange(vc)
|
|
||||||
if vc.Config.Bool("http.hotreload") {
|
if vc.Config.Bool("http.hotreload") {
|
||||||
<script src="/public/hot_reload.js"></script>
|
<script src="/public/hot_reload.js"></script>
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,9 @@ templ Navbar(c *views.Context) {
|
||||||
templ navList(c *views.Context) {
|
templ navList(c *views.Context) {
|
||||||
@createLink(c, "/", "Home", true)
|
@createLink(c, "/", "Home", true)
|
||||||
@createLink(c, "/config", "Config", false)
|
@createLink(c, "/config", "Config", false)
|
||||||
|
@createLink(c, "/devices", "Devices", true)
|
||||||
@createLink(c, "/subreddits", "Subreddits", true)
|
@createLink(c, "/subreddits", "Subreddits", true)
|
||||||
|
@createLink(c, "/schedules", "Schedules", true)
|
||||||
<div class="flex-1 flex-shrink-0"></div>
|
<div class="flex-1 flex-shrink-0"></div>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
@createLink(c, "/about", "About", true)
|
@createLink(c, "/about", "About", true)
|
||||||
|
@ -95,7 +97,7 @@ templ navList(c *views.Context) {
|
||||||
|
|
||||||
templ createLink(c *views.Context, path string, text string, boost bool) {
|
templ createLink(c *views.Context, path string, text string, boost bool) {
|
||||||
<a
|
<a
|
||||||
href={ templ.SafeURL(path) }
|
href={ templ.URL(path) }
|
||||||
class={ utils.CX(map[string]bool{
|
class={ utils.CX(map[string]bool{
|
||||||
"hover:bg-accent": true,
|
"hover:bg-accent": true,
|
||||||
"hover:text-neutral-50": true,
|
"hover:text-neutral-50": true,
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package components
|
|
||||||
|
|
||||||
import "github.com/tigorlazuardi/redmage/views"
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
templ ThemeChange(c *views.Context) {
|
|
||||||
<script src={ fmt.Sprintf("/public/theme-change-%s.min.js", c.Config.String("web.dependencies.themechange.version")) }></script>
|
|
||||||
}
|
|
|
@ -17,26 +17,44 @@ templ ConfigContent(c *views.Context) {
|
||||||
@components.Container() {
|
@components.Container() {
|
||||||
<h1>Config</h1>
|
<h1>Config</h1>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<div class="grid grid-cols-2 items-center">
|
<h2>Theme</h2>
|
||||||
<h2>Theme</h2>
|
@SelectThemeInput()
|
||||||
@SelectThemeInput()
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
</main>
|
</main>
|
||||||
}
|
}
|
||||||
|
|
||||||
templ SelectThemeInput() {
|
templ SelectThemeInput() {
|
||||||
<select class="select select-ghost select-bordered w-full" data-choose-theme>
|
<div
|
||||||
<option value="light">Light (Default)</option>
|
class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6 gap-4"
|
||||||
<option value="dark">Dark</option>
|
onchange="document.querySelector('html').dataset.theme = event.target.value; localStorage.setItem('theme', event.target.value)"
|
||||||
<option value="cupcake">Cupcake</option>
|
>
|
||||||
<option value="bumblebee">Bumblebee</option>
|
@themeRadio("default", "System (Default)")
|
||||||
<option value="emerald">Emerald</option>
|
@themeRadio("light", "Light")
|
||||||
<option value="corporate">Corporate</option>
|
@themeRadio("dark", "Dark")
|
||||||
<option value="synthwave">Synthwave</option>
|
@themeRadio("aqua", "Aqua")
|
||||||
<option value="retru">Retro</option>
|
@themeRadio("bumblebee", "Bumblebee")
|
||||||
<option value="cyberpunk">Cyberpunk</option>
|
@themeRadio("corporate", "Corporate")
|
||||||
<option value="valentine">Valentine</option>
|
@themeRadio("cupcake", "Cupcake")
|
||||||
<option value="halloween">Halloween</option>
|
@themeRadio("cyberpunk", "Cyberpunk")
|
||||||
</select>
|
@themeRadio("emerald", "Emerald")
|
||||||
|
@themeRadio("halloween", "Halloween")
|
||||||
|
@themeRadio("retro", "Retro")
|
||||||
|
@themeRadio("synthwave", "Synthwave")
|
||||||
|
@themeRadio("valentine", "Valentine")
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
{
|
||||||
|
const theme = localStorage.getItem('theme') || 'default';
|
||||||
|
document.querySelector(`input[name="theme-radios"][value="${theme}"]`).checked = true
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ themeRadio(value, display string) {
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label cursor-pointer gap-4 justify-start">
|
||||||
|
<input type="radio" name="theme-radios" class="radio theme-controller" value={ value }/>
|
||||||
|
<span class="label-text">{ display }</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,22 +28,9 @@ templ HomeContent(c *views.Context, data Data) {
|
||||||
@components.ErrorToast(data.Error)
|
@components.ErrorToast(data.Error)
|
||||||
} else {
|
} else {
|
||||||
<section class="mb-4 mx-auto">
|
<section class="mb-4 mx-auto">
|
||||||
<div
|
<h1 class="mb-4">
|
||||||
class="flex flex-wrap content-center gap-x-8"
|
Recently Added
|
||||||
hx-get="/"
|
</h1>
|
||||||
hx-target="#recently-added-images"
|
|
||||||
hx-select="#recently-added-images"
|
|
||||||
hx-swap="outerHTML"
|
|
||||||
hx-trigger="change"
|
|
||||||
hx-include="this"
|
|
||||||
hx-push-url="true"
|
|
||||||
>
|
|
||||||
<h1 class="mb-4">
|
|
||||||
Recently Added
|
|
||||||
</h1>
|
|
||||||
@recentRangeInput(c)
|
|
||||||
@nsfwToggle(c, data)
|
|
||||||
</div>
|
|
||||||
<div id="recently-added-images">
|
<div id="recently-added-images">
|
||||||
if data.TotalImages == 0 {
|
if data.TotalImages == 0 {
|
||||||
<h2 class="mt-4">There are no recently added images in the current time range.</h2>
|
<h2 class="mt-4">There are no recently added images in the current time range.</h2>
|
||||||
|
@ -52,6 +39,20 @@ templ HomeContent(c *views.Context, data Data) {
|
||||||
{ strconv.FormatInt(data.TotalImages, 10) } Images
|
{ strconv.FormatInt(data.TotalImages, 10) } Images
|
||||||
</h2>
|
</h2>
|
||||||
}
|
}
|
||||||
|
<div
|
||||||
|
id="filter-bar"
|
||||||
|
hx-get="/"
|
||||||
|
hx-target="#recently-added-images"
|
||||||
|
hx-select="#recently-added-images"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-trigger="change"
|
||||||
|
hx-include="this"
|
||||||
|
hx-push-url="true"
|
||||||
|
class="flex flex-wrap content-center gap-x-8"
|
||||||
|
>
|
||||||
|
@recentRangeInput(c)
|
||||||
|
@nsfwToggle(c, data)
|
||||||
|
</div>
|
||||||
for _, recently := range data.RecentlyAddedImages {
|
for _, recently := range data.RecentlyAddedImages {
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<h2 class="mt-4">{ recently.Device.Name }</h2>
|
<h2 class="mt-4">{ recently.Device.Name }</h2>
|
||||||
|
@ -82,19 +83,25 @@ templ HomeContent(c *views.Context, data Data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
templ recentRangeInput(c *views.Context) {
|
templ recentRangeInput(c *views.Context) {
|
||||||
<select
|
<div class="form-control">
|
||||||
name="created_at"
|
<label class="label gap-4">
|
||||||
class="select select-ghost select-bordered"
|
<span class="label-text">Range</span>
|
||||||
>
|
<select
|
||||||
@recentlyRangeOption(c, "-10800", "3 Hours")
|
id="select-range"
|
||||||
@recentlyRangeOption(c, "-21600", "6 Hours")
|
name="created_at"
|
||||||
@recentlyRangeOption(c, "-43200", "12 Hours")
|
class="select select-ghost select-bordered"
|
||||||
@recentlyRangeOption(c, "-86400", "1 Day")
|
>
|
||||||
@recentlyRangeOption(c, "-172800", "2 Days")
|
@recentlyRangeOption(c, "-10800", "3 Hours")
|
||||||
@recentlyRangeOption(c, "-259200", "3 Days")
|
@recentlyRangeOption(c, "-21600", "6 Hours")
|
||||||
@recentlyRangeOption(c, "-604800", "7 Days")
|
@recentlyRangeOption(c, "-43200", "12 Hours")
|
||||||
@recentlyRangeOption(c, "-2592000", "30 Days")
|
@recentlyRangeOption(c, "-86400", "1 Day")
|
||||||
</select>
|
@recentlyRangeOption(c, "-172800", "2 Days")
|
||||||
|
@recentlyRangeOption(c, "-259200", "3 Days")
|
||||||
|
@recentlyRangeOption(c, "-604800", "7 Days")
|
||||||
|
@recentlyRangeOption(c, "-2592000", "30 Days")
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
templ recentlyRangeOption(c *views.Context, value, text string) {
|
templ recentlyRangeOption(c *views.Context, value, text string) {
|
||||||
|
@ -108,22 +115,27 @@ templ recentlyRangeOption(c *views.Context, value, text string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
templ nsfwToggle(c *views.Context, data Data) {
|
templ nsfwToggle(c *views.Context, data Data) {
|
||||||
<select
|
<div class="form-control">
|
||||||
name="sfw"
|
<label class="label gap-4">
|
||||||
class="select select-ghost select-bordered"
|
<span class="label-text">NSFW</span>
|
||||||
>
|
<select
|
||||||
if (c.Request.URL.Query().Get("sfw") == "1") || data.SFW {
|
name="sfw"
|
||||||
<option value="0">NSFW - Show</option>
|
class="select select-ghost select-bordered"
|
||||||
<option selected="selected" value="1">NSFW - Hide</option>
|
>
|
||||||
} else {
|
if (c.Request.URL.Query().Get("sfw") == "1") || data.SFW {
|
||||||
<option selected="selected" value="0">NSFW - Show</option>
|
<option value="0">Show</option>
|
||||||
<option value="1">NSFW - Hide</option>
|
<option selected="selected" value="1">Hide</option>
|
||||||
}
|
} else {
|
||||||
</select>
|
<option selected="selected" value="0">Show</option>
|
||||||
|
<option value="1">Hide</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
templ RecentlyAddedImageList(images models.ImageSlice, opts components.ImageCardOption) {
|
templ RecentlyAddedImageList(images models.ImageSlice, opts components.ImageCardOption) {
|
||||||
<div class="overflow-x-auto flex gap-4 p-6 shadow-inner bg-base-300 rounded-2xl w-[85vw] md:w-full scrollbar-track-base-100 scrollbar-thumb-base-200 scrollbar-thin">
|
<div class="overflow-x-auto flex gap-4 p-6 shadow-inner bg-base-300 rounded-2xl w-[85vw] md:w-full scrollbar-track-base-100 scrollbar-thumb-primary scrollbar-thin hover:scrollbar-thumb-base-300">
|
||||||
for _, data := range images {
|
for _, data := range images {
|
||||||
@components.ImageCard(data, 0)
|
@components.ImageCard(data, 0)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue