wip desktop move network to rust
Seto Elkahfi committed
Jul 31, 2024 at 14:07 UTC
dc224b26072449b23ee991876dde8a142b4d7b80
118 files changed
+833
-376
backend/musik88-web/Gemfile
+1
-1
@@ -2,7 +2,7 @@ source 'https://rubygems.org'
2
ruby '3.2.2'
3
4
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
5
-gem 'rails', '6.1.7.7'
5
+gem 'rails', '6.1.7.8'
6
# Use postgresql as the database for Active Record
7
gem 'pg'
8
# Use SCSS for stylesheets
backend/musik88-web/Gemfile.lock
+212
-194
@@ -2,40 +2,40 @@ GEM
2
remote: https://rubygems.org/
3
specs:
4
ace-rails-ap (4.5)
5
- actioncable (6.1.7.7)
6
- actionpack (= 6.1.7.7)
7
- activesupport (= 6.1.7.7)
5
+ actioncable (6.1.7.8)
6
+ actionpack (= 6.1.7.8)
7
+ activesupport (= 6.1.7.8)
8
nio4r (~> 2.0)
9
websocket-driver (>= 0.6.1)
10
- actionmailbox (6.1.7.7)
11
- actionpack (= 6.1.7.7)
12
- activejob (= 6.1.7.7)
13
- activerecord (= 6.1.7.7)
14
- activestorage (= 6.1.7.7)
15
- activesupport (= 6.1.7.7)
10
+ actionmailbox (6.1.7.8)
11
+ actionpack (= 6.1.7.8)
12
+ activejob (= 6.1.7.8)
13
+ activerecord (= 6.1.7.8)
14
+ activestorage (= 6.1.7.8)
15
+ activesupport (= 6.1.7.8)
16
mail (>= 2.7.1)
17
- actionmailer (6.1.7.7)
18
- actionpack (= 6.1.7.7)
19
- actionview (= 6.1.7.7)
20
- activejob (= 6.1.7.7)
21
- activesupport (= 6.1.7.7)
17
+ actionmailer (6.1.7.8)
18
+ actionpack (= 6.1.7.8)
19
+ actionview (= 6.1.7.8)
20
+ activejob (= 6.1.7.8)
21
+ activesupport (= 6.1.7.8)
22
mail (~> 2.5, >= 2.5.4)
23
rails-dom-testing (~> 2.0)
24
- actionpack (6.1.7.7)
25
- actionview (= 6.1.7.7)
26
- activesupport (= 6.1.7.7)
24
+ actionpack (6.1.7.8)
25
+ actionview (= 6.1.7.8)
26
+ activesupport (= 6.1.7.8)
27
rack (~> 2.0, >= 2.0.9)
28
rack-test (>= 0.6.3)
29
rails-dom-testing (~> 2.0)
30
rails-html-sanitizer (~> 1.0, >= 1.2.0)
31
- actiontext (6.1.7.7)
32
- actionpack (= 6.1.7.7)
33
- activerecord (= 6.1.7.7)
34
- activestorage (= 6.1.7.7)
35
- activesupport (= 6.1.7.7)
31
+ actiontext (6.1.7.8)
32
+ actionpack (= 6.1.7.8)
33
+ activerecord (= 6.1.7.8)
34
+ activestorage (= 6.1.7.8)
35
+ activesupport (= 6.1.7.8)
36
nokogiri (>= 1.8.5)
37
- actionview (6.1.7.7)
38
- activesupport (= 6.1.7.7)
37
+ actionview (6.1.7.8)
38
+ activesupport (= 6.1.7.8)
39
builder (~> 3.1)
40
erubi (~> 1.4)
41
rails-dom-testing (~> 2.0)
@@ -54,60 +54,62 @@ GEM
54
railties (>= 3.0)
55
activeadmin_quill_editor (0.3.4)
56
activeadmin (~> 2.0)
57
- activejob (6.1.7.7)
58
- activesupport (= 6.1.7.7)
57
+ activejob (6.1.7.8)
58
+ activesupport (= 6.1.7.8)
59
globalid (>= 0.3.6)
60
- activemodel (6.1.7.7)
61
- activesupport (= 6.1.7.7)
62
- activerecord (6.1.7.7)
63
- activemodel (= 6.1.7.7)
64
- activesupport (= 6.1.7.7)
65
- activestorage (6.1.7.7)
66
- actionpack (= 6.1.7.7)
67
- activejob (= 6.1.7.7)
68
- activerecord (= 6.1.7.7)
69
- activesupport (= 6.1.7.7)
60
+ activemodel (6.1.7.8)
61
+ activesupport (= 6.1.7.8)
62
+ activerecord (6.1.7.8)
63
+ activemodel (= 6.1.7.8)
64
+ activesupport (= 6.1.7.8)
65
+ activestorage (6.1.7.8)
66
+ actionpack (= 6.1.7.8)
67
+ activejob (= 6.1.7.8)
68
+ activerecord (= 6.1.7.8)
69
+ activesupport (= 6.1.7.8)
70
marcel (~> 1.0)
71
mini_mime (>= 1.1.0)
72
- activesupport (6.1.7.7)
72
+ activesupport (6.1.7.8)
73
concurrent-ruby (~> 1.0, >= 1.0.2)
74
i18n (>= 1.6, < 2)
75
minitest (>= 5.1)
76
tzinfo (~> 2.0)
77
zeitwerk (~> 2.3)
78
- addressable (2.8.5)
79
- public_suffix (>= 2.0.2, < 6.0)
78
+ addressable (2.8.7)
79
+ public_suffix (>= 2.0.2, < 7.0)
80
aes_key_wrap (1.1.0)
81
ambry (1.0.0)
82
- arbre (1.6.0)
83
- activesupport (>= 3.0.0, < 7.1)
84
- ruby2_keywords (>= 0.0.2, < 1.0)
82
+ arbre (1.7.0)
83
+ activesupport (>= 3.0.0)
84
+ ruby2_keywords (>= 0.0.2)
85
ast (2.4.2)
86
- autoprefixer-rails (10.4.15.0)
86
+ autoprefixer-rails (10.4.16.0)
87
execjs (~> 2)
88
- aws-eventstream (1.2.0)
89
- aws-partitions (1.833.0)
90
- aws-sdk-core (3.185.0)
91
- aws-eventstream (~> 1, >= 1.0.2)
88
+ aws-eventstream (1.3.0)
89
+ aws-partitions (1.960.0)
90
+ aws-sdk-core (3.201.3)
91
+ aws-eventstream (~> 1, >= 1.3.0)
92
aws-partitions (~> 1, >= 1.651.0)
93
- aws-sigv4 (~> 1.5)
93
+ aws-sigv4 (~> 1.8)
94
jmespath (~> 1, >= 1.6.1)
95
- aws-sdk-kms (1.72.0)
96
- aws-sdk-core (~> 3, >= 3.184.0)
97
- aws-sigv4 (~> 1.1)
98
- aws-sdk-s3 (1.136.0)
99
- aws-sdk-core (~> 3, >= 3.181.0)
95
+ aws-sdk-kms (1.88.0)
96
+ aws-sdk-core (~> 3, >= 3.201.0)
97
+ aws-sigv4 (~> 1.5)
98
+ aws-sdk-s3 (1.156.0)
99
+ aws-sdk-core (~> 3, >= 3.201.0)
100
aws-sdk-kms (~> 1)
101
- aws-sigv4 (~> 1.6)
102
- aws-sigv4 (1.6.0)
101
+ aws-sigv4 (~> 1.5)
102
+ aws-sigv4 (1.9.1)
103
aws-eventstream (~> 1, >= 1.0.2)
104
- base64 (0.1.1)
105
- bcrypt (3.1.19)
106
- bindata (2.4.15)
104
+ base64 (0.2.0)
105
+ bcrypt (3.1.20)
106
+ bigdecimal (3.1.8)
107
+ bindata (2.5.0)
108
bootstrap-sass (3.2.0.4)
109
sass (~> 3.2)
109
- browser (5.3.1)
110
- builder (3.2.4)
110
+ browser (6.0.0)
111
+ builder (3.3.0)
112
+ childprocess (5.0.0)
113
coffee-rails (5.0.0)
114
coffee-script (>= 2.2.0)
115
railties (>= 5.2.0)
@@ -115,52 +117,52 @@ GEM
117
coffee-script-source
118
execjs
119
coffee-script-source (1.12.2)
118
- concurrent-ruby (1.2.2)
120
+ concurrent-ruby (1.3.3)
121
connection_pool (2.4.1)
122
crass (1.0.6)
121
- date (3.3.3)
123
+ date (3.3.4)
124
declarative (0.0.20)
123
- devise (4.9.2)
125
+ devise (4.9.4)
126
bcrypt (~> 3.0)
127
orm_adapter (~> 0.1)
128
railties (>= 4.1.0)
129
responders
130
warden (~> 1.2.3)
129
- devise-jwt (0.11.0)
131
+ devise-jwt (0.12.1)
132
devise (~> 4.0)
131
- warden-jwt_auth (~> 0.8)
132
- devise_invitable (2.0.8)
133
+ warden-jwt_auth (~> 0.10)
134
+ devise_invitable (2.0.9)
135
actionmailer (>= 5.0)
136
devise (>= 4.6)
135
- dotenv (2.8.1)
136
- dotenv-rails (2.8.1)
137
- dotenv (= 2.8.1)
138
- railties (>= 3.2)
137
+ dotenv (3.1.2)
138
+ dotenv-rails (3.1.2)
139
+ dotenv (= 3.1.2)
140
+ railties (>= 6.1)
141
dry-auto_inject (1.0.1)
142
dry-core (~> 1.0)
143
zeitwerk (~> 2.6)
142
- dry-configurable (1.1.0)
144
+ dry-configurable (1.2.0)
145
dry-core (~> 1.0, < 2)
146
zeitwerk (~> 2.6)
147
dry-core (1.0.1)
148
concurrent-ruby (~> 1.0)
149
zeitwerk (~> 2.6)
148
- erubi (1.12.0)
149
- excon (0.104.0)
150
+ erubi (1.13.0)
151
+ excon (0.111.0)
152
execjs (2.9.1)
151
- faraday (2.7.11)
152
- base64
153
- faraday-net_http (>= 2.0, < 3.1)
154
- ruby2_keywords (>= 0.0.4)
153
+ faraday (2.10.0)
154
+ faraday-net_http (>= 2.0, < 3.2)
155
+ logger
156
faraday-follow_redirects (0.3.0)
157
faraday (>= 1, < 3)
157
- faraday-net_http (3.0.2)
158
- ffi (1.16.3)
159
- fog-aws (3.21.0)
158
+ faraday-net_http (3.1.1)
159
+ net-http
160
+ ffi (1.17.0)
161
+ fog-aws (3.24.0)
162
fog-core (~> 2.1)
163
fog-json (~> 1.1)
164
fog-xml (~> 0.1)
163
- fog-core (2.3.0)
165
+ fog-core (2.4.0)
166
builder
167
excon (~> 0.71)
168
formatador (>= 0.2, < 2.0)
@@ -183,43 +185,45 @@ GEM
185
google-api-client (0.53.0)
186
google-apis-core (~> 0.1)
187
google-apis-generator (~> 0.1)
186
- google-apis-core (0.11.1)
188
+ google-apis-core (0.15.1)
189
addressable (~> 2.5, >= 2.5.1)
188
- googleauth (>= 0.16.2, < 2.a)
189
- httpclient (>= 2.8.1, < 3.a)
190
+ googleauth (~> 1.9)
191
+ httpclient (>= 2.8.3, < 3.a)
192
mini_mime (~> 1.0)
193
+ mutex_m
194
representable (~> 3.0)
195
retriable (>= 2.0, < 4.a)
193
- rexml
194
- webrick
195
- google-apis-discovery_v1 (0.14.0)
196
- google-apis-core (>= 0.11.0, < 2.a)
197
- google-apis-generator (0.12.0)
196
+ google-apis-discovery_v1 (0.18.0)
197
+ google-apis-core (>= 0.15.0, < 2.a)
198
+ google-apis-generator (0.15.1)
199
activesupport (>= 5.0)
200
gems (~> 1.2)
200
- google-apis-core (>= 0.11.0, < 2.a)
201
- google-apis-discovery_v1 (~> 0.5)
201
+ google-apis-core (>= 0.15.0, < 2.a)
202
+ google-apis-discovery_v1 (~> 0.18)
203
thor (>= 0.20, < 2.a)
203
- googleauth (1.8.1)
204
- faraday (>= 0.17.3, < 3.a)
204
+ google-cloud-env (2.1.1)
205
+ faraday (>= 1.0, < 3.a)
206
+ googleauth (1.11.0)
207
+ faraday (>= 1.0, < 3.a)
208
+ google-cloud-env (~> 2.1)
209
jwt (>= 1.4, < 3.0)
210
multi_json (~> 1.11)
211
os (>= 0.9, < 2.0)
212
signet (>= 0.16, < 2.a)
209
- has_scope (0.8.1)
213
+ has_scope (0.8.2)
214
actionpack (>= 5.2)
215
activesupport (>= 5.2)
216
hashie (5.0.0)
213
- htmlbeautifier (1.4.2)
217
+ htmlbeautifier (1.4.3)
218
httpclient (2.8.3)
215
- i18n (1.14.1)
219
+ i18n (1.14.5)
220
concurrent-ruby (~> 1.0)
217
- inherited_resources (1.13.1)
218
- actionpack (>= 5.2, < 7.1)
219
- has_scope (~> 0.6)
220
- railties (>= 5.2, < 7.1)
221
- responders (>= 2, < 4)
222
- jbuilder (2.11.5)
221
+ inherited_resources (1.14.0)
222
+ actionpack (>= 6.0)
223
+ has_scope (>= 0.6)
224
+ railties (>= 6.0)
225
+ responders (>= 2)
226
+ jbuilder (2.12.0)
227
actionview (>= 5.0.0)
228
activesupport (>= 5.0.0)
229
jmespath (1.6.2)
@@ -227,14 +231,16 @@ GEM
231
rails-dom-testing (>= 1, < 3)
232
railties (>= 4.2.0)
233
thor (>= 0.14, < 2.0)
230
- json (2.6.3)
231
- json-jwt (1.16.3)
234
+ json (2.7.2)
235
+ json-jwt (1.16.6)
236
activesupport (>= 4.2)
237
aes_key_wrap
238
+ base64
239
bindata
240
faraday (~> 2.0)
241
faraday-follow_redirects
237
- jwt (2.7.1)
242
+ jwt (2.8.2)
243
+ base64
244
kaminari (1.2.2)
245
activesupport (>= 4.1.0)
246
kaminari-actionview (= 1.2.2)
@@ -248,12 +254,14 @@ GEM
254
kaminari-core (= 1.2.2)
255
kaminari-core (1.2.2)
256
language_server-protocol (3.17.0.3)
251
- launchy (2.5.2)
257
+ launchy (3.0.1)
258
addressable (~> 2.8)
253
- letter_opener (1.8.1)
254
- launchy (>= 2.2, < 3)
255
- libv8-node (18.16.0.0)
256
- loofah (2.21.3)
259
+ childprocess (~> 5.0)
260
+ letter_opener (1.10.0)
261
+ launchy (>= 2.2, < 4)
262
+ libv8-node (22.5.1.0)
263
+ logger (1.6.0)
264
+ loofah (2.22.0)
265
crass (~> 1.0.2)
266
nokogiri (>= 1.12.0)
267
mail (2.8.1)
@@ -266,30 +274,34 @@ GEM
274
merit (4.0.3)
275
ambry (~> 1.0.0)
276
zeitwerk
269
- method_source (1.0.0)
270
- mime-types (3.5.1)
277
+ method_source (1.1.0)
278
+ mime-types (3.5.2)
279
mime-types-data (~> 3.2015)
272
- mime-types-data (3.2023.1003)
280
+ mime-types-data (3.2024.0702)
281
mini_mime (1.1.5)
274
- mini_portile2 (2.8.4)
275
- mini_racer (0.8.0)
276
- libv8-node (~> 18.16.0.0)
277
- minitest (5.20.0)
282
+ mini_portile2 (2.8.7)
283
+ mini_racer (0.13.0)
284
+ libv8-node (~> 22.5.1.0)
285
+ minitest (5.24.1)
286
multi_json (1.15.0)
279
- multi_xml (0.6.0)
287
+ multi_xml (0.7.1)
288
+ bigdecimal (~> 3.1)
289
mustermann (3.0.0)
290
ruby2_keywords (~> 0.0.1)
282
- net-imap (0.4.0)
291
+ mutex_m (0.2.0)
292
+ net-http (0.4.1)
293
+ uri
294
+ net-imap (0.4.14)
295
date
296
net-protocol
297
net-pop (0.1.2)
298
net-protocol
287
- net-protocol (0.2.1)
299
+ net-protocol (0.2.2)
300
timeout
289
- net-smtp (0.4.0)
301
+ net-smtp (0.5.0)
302
net-protocol
291
- nio4r (2.5.9)
292
- nokogiri (1.15.4)
303
+ nio4r (2.7.3)
304
+ nokogiri (1.16.7)
305
mini_portile2 (~> 2.8.2)
306
racc (~> 1.4)
307
oauth2 (2.0.9)
@@ -299,64 +311,66 @@ GEM
311
rack (>= 1.2, < 4)
312
snaky_hash (~> 2.0)
313
version_gem (~> 1.1)
302
- omniauth (2.1.1)
314
+ omniauth (2.1.2)
315
hashie (>= 3.4.6)
316
rack (>= 2.2.3)
317
rack-protection
318
omniauth-apple (1.3.0)
319
json-jwt
320
omniauth-oauth2
309
- omniauth-facebook (9.0.0)
310
- omniauth-oauth2 (~> 1.2)
311
- omniauth-google-oauth2 (1.1.1)
321
+ omniauth-facebook (10.0.0)
322
+ bigdecimal
323
+ omniauth-oauth2 (>= 1.2, < 3)
324
+ omniauth-google-oauth2 (1.1.2)
325
jwt (>= 2.0)
313
- oauth2 (~> 2.0.6)
326
+ oauth2 (~> 2.0)
327
omniauth (~> 2.0)
315
- omniauth-oauth2 (~> 1.8.0)
328
+ omniauth-oauth2 (~> 1.8)
329
omniauth-oauth2 (1.8.0)
330
oauth2 (>= 1.4, < 3)
331
omniauth (~> 2.0)
319
- omniauth-rails_csrf_protection (1.0.1)
332
+ omniauth-rails_csrf_protection (1.0.2)
333
actionpack (>= 4.2)
334
omniauth (~> 2.0)
335
omniauth-spotify (0.0.13)
336
omniauth-oauth2 (~> 1.1)
337
orm_adapter (0.5.0)
338
os (1.1.4)
326
- parallel (1.23.0)
327
- parser (3.2.2.4)
339
+ parallel (1.25.1)
340
+ parser (3.3.4.0)
341
ast (~> 2.4.1)
342
racc
330
- pg (1.5.4)
331
- psych (5.1.0)
343
+ pg (1.5.7)
344
+ psych (5.1.2)
345
stringio
333
- public_suffix (5.0.3)
346
+ public_suffix (6.0.1)
347
puma (5.4.0)
348
nio4r (~> 2.0)
336
- racc (1.7.1)
337
- rack (2.2.8)
338
- rack-cors (2.0.1)
349
+ racc (1.8.1)
350
+ rack (2.2.9)
351
+ rack-cors (2.0.2)
352
rack (>= 2.0.0)
340
- rack-protection (3.1.0)
353
+ rack-protection (3.2.0)
354
+ base64 (>= 0.1.0)
355
rack (~> 2.2, >= 2.2.4)
356
rack-proxy (0.7.7)
357
rack
358
rack-test (2.1.0)
359
rack (>= 1.3)
346
- rails (6.1.7.7)
347
- actioncable (= 6.1.7.7)
348
- actionmailbox (= 6.1.7.7)
349
- actionmailer (= 6.1.7.7)
350
- actionpack (= 6.1.7.7)
351
- actiontext (= 6.1.7.7)
352
- actionview (= 6.1.7.7)
353
- activejob (= 6.1.7.7)
354
- activemodel (= 6.1.7.7)
355
- activerecord (= 6.1.7.7)
356
- activestorage (= 6.1.7.7)
357
- activesupport (= 6.1.7.7)
360
+ rails (6.1.7.8)
361
+ actioncable (= 6.1.7.8)
362
+ actionmailbox (= 6.1.7.8)
363
+ actionmailer (= 6.1.7.8)
364
+ actionpack (= 6.1.7.8)
365
+ actiontext (= 6.1.7.8)
366
+ actionview (= 6.1.7.8)
367
+ activejob (= 6.1.7.8)
368
+ activemodel (= 6.1.7.8)
369
+ activerecord (= 6.1.7.8)
370
+ activestorage (= 6.1.7.8)
371
+ activesupport (= 6.1.7.8)
372
bundler (>= 1.15.0)
359
- railties (= 6.1.7.7)
373
+ railties (= 6.1.7.8)
374
sprockets-rails (>= 2.0.0)
375
rails-dom-testing (2.2.0)
376
activesupport (>= 5.0.0)
@@ -365,53 +379,53 @@ GEM
379
rails-html-sanitizer (1.6.0)
380
loofah (~> 2.21)
381
nokogiri (~> 1.14)
368
- railties (6.1.7.7)
369
- actionpack (= 6.1.7.7)
370
- activesupport (= 6.1.7.7)
382
+ railties (6.1.7.8)
383
+ actionpack (= 6.1.7.8)
384
+ activesupport (= 6.1.7.8)
385
method_source
386
rake (>= 12.2)
387
thor (~> 1.0)
388
rainbow (3.1.1)
375
- rake (13.0.6)
389
+ rake (13.2.1)
390
ransack (2.6.0)
391
activerecord (>= 6.0.4)
392
activesupport (>= 6.0.4)
393
i18n
394
rb-fsevent (0.11.2)
381
- rb-inotify (0.10.1)
395
+ rb-inotify (0.11.1)
396
ffi (~> 1.0)
383
- rdoc (6.5.0)
397
+ rdoc (6.7.0)
398
psych (>= 4.0.0)
399
redis (4.4.0)
386
- redis-client (0.17.0)
400
+ redis-client (0.22.2)
401
connection_pool
388
- regexp_parser (2.8.1)
402
+ regexp_parser (2.9.2)
403
representable (3.2.0)
404
declarative (< 0.1.0)
405
trailblazer-option (>= 0.1.1, < 0.2.0)
406
uber (< 0.2.0)
393
- responders (3.1.0)
407
+ responders (3.1.1)
408
actionpack (>= 5.2)
409
railties (>= 5.2)
410
retriable (3.1.2)
397
- rexml (3.2.6)
398
- route_translator (14.0.1)
399
- actionpack (>= 6.1, < 7.1)
400
- activesupport (>= 6.1, < 7.1)
401
- rubocop (1.56.4)
402
- base64 (~> 0.1.1)
411
+ rexml (3.3.2)
412
+ strscan
413
+ route_translator (14.1.2)
414
+ actionpack (>= 6.1, < 8.0)
415
+ activesupport (>= 6.1, < 8.0)
416
+ rubocop (1.65.0)
417
json (~> 2.3)
418
language_server-protocol (>= 3.17.0)
419
parallel (~> 1.10)
406
- parser (>= 3.2.2.3)
420
+ parser (>= 3.3.0.2)
421
rainbow (>= 2.2.2, < 4.0)
408
- regexp_parser (>= 1.8, < 3.0)
422
+ regexp_parser (>= 2.4, < 3.0)
423
rexml (>= 3.2.5, < 4.0)
410
- rubocop-ast (>= 1.28.1, < 2.0)
424
+ rubocop-ast (>= 1.31.1, < 2.0)
425
ruby-progressbar (~> 1.7)
426
unicode-display_width (>= 2.4.0, < 3.0)
413
- rubocop-ast (1.29.0)
414
- parser (>= 3.2.1.0)
427
+ rubocop-ast (1.31.3)
428
+ parser (>= 3.3.1.0)
429
ruby-progressbar (1.13.0)
430
ruby2_keywords (0.0.5)
431
rubystats (0.4.1)
@@ -435,47 +449,51 @@ GEM
449
sdoc (2.6.1)
450
rdoc (>= 5.0)
451
semantic_range (3.0.0)
438
- sentry-rails (5.11.0)
452
+ sentry-rails (5.18.2)
453
railties (>= 5.0)
440
- sentry-ruby (~> 5.11.0)
441
- sentry-ruby (5.11.0)
454
+ sentry-ruby (~> 5.18.2)
455
+ sentry-ruby (5.18.2)
456
+ bigdecimal
457
concurrent-ruby (~> 1.0, >= 1.0.2)
443
- sidekiq (7.1.5)
458
+ sidekiq (7.3.0)
459
concurrent-ruby (< 2)
460
connection_pool (>= 2.3.0)
461
+ logger
462
rack (>= 2.2.4)
447
- redis-client (>= 0.14.0)
448
- signet (0.18.0)
463
+ redis-client (>= 0.22.2)
464
+ signet (0.19.0)
465
addressable (~> 2.8)
466
faraday (>= 0.17.5, < 3.a)
467
jwt (>= 1.5, < 3.0)
468
multi_json (~> 1.10)
453
- sinatra (3.1.0)
469
+ sinatra (3.2.0)
470
mustermann (~> 3.0)
471
rack (~> 2.2, >= 2.2.4)
456
- rack-protection (= 3.1.0)
472
+ rack-protection (= 3.2.0)
473
tilt (~> 2.0)
474
sitemap_generator (6.3.0)
475
builder (~> 3.0)
476
snaky_hash (2.0.1)
477
hashie
478
version_gem (~> 1.1, >= 1.1.1)
463
- split (4.0.2)
479
+ split (4.0.4)
480
+ matrix
481
redis (>= 4.2)
482
rubystats (>= 0.3.0)
483
sinatra (>= 1.2.6)
467
- spring (4.1.1)
484
+ spring (4.2.1)
485
sprockets (3.7.2)
486
concurrent-ruby (~> 1.0)
487
rack (> 1, < 3)
471
- sprockets-rails (3.4.2)
472
- actionpack (>= 5.2)
473
- activesupport (>= 5.2)
488
+ sprockets-rails (3.5.1)
489
+ actionpack (>= 6.1)
490
+ activesupport (>= 6.1)
491
sprockets (>= 3.0.0)
475
- stringio (3.0.8)
476
- thor (1.2.2)
477
- tilt (2.3.0)
478
- timeout (0.4.0)
492
+ stringio (3.1.1)
493
+ strscan (3.1.0)
494
+ thor (1.3.1)
495
+ tilt (2.4.0)
496
+ timeout (0.4.1)
497
tolk (4.1.0)
498
rails (>= 5.0)
499
safe_yaml (>= 0.8.6)
@@ -490,10 +508,11 @@ GEM
508
uglifier (4.2.0)
509
execjs (>= 0.3.0, < 3)
510
unicode-display_width (2.5.0)
493
- version_gem (1.1.3)
511
+ uri (0.13.0)
512
+ version_gem (1.1.4)
513
warden (1.2.9)
514
rack (>= 2.0.9)
496
- warden-jwt_auth (0.8.0)
515
+ warden-jwt_auth (0.10.0)
516
dry-auto_inject (>= 0.8, < 2)
517
dry-configurable (>= 0.13, < 2)
518
jwt (~> 2.1)
@@ -503,12 +522,11 @@ GEM
522
rack-proxy (>= 0.6.1)
523
railties (>= 5.2)
524
semantic_range (>= 2.3.0)
506
- webrick (1.8.1)
525
websocket-driver (0.7.6)
526
websocket-extensions (>= 0.1.0)
527
websocket-extensions (0.1.5)
528
will_paginate (3.3.1)
511
- zeitwerk (2.6.12)
529
+ zeitwerk (2.6.17)
530
531
PLATFORMS
532
ruby
@@ -544,7 +562,7 @@ DEPENDENCIES
562
pg
563
puma (= 5.4.0)
564
rack-cors
547
- rails (= 6.1.7.7)
565
+ rails (= 6.1.7.8)
566
redis (= 4.4.0)
567
route_translator
568
rubocop
frontend/splitfire-desktop/app/_src/App.css
renamed
frontend/splitfire-desktop/app/_src/App.test.js
renamed
frontend/splitfire-desktop/app/_src/App.tsx
renamed
frontend/splitfire-desktop/app/_src/components/karaoke/KaraokeLyricsView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/karaoke/KaraokePlayer.tsx
renamed
frontend/splitfire-desktop/app/_src/components/karaoke/KaraokePlayerView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/karaoke/KaraokeView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/karaoke/LyricSynchRow.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/About.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/AutoCompleteView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/Contact.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/Home.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/Search.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/SearchResultView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/esef/Split.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/esef/SplitFireView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/home/Random.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/home/ReadyToPlay.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/home/SearchFormView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/home/TopVotesView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/SongView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/SongViewConnectProvider.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/SongViewItems.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/SongVotes.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/SongVotesDetailView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/SongVotesView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/components/ButtonSplit.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/components/TitleView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/components/UpDownVotes.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/components/VoterGravatarsViews.tsx
renamed
frontend/splitfire-desktop/app/_src/components/pages/song/components/YoutubeView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/AudioFile.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/AudioPlayer.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/AudioPlayerView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/ControlButtons.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/CountDownView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/HideShowToggle.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/Player.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/PlayerView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/RecordingView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/Song.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/VolumeSliderView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/models/AudioFile.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/models/Mode.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/models/Result.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/models/YouTubeEventTarget.tsx
renamed
frontend/splitfire-desktop/app/_src/components/player/models/YouTubePlayerState.tsx
renamed
frontend/splitfire-desktop/app/_src/components/profiles/BackView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/profiles/Login.tsx
renamed
frontend/splitfire-desktop/app/_src/components/profiles/Logout.tsx
renamed
frontend/splitfire-desktop/app/_src/components/profiles/Profile.tsx
renamed
frontend/splitfire-desktop/app/_src/components/profiles/ProfileFollowers.tsx
renamed
frontend/splitfire-desktop/app/_src/components/profiles/ProfileFollowing.tsx
renamed
frontend/splitfire-desktop/app/_src/components/profiles/ProfileListView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/profiles/ProfileNetworks.tsx
renamed
frontend/splitfire-desktop/app/_src/components/profiles/ProfileView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/profiles/Tabs.tsx
renamed
frontend/splitfire-desktop/app/_src/components/templates/Error.tsx
renamed
frontend/splitfire-desktop/app/_src/components/templates/Footer.tsx
renamed
frontend/splitfire-desktop/app/_src/components/templates/Header.tsx
renamed
frontend/splitfire-desktop/app/_src/components/templates/LoadingView.tsx
renamed
frontend/splitfire-desktop/app/_src/components/templates/Main.tsx
renamed
frontend/splitfire-desktop/app/_src/index.css
renamed
frontend/splitfire-desktop/app/_src/index.tsx
renamed
frontend/splitfire-desktop/app/_src/lib/CurrentUserContext.ts
renamed
frontend/splitfire-desktop/app/_src/lib/axios.ts
renamed
frontend/splitfire-desktop/app/_src/lib/db.ts
renamed
frontend/splitfire-desktop/app/_src/lib/isTauri.ts
renamed
frontend/splitfire-desktop/app/_src/lib/logger.ts
renamed
frontend/splitfire-desktop/app/_src/lib/requestAudioFiles.ts
renamed
frontend/splitfire-desktop/app/_src/lib/requestSplitService.ts
renamed
frontend/splitfire-desktop/app/_src/lib/tauriHandler.ts
renamed
+5
-1
@@ -10,7 +10,11 @@ export const TAURI_PLAYER_PLAY = 'player_play'
10
export const TAURI_PLAYER_PAUSED = 'player_paused'
11
export const TAURI_PLAYER_RESUMED = 'player_resumed'
12
export const TAURI_PLAYER_STOP = 'player_stop'
13
-export const TAURI_PLAYER_RECORDING_LENGTH = 'player_recording_length' // in seconds
13
+export const TAURI_PLAYER_RECORDING_LENGTH = 'player_recording_length' // in seconds
14
+
15
+// Account
16
+export const TAURI_ACCOUNT_LOGIN = 'account_login'
17
+export const TAURI_ACCOUNT_REGISTER = 'account_register'
18
19
export enum TauriResponse {
20
ERROR = 0,
frontend/splitfire-desktop/app/_src/lib/useCountDown.ts
renamed
frontend/splitfire-desktop/app/_src/logo.svg
renamed
frontend/splitfire-desktop/app/_src/models/SongResponse.tsx
renamed
frontend/splitfire-desktop/app/_src/models/SongVotesDetailResponse.tsx
renamed
frontend/splitfire-desktop/app/_src/models/lyricSynches.tsx
renamed
frontend/splitfire-desktop/app/_src/models/user.tsx
renamed
frontend/splitfire-desktop/app/_src/reportWebVitals.js
renamed
frontend/splitfire-desktop/app/_src/setupTests.js
renamed
frontend/splitfire-desktop/app/_src/translations/de.json
renamed
frontend/splitfire-desktop/app/_src/translations/en.json
renamed
frontend/splitfire-desktop/app/_src/translations/es.json
renamed
frontend/splitfire-desktop/app/_src/translations/fr.json
renamed
frontend/splitfire-desktop/app/_src/translations/id.json
renamed
frontend/splitfire-desktop/app/_src/translations/ja.json
renamed
frontend/splitfire-desktop/app/_src/translations/sv.json
renamed
frontend/splitfire-desktop/app/_src/translations/zh.json
renamed
frontend/splitfire-desktop/app/_ui/address-bar.tsx
+2
-34
@@ -1,41 +1,9 @@
1
'use client';
2
3
-import React, { Suspense } from 'react';
4
-import { usePathname, useSearchParams } from 'next/navigation';
3
+import React from 'react';
4
+import { usePathname } from 'next/navigation';
5
import { HomeIcon } from '@heroicons/react/solid';
6
7
-function Params() {
8
- const searchParams = useSearchParams()!;
9
-
10
- return searchParams.toString().length !== 0 ? (
11
- <div className="px-2 text-gray-500">
12
- <span>?</span>
13
- {Array.from(searchParams.entries()).map(([key, value], index) => {
14
- return (
15
- <React.Fragment key={key}>
16
- {index !== 0 ? <span>&</span> : null}
17
- <span className="px-1">
18
- <span
19
- key={key}
20
- className="animate-[highlight_1s_ease-in-out_1] text-gray-100"
21
- >
22
- {key}
23
- </span>
24
- <span>=</span>
25
- <span
26
- key={value}
27
- className="animate-[highlight_1s_ease-in-out_1] text-gray-100"
28
- >
29
- {value}
30
- </span>
31
- </span>
32
- </React.Fragment>
33
- );
34
- })}
35
- </div>
36
- ) : null;
37
-}
38
-
7
export function AddressBar() {
8
const pathname = usePathname();
9
console.log('pathname', pathname);
frontend/splitfire-desktop/app/_ui/components/button.tsx
+1
-2
@@ -1,8 +1,7 @@
1
import * as React from 'react'
2
import { Slot } from '@radix-ui/react-slot'
3
import { cva, type VariantProps } from 'class-variance-authority'
4
-import { cn } from '@/app/_lib/utils'
5
-
4
+import { cn } from '@/lib/utils'
5
6
const buttonVariants = cva(
7
'inline-flex items-center justify-center rounded-md text-sm font-medium shadow ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
frontend/splitfire-desktop/app/_ui/global-nav.tsx
+1
@@ -70,6 +70,7 @@ export function GlobalNav() {
70
71
<div className="space-y-1">
72
<GlobalNavItem key={"login"} item={{name: "Login", slug: "login"}} close={close} />
73
+ <GlobalNavItem key={"register"} item={{name: "Register", slug: "register"}} close={close} />
74
</div>
75
</nav>
76
</div>
frontend/splitfire-desktop/app/globals.css
+1
@@ -1,3 +1,4 @@
1
@tailwind base;
2
@tailwind components;
3
@tailwind utilities;
4
+
\ No newline at end of file
frontend/splitfire-desktop/app/layout.tsx
+10
-10
@@ -1,9 +1,7 @@
1
-import { Metadata } from 'next';
2
-import { AddressBar } from './_ui/address-bar';
3
-import { GlobalNav } from './_ui/global-nav';
4
-import './globals.css';
5
-import { cn } from '@/lib/utils';
6
-
1
+import { Metadata } from "next";
2
+import { AddressBar } from "./_ui/address-bar";
3
+import { GlobalNav } from "./_ui/global-nav";
4
+import "./globals.css";
5
6
export const metadata: Metadata = {
7
title: "SplitFire",
@@ -20,14 +18,16 @@ export default function RootLayout({
18
<body className="bg-gray-1100 overflow-y-scroll bg-[url('/grid.svg')] pb-36">
19
<GlobalNav />
20
<div className="lg:pl-72">
23
- <div className="bg-vc-border-gradient rounded-lg p-px shadow-lg shadow-black/20">
21
+ <div className="bg-vc-border-gradient rounded-lg p-px shadow-lg shadow-black/20">
22
<div className="rounded-lg bg-black">
25
- <AddressBar />
26
- </div>
23
+ <AddressBar />
24
</div>
25
+ </div>
26
<div className="mx-auto max-w-4xl space-y-8 px-2 pt-20 lg:px-8 lg:py-8">
27
<div className="bg-vc-border-gradient rounded-lg p-px shadow-lg shadow-black/20">
30
- <div className="rounded-lg bg-black p-3.5 lg:p-6">{children}</div>
28
+ <div className="rounded-lg bg-black p-3.5 lg:p-6">
29
+ {children}
30
+ </div>
31
</div>
32
</div>
33
</div>
frontend/splitfire-desktop/app/login/layout.tsx
new
+25
@@ -0,0 +1,25 @@
1
+import { Metadata } from 'next';
2
+import React from 'react';
3
+
4
+export const metadata: Metadata = {
5
+ title: "Play",
6
+ description: "an intelligent exression engine.",
7
+};
8
+
9
+
10
+export default async function Layout({
11
+ children,
12
+}: {
13
+ children: React.ReactNode;
14
+}) {
15
+ return (
16
+ <div className="space-y-9">
17
+ <div className="flex justify-between">
18
+ <div className="self-start">
19
+ <h1 className="text-3xl font-bold">Login</h1>
20
+ </div>
21
+ </div>
22
+ <div>{children}</div>
23
+ </div>
24
+ );
25
+}
frontend/splitfire-desktop/app/login/page.tsx
+104
-14
@@ -1,21 +1,111 @@
1
-import Link from "next/link";
1
+"use client";
2
+
3
+import * as Form from "@radix-ui/react-form";
4
+import { invoke } from "@tauri-apps/api/tauri";
5
+import { TAURI_ACCOUNT_LOGIN } from "../_src/lib/tauriHandler";
6
+import { Button } from "../_ui/components/button";
7
+import { useState } from "react";
8
+import { UserContext } from "../_src/lib/CurrentUserContext";
9
+import { CurrentUser, CurrentUserType, db } from "../_src/lib/db";
10
+import { AccountLoginResponse } from "@/models/account";
11
+import { Mode } from "../_src/components/player/models/Mode";
12
13
export default function Page() {
14
+ const [emailOrUsername, setEmailOrUsername] = useState("");
15
+ const [password, setPassword] = useState("");
16
+
17
+ const login = async (update: (user: CurrentUser) => void) => {
18
+ const payload = {
19
+ username: emailOrUsername,
20
+ password: password,
21
+ };
22
+ console.log("payload", payload);
23
+ const response: AccountLoginResponse = await invoke(TAURI_ACCOUNT_LOGIN, payload);
24
+ console.log("response", response);
25
+ let currentUser: CurrentUser = {
26
+ accessToken: "",
27
+ type: CurrentUserType.MAIN,
28
+ user: response.user,
29
+ mode: Mode.Vocal
30
+ }
31
+ db.currentUser.add(currentUser)
32
+ update(currentUser);
33
+ };
34
+
35
return (
5
- <div className="space-y-8">
6
- <h1 className="text-xl font-medium text-gray-300">Login</h1>
7
- <div className="h-screen w-screen flex justify-center items-center bg-slate-100">
8
- <div className="sm:shadow-xl px-8 pb-8 pt-12 sm:bg-white rounded-xl space-y-12">
9
- <h1 className="font-semibold text-2xl">Login</h1>
10
-
11
- <p className="text-center">
12
- Need to create an account?{' '}
13
- <Link className="text-indigo-500 hover:underline" href="/register">
14
- Create Account
15
- </Link>{' '}
16
- </p>
36
+ <div className="prose prose-sm prose-invert max-w-none">
37
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
38
+ <UserContext.Consumer>
39
+ {({ user, updateUser: update }) => (
40
+ <Form.Root
41
+ className="FormRoot"
42
+ onSubmit={(event) => {
43
+ event.preventDefault();
44
+ }}
45
+ >
46
+ <Form.Field className="FormField" name="email">
47
+ <div
48
+ style={{
49
+ display: "flex",
50
+ alignItems: "baseline",
51
+ justifyContent: "space-between",
52
+ }}
53
+ >
54
+ <Form.Label className="FormLabel">Email</Form.Label>
55
+ <Form.Message className="FormMessage" match="valueMissing">
56
+ Please enter your email
57
+ </Form.Message>
58
+ <Form.Message className="FormMessage" match="typeMismatch">
59
+ Please provide a valid email
60
+ </Form.Message>
61
+ </div>
62
+ <Form.Control asChild>
63
+ <input
64
+ className="Input"
65
+ type="email"
66
+ value={emailOrUsername}
67
+ onChange={(e) => setEmailOrUsername(e.currentTarget.value)}
68
+ required
69
+ />
70
+ </Form.Control>
71
+ </Form.Field>
72
+ <Form.Field className="FormField" name="password">
73
+ <div
74
+ style={{
75
+ display: "flex",
76
+ alignItems: "baseline",
77
+ justifyContent: "space-between",
78
+ }}
79
+ >
80
+ <Form.Label className="FormLabel">Password</Form.Label>
81
+ <Form.Message className="FormMessage" match="valueMissing">
82
+ Please enter your email
83
+ </Form.Message>
84
+ <Form.Message className="FormMessage" match="typeMismatch">
85
+ Please provide a valid email
86
+ </Form.Message>
87
+ </div>
88
+ <Form.Control asChild>
89
+ <input
90
+ className="Input"
91
+ type="password"
92
+ value={password}
93
+ onChange={(e) => {
94
+ setPassword(e.currentTarget.value);
95
+ }}
96
+ required
97
+ />
98
+ </Form.Control>
99
+ </Form.Field>
100
+ <Form.Field className="FormField" name="password">
101
+ <Button onClick={() => login(update)} variant={"outline"} size={"lg"}>
102
+ Login
103
+ </Button>
104
+ </Form.Field>
105
+ </Form.Root>
106
+ )}
107
+ </UserContext.Consumer>
108
</div>
109
</div>
19
- </div>
110
);
111
}
frontend/splitfire-desktop/app/page.tsx
+27
-5
@@ -1,10 +1,32 @@
1
+import { SkeletonCard } from "./_ui/skeleton-card";
2
+
3
+export async function generateStaticParams() {
4
+ const posts = [
5
+ { slug: "post-1" },
6
+ { slug: "post-2" },
7
+ { slug: "post-3" },
8
+ ];
9
+
10
+ return posts.map((post) => ({
11
+ slug: post.slug,
12
+ }))
13
+}
14
+
15
export default function Page() {
16
return (
3
- <div className="space-y-8">
4
- <h1 className="text-xl font-medium text-gray-300">Hello, Tauri on Bazel!</h1>
5
- <div className="space-y-10 text-white">
6
- <div className="space-y-5">
7
- <div className="grid grid-cols-1 gap-5 lg:grid-cols-2"></div>
17
+ <div className="space-y-9">
18
+ <div className="flex justify-between">
19
+ <div className="self-start">
20
+ <h1 className="text-3xl font-bold">Discover</h1>
21
+ </div>
22
+ </div>
23
+ <div>
24
+ <div className="prose prose-sm prose-invert max-w-none">
25
+ <div className="grid grid-cols-3 gap-6">
26
+ {Array.from({ length: 20 }).map((_, i) => (
27
+ <SkeletonCard key={i} />
28
+ ))}
29
+ </div>
30
</div>
31
</div>
32
</div>
frontend/splitfire-desktop/app/register/layout.tsx
new
+18
@@ -0,0 +1,18 @@
1
+import React from 'react';
2
+
3
+export default async function Layout({
4
+ children,
5
+}: {
6
+ children: React.ReactNode;
7
+}) {
8
+ return (
9
+ <div className="space-y-9">
10
+ <div className="flex justify-between">
11
+ <div className="self-start">
12
+ <h1 className="text-3xl font-bold">{"Register"}</h1>
13
+ </div>
14
+ </div>
15
+ <div>{children}</div>
16
+ </div>
17
+ );
18
+}
frontend/splitfire-desktop/app/register/page.tsx
new
+97
@@ -0,0 +1,97 @@
1
+'use client';
2
+
3
+import { invoke } from "@tauri-apps/api";
4
+import { useState } from "react";
5
+import * as Form from "@radix-ui/react-form";
6
+import { TAURI_ACCOUNT_REGISTER } from "../_src/lib/tauriHandler";
7
+import { Button } from "../_ui/components/button";
8
+
9
+export default function Page() {
10
+
11
+ const [name, setName] = useState("");
12
+ const [email, setEmail] = useState("");
13
+ const [password, setPassword] = useState("");
14
+
15
+ const register = async () => {
16
+ const payload = {
17
+ name: name,
18
+ email: email,
19
+ password: password,
20
+ };
21
+ console.log("payload", payload);
22
+ const response = await invoke(TAURI_ACCOUNT_REGISTER, payload);
23
+ console.log("response", response);
24
+ };
25
+
26
+ return (
27
+ <div className="prose prose-sm prose-invert max-w-none">
28
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
29
+ <Form.Root className="FormRoot" onSubmit={(event) => { event.preventDefault()}}>
30
+ <Form.Field className="FormField" name="name">
31
+ <div
32
+ style={{
33
+ display: "flex",
34
+ alignItems: "baseline",
35
+ justifyContent: "space-between",
36
+ }}
37
+ >
38
+ <Form.Label className="FormLabel">Name</Form.Label>
39
+ <Form.Message className="FormMessage" match="valueMissing">
40
+ Please enter your name
41
+ </Form.Message>
42
+ <Form.Message className="FormMessage" match="typeMismatch">
43
+ Please provide a valid name
44
+ </Form.Message>
45
+ </div>
46
+ <Form.Control asChild>
47
+ <input className="Input" type="text" value={name} onChange={(e) => setName(e.currentTarget.value)} required />
48
+ </Form.Control>
49
+ </Form.Field>
50
+ <Form.Field className="FormField" name="email">
51
+ <div
52
+ style={{
53
+ display: "flex",
54
+ alignItems: "baseline",
55
+ justifyContent: "space-between",
56
+ }}
57
+ >
58
+ <Form.Label className="FormLabel">Email</Form.Label>
59
+ <Form.Message className="FormMessage" match="valueMissing">
60
+ Please enter your email
61
+ </Form.Message>
62
+ <Form.Message className="FormMessage" match="typeMismatch">
63
+ Please provide a valid email
64
+ </Form.Message>
65
+ </div>
66
+ <Form.Control asChild>
67
+ <input className="Input" type="email" value={email} onChange={(e) => setEmail(e.currentTarget.value)} required />
68
+ </Form.Control>
69
+ </Form.Field>
70
+ <Form.Field className="FormField" name="password">
71
+ <div
72
+ style={{
73
+ display: "flex",
74
+ alignItems: "baseline",
75
+ justifyContent: "space-between",
76
+ }}
77
+ >
78
+ <Form.Label className="FormLabel">Password</Form.Label>
79
+ <Form.Message className="FormMessage" match="valueMissing">
80
+ Please enter your email
81
+ </Form.Message>
82
+ <Form.Message className="FormMessage" match="typeMismatch">
83
+ Please provide a valid email
84
+ </Form.Message>
85
+ </div>
86
+ <Form.Control asChild>
87
+ <input className="Input" type="password" value={password} onChange={(e)=>{setPassword(e.currentTarget.value)}} required />
88
+ </Form.Control>
89
+ </Form.Field>
90
+ <Form.Field className="FormField" name="button">
91
+ <Button onClick={register} variant={"outline"} size={"lg"}>Register</Button>
92
+ </Form.Field>
93
+ </Form.Root>
94
+ </div>
95
+ </div>
96
+ );
97
+}
\ No newline at end of file
frontend/splitfire-desktop/components.json
new
+17
@@ -0,0 +1,17 @@
1
+{
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": false,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "tailwind.config.ts",
8
+ "css": "app/globals.css",
9
+ "baseColor": "slate",
10
+ "cssVariables": false,
11
+ "prefix": ""
12
+ },
13
+ "aliases": {
14
+ "components": "@/components",
15
+ "utils": "@/lib/utils"
16
+ }
17
+}
\ No newline at end of file
frontend/splitfire-desktop/components/ui/button.tsx
new
+56
@@ -0,0 +1,56 @@
1
+import * as React from "react"
2
+import { Slot } from "@radix-ui/react-slot"
3
+import { cva, type VariantProps } from "class-variance-authority"
4
+import { cn } from "@/lib/utils"
5
+
6
+const buttonVariants = cva(
7
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:pointer-events-none disabled:opacity-50 dark:focus-visible:ring-slate-300",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default:
12
+ "bg-slate-900 text-slate-50 shadow hover:bg-slate-900/90 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50/90",
13
+ destructive:
14
+ "bg-red-500 text-slate-50 shadow-sm hover:bg-red-500/90 dark:bg-red-900 dark:text-slate-50 dark:hover:bg-red-900/90",
15
+ outline:
16
+ "border border-slate-200 bg-white shadow-sm hover:bg-slate-100 hover:text-slate-900 dark:border-slate-800 dark:bg-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50",
17
+ secondary:
18
+ "bg-slate-100 text-slate-900 shadow-sm hover:bg-slate-100/80 dark:bg-slate-800 dark:text-slate-50 dark:hover:bg-slate-800/80",
19
+ ghost: "hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-slate-800 dark:hover:text-slate-50",
20
+ link: "text-slate-900 underline-offset-4 hover:underline dark:text-slate-50",
21
+ },
22
+ size: {
23
+ default: "h-9 px-4 py-2",
24
+ sm: "h-8 rounded-md px-3 text-xs",
25
+ lg: "h-10 rounded-md px-8",
26
+ icon: "h-9 w-9",
27
+ },
28
+ },
29
+ defaultVariants: {
30
+ variant: "default",
31
+ size: "default",
32
+ },
33
+ }
34
+)
35
+
36
+export interface ButtonProps
37
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
38
+ VariantProps<typeof buttonVariants> {
39
+ asChild?: boolean
40
+}
41
+
42
+const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
43
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
44
+ const Comp = asChild ? Slot : "button"
45
+ return (
46
+ <Comp
47
+ className={cn(buttonVariants({ variant, size, className }))}
48
+ ref={ref}
49
+ {...props}
50
+ />
51
+ )
52
+ }
53
+)
54
+Button.displayName = "Button"
55
+
56
+export { Button, buttonVariants }
frontend/splitfire-desktop/lib/utils.ts
renamed
frontend/splitfire-desktop/models/account.ts
new
+8
@@ -0,0 +1,8 @@
1
+import { TauriResponse } from "@/app/_src/lib/tauriHandler";
2
+import User from "@/app/_src/models/user";
3
+
4
+export interface AccountLoginResponse {
5
+ status: TauriResponse,
6
+ message: string,
7
+ user: User
8
+}
frontend/splitfire-desktop/package-lock.json
+51
-1
@@ -10,8 +10,9 @@
10
"license": "MIT",
11
"dependencies": {
12
"@heroicons/react": "1.0.6",
13
+ "@radix-ui/react-form": "^0.1.0",
14
"@radix-ui/react-icons": "^1.3.0",
14
- "@radix-ui/react-slot": "^1.0.2",
15
+ "@radix-ui/react-slot": "^1.1.0",
16
"@radix-ui/react-tooltip": "^1.0.7",
17
"@sentry/react": "^7.12.1",
18
"@sentry/tracing": "^7.12.1",
@@ -3457,6 +3458,33 @@
3458
}
3459
}
3460
},
3461
+ "node_modules/@radix-ui/react-form": {
3462
+ "version": "0.1.0",
3463
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-form/-/react-form-0.1.0.tgz",
3464
+ "integrity": "sha512-1/oVYPDjbFILOLIarcGcMKo+y6SbTVT/iUKVEw59CF4offwZgBgC3ZOeSBewjqU0vdA6FWTPWTN63obj55S/tQ==",
3465
+ "dependencies": {
3466
+ "@radix-ui/primitive": "1.1.0",
3467
+ "@radix-ui/react-compose-refs": "1.1.0",
3468
+ "@radix-ui/react-context": "1.1.0",
3469
+ "@radix-ui/react-id": "1.1.0",
3470
+ "@radix-ui/react-label": "2.1.0",
3471
+ "@radix-ui/react-primitive": "2.0.0"
3472
+ },
3473
+ "peerDependencies": {
3474
+ "@types/react": "*",
3475
+ "@types/react-dom": "*",
3476
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
3477
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3478
+ },
3479
+ "peerDependenciesMeta": {
3480
+ "@types/react": {
3481
+ "optional": true
3482
+ },
3483
+ "@types/react-dom": {
3484
+ "optional": true
3485
+ }
3486
+ }
3487
+ },
3488
"node_modules/@radix-ui/react-icons": {
3489
"version": "1.3.0",
3490
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
@@ -3482,6 +3510,28 @@
3510
}
3511
}
3512
},
3513
+ "node_modules/@radix-ui/react-label": {
3514
+ "version": "2.1.0",
3515
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz",
3516
+ "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==",
3517
+ "dependencies": {
3518
+ "@radix-ui/react-primitive": "2.0.0"
3519
+ },
3520
+ "peerDependencies": {
3521
+ "@types/react": "*",
3522
+ "@types/react-dom": "*",
3523
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
3524
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3525
+ },
3526
+ "peerDependenciesMeta": {
3527
+ "@types/react": {
3528
+ "optional": true
3529
+ },
3530
+ "@types/react-dom": {
3531
+ "optional": true
3532
+ }
3533
+ }
3534
+ },
3535
"node_modules/@radix-ui/react-popper": {
3536
"version": "1.2.0",
3537
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
frontend/splitfire-desktop/package.json
+2
-1
@@ -6,8 +6,9 @@
6
"dependencies": {
7
"@heroicons/react": "1.0.6",
8
"@radix-ui/react-icons": "^1.3.0",
9
- "@radix-ui/react-slot": "^1.0.2",
9
+ "@radix-ui/react-slot": "^1.1.0",
10
"@radix-ui/react-tooltip": "^1.0.7",
11
+ "@radix-ui/react-form": "^0.1.0",
12
"@sentry/react": "^7.12.1",
13
"@sentry/tracing": "^7.12.1",
14
"@tauri-apps/api": "^1.5.3",
frontend/splitfire-desktop/src-tauri/src/command/constants.rs
+2
@@ -18,6 +18,8 @@ pub const API_HOST: &str = "api.musik88.com";
18
19
// Paths
20
pub const PATH_AUDIO: &str = "api/v1/splitfire";
21
+pub const PATH_ACCOUNT_LOGIN: &str = "api/v1/login";
22
+pub const PATH_ACCOUNT_REGISTER: &str = "api/v1/register";
23
24
pub fn base_url_builder() -> URLBuilder {
25
let mut url_builder = URLBuilder::new();
frontend/splitfire-desktop/src-tauri/src/command/download_result_files.rs
+1
-24
@@ -1,40 +1,17 @@
1
use crate::{
2
- audio_dir_path,
3
- command::player_prepare::get_mode_from_filename,
4
- players::{BASS_FILE, DRUMS_FILE, OTHER_FILE, VOCALS_FILE},
2
+ audio_dir_path, command::player_prepare::get_mode_from_filename, models::player::ResultFile, players::{BASS_FILE, DRUMS_FILE, OTHER_FILE, VOCALS_FILE}
3
};
4
use anyhow::anyhow;
5
use futures::future;
6
use log::{debug, error, info, warn};
7
use reqwest::{Client, Error, Response};
8
use std::{
11
- fmt::Display,
9
fs::{create_dir_all, File, OpenOptions},
10
io::Write,
11
path::{Path, PathBuf},
12
};
16
-
13
use super::player_set_volume::Mode;
14
19
-#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
20
-pub struct ResultFile {
21
- id: i32,
22
- source_file: String,
23
- filename: String,
24
- pub length: Option<f64>,
25
- onset: Option<Vec<f64>>,
26
-}
27
-
28
-impl Display for ResultFile {
29
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30
- write!(
31
- f,
32
- "{{ id: {}, source_file: {}, filename: {}, length: {:?}, onset: {:?} }}",
33
- self.id, self.source_file, self.filename, self.length, self.onset
34
- )
35
- }
36
-}
37
-
15
pub async fn save_result_files(audio_file_id: &String, result_files: &[ResultFile]) {
16
// Check if we have ~/.sfai/audio/{provider_id} folder and create it if not
17
let audio_id_path = match get_provider_id_dir_path(audio_file_id).await {
frontend/splitfire-desktop/src-tauri/src/command/player_prepare.rs
+2
-46
@@ -1,21 +1,16 @@
1
use super::{
2
constants::{base_url_builder, PATH_AUDIO},
3
- download_result_files::{save_result_files, ResultFile},
3
+ download_result_files::save_result_files,
4
};
5
use crate::{
6
command::{
7
download_result_files::{download_result_files, get_provider_id_dir_path},
8
player_set_volume::Mode,
9
- },
10
- get_soundcard,
11
- players::{BASS_SINK, DRUMS_SINK, OTHER_SINK, VOCALS_SINK},
12
- record::record_instrument::AudioDevice,
9
+ }, get_soundcard, models::player::{AudioFile, AudioFileResponse, PreparePlayerResponse, TauriResponse}, players::{BASS_SINK, DRUMS_SINK, OTHER_SINK, VOCALS_SINK}, record::record_instrument::AudioDevice
10
};
11
use log::{debug, error, info};
12
use reqwest::Client;
13
use rodio::{Decoder, DeviceTrait, OutputStream, Sink};
17
-use serde::{Deserialize, Serialize};
18
-use serde_repr::*;
14
use std::{
15
fs::{self, DirEntry, File},
16
io::BufReader,
@@ -23,45 +18,6 @@ use std::{
18
};
19
use tauri::async_runtime::spawn;
20
26
-#[derive(Serialize, Deserialize)]
27
-enum Status {
28
- #[serde(rename = "downloading")]
29
- Downloading,
30
- #[serde(rename = "splitting")]
31
- Split,
32
- #[serde(rename = "done")]
33
- Done,
34
-}
35
-
36
-#[derive(Serialize, Deserialize)]
37
-struct AudioFile {
38
- id: i32,
39
- name: String,
40
- status: Status,
41
- results: Vec<ResultFile>,
42
-}
43
-
44
-#[derive(Serialize, Deserialize)]
45
-struct AudioFileResponse {
46
- code: i32,
47
- message: String,
48
- audio_file: AudioFile,
49
-}
50
-
51
-#[derive(Serialize_repr)]
52
-#[repr(u8)]
53
-enum TauriResponse {
54
- Error = 0,
55
- Success = 1,
56
-}
57
-
58
-#[derive(Serialize)]
59
-pub struct PreparePlayerResponse {
60
- status: TauriResponse,
61
- message: String,
62
- audio_file_name: Option<String>,
63
-}
64
-
21
#[tauri::command]
22
pub async fn player_prepare(provider_id: String) -> PreparePlayerResponse {
23
debug!("Preparing player for provider_id {}.", provider_id);
frontend/splitfire-desktop/src-tauri/src/lib.rs
+2
@@ -9,6 +9,8 @@ use std::{fs::create_dir_all, path::PathBuf};
9
pub mod command;
10
pub mod players;
11
pub mod record;
12
+pub mod rest;
13
+pub mod models;
14
15
#[cfg(debug_assertions)]
16
const HOME_DIR: &str = ".sfai-dev";
frontend/splitfire-desktop/src-tauri/src/main.rs
+6
-1
@@ -18,6 +18,9 @@ use app::{
18
player_set_volume::{__cmd__player_set_volume, player_set_volume},
19
player_unmount::{__cmd__player_unmount, player_unmount},
20
},
21
+ rest::account::{
22
+ __cmd__account_login, __cmd__account_register, account_login, account_register,
23
+ },
24
sfai_home_dir_path,
25
};
26
use tauri_plugin_log::fern::colors::{Color, ColoredLevelConfig};
@@ -37,6 +40,8 @@ fn main() {
40
.build(),
41
)
42
.invoke_handler(tauri::generate_handler![
43
+ account_login,
44
+ account_register,
45
open_lyrics_editor,
46
open_player,
47
player_record,
@@ -47,7 +52,7 @@ fn main() {
52
player_paused,
53
player_play,
54
player_stop,
50
- player_recording_length
55
+ player_recording_length,
56
])
57
.run(tauri::generate_context!())
58
.expect("Error while running tauri application.");
frontend/splitfire-desktop/src-tauri/src/models/account.rs
new
+30
@@ -0,0 +1,30 @@
1
+use serde::{Deserialize, Serialize};
2
+use super::player::TauriResponse;
3
+
4
+#[derive(Serialize)]
5
+#[derive(Debug)]
6
+pub struct AccountLoginResponse {
7
+ status: TauriResponse,
8
+ message: String,
9
+ user: Option<User>,
10
+}
11
+
12
+#[derive(Serialize, Deserialize)]
13
+#[derive(Debug)]
14
+pub struct LoginResponse {
15
+ code: i32,
16
+ message: String,
17
+ user: User,
18
+}
19
+
20
+#[derive(Serialize, Deserialize, Debug)]
21
+pub struct User {
22
+ id: i32,
23
+ email: String,
24
+ username: String,
25
+ name: String,
26
+ gravatar_url: String,
27
+ followers_count: i32,
28
+ following_count: i32,
29
+ about: String
30
+}
\ No newline at end of file
frontend/splitfire-desktop/src-tauri/src/models/mod.rs
new
+2
@@ -0,0 +1,2 @@
1
+pub mod account;
2
+pub mod player;
\ No newline at end of file
frontend/splitfire-desktop/src-tauri/src/models/player.rs
new
+63
@@ -0,0 +1,63 @@
1
+use std::fmt::Display;
2
+use serde::{Deserialize, Serialize};
3
+use serde_repr::Serialize_repr;
4
+
5
+
6
+#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
7
+pub struct ResultFile {
8
+ id: i32,
9
+ pub source_file: String,
10
+ pub filename: String,
11
+ pub length: Option<f64>,
12
+ pub onset: Option<Vec<f64>>,
13
+}
14
+
15
+impl Display for ResultFile {
16
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17
+ write!(
18
+ f,
19
+ "{{ id: {}, source_file: {}, filename: {}, length: {:?}, onset: {:?} }}",
20
+ self.id, self.source_file, self.filename, self.length, self.onset
21
+ )
22
+ }
23
+}
24
+
25
+#[derive(Serialize, Deserialize)]
26
+enum Status {
27
+ #[serde(rename = "downloading")]
28
+ Downloading,
29
+ #[serde(rename = "splitting")]
30
+ Split,
31
+ #[serde(rename = "done")]
32
+ Done,
33
+}
34
+
35
+#[derive(Serialize, Deserialize)]
36
+pub struct AudioFile {
37
+ pub id: i32,
38
+ pub name: String,
39
+ pub status: Status,
40
+ pub results: Vec<ResultFile>,
41
+}
42
+
43
+#[derive(Serialize, Deserialize)]
44
+pub struct AudioFileResponse {
45
+ pub code: i32,
46
+ pub message: String,
47
+ pub audio_file: AudioFile,
48
+}
49
+
50
+#[derive(Serialize_repr)]
51
+#[repr(u8)]
52
+#[derive(Debug)]
53
+pub enum TauriResponse {
54
+ Error = 0,
55
+ Success = 1,
56
+}
57
+
58
+#[derive(Serialize)]
59
+pub struct PreparePlayerResponse {
60
+ pub status: TauriResponse,
61
+ pub message: String,
62
+ pub audio_file_name: Option<String>,
63
+}
\ No newline at end of file
frontend/splitfire-desktop/src-tauri/src/players.rs
+3
-1
@@ -1,4 +1,4 @@
1
-use crate::command::download_result_files::ResultFile;
1
+use models::player::ResultFile;
2
use hound::WavWriter;
3
use once_cell::sync::OnceCell;
4
use rodio::Sink;
@@ -8,6 +8,8 @@ use std::{
8
sync::{mpsc::Sender, Arc, Mutex},
9
};
10
11
+use crate::models;
12
+
13
pub static mut VOCALS_SINK: OnceCell<Sink> = OnceCell::new();
14
pub static mut DRUMS_SINK: OnceCell<Sink> = OnceCell::new();
15
pub static mut BASS_SINK: OnceCell<Sink> = OnceCell::new();
frontend/splitfire-desktop/src-tauri/src/rest/account.rs
new
+82
@@ -0,0 +1,82 @@
1
+use log::debug;
2
+use reqwest::Client;
3
+use serde_json::json;
4
+use tauri;
5
+use crate::{command::constants::{base_url_builder, PATH_ACCOUNT_LOGIN, PATH_ACCOUNT_REGISTER}, models::account::LoginResponse};
6
+
7
+#[tauri::command]
8
+pub async fn account_login(username: String, password: String) {
9
+ debug!("Logging in with username {}.", username);
10
+ // Login
11
+ let body = json!( {
12
+ "username": username,
13
+ "password": password
14
+ });
15
+ let response = Client::new()
16
+ .post(login_url_builder())
17
+ .json(&body)
18
+ .send()
19
+ .await;
20
+
21
+ match response {
22
+ Ok(response) => {
23
+ debug!("Got response: {:?}", response);
24
+ let res: LoginResponse = match response.json().await {
25
+ Ok(json) => json,
26
+ Err(e) => {
27
+ println!("Failed to parse response: {:?}", e);
28
+ return;
29
+ }
30
+ };
31
+ debug!("Login response: {:?}", res);
32
+ }
33
+ Err(e) => {
34
+ println!("Failed to get response: {:?}", e);
35
+ }
36
+ }
37
+}
38
+
39
+#[tauri::command]
40
+pub async fn account_register(username: String, email: String, password: String) {
41
+ debug!("Registering with username {} and email {}.", username, email);
42
+ // Register
43
+ let body = json!( {
44
+ "username": username,
45
+ "email": email,
46
+ "password": password
47
+ });
48
+ let response = Client::new()
49
+ .post(register_url_builder())
50
+ .json(&body)
51
+ .send()
52
+ .await;
53
+
54
+ match response {
55
+ Ok(response) => {
56
+ debug!("Got response: {:?}", response);
57
+ let res: LoginResponse = match response.json().await {
58
+ Ok(json) => json,
59
+ Err(e) => {
60
+ println!("Failed to parse response: {:?}", e);
61
+ return;
62
+ }
63
+ };
64
+ debug!("Register response: {:?}", res);
65
+ }
66
+ Err(e) => {
67
+ println!("Failed to get response: {:?}", e);
68
+ }
69
+ }
70
+}
71
+
72
+fn login_url_builder() -> String {
73
+ let mut base_url = base_url_builder();
74
+ base_url.add_route(PATH_ACCOUNT_LOGIN);
75
+ base_url.build()
76
+}
77
+
78
+fn register_url_builder() -> String {
79
+ let mut base_url = base_url_builder();
80
+ base_url.add_route(PATH_ACCOUNT_REGISTER);
81
+ base_url.build()
82
+}
\ No newline at end of file
frontend/splitfire-desktop/src-tauri/src/rest/mod.rs
new
+1
@@ -0,0 +1 @@
1
+pub mod account;
\ No newline at end of file
frontend/splitfire-desktop/tailwind.config.ts
+1
-41
@@ -7,7 +7,7 @@ const config = {
7
'./components/**/*.{ts,tsx}',
8
'./app/**/*.{ts,tsx}',
9
'./src/**/*.{ts,tsx}',
10
- ],
10
+ ],
11
prefix: "",
12
theme: {
13
container: {
@@ -18,46 +18,6 @@ const config = {
18
},
19
},
20
extend: {
21
- colors: {
22
- border: "hsl(var(--border))",
23
- input: "hsl(var(--input))",
24
- ring: "hsl(var(--ring))",
25
- background: "hsl(var(--background))",
26
- foreground: "hsl(var(--foreground))",
27
- primary: {
28
- DEFAULT: "hsl(var(--primary))",
29
- foreground: "hsl(var(--primary-foreground))",
30
- },
31
- secondary: {
32
- DEFAULT: "hsl(var(--secondary))",
33
- foreground: "hsl(var(--secondary-foreground))",
34
- },
35
- destructive: {
36
- DEFAULT: "hsl(var(--destructive))",
37
- foreground: "hsl(var(--destructive-foreground))",
38
- },
39
- muted: {
40
- DEFAULT: "hsl(var(--muted))",
41
- foreground: "hsl(var(--muted-foreground))",
42
- },
43
- accent: {
44
- DEFAULT: "hsl(var(--accent))",
45
- foreground: "hsl(var(--accent-foreground))",
46
- },
47
- popover: {
48
- DEFAULT: "hsl(var(--popover))",
49
- foreground: "hsl(var(--popover-foreground))",
50
- },
51
- card: {
52
- DEFAULT: "hsl(var(--card))",
53
- foreground: "hsl(var(--card-foreground))",
54
- },
55
- },
56
- borderRadius: {
57
- lg: "var(--radius)",
58
- md: "calc(var(--radius) - 2px)",
59
- sm: "calc(var(--radius) - 4px)",
60
- },
21
keyframes: {
22
"accordion-down": {
23
from: { height: "0" },