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" },