Thread viewer for Bluesky
1<script lang="ts">
2 import { showLoginDialog } from './Dialogs.svelte';
3 import { account } from '../models/account.svelte.js';
4 import { settings } from '../models/settings.svelte.js';
5 import { getBaseLocation } from '../router.js';
6 import AccountMenuButton from './AccountMenuButton.svelte';
7 import LoadableImage from './LoadableImage.svelte';
8
9 let menuVisible = $state(false);
10
11 $effect(() => {
12 let html = document.body.parentNode!
13 html.addEventListener('click', hideMenu);
14
15 return () => {
16 html.removeEventListener('click', hideMenu);
17 };
18 });
19
20 function hideMenu() {
21 menuVisible = false;
22 }
23
24 function toggleMenu(e: Event) {
25 e.stopPropagation();
26 menuVisible = !menuVisible;
27 }
28
29 function toggleBiohazard(e: Event) {
30 e.preventDefault();
31
32 if (settings.biohazardsEnabled === false) {
33 settings.biohazardsEnabled = true;
34 } else {
35 settings.biohazardsEnabled = false;
36 }
37 }
38
39 function toggleIncognito(e: Event) {
40 e.preventDefault();
41 account.toggleIncognitoMode();
42 }
43
44 function showLoginScreen(e: Event) {
45 e.preventDefault();
46
47 showLoginDialog({ showClose: true });
48 menuVisible = false;
49 }
50
51 function logOut(e: Event) {
52 e.preventDefault();
53 account.logOut();
54 }
55</script>
56
57<div id="account" onclick={toggleMenu} class={{ active: menuVisible }}>
58 {#if account.isIncognito}
59 <i class="fa-solid fa-user-secret fa-lg"></i>
60
61 {:else if !account.loggedIn || account.avatarIsLoading}
62 <i class="fa-regular fa-user-circle fa-xl"></i>
63
64 {:else if account.loggedIn && account.avatarURL}
65 <LoadableImage class="avatar" src={account.avatarURL}>
66 {#snippet loading()}
67 <i class="fa-regular fa-user-circle fa-xl"></i>
68 {/snippet}
69 {#snippet error()}
70 <i class="fa-solid fa-user-circle fa-xl"></i>
71 {/snippet}
72 </LoadableImage>
73
74 {:else}
75 <i class="fa-solid fa-user-circle fa-xl"></i>
76 {/if}
77</div>
78
79<div id="account_menu" style="visibility: {menuVisible ? 'visible' : 'hidden'}" onclick={(e) => e.stopPropagation()}>
80 <ul>
81 {#if account.loggedIn}
82 <AccountMenuButton
83 onclick={toggleIncognito}
84 label="Incognito mode"
85 title="Temporarily load threads as a logged-out user"
86 showCheckmark={account.isIncognito}
87 />
88 {/if}
89
90 <AccountMenuButton
91 onclick={toggleBiohazard}
92 label="Show infohazards"
93 title="Show links to blocked and hidden comments"
94 showCheckmark={settings.biohazardsEnabled !== false}
95 />
96
97 {#if !account.loggedIn}
98 <AccountMenuButton onclick={showLoginScreen} label="Log in" />
99 {:else}
100 <AccountMenuButton onclick={logOut} label="Log out" />
101 {/if}
102
103 <li class="link"><a href="{getBaseLocation()}">Home</a></li>
104 <li class="link"><a href="?page=posting_stats">Posting stats</a></li>
105 <li class="link"><a href="?page=like_stats">Like stats</a></li>
106 <li class="link"><a href="?page=search">Timeline search</a></li>
107 <li class="link"><a href="?page=search&mode=likes">Archive search</a></li>
108 </ul>
109</div>
110
111<style>
112 #account {
113 position: fixed;
114 top: 10px;
115 left: 10px;
116 line-height: 24px;
117 z-index: 20;
118 user-select: none;
119 -webkit-user-select: none;
120 }
121
122 #account i {
123 opacity: 0.4;
124 }
125
126 #account i:hover {
127 cursor: pointer;
128 opacity: 0.6;
129 }
130
131 #account :global(img.avatar) {
132 width: 24px;
133 height: 24px;
134 border-radius: 13px;
135 box-shadow: 0px 0px 2px black;
136 }
137
138 #account_menu {
139 position: fixed;
140 visibility: hidden;
141 top: 5px;
142 left: 5px;
143 padding-top: 30px;
144 z-index: 15;
145 background: hsl(210, 33.33%, 94.0%);
146 border: 1px solid #ccc;
147 border-radius: 5px;
148 user-select: none;
149 -webkit-user-select: none;
150 }
151
152 #account_menu ul {
153 list-style-type: none;
154 margin: 0px 0px 10px;
155 padding: 6px 11px;
156 }
157
158 #account_menu :global(li:not(.link) + li.link) {
159 margin-top: 16px;
160 padding-top: 10px;
161 border-top: 1px solid #ccc;
162 }
163
164 li.link {
165 margin-top: 8px;
166 margin-left: 2px;
167 }
168
169 li.link a {
170 font-size: 11pt;
171 color: #333;
172 }
173
174 @media (prefers-color-scheme: dark) {
175 #account.active {
176 color: #333;
177 }
178
179 #account_menu {
180 background: hsl(210, 33.33%, 94.0%);
181 border-color: #ccc;
182 }
183 }
184</style>