riptide-transfer 1.3.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- riptide/__init__.py +28 -0
- riptide/__main__.py +4 -0
- riptide/app.py +45 -0
- riptide/core/__init__.py +1 -0
- riptide/core/config.py +176 -0
- riptide/core/file_select.py +89 -0
- riptide/core/firewall.py +552 -0
- riptide/core/focus.py +82 -0
- riptide/core/identity.py +243 -0
- riptide/core/nat.py +102 -0
- riptide/core/session.py +887 -0
- riptide/core/transfer.py +89 -0
- riptide/screens/__init__.py +1 -0
- riptide/screens/create.py +529 -0
- riptide/screens/join.py +479 -0
- riptide/screens/menu.py +94 -0
- riptide/screens/session_screen.py +1059 -0
- riptide/theme.py +1049 -0
- riptide_transfer-1.3.6.dist-info/METADATA +176 -0
- riptide_transfer-1.3.6.dist-info/RECORD +23 -0
- riptide_transfer-1.3.6.dist-info/WHEEL +5 -0
- riptide_transfer-1.3.6.dist-info/entry_points.txt +2 -0
- riptide_transfer-1.3.6.dist-info/top_level.txt +1 -0
riptide/theme.py
ADDED
|
@@ -0,0 +1,1049 @@
|
|
|
1
|
+
"""Theme constants. Pure terminal transparency, coral accent, muted metadata."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textual.renderables.blank as _blank_mod
|
|
5
|
+
from rich.style import Style as _RichStyle
|
|
6
|
+
from textual.color import Color as _Color
|
|
7
|
+
import textual.style as _style_mod
|
|
8
|
+
import textual.filter as _filter_mod
|
|
9
|
+
|
|
10
|
+
# Patch Textual's Blank visual to emit Style() with no background color for transparent/alpha=0
|
|
11
|
+
_orig_blank_init = _blank_mod.Blank.__init__
|
|
12
|
+
def _transparent_blank_init(self, color: _Color | str = "transparent") -> None:
|
|
13
|
+
c = _Color.parse(color) if isinstance(color, str) else color
|
|
14
|
+
if c.is_transparent or getattr(c, "a", 1) == 0:
|
|
15
|
+
self._rich_style = _RichStyle()
|
|
16
|
+
else:
|
|
17
|
+
_orig_blank_init(self, color)
|
|
18
|
+
_blank_mod.Blank.__init__ = _transparent_blank_init
|
|
19
|
+
|
|
20
|
+
# Patch Textual's Style.rich_style and rich_style_with_offset so transparent background has bgcolor=None
|
|
21
|
+
_orig_rich_style_func = _style_mod.Style.rich_style.func
|
|
22
|
+
def _patched_rich_style(self) -> _RichStyle:
|
|
23
|
+
rs = _orig_rich_style_func(self)
|
|
24
|
+
bg = getattr(self, "background", None)
|
|
25
|
+
if bg is not None and (getattr(bg, "a", 1) == 0 or getattr(bg, "is_transparent", False)):
|
|
26
|
+
return _RichStyle(
|
|
27
|
+
color=rs.color,
|
|
28
|
+
bgcolor=None,
|
|
29
|
+
bold=rs.bold,
|
|
30
|
+
dim=rs.dim,
|
|
31
|
+
italic=rs.italic,
|
|
32
|
+
underline=rs.underline,
|
|
33
|
+
underline2=rs.underline2,
|
|
34
|
+
reverse=rs.reverse,
|
|
35
|
+
strike=rs.strike,
|
|
36
|
+
blink=rs.blink,
|
|
37
|
+
link=rs.link,
|
|
38
|
+
meta=rs.meta,
|
|
39
|
+
)
|
|
40
|
+
return rs
|
|
41
|
+
_style_mod.Style.rich_style = property(_patched_rich_style)
|
|
42
|
+
|
|
43
|
+
_orig_rich_style_with_offset = _style_mod.Style.rich_style_with_offset
|
|
44
|
+
def _patched_rich_style_with_offset(self, x: int, y: int) -> _RichStyle:
|
|
45
|
+
rs = _orig_rich_style_with_offset(self, x, y)
|
|
46
|
+
bg = getattr(self, "background", None)
|
|
47
|
+
if bg is not None and (getattr(bg, "a", 1) == 0 or getattr(bg, "is_transparent", False)):
|
|
48
|
+
return _RichStyle(
|
|
49
|
+
color=rs.color,
|
|
50
|
+
bgcolor=None,
|
|
51
|
+
bold=rs.bold,
|
|
52
|
+
dim=rs.dim,
|
|
53
|
+
italic=rs.italic,
|
|
54
|
+
underline=rs.underline,
|
|
55
|
+
underline2=rs.underline2,
|
|
56
|
+
reverse=rs.reverse,
|
|
57
|
+
strike=rs.strike,
|
|
58
|
+
blink=rs.blink,
|
|
59
|
+
link=rs.link,
|
|
60
|
+
meta=rs.meta,
|
|
61
|
+
)
|
|
62
|
+
return rs
|
|
63
|
+
_style_mod.Style.rich_style_with_offset = _patched_rich_style_with_offset
|
|
64
|
+
|
|
65
|
+
# Guard monochrome filter against None styles
|
|
66
|
+
_orig_monochrome_style = _filter_mod.monochrome_style
|
|
67
|
+
def _patched_monochrome_style(style: _RichStyle | None) -> _RichStyle:
|
|
68
|
+
if style is None:
|
|
69
|
+
return _RichStyle()
|
|
70
|
+
return _orig_monochrome_style(style)
|
|
71
|
+
_filter_mod.monochrome_style = _patched_monochrome_style
|
|
72
|
+
|
|
73
|
+
BACKGROUND = "transparent"
|
|
74
|
+
SURFACE = "transparent"
|
|
75
|
+
ACCENT = "#FF6B6B"
|
|
76
|
+
TEXT = "#E8E8E8"
|
|
77
|
+
DIM = "#71717A"
|
|
78
|
+
SUCCESS = "#78DC8C"
|
|
79
|
+
WARNING = "#FFD166"
|
|
80
|
+
ERROR = "#FF6B6B"
|
|
81
|
+
# Page headers, larger than body text. Terminals render all text
|
|
82
|
+
# at one pixel size, which Textual cannot change per widget, so
|
|
83
|
+
# a "larger" header here means a 5-row block-letter banner, bold
|
|
84
|
+
# and accent coloured, in its own taller header row. This is the
|
|
85
|
+
# same trick as the menu's ANSI Shadow banner, scaled to short
|
|
86
|
+
# page titles so it fits an 80-column terminal.
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# Session roles: the Create Server side (listener) is the host,
|
|
92
|
+
# the Join Server side (dialler) is the client.
|
|
93
|
+
BANNER_HOST = r""" __ ______ __________
|
|
94
|
+
/ // / __ \/ __/_ __/
|
|
95
|
+
/ _ / /_/ /\ \ / /
|
|
96
|
+
/_//_/\____/___/ /_/"""
|
|
97
|
+
|
|
98
|
+
BANNER_CLIENT = r""" _______ _________ ________
|
|
99
|
+
/ ___/ / / _/ __/ |/ /_ __/
|
|
100
|
+
/ /__/ /___/ // _// / / /
|
|
101
|
+
\___/____/___/___/_/|_/ /_/"""
|
|
102
|
+
|
|
103
|
+
BANNER_CREATE = r""" ________ _______ __________
|
|
104
|
+
/ ___/ _ \/ __/ _ /_ __/ __/
|
|
105
|
+
/ /__/ , _/ _// __ |/ / / _/
|
|
106
|
+
\___/_/|_/___/_/ |_/_/ /___/"""
|
|
107
|
+
|
|
108
|
+
BANNER_JOIN = r""" ______ _____ __
|
|
109
|
+
__ / / __ \/ _/ |/ /
|
|
110
|
+
/ // / /_/ // // /
|
|
111
|
+
\___/\____/___/_/|_/"""
|
|
112
|
+
HEADER_BANNER = """\
|
|
113
|
+
██████╗ ██╗██████╗ ████████╗██╗██████╗ ███████╗
|
|
114
|
+
██╔══██╗██║██╔══██╗╚══██╔══╝██║██╔══██╗██╔════╝
|
|
115
|
+
██████╔╝██║██████╔╝ ██║ ██║██║ ██║█████╗
|
|
116
|
+
██╔══██╗██║██╔═══╝ ██║ ██║██║ ██║██╔══╝
|
|
117
|
+
██║ ██║██║██║ ██║ ██║██████╔╝███████╗
|
|
118
|
+
╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚═╝╚═════╝ ╚══════╝\
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
HEADER_LINES = HEADER_BANNER.splitlines()
|
|
122
|
+
|
|
123
|
+
TAGLINES = {
|
|
124
|
+
"home": "Direct, encrypted PC-to-PC file transfer · Zero cloud storage, zero intermediate hops",
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
CSS = """
|
|
128
|
+
App, Screen {
|
|
129
|
+
background: transparent !important;
|
|
130
|
+
color: #E8E8E8;
|
|
131
|
+
layout: vertical;
|
|
132
|
+
padding: 1 2;
|
|
133
|
+
layers: base overlay;
|
|
134
|
+
}
|
|
135
|
+
Static, Label {
|
|
136
|
+
background: transparent;
|
|
137
|
+
color: #E8E8E8;
|
|
138
|
+
}
|
|
139
|
+
.header {
|
|
140
|
+
color: #FF6B6B;
|
|
141
|
+
text-style: bold;
|
|
142
|
+
text-align: center;
|
|
143
|
+
padding: 0 0 1 0;
|
|
144
|
+
}
|
|
145
|
+
.version-tag {
|
|
146
|
+
color: #FF6B6B;
|
|
147
|
+
text-style: bold;
|
|
148
|
+
text-align: center;
|
|
149
|
+
}
|
|
150
|
+
.subheader {
|
|
151
|
+
color: #71717A;
|
|
152
|
+
text-align: center;
|
|
153
|
+
padding: 0 0 1 0;
|
|
154
|
+
}
|
|
155
|
+
.screen-title {
|
|
156
|
+
color: #FF6B6B;
|
|
157
|
+
text-style: bold;
|
|
158
|
+
padding: 1 0 0 0;
|
|
159
|
+
}
|
|
160
|
+
.screen-desc {
|
|
161
|
+
color: #71717A;
|
|
162
|
+
padding: 0 0 1 0;
|
|
163
|
+
}
|
|
164
|
+
.dim {
|
|
165
|
+
color: #71717A;
|
|
166
|
+
}
|
|
167
|
+
.accent {
|
|
168
|
+
color: #FF6B6B;
|
|
169
|
+
}
|
|
170
|
+
.success {
|
|
171
|
+
color: #78DC8C;
|
|
172
|
+
}
|
|
173
|
+
.warning {
|
|
174
|
+
color: #FFD166;
|
|
175
|
+
}
|
|
176
|
+
.error {
|
|
177
|
+
color: #FF6B6B;
|
|
178
|
+
}
|
|
179
|
+
.keymap-bar {
|
|
180
|
+
dock: bottom;
|
|
181
|
+
height: 1;
|
|
182
|
+
color: #71717A;
|
|
183
|
+
background: transparent;
|
|
184
|
+
padding: 0 1;
|
|
185
|
+
}
|
|
186
|
+
.keymap-key {
|
|
187
|
+
color: #E8E8E8;
|
|
188
|
+
text-style: bold;
|
|
189
|
+
}
|
|
190
|
+
/* Input fields, antigravity-cli style: a bordered composer box
|
|
191
|
+
with a dim label above it and a hint below it, not a bare
|
|
192
|
+
input. Placeholder text is grey, focus border is the accent. */
|
|
193
|
+
Input {
|
|
194
|
+
border: round #9696a3;
|
|
195
|
+
background: transparent;
|
|
196
|
+
color: #E8E8E8;
|
|
197
|
+
height: 3;
|
|
198
|
+
padding: 0 1;
|
|
199
|
+
margin: 0 0 1 0;
|
|
200
|
+
}
|
|
201
|
+
Input:focus {
|
|
202
|
+
border: round #FF6B6B;
|
|
203
|
+
}
|
|
204
|
+
Input > .input--placeholder {
|
|
205
|
+
color: #9696a3;
|
|
206
|
+
}
|
|
207
|
+
.composer-label {
|
|
208
|
+
color: #D7D7D7;
|
|
209
|
+
text-style: bold;
|
|
210
|
+
padding: 1 0 0 0;
|
|
211
|
+
}
|
|
212
|
+
.composer-hint {
|
|
213
|
+
color: #D0D0D0;
|
|
214
|
+
padding: 0 0 1 0;
|
|
215
|
+
}
|
|
216
|
+
.composer {
|
|
217
|
+
padding: 0 1 1 1;
|
|
218
|
+
margin: 1 0;
|
|
219
|
+
background: transparent;
|
|
220
|
+
}
|
|
221
|
+
/* Buttons - streamlined, non-bulky */
|
|
222
|
+
Button {
|
|
223
|
+
background: transparent;
|
|
224
|
+
color: #E8E8E8;
|
|
225
|
+
border: round #3F3F46;
|
|
226
|
+
height: 3;
|
|
227
|
+
margin: 0 1;
|
|
228
|
+
text-style: bold;
|
|
229
|
+
}
|
|
230
|
+
Button:focus {
|
|
231
|
+
background: transparent;
|
|
232
|
+
color: #FF6B6B;
|
|
233
|
+
border: round #FF6B6B;
|
|
234
|
+
}
|
|
235
|
+
Button.primary {
|
|
236
|
+
border: round #FF6B6B;
|
|
237
|
+
color: #FF6B6B;
|
|
238
|
+
}
|
|
239
|
+
Button.primary:focus {
|
|
240
|
+
background: #FF6B6B;
|
|
241
|
+
color: #121212;
|
|
242
|
+
}
|
|
243
|
+
Button.allow {
|
|
244
|
+
background: #78DC8C;
|
|
245
|
+
color: #121212;
|
|
246
|
+
text-style: bold;
|
|
247
|
+
border: none;
|
|
248
|
+
width: 22;
|
|
249
|
+
min-width: 22;
|
|
250
|
+
height: 3;
|
|
251
|
+
}
|
|
252
|
+
Button.allow:focus {
|
|
253
|
+
background: #8EEC9F;
|
|
254
|
+
color: #000000;
|
|
255
|
+
border: tall #FFFFFF;
|
|
256
|
+
}
|
|
257
|
+
Button.deny {
|
|
258
|
+
background: #FF6B6B;
|
|
259
|
+
color: #121212;
|
|
260
|
+
text-style: bold;
|
|
261
|
+
border: none;
|
|
262
|
+
width: 22;
|
|
263
|
+
min-width: 22;
|
|
264
|
+
height: 3;
|
|
265
|
+
}
|
|
266
|
+
Button.deny:focus {
|
|
267
|
+
background: #FF8585;
|
|
268
|
+
color: #000000;
|
|
269
|
+
border: tall #FFFFFF;
|
|
270
|
+
}
|
|
271
|
+
ProgressBar {
|
|
272
|
+
margin: 1 0;
|
|
273
|
+
}
|
|
274
|
+
ProgressBar > .bar--bar {
|
|
275
|
+
background: #FF6B6B;
|
|
276
|
+
}
|
|
277
|
+
OptionList {
|
|
278
|
+
background: transparent;
|
|
279
|
+
border: none;
|
|
280
|
+
padding: 1 2;
|
|
281
|
+
height: auto;
|
|
282
|
+
}
|
|
283
|
+
OptionList:focus {
|
|
284
|
+
border: none;
|
|
285
|
+
}
|
|
286
|
+
OptionList > .option-list--option {
|
|
287
|
+
padding: 0 1;
|
|
288
|
+
background: transparent;
|
|
289
|
+
color: #E0E0E0;
|
|
290
|
+
}
|
|
291
|
+
OptionList > .option-list--option-highlighted {
|
|
292
|
+
background: transparent;
|
|
293
|
+
color: #FF6B6B;
|
|
294
|
+
text-style: bold;
|
|
295
|
+
}
|
|
296
|
+
ListView {
|
|
297
|
+
background: transparent;
|
|
298
|
+
border: round #3F3F46;
|
|
299
|
+
padding: 0 1;
|
|
300
|
+
height: 16;
|
|
301
|
+
}
|
|
302
|
+
ListView:focus {
|
|
303
|
+
border: round #FF6B6B;
|
|
304
|
+
}
|
|
305
|
+
ListItem {
|
|
306
|
+
background: transparent;
|
|
307
|
+
padding: 0 1;
|
|
308
|
+
}
|
|
309
|
+
ListItem.-highlight,
|
|
310
|
+
ListItem.--highlight {
|
|
311
|
+
background: transparent;
|
|
312
|
+
}
|
|
313
|
+
.file-row {
|
|
314
|
+
width: 100%;
|
|
315
|
+
height: 1;
|
|
316
|
+
layout: horizontal;
|
|
317
|
+
background: transparent;
|
|
318
|
+
}
|
|
319
|
+
/* File manager colours, in priority order:
|
|
320
|
+
remaining files grey, selected files accent, and the hovered
|
|
321
|
+
(highlighted) row pure white, even if it is also selected.
|
|
322
|
+
The -highlight rules come last so hover/focus wins over selected. */
|
|
323
|
+
.file-name {
|
|
324
|
+
width: 1fr;
|
|
325
|
+
min-width: 12;
|
|
326
|
+
color: #E0E0E0;
|
|
327
|
+
}
|
|
328
|
+
ListItem.selected .file-name {
|
|
329
|
+
color: #FF6B6B;
|
|
330
|
+
text-style: bold;
|
|
331
|
+
}
|
|
332
|
+
ListItem.selected .file-size,
|
|
333
|
+
ListItem.selected .file-mtime {
|
|
334
|
+
color: #E0E0E0;
|
|
335
|
+
}
|
|
336
|
+
ListItem.-highlight,
|
|
337
|
+
ListItem.--highlight,
|
|
338
|
+
ListItem.-highlight *,
|
|
339
|
+
ListItem.--highlight *,
|
|
340
|
+
ListItem.-highlight Label,
|
|
341
|
+
ListItem.--highlight Label,
|
|
342
|
+
ListItem.-highlight .file-name,
|
|
343
|
+
ListItem.--highlight .file-name,
|
|
344
|
+
ListItem.-highlight .file-size,
|
|
345
|
+
ListItem.--highlight .file-size,
|
|
346
|
+
ListItem.-highlight .file-mtime,
|
|
347
|
+
ListItem.--highlight .file-mtime,
|
|
348
|
+
ListItem.selected.-highlight Label,
|
|
349
|
+
ListItem.selected.--highlight Label,
|
|
350
|
+
ListView:focus > ListItem.-highlight Label,
|
|
351
|
+
ListView:focus > ListItem.--highlight Label {
|
|
352
|
+
color: #FFFFFF !important;
|
|
353
|
+
text-style: bold !important;
|
|
354
|
+
}
|
|
355
|
+
.file-size {
|
|
356
|
+
width: 12;
|
|
357
|
+
text-align: right;
|
|
358
|
+
color: #E0E0E0;
|
|
359
|
+
}
|
|
360
|
+
.file-mtime {
|
|
361
|
+
width: 22;
|
|
362
|
+
text-align: right;
|
|
363
|
+
color: #E0E0E0;
|
|
364
|
+
}
|
|
365
|
+
.file-header-pointer {
|
|
366
|
+
width: 2;
|
|
367
|
+
min-width: 2;
|
|
368
|
+
max-width: 2;
|
|
369
|
+
padding: 0;
|
|
370
|
+
margin: 0;
|
|
371
|
+
}
|
|
372
|
+
.file-pointer {
|
|
373
|
+
width: 2;
|
|
374
|
+
min-width: 2;
|
|
375
|
+
max-width: 2;
|
|
376
|
+
color: #FF6B6B;
|
|
377
|
+
text-style: bold;
|
|
378
|
+
padding: 0;
|
|
379
|
+
margin: 0;
|
|
380
|
+
}
|
|
381
|
+
.file-header-row {
|
|
382
|
+
width: 100%;
|
|
383
|
+
height: 1;
|
|
384
|
+
layout: horizontal;
|
|
385
|
+
padding: 0 1;
|
|
386
|
+
color: #E0E0E0;
|
|
387
|
+
text-style: bold;
|
|
388
|
+
}
|
|
389
|
+
.file-header-name {
|
|
390
|
+
width: 1fr;
|
|
391
|
+
color: #E0E0E0;
|
|
392
|
+
text-style: bold;
|
|
393
|
+
}
|
|
394
|
+
.file-header-size {
|
|
395
|
+
width: 12;
|
|
396
|
+
text-align: right;
|
|
397
|
+
color: #E0E0E0;
|
|
398
|
+
text-style: bold;
|
|
399
|
+
}
|
|
400
|
+
.file-header-mtime {
|
|
401
|
+
width: 22;
|
|
402
|
+
text-align: right;
|
|
403
|
+
color: #E0E0E0;
|
|
404
|
+
text-style: bold;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/* Redesigned Session Screen Styles */
|
|
408
|
+
#session_scroll {
|
|
409
|
+
height: 1fr;
|
|
410
|
+
overflow-y: auto;
|
|
411
|
+
padding: 0;
|
|
412
|
+
margin: 0;
|
|
413
|
+
}
|
|
414
|
+
/* Create Server page: plain container, no scroll container, so
|
|
415
|
+
no vertical scrollbar can appear on this page. */
|
|
416
|
+
#create_content {
|
|
417
|
+
height: 1fr;
|
|
418
|
+
width: 100%;
|
|
419
|
+
padding: 0;
|
|
420
|
+
margin: 0;
|
|
421
|
+
}
|
|
422
|
+
#session_header_row {
|
|
423
|
+
width: 100%;
|
|
424
|
+
height: 5;
|
|
425
|
+
max-height: 5;
|
|
426
|
+
layout: horizontal;
|
|
427
|
+
margin: 0;
|
|
428
|
+
padding: 0;
|
|
429
|
+
}
|
|
430
|
+
#session_host_title {
|
|
431
|
+
width: auto;
|
|
432
|
+
height: 5;
|
|
433
|
+
color: #FF6B6B;
|
|
434
|
+
text-style: bold;
|
|
435
|
+
padding: 0;
|
|
436
|
+
margin: 0;
|
|
437
|
+
}
|
|
438
|
+
/* Router port-forwarding notice, shown only when port was closed in OS firewall.
|
|
439
|
+
The banner text is not bold. The banner has no bottom margin:
|
|
440
|
+
the 1-row gap it used to leave is now a blank widget,
|
|
441
|
+
#router_banner_spacer, which writes blank spaces into that
|
|
442
|
+
row and so covers the menu's RIPTIDE logo underneath, while
|
|
443
|
+
the screen itself stays transparent. Total height before the
|
|
444
|
+
CREATE header is unchanged: banner height plus 1 blank row. */
|
|
445
|
+
#router_banner {
|
|
446
|
+
display: none;
|
|
447
|
+
width: 100%;
|
|
448
|
+
height: auto;
|
|
449
|
+
background: #FFD166;
|
|
450
|
+
color: #121212;
|
|
451
|
+
text-align: center;
|
|
452
|
+
padding: 1 2;
|
|
453
|
+
margin: 0 0 0 0;
|
|
454
|
+
}
|
|
455
|
+
#router_banner_spacer {
|
|
456
|
+
display: none;
|
|
457
|
+
width: 100%;
|
|
458
|
+
height: 1;
|
|
459
|
+
background: transparent;
|
|
460
|
+
padding: 0;
|
|
461
|
+
margin: 0;
|
|
462
|
+
}
|
|
463
|
+
.session-header-text {
|
|
464
|
+
color: #FF6B6B;
|
|
465
|
+
text-style: bold;
|
|
466
|
+
}
|
|
467
|
+
#session_peer_info {
|
|
468
|
+
width: 1fr;
|
|
469
|
+
height: 5;
|
|
470
|
+
layout: vertical;
|
|
471
|
+
padding: 0;
|
|
472
|
+
margin: 0;
|
|
473
|
+
}
|
|
474
|
+
#peer_client_label {
|
|
475
|
+
width: 100%;
|
|
476
|
+
height: 1;
|
|
477
|
+
text-align: right;
|
|
478
|
+
color: #E8E8E8;
|
|
479
|
+
text-style: bold;
|
|
480
|
+
padding: 0;
|
|
481
|
+
margin: 0;
|
|
482
|
+
}
|
|
483
|
+
#peer_status_label {
|
|
484
|
+
width: 100%;
|
|
485
|
+
height: 1;
|
|
486
|
+
text-align: right;
|
|
487
|
+
padding: 0;
|
|
488
|
+
margin: 0;
|
|
489
|
+
}
|
|
490
|
+
#status {
|
|
491
|
+
width: 100%;
|
|
492
|
+
height: 1;
|
|
493
|
+
padding: 0;
|
|
494
|
+
margin: 0;
|
|
495
|
+
color: #71717A;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
#browser_box {
|
|
499
|
+
width: 100%;
|
|
500
|
+
height: auto;
|
|
501
|
+
border: round #3F3F46;
|
|
502
|
+
background: transparent;
|
|
503
|
+
padding: 0 1;
|
|
504
|
+
margin: 1 0;
|
|
505
|
+
}
|
|
506
|
+
#browser_box:focus-within {
|
|
507
|
+
border: round #FF6B6B;
|
|
508
|
+
}
|
|
509
|
+
#browser_header_row {
|
|
510
|
+
width: 100%;
|
|
511
|
+
height: 1;
|
|
512
|
+
layout: horizontal;
|
|
513
|
+
padding: 0;
|
|
514
|
+
margin: 0;
|
|
515
|
+
}
|
|
516
|
+
#browser_path {
|
|
517
|
+
width: 1fr;
|
|
518
|
+
height: 1;
|
|
519
|
+
color: #E8E8E8;
|
|
520
|
+
text-style: bold;
|
|
521
|
+
padding: 0;
|
|
522
|
+
margin: 0;
|
|
523
|
+
}
|
|
524
|
+
#browser_search_indicator {
|
|
525
|
+
width: auto;
|
|
526
|
+
height: 1;
|
|
527
|
+
color: #FFD166;
|
|
528
|
+
text-style: bold;
|
|
529
|
+
padding: 0;
|
|
530
|
+
margin: 0;
|
|
531
|
+
}
|
|
532
|
+
#browser_separator {
|
|
533
|
+
width: 100%;
|
|
534
|
+
height: 1;
|
|
535
|
+
color: #3F3F46;
|
|
536
|
+
padding: 0;
|
|
537
|
+
margin: 0;
|
|
538
|
+
}
|
|
539
|
+
#browser_box ListView#cwd_list {
|
|
540
|
+
width: 100%;
|
|
541
|
+
height: 10;
|
|
542
|
+
border: none;
|
|
543
|
+
padding: 0;
|
|
544
|
+
margin: 0;
|
|
545
|
+
}
|
|
546
|
+
#browser_box ListView#cwd_list:focus {
|
|
547
|
+
border: none;
|
|
548
|
+
}
|
|
549
|
+
#browser_hint {
|
|
550
|
+
width: 100%;
|
|
551
|
+
height: 1;
|
|
552
|
+
padding: 0;
|
|
553
|
+
margin: 0;
|
|
554
|
+
color: #71717A;
|
|
555
|
+
}
|
|
556
|
+
#create_actions {
|
|
557
|
+
width: 100%;
|
|
558
|
+
layout: horizontal;
|
|
559
|
+
padding: 1 0;
|
|
560
|
+
margin: 0;
|
|
561
|
+
}
|
|
562
|
+
#create_actions Button {
|
|
563
|
+
margin: 0 1;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
#selected_files_section,
|
|
567
|
+
#selected_files_list,
|
|
568
|
+
#selected_files_section Vertical {
|
|
569
|
+
width: 100%;
|
|
570
|
+
height: auto;
|
|
571
|
+
margin: 0;
|
|
572
|
+
padding: 0;
|
|
573
|
+
background: transparent;
|
|
574
|
+
}
|
|
575
|
+
#selected_header {
|
|
576
|
+
width: 100%;
|
|
577
|
+
height: 1;
|
|
578
|
+
margin: 0;
|
|
579
|
+
padding: 0;
|
|
580
|
+
}
|
|
581
|
+
.selected-file-item {
|
|
582
|
+
width: 100%;
|
|
583
|
+
height: 1;
|
|
584
|
+
color: #FF6B6B;
|
|
585
|
+
margin: 0;
|
|
586
|
+
padding: 0;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.composer {
|
|
590
|
+
width: 100%;
|
|
591
|
+
height: auto;
|
|
592
|
+
padding: 0;
|
|
593
|
+
margin: 0;
|
|
594
|
+
background: transparent;
|
|
595
|
+
}
|
|
596
|
+
.composer-label {
|
|
597
|
+
width: 100%;
|
|
598
|
+
height: 1;
|
|
599
|
+
padding: 0;
|
|
600
|
+
margin: 0;
|
|
601
|
+
color: #71717A;
|
|
602
|
+
text-style: bold;
|
|
603
|
+
}
|
|
604
|
+
.composer-hint {
|
|
605
|
+
width: 100%;
|
|
606
|
+
height: 1;
|
|
607
|
+
padding: 0;
|
|
608
|
+
margin: 0;
|
|
609
|
+
color: #71717A;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
#download_composer {
|
|
613
|
+
width: 100%;
|
|
614
|
+
height: auto;
|
|
615
|
+
padding: 0;
|
|
616
|
+
margin: 2 0 0 0;
|
|
617
|
+
background: transparent;
|
|
618
|
+
}
|
|
619
|
+
#download_composer .composer-label {
|
|
620
|
+
width: 100%;
|
|
621
|
+
height: 1;
|
|
622
|
+
color: #D7D7D7;
|
|
623
|
+
text-style: bold;
|
|
624
|
+
padding: 0;
|
|
625
|
+
margin: 0;
|
|
626
|
+
}
|
|
627
|
+
#download_composer Input {
|
|
628
|
+
width: 100%;
|
|
629
|
+
height: 3;
|
|
630
|
+
border: round #3F3F46;
|
|
631
|
+
background: transparent;
|
|
632
|
+
color: #D7D7D7;
|
|
633
|
+
padding: 0 1;
|
|
634
|
+
margin: 0;
|
|
635
|
+
}
|
|
636
|
+
#download_composer Input > .input--placeholder {
|
|
637
|
+
color: #D7D7D7;
|
|
638
|
+
}
|
|
639
|
+
#download_composer Input:focus {
|
|
640
|
+
border: round #FF6B6B;
|
|
641
|
+
}
|
|
642
|
+
#download_denied_message {
|
|
643
|
+
display: none;
|
|
644
|
+
width: 100%;
|
|
645
|
+
height: auto;
|
|
646
|
+
color: #FF6B6B;
|
|
647
|
+
text-style: bold;
|
|
648
|
+
padding: 0;
|
|
649
|
+
margin: 0;
|
|
650
|
+
}
|
|
651
|
+
#download_denied_message.active {
|
|
652
|
+
display: block;
|
|
653
|
+
}
|
|
654
|
+
#download_composer.disabled {
|
|
655
|
+
opacity: 0.35;
|
|
656
|
+
}
|
|
657
|
+
#download_composer.disabled Input {
|
|
658
|
+
border: round #27272A;
|
|
659
|
+
color: #52525B;
|
|
660
|
+
}
|
|
661
|
+
#download_composer.disabled .composer-label {
|
|
662
|
+
color: #52525B;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
#progress_section {
|
|
666
|
+
width: 100%;
|
|
667
|
+
height: auto;
|
|
668
|
+
margin: 1 0 0 0;
|
|
669
|
+
padding: 0;
|
|
670
|
+
display: none;
|
|
671
|
+
}
|
|
672
|
+
#progress_section ProgressBar#bar,
|
|
673
|
+
ProgressBar#bar,
|
|
674
|
+
ProgressBar {
|
|
675
|
+
width: 100% !important;
|
|
676
|
+
min-width: 100% !important;
|
|
677
|
+
margin: 0 !important;
|
|
678
|
+
padding: 0 !important;
|
|
679
|
+
}
|
|
680
|
+
ProgressBar > Bar {
|
|
681
|
+
width: 1fr !important;
|
|
682
|
+
}
|
|
683
|
+
ProgressBar > .bar--bar {
|
|
684
|
+
width: 100% !important;
|
|
685
|
+
background: #FF6B6B;
|
|
686
|
+
}
|
|
687
|
+
#transfer_complete_message {
|
|
688
|
+
width: 100%;
|
|
689
|
+
height: auto;
|
|
690
|
+
text-align: center;
|
|
691
|
+
color: #78DC8C;
|
|
692
|
+
text-style: bold;
|
|
693
|
+
margin: 1 0;
|
|
694
|
+
display: none;
|
|
695
|
+
}
|
|
696
|
+
#progress_metrics_row {
|
|
697
|
+
width: 100%;
|
|
698
|
+
height: 1;
|
|
699
|
+
layout: horizontal;
|
|
700
|
+
margin: 0;
|
|
701
|
+
padding: 0;
|
|
702
|
+
}
|
|
703
|
+
.progress-metric {
|
|
704
|
+
width: 1fr;
|
|
705
|
+
text-align: center;
|
|
706
|
+
color: #FF6B6B;
|
|
707
|
+
}
|
|
708
|
+
.progress-metric-left {
|
|
709
|
+
width: 1fr;
|
|
710
|
+
text-align: left;
|
|
711
|
+
color: #FF6B6B;
|
|
712
|
+
}
|
|
713
|
+
.progress-metric-right {
|
|
714
|
+
width: 1fr;
|
|
715
|
+
text-align: right;
|
|
716
|
+
color: #FF6B6B;
|
|
717
|
+
}
|
|
718
|
+
#progress_file_row {
|
|
719
|
+
width: 100%;
|
|
720
|
+
height: 1;
|
|
721
|
+
layout: horizontal;
|
|
722
|
+
margin: 0;
|
|
723
|
+
padding: 0;
|
|
724
|
+
}
|
|
725
|
+
#progress_file_name {
|
|
726
|
+
width: 1fr;
|
|
727
|
+
min-width: 12;
|
|
728
|
+
height: 1;
|
|
729
|
+
color: #E8E8E8;
|
|
730
|
+
text-style: bold;
|
|
731
|
+
}
|
|
732
|
+
#progress_file_size {
|
|
733
|
+
width: auto;
|
|
734
|
+
height: 1;
|
|
735
|
+
text-align: right;
|
|
736
|
+
color: #71717A;
|
|
737
|
+
}
|
|
738
|
+
#session_scroll {
|
|
739
|
+
layer: base;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/* Download Request Modal Popup (centered, blank background).
|
|
743
|
+
A terminal cell has one solid background colour, so true alpha
|
|
744
|
+
blending over the page below is not possible: rgba(0,0,0,0.5)
|
|
745
|
+
did not dim the page, it just rendered as an opaque layer.
|
|
746
|
+
Instead of a solid dark grey overlay, the overlay is
|
|
747
|
+
transparent: its full-screen widget still writes blank spaces
|
|
748
|
+
into the cells outside the card, covering the page below,
|
|
749
|
+
while the background stays the terminal background. The card
|
|
750
|
+
itself stays solid, with a red border on top. */
|
|
751
|
+
#download_modal_overlay {
|
|
752
|
+
layer: overlay;
|
|
753
|
+
display: none;
|
|
754
|
+
align: center middle;
|
|
755
|
+
width: 100%;
|
|
756
|
+
height: 100%;
|
|
757
|
+
background: transparent;
|
|
758
|
+
}
|
|
759
|
+
#download_modal_overlay.active {
|
|
760
|
+
display: block;
|
|
761
|
+
}
|
|
762
|
+
#download_modal_card {
|
|
763
|
+
width: 60;
|
|
764
|
+
max-width: 90%;
|
|
765
|
+
height: auto;
|
|
766
|
+
border: none;
|
|
767
|
+
/* Popup inside is dark grey, #3F3F46, so the card still
|
|
768
|
+
stands out against the blank background outside it,
|
|
769
|
+
with its red border. */
|
|
770
|
+
background: #3F3F46;
|
|
771
|
+
padding: 1 2;
|
|
772
|
+
align: center middle;
|
|
773
|
+
}
|
|
774
|
+
#download_modal_title {
|
|
775
|
+
width: 100%;
|
|
776
|
+
text-align: center;
|
|
777
|
+
color: #FFD166;
|
|
778
|
+
text-style: bold;
|
|
779
|
+
margin: 0 0 1 0;
|
|
780
|
+
}
|
|
781
|
+
#download_modal_card #download_approval {
|
|
782
|
+
width: 100%;
|
|
783
|
+
text-align: center;
|
|
784
|
+
color: #E8E8E8;
|
|
785
|
+
margin: 0 0 1 0;
|
|
786
|
+
}
|
|
787
|
+
#download_modal_actions {
|
|
788
|
+
width: 100%;
|
|
789
|
+
height: auto;
|
|
790
|
+
align: center middle;
|
|
791
|
+
margin: 1 0;
|
|
792
|
+
}
|
|
793
|
+
#download_modal_actions Button {
|
|
794
|
+
margin: 0 2;
|
|
795
|
+
min-width: 16;
|
|
796
|
+
}
|
|
797
|
+
#download_modal_actions Button.allow {
|
|
798
|
+
background: #78DC8C;
|
|
799
|
+
color: #121212;
|
|
800
|
+
text-style: bold;
|
|
801
|
+
}
|
|
802
|
+
#download_modal_actions Button.allow:focus {
|
|
803
|
+
background: #8EEC9F;
|
|
804
|
+
color: #000000;
|
|
805
|
+
border: tall #FFFFFF;
|
|
806
|
+
}
|
|
807
|
+
#download_modal_actions Button.deny {
|
|
808
|
+
background: #FF6B6B;
|
|
809
|
+
color: #121212;
|
|
810
|
+
text-style: bold;
|
|
811
|
+
}
|
|
812
|
+
#download_modal_actions Button.deny:focus {
|
|
813
|
+
background: #FF8787;
|
|
814
|
+
color: #000000;
|
|
815
|
+
border: tall #FFFFFF;
|
|
816
|
+
}
|
|
817
|
+
#download_modal_footer {
|
|
818
|
+
width: 100%;
|
|
819
|
+
text-align: center;
|
|
820
|
+
color: #71717A;
|
|
821
|
+
margin: 1 0 0 0;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
#footer_bar {
|
|
825
|
+
dock: bottom;
|
|
826
|
+
width: 100%;
|
|
827
|
+
height: 1;
|
|
828
|
+
layout: horizontal;
|
|
829
|
+
background: transparent;
|
|
830
|
+
padding: 0 1;
|
|
831
|
+
margin: 0;
|
|
832
|
+
}
|
|
833
|
+
.keymap-item {
|
|
834
|
+
width: 1fr;
|
|
835
|
+
text-align: center;
|
|
836
|
+
color: #71717A;
|
|
837
|
+
}
|
|
838
|
+
.keymap-left {
|
|
839
|
+
text-align: left;
|
|
840
|
+
}
|
|
841
|
+
.keymap-right {
|
|
842
|
+
text-align: right;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/* Join Screen Redesign Styles */
|
|
846
|
+
#public_ip {
|
|
847
|
+
width: 100%;
|
|
848
|
+
height: 1;
|
|
849
|
+
color: #E8E8E8;
|
|
850
|
+
text-style: bold;
|
|
851
|
+
margin: 0 0 1 0;
|
|
852
|
+
padding: 0;
|
|
853
|
+
}
|
|
854
|
+
#incoming_card {
|
|
855
|
+
width: 100%;
|
|
856
|
+
height: auto;
|
|
857
|
+
border: round #3F3F46;
|
|
858
|
+
background: transparent;
|
|
859
|
+
padding: 1 2;
|
|
860
|
+
margin: 1 0;
|
|
861
|
+
}
|
|
862
|
+
#incoming_card.active {
|
|
863
|
+
border: round #78DC8C;
|
|
864
|
+
}
|
|
865
|
+
#incoming {
|
|
866
|
+
width: 100%;
|
|
867
|
+
height: auto;
|
|
868
|
+
margin: 0;
|
|
869
|
+
padding: 0;
|
|
870
|
+
color: #E8E8E8;
|
|
871
|
+
}
|
|
872
|
+
#create_actions {
|
|
873
|
+
width: 100%;
|
|
874
|
+
height: auto;
|
|
875
|
+
layout: horizontal;
|
|
876
|
+
align: center middle;
|
|
877
|
+
margin: 1 0 0 0;
|
|
878
|
+
padding: 0;
|
|
879
|
+
}
|
|
880
|
+
#create_actions Button {
|
|
881
|
+
width: 22;
|
|
882
|
+
min-width: 22;
|
|
883
|
+
height: 3;
|
|
884
|
+
margin: 0 2;
|
|
885
|
+
text-style: bold;
|
|
886
|
+
border: none;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/* Join Server Styles */
|
|
890
|
+
#join_body {
|
|
891
|
+
width: 100%;
|
|
892
|
+
height: 1fr;
|
|
893
|
+
layout: vertical;
|
|
894
|
+
padding: 1 2;
|
|
895
|
+
margin: 0;
|
|
896
|
+
}
|
|
897
|
+
#join_top_section {
|
|
898
|
+
width: 100%;
|
|
899
|
+
height: 3fr;
|
|
900
|
+
layout: vertical;
|
|
901
|
+
padding: 0;
|
|
902
|
+
margin: 0;
|
|
903
|
+
}
|
|
904
|
+
.create-section-title {
|
|
905
|
+
width: 100%;
|
|
906
|
+
height: 1;
|
|
907
|
+
color: #E8E8E8;
|
|
908
|
+
text-style: bold;
|
|
909
|
+
margin: 0 0 1 0;
|
|
910
|
+
}
|
|
911
|
+
#saved_devices {
|
|
912
|
+
width: 100%;
|
|
913
|
+
height: 1fr;
|
|
914
|
+
max-height: 100%;
|
|
915
|
+
overflow-y: auto;
|
|
916
|
+
padding: 0;
|
|
917
|
+
margin: 0;
|
|
918
|
+
}
|
|
919
|
+
.device-item {
|
|
920
|
+
width: 100%;
|
|
921
|
+
height: 1;
|
|
922
|
+
color: #71717A;
|
|
923
|
+
margin: 0 0 1 0;
|
|
924
|
+
}
|
|
925
|
+
#empty_devices {
|
|
926
|
+
width: 100%;
|
|
927
|
+
height: auto;
|
|
928
|
+
color: #71717A;
|
|
929
|
+
}
|
|
930
|
+
#join_input_section {
|
|
931
|
+
width: 100%;
|
|
932
|
+
height: auto;
|
|
933
|
+
align-horizontal: center;
|
|
934
|
+
margin: 0;
|
|
935
|
+
padding: 0;
|
|
936
|
+
}
|
|
937
|
+
#join_input_section Input {
|
|
938
|
+
width: 80;
|
|
939
|
+
max-width: 95%;
|
|
940
|
+
height: 5;
|
|
941
|
+
padding: 1 1;
|
|
942
|
+
margin: 0;
|
|
943
|
+
}
|
|
944
|
+
#join_input_section .composer-label {
|
|
945
|
+
width: 80;
|
|
946
|
+
max-width: 95%;
|
|
947
|
+
color: #FF6B6B;
|
|
948
|
+
text-style: bold;
|
|
949
|
+
text-align: left;
|
|
950
|
+
padding: 0 0 1 0;
|
|
951
|
+
}
|
|
952
|
+
#join_input_section .composer-hint {
|
|
953
|
+
width: 80;
|
|
954
|
+
max-width: 95%;
|
|
955
|
+
color: #71717A;
|
|
956
|
+
padding: 1 0 0 0;
|
|
957
|
+
}
|
|
958
|
+
#join_bottom_section {
|
|
959
|
+
width: 100%;
|
|
960
|
+
height: 1fr;
|
|
961
|
+
align-horizontal: center;
|
|
962
|
+
padding: 1 0 0 0;
|
|
963
|
+
}
|
|
964
|
+
#join_bottom_section #status {
|
|
965
|
+
width: 60;
|
|
966
|
+
max-width: 90%;
|
|
967
|
+
text-align: center;
|
|
968
|
+
color: #71717A;
|
|
969
|
+
margin: 0 0 1 0;
|
|
970
|
+
}
|
|
971
|
+
/* Fingerprint Approval Modal Popup, like the download request modal.
|
|
972
|
+
Blank background, for the same reason as the download overlay:
|
|
973
|
+
the overlay widget writes blank spaces outside the card, while
|
|
974
|
+
the background stays the terminal background. */
|
|
975
|
+
#fingerprint_modal_overlay {
|
|
976
|
+
layer: overlay;
|
|
977
|
+
display: none;
|
|
978
|
+
align: center middle;
|
|
979
|
+
width: 100%;
|
|
980
|
+
height: 100%;
|
|
981
|
+
background: transparent;
|
|
982
|
+
}
|
|
983
|
+
#fingerprint_modal_overlay.active {
|
|
984
|
+
display: block;
|
|
985
|
+
}
|
|
986
|
+
#fingerprint_modal_card {
|
|
987
|
+
width: 60;
|
|
988
|
+
max-width: 90%;
|
|
989
|
+
height: auto;
|
|
990
|
+
border: none;
|
|
991
|
+
/* Same dark grey as the download card, standing out against
|
|
992
|
+
the blank background outside it. */
|
|
993
|
+
background: #3F3F46;
|
|
994
|
+
padding: 1 2;
|
|
995
|
+
align: center middle;
|
|
996
|
+
}
|
|
997
|
+
#fingerprint_modal_title {
|
|
998
|
+
width: 100%;
|
|
999
|
+
text-align: center;
|
|
1000
|
+
color: #FFD166;
|
|
1001
|
+
text-style: bold;
|
|
1002
|
+
margin: 0 0 1 0;
|
|
1003
|
+
}
|
|
1004
|
+
#fingerprint_modal_card #fingerprint_modal_body {
|
|
1005
|
+
width: 100%;
|
|
1006
|
+
text-align: center;
|
|
1007
|
+
color: #E8E8E8;
|
|
1008
|
+
margin: 0 0 1 0;
|
|
1009
|
+
}
|
|
1010
|
+
#fingerprint_modal_actions {
|
|
1011
|
+
width: 100%;
|
|
1012
|
+
height: auto;
|
|
1013
|
+
align: center middle;
|
|
1014
|
+
margin: 1 0;
|
|
1015
|
+
}
|
|
1016
|
+
#fingerprint_modal_actions Button {
|
|
1017
|
+
margin: 0 2;
|
|
1018
|
+
min-width: 16;
|
|
1019
|
+
}
|
|
1020
|
+
#fingerprint_modal_actions Button.allow {
|
|
1021
|
+
background: #78DC8C;
|
|
1022
|
+
color: #121212;
|
|
1023
|
+
text-style: bold;
|
|
1024
|
+
}
|
|
1025
|
+
#fingerprint_modal_actions Button.allow:focus {
|
|
1026
|
+
background: #8EEC9F;
|
|
1027
|
+
color: #000000;
|
|
1028
|
+
border: tall #FFFFFF;
|
|
1029
|
+
}
|
|
1030
|
+
#fingerprint_modal_actions Button.deny {
|
|
1031
|
+
background: #FF6B6B;
|
|
1032
|
+
color: #121212;
|
|
1033
|
+
text-style: bold;
|
|
1034
|
+
}
|
|
1035
|
+
#fingerprint_modal_actions Button.deny:focus {
|
|
1036
|
+
background: #FF8787;
|
|
1037
|
+
color: #000000;
|
|
1038
|
+
border: tall #FFFFFF;
|
|
1039
|
+
}
|
|
1040
|
+
#fingerprint_modal_footer {
|
|
1041
|
+
width: 100%;
|
|
1042
|
+
text-align: center;
|
|
1043
|
+
color: #71717A;
|
|
1044
|
+
margin: 1 0 0 0;
|
|
1045
|
+
}
|
|
1046
|
+
#join_bottom_section #join {
|
|
1047
|
+
display: none;
|
|
1048
|
+
}
|
|
1049
|
+
"""
|