commits
Signed-off-by: eti <eti@eti.tf>
Signed-off-by: Matías Insaurralde <matias@insaurral.de>
Signed-off-by: Patrick Dewey <p@pdewey.com>
larger hitslop for thumbs
Signed-off-by: oppiliappan <me@oppi.li>
This is API call is idempotent. If the contact doesn't previously exist
on Resend, adding to Segment will fail.
Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.org>
Signed-off-by: oppiliappan <me@oppi.li>
Signed-off-by: oppiliappan <me@oppi.li>
Signed-off-by: oppiliappan <me@oppi.li>
the newsletter widget used only localStorage to remember whether a user
had signed up or dismissed it, so the cta kept reappearing whenever a
user opened tangled on another device or browser. for logged-in users,
store the state in a newsletter_preferences table keyed on did with an
enum status ('subscribed' | 'dismissed') and the email they gave us.
the home and timeline handlers read this row to decide whether to
render the widget, and the server-rendered gfi banner widens when the
widget is gone so the grid doesn't leave an empty column.
resend stays the source of truth for the mailing list itself (sending,
bounces, one-click unsubscribes) — the new table only answers the
render-time question 'should this did see the widget right now?',
which resend cannot cheaply answer because it's keyed on email rather
than did and would add a network hop to every timeline render.
anonymous visitors keep the localStorage fallback. the client-side
'already dismissed in a past session' path deliberately only calls
hide() (not dismiss()) so that a stale localStorage flag can't clobber
a subscribed row set from another device.
Signed-off-by: eti <eti@eti.tf>
the newsletter widget was being rendered twice on the timeline (once for
mobile, once for desktop) via hidden/visible wrapper divs. both copies
shared the same element ids (newsletter-widget, newsletter-widget-msg),
so desktop submissions swapped into the hidden mobile copy and appeared
to do nothing. collapse the two layouts into one responsive grid with
tailwind order/col-start utilities so the widget lives in the dom
exactly once, and drop the mutationobserver wiring in favour of a small
delegated click listener that also handles gfi banner widening on
dismiss.
consolidate the three signup form variants (banner, widget, home hero)
into a single newsletterForm fragment that takes a dict(Id, Variant).
each instance gets a unique response-span id (newsletter-msg-<Id>) so
multiple forms can coexist on a page without id collisions.
move the handler's inline html/tailwind response strings into a
newsletterResponse template rendered through pages, so the response id
round-trips with the form's hx-target via an hx-vals target field.
drop the stray blank line in base.html.
Signed-off-by: eti <eti@eti.tf>
upgrade to resend-go/v3 and add a newsletter signup endpoint. replace
the join CTA with a newsletter signup form. rework the timeline page to
be a two-column layout on desktop.
Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.org>
Signed-off-by: eti <eti@eti.tf>
Signed-off-by: Matías Insaurralde <matias@insaurral.de>
Signed-off-by: Matías Insaurralde <matias@insaurral.de>
Avoid allocating a new http.Client on every resyncRepo call.
http.Client is safe for concurrent use and reusing it enables
TCP connection pooling across checks to the same knot.
Signed-off-by: Matías Insaurralde <matias@insaurral.de>
Signed-off-by: eti <eti@eti.tf>
Signed-off-by: Techno Duck <duck@technoduck.me>
Replace the footer's leading slot with the author's avatar and handle for
issue and pull request cards. For long handles, ellipsize and drop the
reaction and comment counts to keep the tangled logo visible.
appview/{issues,pulls}: send author info to ogre
Resolve the author's handle and avatar URL from the issue/pull owner DID
and pass them in the payload so ogre can render the author in the card
footer.
Signed-off-by: eti eti@eti.tf
That's token is meant to be public.
Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.org>
Sets the distinct id to 'anonymous' for logged out searches. Let's stick
to this for any future logged out events.
Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.org>
having a primary call to action always present in the nav bar was
creating issues with other call to actions at a hierarchical level
this change prevents buttons clashing against each other because of
their level of importance
*As a rule of thumb, the main call to action on a page should be
heaviest in weight when compared to other buttons and/or links. All
other action items should appear secondary in terms of color, placement,
shape, and overall weight allocation.*
refs:
-
https://www.smashingmagazine.com/2009/10/call-to-action-buttons-examples-and-best-practices/#offer-secondary-alternative-actions
-
https://uxmag.com/articles/usability-tip-one-main-call-to-action-item-per-task#:~:text=As%20a%20rule,to%20move%20forward.
Signed-off-by: eti <eti@eti.tf>
Lewis: May this revision serve well! <lewis@tangled.org>
Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.org>
Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.org>
And some misc. css tweaks.
Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.org>
Add nix/pkgs/blog.nix to build the blog with proper static assets
including the dolly favicon files. Update the CI workflow to generate
favicons using the dolly tool before building.
The favicon was missing in production because appview/pages/static/* is
gitignored, and the CI workflow wasn't generating the dolly icons.
Signed-off-by: eti <eti@eti.tf>
`after-request` is not triggered because the response causes a full page
reload.
Persisted input values were due to browser autofill, not htmx state.
Signed-off-by: tobinio <Tobias.frischmann1@gmail.com>
large repos like witchsky seem to require a large request window. the
real issue here is the transaction process: we should use the knotstream
to identify successful/failed merges, and not depend entirely on the
request timeout.
additionaly: investigate the root cause of slow merges.
Signed-off-by: oppiliappan <me@oppi.li>
Signed-off-by: Will Andrews <did:plc:dadhhalkfcq3gucaq25hjqon>
Signed-off-by: eti <eti@eti.tf>
Signed-off-by: Seongmin Lee <git@boltless.me>
Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.org>
This is not required anymore. `MultiAccountUser` can just hold active
user DID.
Signed-off-by: Seongmin Lee <git@boltless.me>
In most helper methods, DID is enough. Don't pass entire session info.
Signed-off-by: Seongmin Lee <git@boltless.me>
We are using `MultiAccountUser.Did()` to get current DID instead.
Signed-off-by: Seongmin Lee <git@boltless.me>
We should resolve handle on render and we are already doing that.
Removing the unused field.
Signed-off-by: Seongmin Lee <git@boltless.me>
Signed-off-by: Seongmin Lee <git@boltless.me>
idk why was this added. Seems like it isn't used?
Signed-off-by: Seongmin Lee <git@boltless.me>
We don't need to pass full `MultiAccountUser` here. just `[]AccountInfo`
should be enough. This way, we can make `MultiAccountUser` to always
hold an active user.
Signed-off-by: Seongmin Lee <git@boltless.me>
- `AccountRegistry.OtherAccounts()` is not used anywhere
- Removed several legacy session value names from `oauth/consts.go`
- We can just embed the `oauth.GetUser()` now
Signed-off-by: Seongmin Lee <git@boltless.me>
`oauth.ClientSessionData.HostURL` is not validated after first session
creation. If user switches the PDS while logged in, `.HostURL` will
still point to old PDS, showing account management options for `tngl.sh`
users. This can confuse users to accidentally put account in odd state
(activated in both PDSes)
Instead, always resolve Handles and PDS hosts on-demand. Technically
`HostURL` is used on creating authorized atpclient, but that's ok
because request to old PDS will reject the request.
Ideally we should revoke user sessions on `#account` event, indigo
currently doesn't support DID based revoking.
Signed-off-by: Seongmin Lee <git@boltless.me>
PDS might have different domain for PDS hostname & user handles
Signed-off-by: Seongmin Lee <git@boltless.me>
Lewis: May this revision serve well! <lewis@tangled.org>
Signed-off-by: Seongmin Lee <git@boltless.me>
Signed-off-by: Seongmin Lee <git@boltless.me>
Signed-off-by: Seongmin Lee <git@boltless.me>
Signed-off-by: Seongmin Lee <git@boltless.me>
Signed-off-by: Seongmin Lee <git@boltless.me>
Signed-off-by: oppiliappan <me@oppi.li>
knotmirror update happens asynchronously, so if we immediately refresh
the page, default branch will rollback to original.
Not refreshing a page here is totally fine.
Signed-off-by: Seongmin Lee <git@boltless.me>
Signed-off-by: Seongmin Lee <git@boltless.me>
Signed-off-by: Seongmin Lee <git@boltless.me>
Signed-off-by: Patrick Dewey <p@pdewey.com>
Signed-off-by: Patrick Dewey <p@pdewey.com>
Signed-off-by: Patrick Dewey <p@pdewey.com>
Signed-off-by: oppiliappan <me@oppi.li>
Signed-off-by: oppiliappan <me@oppi.li>
Signed-off-by: oppiliappan <me@oppi.li>
the newsletter widget used only localStorage to remember whether a user
had signed up or dismissed it, so the cta kept reappearing whenever a
user opened tangled on another device or browser. for logged-in users,
store the state in a newsletter_preferences table keyed on did with an
enum status ('subscribed' | 'dismissed') and the email they gave us.
the home and timeline handlers read this row to decide whether to
render the widget, and the server-rendered gfi banner widens when the
widget is gone so the grid doesn't leave an empty column.
resend stays the source of truth for the mailing list itself (sending,
bounces, one-click unsubscribes) — the new table only answers the
render-time question 'should this did see the widget right now?',
which resend cannot cheaply answer because it's keyed on email rather
than did and would add a network hop to every timeline render.
anonymous visitors keep the localStorage fallback. the client-side
'already dismissed in a past session' path deliberately only calls
hide() (not dismiss()) so that a stale localStorage flag can't clobber
a subscribed row set from another device.
Signed-off-by: eti <eti@eti.tf>
the newsletter widget was being rendered twice on the timeline (once for
mobile, once for desktop) via hidden/visible wrapper divs. both copies
shared the same element ids (newsletter-widget, newsletter-widget-msg),
so desktop submissions swapped into the hidden mobile copy and appeared
to do nothing. collapse the two layouts into one responsive grid with
tailwind order/col-start utilities so the widget lives in the dom
exactly once, and drop the mutationobserver wiring in favour of a small
delegated click listener that also handles gfi banner widening on
dismiss.
consolidate the three signup form variants (banner, widget, home hero)
into a single newsletterForm fragment that takes a dict(Id, Variant).
each instance gets a unique response-span id (newsletter-msg-<Id>) so
multiple forms can coexist on a page without id collisions.
move the handler's inline html/tailwind response strings into a
newsletterResponse template rendered through pages, so the response id
round-trips with the form's hx-target via an hx-vals target field.
drop the stray blank line in base.html.
Signed-off-by: eti <eti@eti.tf>
Replace the footer's leading slot with the author's avatar and handle for
issue and pull request cards. For long handles, ellipsize and drop the
reaction and comment counts to keep the tangled logo visible.
appview/{issues,pulls}: send author info to ogre
Resolve the author's handle and avatar URL from the issue/pull owner DID
and pass them in the payload so ogre can render the author in the card
footer.
Signed-off-by: eti eti@eti.tf
having a primary call to action always present in the nav bar was
creating issues with other call to actions at a hierarchical level
this change prevents buttons clashing against each other because of
their level of importance
*As a rule of thumb, the main call to action on a page should be
heaviest in weight when compared to other buttons and/or links. All
other action items should appear secondary in terms of color, placement,
shape, and overall weight allocation.*
refs:
-
https://www.smashingmagazine.com/2009/10/call-to-action-buttons-examples-and-best-practices/#offer-secondary-alternative-actions
-
https://uxmag.com/articles/usability-tip-one-main-call-to-action-item-per-task#:~:text=As%20a%20rule,to%20move%20forward.
Signed-off-by: eti <eti@eti.tf>
Add nix/pkgs/blog.nix to build the blog with proper static assets
including the dolly favicon files. Update the CI workflow to generate
favicons using the dolly tool before building.
The favicon was missing in production because appview/pages/static/* is
gitignored, and the CI workflow wasn't generating the dolly icons.
Signed-off-by: eti <eti@eti.tf>
large repos like witchsky seem to require a large request window. the
real issue here is the transaction process: we should use the knotstream
to identify successful/failed merges, and not depend entirely on the
request timeout.
additionaly: investigate the root cause of slow merges.
Signed-off-by: oppiliappan <me@oppi.li>
`oauth.ClientSessionData.HostURL` is not validated after first session
creation. If user switches the PDS while logged in, `.HostURL` will
still point to old PDS, showing account management options for `tngl.sh`
users. This can confuse users to accidentally put account in odd state
(activated in both PDSes)
Instead, always resolve Handles and PDS hosts on-demand. Technically
`HostURL` is used on creating authorized atpclient, but that's ok
because request to old PDS will reject the request.
Ideally we should revoke user sessions on `#account` event, indigo
currently doesn't support DID based revoking.
Signed-off-by: Seongmin Lee <git@boltless.me>