This repository has no description
1{{ define "title" }}Timeline · Tangled{{ end }}
2
3{{ define "extrameta" }}
4 <meta property="og:title" content="Timeline · Tangled" />
5 <meta property="og:type" content="object" />
6 <meta property="og:url" content="https://tangled.org" />
7 <meta property="og:description" content="The next-generation social coding platform" />
8{{ end }}
9
10{{ define "mainLayout" }}
11<div class="flex-grow flex flex-col -mt-4">
12 <main class="flex-grow flex flex-col">{{ block "content" . }}{{ end }}</main>
13</div>
14{{ end }}
15
16{{ define "content" }}
17<div id="timeline-grid" class="flex flex-col w-full max-w-[1920px] mx-auto md:grid md:grid-cols-[minmax(0,1fr)_minmax(0,2fr)_minmax(0,1fr)] md:items-start">
18
19 <div class="hidden md:flex md:flex-col md:gap-4 md:pt-4 md:px-4 md:sticky md:top-0 md:h-screen md:overflow-y-auto md:pb-4 md:w-full md:max-w-[400px]">
20 {{ if .Onboarding.Active }}
21 {{ template "timeline/fragments/welcome" . }}
22 {{ end }}
23 {{ template "timeline/fragments/notifications" . }}
24 {{ template "timeline/fragments/recents" . }}
25 </div>
26
27 <div class="order-2 md:order-none md:col-start-2 md:row-start-1 md:w-full md:max-w-[600px] md:mx-auto">
28 {{ template "timeline/fragments/timeline" . }}
29 </div>
30
31 <div class="order-1 md:order-none flex flex-col gap-4 md:col-start-3 md:row-start-1 md:w-full md:max-w-[400px] md:ml-auto md:pt-4 md:px-4 md:sticky md:top-0 md:h-screen md:overflow-y-auto md:pb-4">
32 {{ if .ShowNewsletter }}
33 <div id="newsletter-col" class="order-first md:order-last">
34 {{ template "timeline/fragments/newsletterWidget" . }}
35 </div>
36 {{ end }}
37
38 {{ template "timeline/fragments/trending" . }}
39
40 <div class="hidden md:block">
41 {{ template "timeline/fragments/announcements" . }}
42 </div>
43
44 {{ if and .LoggedInUser .VouchSuggestions }}
45 <div class="hidden md:block">
46 {{ template "timeline/fragments/vouchSuggestions" . }}
47 </div>
48 {{ end }}
49 </div>
50</div>
51
52{{ if .ShowNewsletter }}
53<script>
54 (function() {
55 var DISMISS_KEY = 'newsletter-dismissed';
56 var newsletterCol = document.getElementById('newsletter-col');
57 if (!newsletterCol) return;
58
59 // hide removes the widget from the DOM without persisting anything.
60 // Used when this browser's localStorage says we already dismissed in a
61 // past session — the server has already told us .ShowNewsletter is true
62 // (no DB row), so we deliberately do NOT re-POST /newsletter/dismiss
63 // here: that would clobber a 'subscribed' row created from another
64 // device after this localStorage entry was set.
65 function hide() {
66 newsletterCol.remove();
67 }
68
69 // dismiss is the user-initiated path. Persists both locally and (for
70 // logged-in users) server-side so the widget stays hidden on all their
71 // devices.
72 function dismiss() {
73 hide();
74 try { localStorage.setItem(DISMISS_KEY, '1'); } catch (e) {}
75 fetch('/newsletter/dismiss', { method: 'POST', credentials: 'same-origin' })
76 .catch(function () { /* localStorage is the fallback */ });
77 }
78
79 try {
80 if (localStorage.getItem(DISMISS_KEY) === '1') {
81 hide();
82 return;
83 }
84 } catch (e) { /* storage disabled; keep widget visible */ }
85
86 newsletterCol.addEventListener('click', function(e) {
87 if (e.target.closest('[data-newsletter-dismiss]')) dismiss();
88 });
89 })();
90</script>
91{{ end }}
92{{ end }}