WIP PWA for Grain
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add terms page component

+181
+181
src/components/pages/grain-terms.js
··· 1 + import { LitElement, html, css } from 'lit'; 2 + import '../atoms/grain-icon.js'; 3 + 4 + export class GrainTerms extends LitElement { 5 + static styles = css` 6 + :host { 7 + display: block; 8 + max-width: var(--feed-max-width); 9 + margin: 0 auto; 10 + min-height: 100vh; 11 + min-height: 100dvh; 12 + padding-bottom: 80px; 13 + background: var(--color-bg-primary); 14 + } 15 + .header { 16 + display: flex; 17 + align-items: center; 18 + gap: var(--space-sm); 19 + padding: var(--space-md) var(--space-sm); 20 + } 21 + @media (min-width: 600px) { 22 + .header { 23 + padding-left: 0; 24 + padding-right: 0; 25 + } 26 + } 27 + .back-button { 28 + background: none; 29 + border: none; 30 + padding: 8px; 31 + cursor: pointer; 32 + color: var(--color-text-primary); 33 + margin-left: -8px; 34 + } 35 + h1 { 36 + font-size: var(--font-size-md); 37 + font-weight: var(--font-weight-semibold); 38 + color: var(--color-text-primary); 39 + margin: 0; 40 + } 41 + .content { 42 + padding: 0 var(--space-sm); 43 + } 44 + @media (min-width: 600px) { 45 + .content { 46 + padding: 0; 47 + } 48 + } 49 + .last-updated { 50 + font-size: var(--font-size-xs); 51 + color: var(--color-text-secondary); 52 + margin-bottom: var(--space-lg); 53 + } 54 + section { 55 + margin-bottom: var(--space-lg); 56 + } 57 + h2 { 58 + font-size: var(--font-size-sm); 59 + font-weight: var(--font-weight-semibold); 60 + color: var(--color-text-primary); 61 + margin: 0 0 var(--space-xs) 0; 62 + } 63 + p { 64 + font-size: var(--font-size-xs); 65 + color: var(--color-text-secondary); 66 + line-height: 1.5; 67 + margin: 0 0 var(--space-sm) 0; 68 + } 69 + a { 70 + color: var(--color-accent); 71 + } 72 + code { 73 + background: var(--color-bg-elevated); 74 + padding: 2px 4px; 75 + border-radius: 4px; 76 + font-size: var(--font-size-xs); 77 + } 78 + `; 79 + 80 + #goBack() { 81 + history.back(); 82 + } 83 + 84 + render() { 85 + return html` 86 + <div class="header"> 87 + <button class="back-button" @click=${this.#goBack}> 88 + <grain-icon name="back" size="20"></grain-icon> 89 + </button> 90 + <h1>Terms and Conditions</h1> 91 + </div> 92 + <div class="content"> 93 + <p class="last-updated">Last Updated: June 3, 2025</p> 94 + 95 + <section> 96 + <h2>Overview</h2> 97 + <p> 98 + Grain is a photo sharing app built on the 99 + <a href="https://atproto.com/" target="_blank" rel="noopener noreferrer">AT Protocol</a>. 100 + All data, including photos, galleries, favorites, and metadata, is public and stored on the AT Protocol network. 101 + Users can upload photos, create and favorite galleries, and view non-location EXIF metadata. 102 + </p> 103 + <p> 104 + Grain is an open source project. These Terms apply to your use of the hosted version at 105 + <code>grain.social</code>, not to self-hosted instances or forks of the source code. 106 + </p> 107 + </section> 108 + 109 + <section> 110 + <h2>Account and Data Ownership</h2> 111 + <p> 112 + Grain uses the AT Protocol, so users retain full control over their data. 113 + We are an independent project and not affiliated with Bluesky or the AT Protocol. 114 + </p> 115 + <p> 116 + If you use a <code>grain.social</code> handle, your data may be stored on our own self-hosted 117 + <a href="https://atproto.com/guides/glossary#pds-personal-data-server" target="_blank" rel="noopener noreferrer">PDS (Personal Data Server)</a> 118 + in accordance with protocol standards. 119 + </p> 120 + </section> 121 + 122 + <section> 123 + <h2>Content</h2> 124 + <p> 125 + You are responsible for any content you share. Do not upload content you do not have rights to. 126 + All uploads are publicly visible and cannot currently be set as private. 127 + </p> 128 + </section> 129 + 130 + <section> 131 + <h2>Analytics</h2> 132 + <p> 133 + We use <a href="https://www.goatcounter.com/" target="_blank" rel="noopener noreferrer">Goatcounter</a> 134 + for basic analytics. No personal data is collected, tracked, or sold. 135 + </p> 136 + </section> 137 + 138 + <section> 139 + <h2>Prohibited Conduct</h2> 140 + <p> 141 + Do not upload illegal content, harass users, impersonate others, or attempt to disrupt the network. 142 + </p> 143 + </section> 144 + 145 + <section> 146 + <h2>Disclaimers</h2> 147 + <p> 148 + Grain is provided "as is." We do not guarantee uptime, data retention, or uninterrupted access. 149 + </p> 150 + </section> 151 + 152 + <section> 153 + <h2>Termination</h2> 154 + <p> 155 + We reserve the right to suspend or terminate your access to Grain at any time, without prior notice, 156 + for conduct that we believe violates these Terms, our community standards, or is harmful to other users 157 + or the AT Protocol network. Terminated accounts may lose access to uploaded content unless retained 158 + through the protocol's data persistence mechanisms. 159 + </p> 160 + </section> 161 + 162 + <section> 163 + <h2>Changes</h2> 164 + <p> 165 + We may update these terms periodically. Continued use means acceptance of any changes. 166 + </p> 167 + </section> 168 + 169 + <section> 170 + <h2>Contact</h2> 171 + <p> 172 + For any questions about these Terms, your account, or issues with the app, you can contact us at 173 + <a href="mailto:support@grain.social">support@grain.social</a>. 174 + </p> 175 + </section> 176 + </div> 177 + `; 178 + } 179 + } 180 + 181 + customElements.define('grain-terms', GrainTerms);