5 Commits

Author SHA1 Message Date
nkanaev
4b3a278679 Update changelog.md 2025-09-23 21:59:32 +01:00
nkanaev
aa06e65c59 redesign auto-refresh UI 2025-09-23 21:59:32 +01:00
nkanaev
dd57abefdd Update .gitignore 2025-09-23 21:59:32 +01:00
nkanaev
be8ba62bb1 make manifest.json public 2025-09-23 21:59:32 +01:00
nkanaev
b7895f6743 auth cookie directives 2025-09-23 21:59:32 +01:00
8 changed files with 48 additions and 13 deletions

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@
*.db-wal
*.syso
versioninfo.rc
.DS_Store

View File

@@ -1,7 +1,9 @@
# upcoming
- (new) serve on unix socket (thanks to @rvighne)
- (new) more auto-refresh options: 12h & 24h (thanks to @aswerkljh for suggestion)
- (fix) smooth scrolling on iOS (thanks to gatheraled)
- (etc) cookie security measures (thanks to Tom Fitzhenry)
# v2.5 (2025-03-26)

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg>

After

Width:  |  Height:  |  Size: 269 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-up"><polyline points="18 15 12 9 6 15"></polyline></svg>

After

Width:  |  Height:  |  Size: 268 B

View File

@@ -78,12 +78,20 @@
<header class="dropdown-header" role="heading" aria-level="2">Auto Refresh</header>
<div class="row text-center m-0">
<button class="dropdown-item col-4 px-0" :aria-pressed="!refreshRate" :class="{active: !refreshRate}" @click.stop="refreshRate = 0">0</button>
<button class="dropdown-item col-4 px-0" :aria-pressed="refreshRate == 10" :class="{active: refreshRate == 10}" @click.stop="refreshRate = 10">10m</button>
<button class="dropdown-item col-4 px-0" :aria-pressed="refreshRate == 30" :class="{active: refreshRate == 30}" @click.stop="refreshRate = 30">30m</button>
<button class="dropdown-item col-4 px-0" :aria-pressed="refreshRate == 60" :class="{active: refreshRate == 60}" @click.stop="refreshRate = 60">1h</button>
<button class="dropdown-item col-4 px-0" :aria-pressed="refreshRate == 120" :class="{active: refreshRate == 120}" @click.stop="refreshRate = 120">2h</button>
<button class="dropdown-item col-4 px-0" :aria-pressed="refreshRate == 240" :class="{active: refreshRate == 240}" @click.stop="refreshRate = 240">4h</button>
<button class="dropdown-item col-4 px-0"
@click.stop="changeRefreshRate(-1)"
:disabled="!refreshRate">
<span class="icon">
{% inline "chevron-down.svg" %}
</span>
</button>
<div class="col-4 d-flex align-items-center justify-content-center">{{ refreshRateTitle }}</div>
<button class="dropdown-item col-4 px-0"
@click.stop="changeRefreshRate(1)" :disabled="refreshRate === refreshRateOptions.at(-1).value">
<span class="icon">
{% inline "chevron-up.svg" %}
</span>
</button>
</div>
<div class="dropdown-divider"></div>

View File

@@ -252,6 +252,17 @@ var vm = new Vue({
'refreshRate': s.refresh_rate,
'authenticated': app.authenticated,
'feed_errors': {},
'refreshRateOptions': [
{ title: "0", value: 0 },
{ title: "10m", value: 10 },
{ title: "30m", value: 30 },
{ title: "1h", value: 60 },
{ title: "2h", value: 120 },
{ title: "4h", value: 240 },
{ title: "12h", value: 720 },
{ title: "24h", value: 1440 },
],
}
},
computed: {
@@ -309,7 +320,11 @@ var vm = new Vue({
contentVideos: function() {
if (!this.itemSelectedDetails) return []
return (this.itemSelectedDetails.media_links || []).filter(l => l.type === 'video')
}
},
refreshRateTitle: function () {
const entry = this.refreshRateOptions.find(o => o.value === this.refreshRate)
return entry ? entry.title : '0'
},
},
watch: {
'theme': {
@@ -778,6 +793,12 @@ var vm = new Vue({
if (target && scroll) scrollto(target, scroll)
})
},
changeRefreshRate: function(offset) {
const curIdx = this.refreshRateOptions.findIndex(o => o.value === this.refreshRate)
if (curIdx <= 0 && offset < 0) return
if (curIdx >= (this.refreshRateOptions.length - 1) && offset > 0) return
this.refreshRate = this.refreshRateOptions[curIdx + offset].value
},
}
})

View File

@@ -7,7 +7,6 @@ import (
"encoding/hex"
"net/http"
"strings"
"time"
)
func IsAuthenticated(req *http.Request, username, password string) bool {
@@ -26,8 +25,10 @@ func Authenticate(rw http.ResponseWriter, username, password, basepath string) {
http.SetCookie(rw, &http.Cookie{
Name: "auth",
Value: username + ":" + secret(username, password),
Expires: time.Now().Add(time.Hour * 24 * 7), // 1 week,
MaxAge: 604800, // 1 week
Path: basepath,
Secure: true,
SameSite: http.SameSiteLaxMode,
})
}

View File

@@ -34,7 +34,7 @@ func (s *Server) handler() http.Handler {
BasePath: s.BasePath,
Username: s.Username,
Password: s.Password,
Public: []string{"/static", "/fever"},
Public: []string{"/static", "/fever", "/manifest.json"},
DB: s.db,
}
r.Use(a.Handler)